Mock remote census responses in tests using XML

By using real XML responses developers will be able to understand better
how the integration works (the data flow), and the correspondency between
`remote_census` settings and their place at a real XML response.

As `stubbed_responses` methods were removed from the model layer now the
stubbing part should be managed from the test environment code so also
added a new helper module `RemoteCensusSetup` that can be used anywhere
where we need to call the web service.

Co-Authored-By: Javi Martín <javim@elretirao.net>
This commit is contained in:
Senén Rodero Rodríguez
2020-10-30 11:16:48 +01:00
committed by Javi Martín
parent 8257a82f2f
commit ac6260a2ef
14 changed files with 185 additions and 209 deletions

View File

@@ -77,7 +77,7 @@ class RemoteCensusApi
request = request(document_type, document_number, date_of_birth, postal_code) request = request(document_type, document_number, date_of_birth, postal_code)
client.call(Setting["remote_census.request.method_name"].to_sym, message: request).body client.call(Setting["remote_census.request.method_name"].to_sym, message: request).body
else else
stubbed_response(document_type, document_number) stubbed_invalid_response
end end
end end
@@ -119,34 +119,10 @@ class RemoteCensusApi
end end
def end_point_available? def end_point_available?
Rails.env.staging? || Rails.env.preproduction? || Rails.env.production? !Rails.env.development?
end
def stubbed_response(document_type, document_number)
if (document_number == "12345678Z" || document_number == "12345678Y") && document_type == "1"
stubbed_valid_response
else
stubbed_invalid_response
end
end
def stubbed_valid_response
{
response: {
data: {
date_of_birth: "31-12-1980",
document_number: "12345678Z",
gender: "Male",
name: "William",
surname: "Widmore",
postal_code: "28013",
district_code: "01"
}
}
}
end end
def stubbed_invalid_response def stubbed_invalid_response
{ response: { data: {}}} {}
end end
end end

View File

@@ -0,0 +1,8 @@
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<s:Body>
<response>
<data>
</data>
</response>
</s:Body>
</s:Envelope>

View File

@@ -0,0 +1,15 @@
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<s:Body>
<response>
<data>
<date_of_birth>31/12/1980</date_of_birth>
<document_number>12345678Z</document_number>
<gender>Male</gender>
<name>William</name>
<surname>Widmore</surname>
<postal_code>28013</postal_code>
<district_code>01</district_code>
</data>
</response>
</s:Body>
</s:Envelope>

View File

