From ac6260a2efd68d5612ed047b90acc9df477aa70a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sen=C3=A9n=20Rodero=20Rodr=C3=ADguez?= Date: Fri, 30 Oct 2020 11:16:48 +0100 Subject: [PATCH] Mock remote census responses in tests using XML MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- lib/remote_census_api.rb | 30 +-- .../files/remote_census_api/invalid.xml | 8 + .../files/remote_census_api/valid.xml | 15 ++ spec/lib/remote_census_api_spec.rb | 240 ++++++------------ spec/models/officing/residence_spec.rb | 16 +- spec/models/signature_sheet_spec.rb | 31 +-- spec/models/signature_spec.rb | 2 + spec/spec_helper.rb | 6 + spec/support/common_actions.rb | 1 + .../common_actions/remote_census_mock.rb | 30 +++ spec/system/admin/signature_sheets_spec.rb | 5 + .../management/document_verifications_spec.rb | 5 +- spec/system/officing/residence_spec.rb | 4 +- spec/system/verification/residence_spec.rb | 1 + 14 files changed, 185 insertions(+), 209 deletions(-) create mode 100644 spec/fixtures/files/remote_census_api/invalid.xml create mode 100644 spec/fixtures/files/remote_census_api/valid.xml create mode 100644 spec/support/common_actions/remote_census_mock.rb diff --git a/lib/remote_census_api.rb b/lib/remote_census_api.rb index ceb1f8c98..5cea6142e 100644 --- a/lib/remote_census_api.rb +++ b/lib/remote_census_api.rb @@ -77,7 +77,7 @@ class RemoteCensusApi request = request(document_type, document_number, date_of_birth, postal_code) client.call(Setting["remote_census.request.method_name"].to_sym, message: request).body else - stubbed_response(document_type, document_number) + stubbed_invalid_response end end @@ -119,34 +119,10 @@ class RemoteCensusApi end def end_point_available? - Rails.env.staging? || Rails.env.preproduction? || Rails.env.production? - 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" - } - } - } + !Rails.env.development? end def stubbed_invalid_response - { response: { data: {}}} + {} end end diff --git a/spec/fixtures/files/remote_census_api/invalid.xml b/spec/fixtures/files/remote_census_api/invalid.xml new file mode 100644 index 000000000..6d8f6d1f5 --- /dev/null +++ b/spec/fixtures/files/remote_census_api/invalid.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/spec/fixtures/files/remote_census_api/valid.xml b/spec/fixtures/files/remote_census_api/valid.xml new file mode 100644 index 000000000..0ca6f7360 --- /dev/null +++ b/spec/fixtures/files/remote_census_api/valid.xml @@ -0,0 +1,15 @@ + + + + + 31/12/1980 + 12345678Z + Male + William + Widmore + 28013 + 01 + + + + diff --git a/spec/lib/remote_census_api_spec.rb b/spec/lib/remote_census_api_spec.rb index 50aec27ea..152d1b946 100644 --- a/spec/lib/remote_census_api_spec.rb +++ b/spec/lib/remote_census_api_spec.rb @@ -4,175 +4,91 @@ describe RemoteCensusApi do let(:api) { RemoteCensusApi.new } describe "#call", :remote_census do - before do - Setting["remote_census.response.valid"] = "response.data.date_of_birth" - end + it "returns a valid response correctly fullfilled when remote response returns a valid response" do + %w[12345678 12345678z].each { mock_invalid_remote_census_response } + %w[12345678Z].each { mock_valid_remote_census_response } - let(:invalid_body) { { response: { data: {}}} } - 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") + response = api.call("1", "12345678Z", Date.parse("31/12/1980"), "28013") 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.postal_code).to eq "28013" expect(response.gender).to eq "male" expect(response.name).to eq "William Widmore" 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 diff --git a/spec/models/officing/residence_spec.rb b/spec/models/officing/residence_spec.rb index 512d2a232..621e24ab8 100644 --- a/spec/models/officing/residence_spec.rb +++ b/spec/models/officing/residence_spec.rb @@ -43,6 +43,8 @@ describe Officing::Residence do end it "is valid" do + mock_valid_remote_census_response + expect(custom_residence).to be_valid end @@ -59,27 +61,34 @@ describe Officing::Residence do it "is valid without a year of birth when date_of_birth is present" do custom_residence.year_of_birth = nil + mock_valid_remote_census_response + expect(custom_residence).to be_valid end it "is not valid without a date of birth" do custom_residence.date_of_birth = nil + mock_valid_remote_census_response + expect(custom_residence).not_to be_valid end it "is not valid without a postal_code" do custom_residence.postal_code = nil + mock_valid_remote_census_response + expect(custom_residence).not_to be_valid end 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", "date_of_birth(2i)" => "1", "date_of_birth(1i)" => "1980") + expect(custom_residence).not_to be_valid expect(custom_residence.errors[:date_of_birth]).to be_empty end @@ -99,6 +108,11 @@ describe Officing::Residence do :invalid, document_number: "12345678Z", postal_code: "00001") + + %w[12345678 12345678z 12345678Z].each do + mock_invalid_remote_census_response + end + residence.save expect(FailedCensusCall.count).to eq(1) diff --git a/spec/models/signature_sheet_spec.rb b/spec/models/signature_sheet_spec.rb index 8eb16b6d3..c32e94b5c 100644 --- a/spec/models/signature_sheet_spec.rb +++ b/spec/models/signature_sheet_spec.rb @@ -112,14 +112,15 @@ describe SignatureSheet do expect(signature_sheet.processed).to eq(true) end - context "with remote census active" do - before do - Setting["feature.remote_census"] = true - end - + context "with remote census active", :remote_census 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" 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 expect(Signature.count).to eq(2) @@ -132,10 +133,12 @@ describe SignatureSheet do end 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" 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 expect(Signature.count).to eq(2) @@ -145,15 +148,15 @@ describe SignatureSheet do expect(Signature.last.document_number).to eq("456B") expect(Signature.last.date_of_birth).to eq(Date.parse("01/02/1980")) expect(Signature.last.postal_code).to eq(nil) - - Setting["remote_census.request.date_of_birth"] = nil end 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" 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 expect(Signature.count).to eq(2) @@ -163,16 +166,13 @@ describe SignatureSheet do expect(Signature.last.document_number).to eq("456B") expect(Signature.last.date_of_birth).to eq(nil) expect(Signature.last.postal_code).to eq("28002") - - Setting["remote_census.request.postal_code"] = nil end 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" 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 expect(Signature.count).to eq(2) @@ -182,9 +182,6 @@ describe SignatureSheet do expect(Signature.last.document_number).to eq("456B") expect(Signature.last.date_of_birth).to eq(Date.parse("01/02/1980")) 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 diff --git a/spec/models/signature_spec.rb b/spec/models/signature_spec.rb index 7bfea9419..aa524a670 100644 --- a/spec/models/signature_spec.rb +++ b/spec/models/signature_spec.rb @@ -230,6 +230,8 @@ describe Signature do date_of_birth: "31/12/1980", postal_code: "28013") + mock_valid_remote_census_response + expect_any_instance_of(Signature).to receive(:assign_vote_to_user).exactly(1).times signature.verify diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 868931d90..df40b8c01 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -128,6 +128,12 @@ RSpec.configure do |config| Setting["remote_census.response.name"] = "response.data.name" Setting["remote_census.response.surname"] = "response.data.surname" Setting["remote_census.response.valid"] = "response.data.document_number" + + savon.mock! + end + + config.after(:each, :remote_census) do + savon.unmock! end # Allows RSpec to persist some state between runs in order to support diff --git a/spec/support/common_actions.rb b/spec/support/common_actions.rb index 42d5432b7..ab84b1500 100644 --- a/spec/support/common_actions.rb +++ b/spec/support/common_actions.rb @@ -8,6 +8,7 @@ module CommonActions include Notifications include Polls include Proposals + include RemoteCensusMock include Tags include Translations include Users diff --git a/spec/support/common_actions/remote_census_mock.rb b/spec/support/common_actions/remote_census_mock.rb new file mode 100644 index 000000000..b140c17e4 --- /dev/null +++ b/spec/support/common_actions/remote_census_mock.rb @@ -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 diff --git a/spec/system/admin/signature_sheets_spec.rb b/spec/system/admin/signature_sheets_spec.rb index e68dbdd8b..254d156c4 100644 --- a/spec/system/admin/signature_sheets_spec.rb +++ b/spec/system/admin/signature_sheets_spec.rb @@ -77,6 +77,11 @@ describe "Signature sheets" do end 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 proposal = create(:proposal) visit new_admin_signature_sheet_path diff --git a/spec/system/management/document_verifications_spec.rb b/spec/system/management/document_verifications_spec.rb index 62b364e2f..53a2c0c7e 100644 --- a/spec/system/management/document_verifications_spec.rb +++ b/spec/system/management/document_verifications_spec.rb @@ -67,7 +67,10 @@ describe "DocumentVerifications" do expect(page).to have_content "This document is not registered" 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 fill_in "document_verification_document_number", with: "12345678Z" select_date "31-December-1980", from: "document_verification_date_of_birth" diff --git a/spec/system/officing/residence_spec.rb b/spec/system/officing/residence_spec.rb index 0abbb6124..6facb7c43 100644 --- a/spec/system/officing/residence_spec.rb +++ b/spec/system/officing/residence_spec.rb @@ -147,6 +147,8 @@ describe "Residence", :with_frozen_time do end scenario "can verify voter with date_of_birth and postal_code fields" do + mock_valid_remote_census_response + within("#side_menu") do click_link "Validate document" end @@ -154,7 +156,7 @@ describe "Residence", :with_frozen_time do select "DNI", from: "residence_document_type" fill_in "residence_document_number", with: "12345678Z" 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" diff --git a/spec/system/verification/residence_spec.rb b/spec/system/verification/residence_spec.rb index 7c60bebef..7b72e5523 100644 --- a/spec/system/verification/residence_spec.rb +++ b/spec/system/verification/residence_spec.rb @@ -23,6 +23,7 @@ describe "Residence" do scenario "Verify resident throught RemoteCensusApi", :remote_census do user = create(:user) login_as(user) + mock_valid_remote_census_response visit account_path click_link "Verify my account"