@@ -4,175 +4,91 @@ describe RemoteCensusApi do
let(:api) { RemoteCensusApi.new } let(:api) { RemoteCensusApi.new }
describe "#call", :remote_census do describe "#call", :remote_census do
before do it "returns a valid response correctly fullfilled when remote response returns a valid response" do
Setting["remote_census.response.valid"] = "response.data.date_of_birth" %w[12345678 12345678z].each { mock_invalid_remote_census_response }
end %w[12345678Z].each { mock_valid_remote_census_response }
let(:invalid_body) { { response: { data: {}}} } response = api.call("1", "12345678Z", Date.parse("31/12/1980"), "28013")
let(:valid_body) { { response: { data: { date_of_birth: "1-1-1980" }}} }
it "returns the response for the first valid variant" do
date = Date.parse("01/01/1983")
allow(api).to receive(:get_response_body).with(1, "00123456", date, "28001").and_return(invalid_body)
allow(api).to receive(:get_response_body).with(1, "123456", date, "28001").and_return(invalid_body)
allow(api).to receive(:get_response_body).with(1, "0123456", date, "28001").and_return(valid_body)
response = api.call(1, "123456", date, "28001")
expect(response).to be_valid expect(response).to be_valid
expect(response.date_of_birth).to eq(Date.new(1980, 1, 1))
end
it "returns the response for the first valid variant without send date_of_birth and postal_code" do
allow(api).to receive(:get_response_body).with(1, "00123456", nil, nil).and_return(invalid_body)
allow(api).to receive(:get_response_body).with(1, "123456", nil, nil).and_return(invalid_body)
allow(api).to receive(:get_response_body).with(1, "0123456", nil, nil).and_return(valid_body)
response = api.call(1, "123456", nil, nil)
expect(response).to be_valid
expect(response.date_of_birth).to eq(Date.new(1980, 1, 1))
end
it "returns the last failed response" do
date = Date.parse("01/01/1983")
allow(api).to receive(:get_response_body).with(1, "00123456", date, "28001").and_return(invalid_body)
allow(api).to receive(:get_response_body).with(1, "123456", date, "28001").and_return(invalid_body)
allow(api).to receive(:get_response_body).with(1, "0123456", date, "28001").and_return(invalid_body)
response = api.call(1, "123456", date, "28001")
expect(response).not_to be_valid
end
end
describe "request structure correctly filled" do
before do
Setting["feature.remote_census"] = true
Setting["remote_census.request.structure"] = '{ "request":
{ "codigo_institucion": 1,
"codigo_portal": 1,
"codigo_usuario": 1,
"documento": null,
"tipo_documento": null,
"codigo_idioma": 102,
"nivel": 3 }
}'
Setting["remote_census.request.document_type"] = "request.tipo_documento"
Setting["remote_census.request.document_number"] = "request.documento"
Setting["remote_census.request.date_of_birth"] = nil
Setting["remote_census.request.postal_code"] = nil
end
it "with default values" do
document_type = "1"
document_number = "0123456"
request = RemoteCensusApi.new.send(:request, document_type, document_number, nil, nil)
expect(request).to eq({ "request" =>
{ "codigo_institucion" => 1,
"codigo_portal" => 1,
"codigo_usuario" => 1,
"documento" => "0123456",
"tipo_documento" => "1",
"codigo_idioma" => 102,
"nivel" => 3 }
})
end
it "when send date_of_birth and postal_code but are not configured" do
document_type = "1"
document_number = "0123456"
date_of_birth = Date.new(1980, 1, 1)
postal_code = "28001"
request = RemoteCensusApi.new.send(:request, document_type, document_number, date_of_birth, postal_code)
expect(request).to eq({ "request" =>
{ "codigo_institucion" => 1,
"codigo_portal" => 1,
"codigo_usuario" => 1,
"documento" => "0123456",
"tipo_documento" => "1",
"codigo_idioma" => 102,
"nivel" => 3 }
})
end
it "when send date_of_birth and postal_code but are configured" do
Setting["remote_census.request.structure"] = '{ "request":
{ "codigo_institucion": 1,
"codigo_portal": 1,
"codigo_usuario": 1,
"documento": "nil",
"tipo_documento": "null",
"fecha_nacimiento": "null",
"codigo_postal": "nil",
"codigo_idioma": 102,
"nivel": 3 }
}'
Setting["remote_census.request.date_of_birth"] = "request.fecha_nacimiento"
Setting["remote_census.request.postal_code"] = "request.codigo_postal"
document_type = "1"
document_number = "0123456"
date_of_birth = Date.new(1980, 1, 1)
postal_code = "28001"
request = RemoteCensusApi.new.send(:request, document_type, document_number, date_of_birth, postal_code)
expect(request).to eq({ "request" =>
{ "codigo_institucion" => 1,
"codigo_portal" => 1,
"codigo_usuario" => 1,
"documento" => "0123456",
"tipo_documento" => "1",
"fecha_nacimiento" => "1980-01-01",
"codigo_postal" => "28001",
"codigo_idioma" => 102,
"nivel" => 3 }
})
end
end
describe "get_response_body" do
before do
Setting["feature.remote_census"] = true
end
it "return expected stubbed_response" do
document_type = "1"
document_number = "12345678Z"
response = RemoteCensusApi.new.send(:get_response_body, document_type, document_number, nil, nil)
expect(response).to eq({ response: {
data: {
date_of_birth: "31-12-1980",
document_number: "12345678Z",
gender: "Male",
name: "William",
surname: "Widmore",
postal_code: "28013",
district_code: "01"
}
}
})
end
end
describe "RemoteCensusApi::Response", :remote_census do
it "return expected response methods with default values" do
document_type = "1"
document_number = "12345678Z"
get_response_body = RemoteCensusApi.new.send(:get_response_body, document_type, document_number, nil, nil)
response = RemoteCensusApi::Response.new(get_response_body)
expect(response.valid?).to eq true
expect(response.date_of_birth).to eq Time.zone.local(1980, 12, 31).to_date expect(response.date_of_birth).to eq Time.zone.local(1980, 12, 31).to_date
expect(response.postal_code).to eq "28013" expect(response.postal_code).to eq "28013"
expect(response.gender).to eq "male" expect(response.gender).to eq "male"
expect(response.name).to eq "William Widmore" expect(response.name).to eq "William Widmore"
end end
it "returns an invalid response all variants return invalid responses" do
%w[99999999 99999999z 99999999Z].each { mock_invalid_remote_census_response }
response = api.call("1", "99999999Z", Date.parse("31/12/1980"), "28013")
expect(response).not_to be_valid
end
describe "request messages" do
let(:valid_response) { File.read("spec/fixtures/files/remote_census_api/valid.xml") }
def request_with(params)
{ "request" => params }
end
it "includes date_of_birth and postal_code when request structure is configured" do
params = {
"document_type" => "1",
"date_of_birth" => "1980-12-31",
"postal_code" => "28013"
}
savon.expects(:verify_residence)
.with(message: request_with(params.merge("document_number" => "12345678")))
.returns(valid_response)
api.call("1", "12345678Z", Date.parse("31/12/1980"), "28013")
end
it "does not include date_of_birth and postal_code when not configured" do
Setting["remote_census.request.date_of_birth"] = nil
Setting["remote_census.request.postal_code"] = nil
Setting["remote_census.request.structure"] = '{ "request":
{
"document_number": "nil",
"document_type": "null"
}
}'
params = { "document_type" => "1" }
savon.expects(:verify_residence)
.with(message: request_with(params.merge("document_number" => "12345678")))
.returns(valid_response)
api.call("1", "12345678Z", Date.parse("31/12/1980"), "28013")
end
it "includes custom parameters when configured" do
Setting["remote_census.request.structure"] = '{ "request":
{
"document_type": "null",
"document_number": "nil",
"date_of_birth": "null",
"postal_code": "nil",
"api_key": "your_api_key"
}
}'
params = {
"document_type" => "1",
"date_of_birth" => "1980-12-31",
"postal_code" => "28013",
"api_key" => "your_api_key"
}
savon.expects(:verify_residence)
.with(message: request_with(params.merge("document_number" => "12345678")))
.returns(valid_response)
api.call("1", "12345678Z", Date.parse("31/12/1980"), "28013")
end
end
end end
end end

View File

@@ -43,6 +43,8 @@ describe Officing::Residence do
end end
it "is valid" do it "is valid" do
mock_valid_remote_census_response
expect(custom_residence).to be_valid expect(custom_residence).to be_valid
end end
@@ -59,27 +61,34 @@ describe Officing::Residence do
it "is valid without a year of birth when date_of_birth is present" do it "is valid without a year of birth when date_of_birth is present" do
custom_residence.year_of_birth = nil custom_residence.year_of_birth = nil
mock_valid_remote_census_response
expect(custom_residence).to be_valid expect(custom_residence).to be_valid
end end
it "is not valid without a date of birth" do it "is not valid without a date of birth" do
custom_residence.date_of_birth = nil custom_residence.date_of_birth = nil
mock_valid_remote_census_response
expect(custom_residence).not_to be_valid expect(custom_residence).not_to be_valid
end end
it "is not valid without a postal_code" do it "is not valid without a postal_code" do
custom_residence.postal_code = nil custom_residence.postal_code = nil
mock_valid_remote_census_response
expect(custom_residence).not_to be_valid expect(custom_residence).not_to be_valid
end end
describe "dates" do describe "dates" do
it "is valid with a valid date of birth" do it "is not valid but not because date of birth" do
custom_residence = Officing::Residence.new("date_of_birth(3i)" => "1", custom_residence = Officing::Residence.new("date_of_birth(3i)" => "1",
"date_of_birth(2i)" => "1", "date_of_birth(2i)" => "1",
"date_of_birth(1i)" => "1980") "date_of_birth(1i)" => "1980")
expect(custom_residence).not_to be_valid
expect(custom_residence.errors[:date_of_birth]).to be_empty expect(custom_residence.errors[:date_of_birth]).to be_empty
end end
@@ -99,6 +108,11 @@ describe Officing::Residence do
:invalid, :invalid,
document_number: "12345678Z", document_number: "12345678Z",
postal_code: "00001") postal_code: "00001")
%w[12345678 12345678z 12345678Z].each do
mock_invalid_remote_census_response
end
residence.save residence.save
expect(FailedCensusCall.count).to eq(1) expect(FailedCensusCall.count).to eq(1)

View File

@@ -112,14 +112,15 @@ describe SignatureSheet do
expect(signature_sheet.processed).to eq(true) expect(signature_sheet.processed).to eq(true)
end end
context "with remote census active" do context "with remote census active", :remote_census do
before do
Setting["feature.remote_census"] = true
end
it "creates signatures for each group with document_number" do it "creates signatures for each group with document_number" do
Setting["remote_census.request.date_of_birth"] = nil
Setting["remote_census.request.postal_code"] = nil
required_fields_to_verify = "123A; 456B" required_fields_to_verify = "123A; 456B"
signature_sheet = create(:signature_sheet, required_fields_to_verify: required_fields_to_verify) signature_sheet = create(:signature_sheet, required_fields_to_verify: required_fields_to_verify)
%w[123A 456B].each { mock_valid_remote_census_response }
signature_sheet.verify_signatures signature_sheet.verify_signatures
expect(Signature.count).to eq(2) expect(Signature.count).to eq(2)
@@ -132,10 +133,12 @@ describe SignatureSheet do
end end
it "creates signatures for each group with document_number and date_of_birth" do it "creates signatures for each group with document_number and date_of_birth" do
Setting["remote_census.request.date_of_birth"] = "some.value" Setting["remote_census.request.postal_code"] = nil
required_fields_to_verify = "123A, 01/01/1980; 456B, 01/02/1980" required_fields_to_verify = "123A, 01/01/1980; 456B, 01/02/1980"
signature_sheet = create(:signature_sheet, required_fields_to_verify: required_fields_to_verify) signature_sheet = create(:signature_sheet, required_fields_to_verify: required_fields_to_verify)
%w[123A 456B].each { mock_valid_remote_census_response }
signature_sheet.verify_signatures signature_sheet.verify_signatures
expect(Signature.count).to eq(2) expect(Signature.count).to eq(2)
@@ -145,15 +148,15 @@ describe SignatureSheet do
expect(Signature.last.document_number).to eq("456B") expect(Signature.last.document_number).to eq("456B")
expect(Signature.last.date_of_birth).to eq(Date.parse("01/02/1980")) expect(Signature.last.date_of_birth).to eq(Date.parse("01/02/1980"))
expect(Signature.last.postal_code).to eq(nil) expect(Signature.last.postal_code).to eq(nil)
Setting["remote_census.request.date_of_birth"] = nil
end end
it "creates signatures for each group with document_number and postal_code" do it "creates signatures for each group with document_number and postal_code" do
Setting["remote_census.request.postal_code"] = "some.value" Setting["remote_census.request.date_of_birth"] = nil
required_fields_to_verify = "123A, 28001; 456B, 28002" required_fields_to_verify = "123A, 28001; 456B, 28002"
signature_sheet = create(:signature_sheet, required_fields_to_verify: required_fields_to_verify) signature_sheet = create(:signature_sheet, required_fields_to_verify: required_fields_to_verify)
%w[123A 456B].each { mock_valid_remote_census_response }
signature_sheet.verify_signatures signature_sheet.verify_signatures
expect(Signature.count).to eq(2) expect(Signature.count).to eq(2)
@@ -163,16 +166,13 @@ describe SignatureSheet do
expect(Signature.last.document_number).to eq("456B") expect(Signature.last.document_number).to eq("456B")
expect(Signature.last.date_of_birth).to eq(nil) expect(Signature.last.date_of_birth).to eq(nil)
expect(Signature.last.postal_code).to eq("28002") expect(Signature.last.postal_code).to eq("28002")
Setting["remote_census.request.postal_code"] = nil
end end
it "creates signatures for each group with document_number, postal_code and date_of_birth" do it "creates signatures for each group with document_number, postal_code and date_of_birth" do
Setting["remote_census.request.date_of_birth"] = "some.value"
Setting["remote_census.request.postal_code"] = "some.value"
required_fields_to_verify = "123A, 01/01/1980, 28001; 456B, 01/02/1980, 28002" required_fields_to_verify = "123A, 01/01/1980, 28001; 456B, 01/02/1980, 28002"
signature_sheet = create(:signature_sheet, required_fields_to_verify: required_fields_to_verify) signature_sheet = create(:signature_sheet, required_fields_to_verify: required_fields_to_verify)
%w[123A 456B].each { mock_valid_remote_census_response }
signature_sheet.verify_signatures signature_sheet.verify_signatures
expect(Signature.count).to eq(2) expect(Signature.count).to eq(2)
@@ -182,9 +182,6 @@ describe SignatureSheet do
expect(Signature.last.document_number).to eq("456B") expect(Signature.last.document_number).to eq("456B")
expect(Signature.last.date_of_birth).to eq(Date.parse("01/02/1980")) expect(Signature.last.date_of_birth).to eq(Date.parse("01/02/1980"))
expect(Signature.last.postal_code).to eq("28002") expect(Signature.last.postal_code).to eq("28002")
Setting["remote_census.request.date_of_birth"] = nil
Setting["remote_census.request.postal_code"] = nil
end end
end end
end end

View File

@@ -230,6 +230,8 @@ describe Signature do
date_of_birth: "31/12/1980", date_of_birth: "31/12/1980",
postal_code: "28013") postal_code: "28013")
mock_valid_remote_census_response
expect_any_instance_of(Signature).to receive(:assign_vote_to_user).exactly(1).times expect_any_instance_of(Signature).to receive(:assign_vote_to_user).exactly(1).times
signature.verify signature.verify

View File

@@ -128,6 +128,12 @@ RSpec.configure do |config|
Setting["remote_census.response.name"] = "response.data.name" Setting["remote_census.response.name"] = "response.data.name"
Setting["remote_census.response.surname"] = "response.data.surname" Setting["remote_census.response.surname"] = "response.data.surname"
Setting["remote_census.response.valid"] = "response.data.document_number" Setting["remote_census.response.valid"] = "response.data.document_number"
savon.mock!
end
config.after(:each, :remote_census) do
savon.unmock!
end end
# Allows RSpec to persist some state between runs in order to support # Allows RSpec to persist some state between runs in order to support

View File

@@ -8,6 +8,7 @@ module CommonActions
include Notifications include Notifications
include Polls include Polls
include Proposals include Proposals
include RemoteCensusMock
include Tags include Tags
include Translations include Translations
include Users include Users

View File

@@ -0,0 +1,30 @@
require "savon/mock/spec_helper"
module RemoteCensusMock
include Savon::SpecHelper
include DocumentParser
def mock_valid_remote_census_response
mock_remote_census_response(File.read("spec/fixtures/files/remote_census_api/valid.xml"))
end
def mock_invalid_remote_census_response
mock_remote_census_response(File.read("spec/fixtures/files/remote_census_api/invalid.xml"))
end
def mock_invalid_signature_sheet_remote_census_response
xml = File.read("spec/fixtures/files/remote_census_api/invalid.xml")
Signature.new.document_types.each do |document_type|
get_document_number_variants(document_type, "12345678Z").each do
mock_remote_census_response(xml)
end
end
end
def mock_remote_census_response(xml)
savon.expects(Setting["remote_census.request.method_name"].to_sym)
.with(message: :any)
.returns(xml)
end
end

View File

@@ -77,6 +77,11 @@ describe "Signature sheets" do
end end
context "Create throught all required_fields_to_verify of custom census api", :remote_census do context "Create throught all required_fields_to_verify of custom census api", :remote_census do
before do
mock_valid_remote_census_response
mock_invalid_signature_sheet_remote_census_response
end
scenario "Proposal" do scenario "Proposal" do
proposal = create(:proposal) proposal = create(:proposal)
visit new_admin_signature_sheet_path visit new_admin_signature_sheet_path

View File

@@ -67,7 +67,10 @@ describe "DocumentVerifications" do
expect(page).to have_content "This document is not registered" expect(page).to have_content "This document is not registered"
end end
scenario "Verifying a user which does exists in the census but not in the db redirects allows sending an email" do scenario "Verifying a user which does exists in the census but not in the db
redirects allows sending an email" do
mock_valid_remote_census_response
visit management_document_verifications_path visit management_document_verifications_path
fill_in "document_verification_document_number", with: "12345678Z" fill_in "document_verification_document_number", with: "12345678Z"
select_date "31-December-1980", from: "document_verification_date_of_birth" select_date "31-December-1980", from: "document_verification_date_of_birth"

View File

@@ -147,6 +147,8 @@ describe "Residence", :with_frozen_time do
end end
scenario "can verify voter with date_of_birth and postal_code fields" do scenario "can verify voter with date_of_birth and postal_code fields" do
mock_valid_remote_census_response
within("#side_menu") do within("#side_menu") do
click_link "Validate document" click_link "Validate document"
end end
@@ -154,7 +156,7 @@ describe "Residence", :with_frozen_time do
select "DNI", from: "residence_document_type" select "DNI", from: "residence_document_type"
fill_in "residence_document_number", with: "12345678Z" fill_in "residence_document_number", with: "12345678Z"
select_date "31-December-1980", from: "residence_date_of_birth" select_date "31-December-1980", from: "residence_date_of_birth"
fill_in "residence_postal_code", with: "28001" fill_in "residence_postal_code", with: "28013"
click_button "Validate document" click_button "Validate document"

View File

@@ -23,6 +23,7 @@ describe "Residence" do
scenario "Verify resident throught RemoteCensusApi", :remote_census do scenario "Verify resident throught RemoteCensusApi", :remote_census do
user = create(:user) user = create(:user)
login_as(user) login_as(user)
mock_valid_remote_census_response
visit account_path visit account_path
click_link "Verify my account" click_link "Verify my account"