defra_ruby_validators 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 423deb6f44961525a9612a533db996555e296701
4
+ data.tar.gz: 3b0e8e06f17f4e5fb7999ab5e684f76453fe792d
5
+ SHA512:
6
+ metadata.gz: 86868cd7dd7b19ea0b7112599c90c534151f02491fafc1af0e3fdeb816c3ff9e90f4299b196f323da3e4791431146a1c7d8acf58295b9bc7ed7d2caffa099bdf
7
+ data.tar.gz: b39a209754d3676202d5b2c95d7af7d11a2228b3befd60c68d3084b60b0de6a9bfbdca304354864a669555bcbbcf32c9e97780f140569e1f697c1780652dc2e8
data/LICENSE ADDED
@@ -0,0 +1,8 @@
1
+ The Open Government Licence (OGL) Version 3
2
+
3
+ Copyright (c) 2019 Environment Agency
4
+
5
+ This source code is licensed under the Open Government Licence v3.0. To view this
6
+ licence, visit www.nationalarchives.gov.uk/doc/open-government-licence/version/3
7
+ or write to the Information Policy Team, The National Archives, Kew, Richmond,
8
+ Surrey, TW9 4DU.
data/README.md ADDED
@@ -0,0 +1,87 @@
1
+ <img src="/defra-ruby-validators.png" alt="Defra ruby validators logo" />
2
+
3
+ [![Build Status](https://travis-ci.com/DEFRA/defra-ruby-validators.svg?branch=master)](https://travis-ci.com/DEFRA/defra-ruby-validators)
4
+ [![Maintainability](https://api.codeclimate.com/v1/badges/a0f8611f1a879786f642/maintainability)](https://codeclimate.com/github/DEFRA/defra-ruby-validators/maintainability)
5
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/a0f8611f1a879786f642/test_coverage)](https://codeclimate.com/github/DEFRA/defra-ruby-validators/test_coverage)
6
+ [![Licence](https://img.shields.io/badge/Licence-OGLv3-blue.svg)](http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3)
7
+
8
+ Package of validations commonly used in Defra Rails based digital services.
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile
13
+
14
+ ```ruby
15
+ gem "defra_ruby_validators"
16
+ ```
17
+
18
+ And then update your dependencies by calling
19
+
20
+ ```bash
21
+ bundle install
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ With this gem installed, a number of active model based validators become available.
27
+
28
+ ### Companies House number
29
+
30
+ This validator checks the company registration number provided. Specifically it first checks that it matches a known format. All registration numbers are 8 characters long but can be formatted in the following ways.
31
+
32
+ - 09764739
33
+ - 10997904
34
+ - SC534714
35
+ - IP00141R
36
+
37
+ If the format is valid, it then makes a call to Companies House to validate that the number
38
+
39
+ - is recognised
40
+ - belongs to an 'active' company
41
+
42
+ A company can be in various states for example liquidation, which means for the purposes of Defra its not a valid entity. So we check the status along with the number as part of the validation.
43
+
44
+ Add it to your model or form object using
45
+
46
+ ```ruby
47
+ validates :company_no, "defra_ruby_validators/companies_house_number": true
48
+ ```
49
+
50
+ A locale hint plus help text is also available for your views, that details what a registration number is and the restrictions, e.g
51
+
52
+ ```erb
53
+ <span class="form-hint"><%= t("defra_validators.companies_house_number.hint") %></span>
54
+
55
+ <div class="form-group">
56
+ <details>
57
+ <summary>
58
+ <span class="summary"><%= t("defra_validators.companies_house_number.help.heading") %></span>
59
+ </summary>
60
+ <div class="panel panel-border-narrow">
61
+ <p><%= t("defra_validators.companies_house_number.help.#{@form.business_type}") %></p>
62
+ </div>
63
+ </details>
64
+ </div>
65
+ ```
66
+
67
+ ## Contributing to this project
68
+
69
+ If you have an idea you'd like to contribute please log an issue.
70
+
71
+ All contributions should be submitted via a pull request.
72
+
73
+ ## License
74
+
75
+ THIS INFORMATION IS LICENSED UNDER THE CONDITIONS OF THE OPEN GOVERNMENT LICENCE found at:
76
+
77
+ http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3
78
+
79
+ The following attribution statement MUST be cited in your products and applications when using this information.
80
+
81
+ > Contains public sector information licensed under the Open Government license v3
82
+
83
+ ### About the license
84
+
85
+ The Open Government Licence (OGL) was developed by the Controller of Her Majesty's Stationery Office (HMSO) to enable information providers in the public sector to license the use and re-use of their information under a common open licence.
86
+
87
+ It is designed to encourage use and re-use of information freely and flexibly, with only a few conditions.
data/Rakefile ADDED
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "bundler/setup"
5
+ rescue LoadError
6
+ puts "You must `gem install bundler` and `bundle install` to run rake tasks"
7
+ end
8
+
9
+ Bundler::GemHelper.install_tasks
10
+
11
+ # This is wrapped to prevent an error when rake is called in environments where
12
+ # rspec may not be available, e.g. production. As such we don't need to handle
13
+ # the error.
14
+ # rubocop:disable Lint/HandleExceptions
15
+ begin
16
+ require "rspec/core/rake_task"
17
+
18
+ RSpec::Core::RakeTask.new(:spec)
19
+
20
+ task default: :spec
21
+ rescue LoadError
22
+ # no rspec available
23
+ end
24
+
25
+ begin
26
+ require "github_changelog_generator/task"
27
+
28
+ GitHubChangelogGenerator::RakeTask.new :changelog do |config|
29
+ end
30
+ rescue LoadError
31
+ # no changelog available
32
+ end
33
+ # rubocop:enable Lint/HandleExceptions
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "defra/ruby/validators"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "defra_ruby_validators/engine"
4
+
5
+ module DefraRubyValidators
6
+ # See lib/defra_ruby_validators/validators.rb for the main content.
7
+ # We have this file which just require's engine.rb to support using the gem
8
+ # in a rails project.
9
+ # For our test suite, we just want the typical listing of `require "filex"`,
10
+ # as the engine references using Rails.
11
+ # We also have the gem setup to support being configured from the host app.
12
+ # This is all done in `validators.rb`, which is picked up by `engine.rb` as
13
+ # well.
14
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRubyValidators
4
+ class CompaniesHouseNumberValidator < ActiveModel::EachValidator
5
+
6
+ # Examples we need to validate are
7
+ # 10997904, 09764739
8
+ # SC534714, CE000958
9
+ # IP00141R, IP27702R, SP02252R
10
+ # https://assets.publishing.service.gov.uk/government/uploads/system/uploads/attachment_data/file/426891/uniformResourceIdentifiersCustomerGuide.pdf
11
+ VALID_COMPANIES_HOUSE_REGISTRATION_NUMBER_REGEX = Regexp.new(
12
+ /\A(\d{8,8}$)|([a-zA-Z]{2}\d{6}$)|([a-zA-Z]{2}\d{5}[a-zA-Z]{1}$)\z/i
13
+ ).freeze
14
+
15
+ def validate_each(record, attribute, value)
16
+ return false unless value_is_present?(record, attribute, value)
17
+ return false unless format_is_valid?(record, attribute, value)
18
+
19
+ validate_with_companies_house(record, attribute, value)
20
+ end
21
+
22
+ private
23
+
24
+ def value_is_present?(record, attribute, value)
25
+ return true if value.present?
26
+
27
+ record.errors[attribute] << error_message("blank")
28
+ false
29
+ end
30
+
31
+ def format_is_valid?(record, attribute, value)
32
+ return true if value.match?(VALID_COMPANIES_HOUSE_REGISTRATION_NUMBER_REGEX)
33
+
34
+ record.errors[attribute] << error_message("invalid")
35
+ false
36
+ end
37
+
38
+ def validate_with_companies_house(record, attribute, value)
39
+ case CompaniesHouseService.new(value).status
40
+ when :active
41
+ true
42
+ when :inactive
43
+ record.errors[attribute] << error_message("inactive")
44
+ when :not_found
45
+ record.errors[attribute] << error_message("not_found")
46
+ end
47
+ rescue StandardError
48
+ record.errors[attribute] << error_message("error")
49
+ end
50
+
51
+ def error_message(error)
52
+ I18n.t("defra_ruby_validators.companies_house_number.errors.#{error}")
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rest-client"
4
+
5
+ module DefraRubyValidators
6
+ class CompaniesHouseService
7
+ def initialize(company_no)
8
+ @company_no = company_no
9
+ @url = "#{DefraRubyValidators.configuration.companies_house_host}#{@company_no}"
10
+ @api_key = DefraRubyValidators.configuration.companies_house_api_key
11
+ end
12
+
13
+ def status
14
+ response = RestClient::Request.execute(
15
+ method: :get,
16
+ url: @url,
17
+ user: @api_key,
18
+ password: ""
19
+ )
20
+
21
+ json = JSON.parse(response)
22
+
23
+ status_is_allowed?(json["company_status"]) ? :active : :inactive
24
+ rescue RestClient::ResourceNotFound
25
+ :not_found
26
+ end
27
+
28
+ private
29
+
30
+ def status_is_allowed?(status)
31
+ %w[active voluntary-arrangement].include?(status)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "defra_ruby_validators/validators"
4
+
5
+ module DefraRubyValidators
6
+ # Engine used to load in the custom validations
7
+ class Engine < ::Rails::Engine
8
+ isolate_namespace DefraRubyValidators
9
+
10
+ # Add a load path for this specific Engine
11
+ config.autoload_paths += Dir[File.join(config.root, "lib", "**")]
12
+
13
+ # Load I18n translation files from engine before loading ones from the host app
14
+ # This means values in the host app can override those in the engine
15
+ config.before_initialize do
16
+ engine_locales = Dir["#{config.root}/config/locales/**/*.yml"]
17
+ config.i18n.load_path = engine_locales + config.i18n.load_path
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_model"
4
+ require "defra_ruby_validators/version"
5
+ require "defra_ruby_validators/companies_house_service"
6
+
7
+ require "defra_ruby_validators/companies_house_number_validator"
8
+
9
+ module DefraRubyValidators
10
+ # Enable the ability to configure the gem from its host app, rather than
11
+ # reading directly from env vars. Derived from
12
+ # https://robots.thoughtbot.com/mygem-configure-block
13
+ class << self
14
+ attr_writer :configuration
15
+
16
+ def configuration
17
+ @configuration ||= Configuration.new
18
+ end
19
+ end
20
+
21
+ def self.configure
22
+ yield(configuration)
23
+ end
24
+
25
+ class Configuration
26
+ attr_accessor :companies_house_host, :companies_house_api_key
27
+
28
+ def initialize
29
+ @companies_house_host = "https://api.companieshouse.gov.uk/company/"
30
+ @companies_house_api_key = nil
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRubyValidators
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,67 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.companieshouse.gov.uk/company/07281919
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - "*/*"
12
+ Accept-Encoding:
13
+ - gzip, deflate
14
+ User-Agent:
15
+ - rest-client/2.0.2 (darwin17.3.0 x86_64) ruby/2.4.2p198
16
+ Host:
17
+ - api.companieshouse.gov.uk
18
+ Authorization:
19
+ - Basic MnZodWowb1dhYk13N2h6TnpBVWlTT2ctNktpVVRCcFhCRF83Zktibzo=
20
+ response:
21
+ status:
22
+ code: 200
23
+ message: OK
24
+ headers:
25
+ Date:
26
+ - Mon, 28 Jan 2019 09:38:50 GMT
27
+ Content-Type:
28
+ - application/json
29
+ Content-Length:
30
+ - '979'
31
+ Connection:
32
+ - keep-alive
33
+ Access-Control-Allow-Credentials:
34
+ - 'true'
35
+ Access-Control-Allow-Headers:
36
+ - X-RateLimit-Query, origin, content-type, content-length, user-agent, host,
37
+ accept, authorization
38
+ Access-Control-Expose-Headers:
39
+ - Location,www-authenticate,cache-control,pragma,content-type,expires,last-modified
40
+ - X-RateLimit-Window, X-RateLimit-Limit, X-RateLimit-Remain, X-RateLimit-Reset,
41
+ Location, www-authenticate, cache-control, pragma, content-type, expires,
42
+ last-modified
43
+ Access-Control-Max-Age:
44
+ - '3600'
45
+ Cache-Control:
46
+ - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
47
+ Pragma:
48
+ - no-cache
49
+ X-Ratelimit-Limit:
50
+ - '600'
51
+ X-Ratelimit-Remain:
52
+ - '596'
53
+ X-Ratelimit-Reset:
54
+ - '1548668445'
55
+ X-Ratelimit-Window:
56
+ - 5m
57
+ Server:
58
+ - CompaniesHouse
59
+ body:
60
+ encoding: UTF-8
61
+ string: '{"sic_codes":["82990"],"company_number":"07281919","has_been_liquidated":false,"accounts":{"last_accounts":{"made_up_to":"2013-06-30","type":"total-exemption-small"},"accounting_reference_date":{"day":"30","month":"06"}},"last_full_members_list_date":"2014-06-11","status":"active","type":"ltd","date_of_creation":"2010-06-11","registered_office_address":{"postal_code":"HA8
62
+ 7EJ","locality":"Edgware","region":"Middlesex","address_line_1":"8th Floor
63
+ Elizabeth House","address_line_2":"54-58 High Street"},"undeliverable_registered_office_address":false,"company_name":"DIRECT
64
+ SKIPS UK LTD","annual_return":{"last_made_up_to":"2014-06-11"},"jurisdiction":"england-wales","etag":"1cdef5bc2a020b3e9003b086033b64b78bcb28f6","company_status":"dissolved","has_insolvency_history":false,"has_charges":false,"links":{"self":"/company/07281919","filing_history":"/company/07281919/filing-history","officers":"/company/07281919/officers"},"date_of_cessation":"2016-01-05","can_file":false}'
65
+ http_version:
66
+ recorded_at: Mon, 28 Jan 2019 09:38:50 GMT
67
+ recorded_with: VCR 4.0.0
@@ -0,0 +1,64 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.companieshouse.gov.uk/company/99999999
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - "*/*"
12
+ Accept-Encoding:
13
+ - gzip, deflate
14
+ User-Agent:
15
+ - rest-client/2.0.2 (darwin17.3.0 x86_64) ruby/2.4.2p198
16
+ Host:
17
+ - api.companieshouse.gov.uk
18
+ Authorization:
19
+ - Basic MnZodWowb1dhYk13N2h6TnpBVWlTT2ctNktpVVRCcFhCRF83Zktibzo=
20
+ response:
21
+ status:
22
+ code: 404
23
+ message: Not Found
24
+ headers:
25
+ Date:
26
+ - Mon, 28 Jan 2019 09:38:50 GMT
27
+ Content-Type:
28
+ - application/json
29
+ Content-Length:
30
+ - '70'
31
+ Connection:
32
+ - keep-alive
33
+ Access-Control-Allow-Credentials:
34
+ - 'true'
35
+ Access-Control-Allow-Headers:
36
+ - X-RateLimit-Query, origin, content-type, content-length, user-agent, host,
37
+ accept, authorization
38
+ Access-Control-Expose-Headers:
39
+ - Location,www-authenticate,cache-control,pragma,content-type,expires,last-modified
40
+ - X-RateLimit-Window, X-RateLimit-Limit, X-RateLimit-Remain, X-RateLimit-Reset,
41
+ Location, www-authenticate, cache-control, pragma, content-type, expires,
42
+ last-modified
43
+ Access-Control-Max-Age:
44
+ - '3600'
45
+ Cache-Control:
46
+ - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
47
+ Pragma:
48
+ - no-cache
49
+ X-Ratelimit-Limit:
50
+ - '600'
51
+ X-Ratelimit-Remain:
52
+ - '597'
53
+ X-Ratelimit-Reset:
54
+ - '1548668445'
55
+ X-Ratelimit-Window:
56
+ - 5m
57
+ Server:
58
+ - CompaniesHouse
59
+ body:
60
+ encoding: UTF-8
61
+ string: '{"errors":[{"error":"company-profile-not-found","type":"ch:service"}]}'
62
+ http_version:
63
+ recorded_at: Mon, 28 Jan 2019 09:38:50 GMT
64
+ recorded_with: VCR 4.0.0
@@ -0,0 +1,65 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.companieshouse.gov.uk/company/09360070
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - "*/*"
12
+ Accept-Encoding:
13
+ - gzip, deflate
14
+ User-Agent:
15
+ - rest-client/2.0.2 (darwin17.3.0 x86_64) ruby/2.4.2p198
16
+ Host:
17
+ - api.companieshouse.gov.uk
18
+ Authorization:
19
+ - Basic MnZodWowb1dhYk13N2h6TnpBVWlTT2ctNktpVVRCcFhCRF83Zktibzo=
20
+ response:
21
+ status:
22
+ code: 200
23
+ message: OK
24
+ headers:
25
+ Date:
26
+ - Sun, 27 Jan 2019 23:57:58 GMT
27
+ Content-Type:
28
+ - application/json
29
+ Content-Length:
30
+ - '1178'
31
+ Connection:
32
+ - keep-alive
33
+ Access-Control-Allow-Credentials:
34
+ - 'true'
35
+ Access-Control-Allow-Headers:
36
+ - X-RateLimit-Query, origin, content-type, content-length, user-agent, host,
37
+ accept, authorization
38
+ Access-Control-Expose-Headers:
39
+ - Location,www-authenticate,cache-control,pragma,content-type,expires,last-modified
40
+ - X-RateLimit-Window, X-RateLimit-Limit, X-RateLimit-Remain, X-RateLimit-Reset,
41
+ Location, www-authenticate, cache-control, pragma, content-type, expires,
42
+ last-modified
43
+ Access-Control-Max-Age:
44
+ - '3600'
45
+ Cache-Control:
46
+ - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
47
+ Pragma:
48
+ - no-cache
49
+ X-Ratelimit-Limit:
50
+ - '600'
51
+ X-Ratelimit-Remain:
52
+ - '598'
53
+ X-Ratelimit-Reset:
54
+ - '1548633621'
55
+ X-Ratelimit-Window:
56
+ - 5m
57
+ Server:
58
+ - CompaniesHouse
59
+ body:
60
+ encoding: UTF-8
61
+ string: '{"type":"ltd","company_name":"0800 WASTE LTD.","has_insolvency_history":false,"accounts":{"next_due":"2019-09-30","next_made_up_to":"2018-12-31","next_accounts":{"overdue":false,"period_start_on":"2018-01-01","due_on":"2019-09-30","period_end_on":"2018-12-31"},"accounting_reference_date":{"month":"12","day":"31"},"last_accounts":{"period_end_on":"2017-12-31","period_start_on":"2017-01-01","made_up_to":"2017-12-31"},"overdue":false},"undeliverable_registered_office_address":false,"etag":"0ec9d00cab0ffee2ef1f5d59f4f714fa5b1618f5","company_number":"09360070","registered_office_address":{"postal_code":"SM3
62
+ 9ND","locality":"Sutton","region":"Surrey","address_line_1":"21 Haslam Avenue"},"jurisdiction":"england-wales","date_of_creation":"2014-12-18","company_status":"active","has_charges":false,"sic_codes":["38110"],"last_full_members_list_date":"2015-12-18","confirmation_statement":{"overdue":false,"next_made_up_to":"2020-01-23","last_made_up_to":"2019-01-23","next_due":"2020-02-06"},"links":{"self":"/company/09360070","filing_history":"/company/09360070/filing-history","officers":"/company/09360070/officers"},"registered_office_is_in_dispute":false,"can_file":true}'
63
+ http_version:
64
+ recorded_at: Sun, 27 Jan 2019 23:57:58 GMT
65
+ recorded_with: VCR 4.0.0
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRubyValidators
4
+ RSpec.describe CompaniesHouseNumberValidator do
5
+ context "when given a valid company number" do
6
+ before do
7
+ allow_any_instance_of(CompaniesHouseService).to receive(:status).and_return(:active)
8
+ end
9
+
10
+ %w[10997904 09764739 SC534714 IP00141R].each do |company_no|
11
+ context "like #{company_no}" do
12
+ it "confirms the number is valid" do
13
+ expect(DummyCompaniesHouseNumber.new(company_no)).to be_valid
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ context "when given an invalid company number" do
20
+ context "because it is blank" do
21
+ subject { DummyCompaniesHouseNumber.new("") }
22
+
23
+ it "confirms the number is not valid" do
24
+ expect(subject).to_not be_valid
25
+ end
26
+ it "adds an error to the subject's errors collection" do
27
+ subject.valid?
28
+ expect(subject.errors.count).to eq(1)
29
+ end
30
+ it "adds an error with the correct message" do
31
+ subject.valid?
32
+ expect(subject.errors[:company_no][0]).to eq(I18n.t("defra_ruby_validators.companies_house_number.errors.blank"))
33
+ end
34
+ end
35
+
36
+ context "because the format is wrong" do
37
+ subject { DummyCompaniesHouseNumber.new("foobar42") }
38
+
39
+ it "confirms the number is not valid" do
40
+ expect(subject).to_not be_valid
41
+ end
42
+ it "adds an error to the subject's errors collection" do
43
+ subject.valid?
44
+ expect(subject.errors.count).to eq(1)
45
+ end
46
+ it "adds an error with the correct message" do
47
+ subject.valid?
48
+ expect(subject.errors[:company_no][0]).to eq(I18n.t("defra_ruby_validators.companies_house_number.errors.invalid"))
49
+ end
50
+ end
51
+
52
+ context "because it's not found on companies house" do
53
+ before do
54
+ allow_any_instance_of(CompaniesHouseService).to receive(:status).and_return(:not_found)
55
+ end
56
+
57
+ subject { DummyCompaniesHouseNumber.new("99999999") }
58
+
59
+ it "confirms the number is not valid" do
60
+ expect(subject).to_not be_valid
61
+ end
62
+ it "adds an error to the subject's errors collection" do
63
+ subject.valid?
64
+ expect(subject.errors.count).to eq(1)
65
+ end
66
+ it "adds an error with the correct message" do
67
+ subject.valid?
68
+ expect(subject.errors[:company_no][0]).to eq(I18n.t("defra_ruby_validators.companies_house_number.errors.not_found"))
69
+ end
70
+ end
71
+
72
+ context "because it's not 'active' on companies house" do
73
+ before do
74
+ allow_any_instance_of(CompaniesHouseService).to receive(:status).and_return(:inactive)
75
+ end
76
+
77
+ subject { DummyCompaniesHouseNumber.new("07281919") }
78
+
79
+ it "confirms the number is not valid" do
80
+ expect(subject).to_not be_valid
81
+ end
82
+ it "adds an error to the subject's errors collection" do
83
+ subject.valid?
84
+ expect(subject.errors.count).to eq(1)
85
+ end
86
+ it "adds an error with the correct message" do
87
+ subject.valid?
88
+ expect(subject.errors[:company_no][0]).to eq(I18n.t("defra_ruby_validators.companies_house_number.errors.inactive"))
89
+ end
90
+ end
91
+ end
92
+
93
+ context "when there is an error connecting with companies house" do
94
+ before do
95
+ allow_any_instance_of(CompaniesHouseService).to receive(:status).and_raise(StandardError)
96
+ end
97
+
98
+ subject { DummyCompaniesHouseNumber.new("10997904") }
99
+
100
+ it "confirms the number is not valid" do
101
+ expect(subject).to_not be_valid
102
+ end
103
+ it "adds an error to the subject's errors collection" do
104
+ subject.valid?
105
+ expect(subject.errors.count).to eq(1)
106
+ end
107
+ it "adds an error with the correct message" do
108
+ subject.valid?
109
+ expect(subject.errors[:company_no][0]).to eq(I18n.t("defra_ruby_validators.companies_house_number.errors.error"))
110
+ end
111
+ end
112
+
113
+ class DummyCompaniesHouseNumber
114
+ include ActiveModel::Model
115
+
116
+ attr_accessor :company_no
117
+
118
+ def initialize(company_no)
119
+ @company_no = company_no
120
+ end
121
+
122
+ validates :company_no, "defra_ruby_validators/companies_house_number": true
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRubyValidators
4
+ RSpec.describe CompaniesHouseService do
5
+ let(:companies_house_service) { CompaniesHouseService.new("09360070") }
6
+
7
+ context "when a company_no is for an active company" do
8
+ it "returns :active" do
9
+ VCR.use_cassette("company_no_valid") do
10
+ expect(companies_house_service.status).to eq(:active)
11
+ end
12
+ end
13
+ end
14
+
15
+ context "when a company_no is not found" do
16
+ let(:companies_house_service) { CompaniesHouseService.new("99999999") }
17
+
18
+ it "returns :not_found" do
19
+ VCR.use_cassette("company_no_not_found") do
20
+ expect(companies_house_service.status).to eq(:not_found)
21
+ end
22
+ end
23
+ end
24
+
25
+ context "when a company_no is inactive" do
26
+ let(:companies_house_service) { CompaniesHouseService.new("07281919") }
27
+
28
+ it "returns :inactive" do
29
+ VCR.use_cassette("company_no_inactive") do
30
+ expect(companies_house_service.status).to eq(:inactive)
31
+ end
32
+ end
33
+ end
34
+
35
+ context "when the request times out" do
36
+ it "raises an exception" do
37
+ VCR.turned_off do
38
+ host = "https://api.companieshouse.gov.uk/"
39
+ stub_request(:any, /.*#{host}.*/).to_timeout
40
+ expect { companies_house_service.status }.to raise_error(StandardError)
41
+ end
42
+ end
43
+ end
44
+
45
+ context "when the request returns an error" do
46
+ it "raises an exception" do
47
+ VCR.turned_off do
48
+ host = "https://api.companieshouse.gov.uk/"
49
+ stub_request(:any, /.*#{host}.*/).to_raise(SocketError)
50
+ expect { companies_house_service.status }.to raise_error(StandardError)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe DefraRubyValidators do
4
+ it "has a version number" do
5
+ expect(DefraRubyValidators::VERSION).not_to be nil
6
+ end
7
+ end
data/spec/examples.txt ADDED
@@ -0,0 +1,15 @@
1
+ example_id | status | run_time |
2
+ ------------------------------------------------------------------------------ | ------ | ---------------------- |
3
+ ./spec/defra_ruby_validators/companies_house_number_validator_spec.rb[1:1:1:1] | passed | 0.02962 seconds |
4
+ ./spec/defra_ruby_validators/companies_house_number_validator_spec.rb[1:1:2:1] | passed | 0.00043 seconds |
5
+ ./spec/defra_ruby_validators/companies_house_number_validator_spec.rb[1:1:3:1] | passed | 0.00026 seconds |
6
+ ./spec/defra_ruby_validators/companies_house_number_validator_spec.rb[1:1:4:1] | passed | 0.00026 seconds |
7
+ ./spec/defra_ruby_validators/companies_house_number_validator_spec.rb[1:2:1:1] | passed | 0.01795 seconds |
8
+ ./spec/defra_ruby_validators/companies_house_number_validator_spec.rb[1:2:1:2] | passed | 1 minute 29.46 seconds |
9
+ ./spec/defra_ruby_validators/companies_house_number_validator_spec.rb[1:2:2:1] | failed | 0.02416 seconds |
10
+ ./spec/defra_ruby_validators/companies_house_service_spec.rb[1:1:1] | passed | 0.0289 seconds |
11
+ ./spec/defra_ruby_validators/companies_house_service_spec.rb[1:2:1] | passed | 0.01738 seconds |
12
+ ./spec/defra_ruby_validators/companies_house_service_spec.rb[1:3:1] | passed | 0.01767 seconds |
13
+ ./spec/defra_ruby_validators/companies_house_service_spec.rb[1:4:1] | passed | 0.01833 seconds |
14
+ ./spec/defra_ruby_validators/companies_house_service_spec.rb[1:5:1] | passed | 0.01512 seconds |
15
+ ./spec/defra_ruby_validators/version_spec.rb[1:1] | passed | 0.00209 seconds |
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+
5
+ # Test coverage reporting
6
+ require "simplecov"
7
+ SimpleCov.start
8
+
9
+ # Support debugging in the tests
10
+ require "byebug"
11
+ # Load env vars from a text file
12
+ require "dotenv/load"
13
+ # Need to require our actual code files
14
+ require "defra_ruby_validators/validators"
15
+
16
+ # The following line is provided for convenience purposes. It has the downside
17
+ # of increasing the boot-up time by auto-requiring all files in the support
18
+ # directory. However in a small gem like this the increase should be neglible
19
+ Dir[File.join(__dir__, "support", "**", "*.rb")].each { |f| require f }
20
+
21
+ RSpec.configure do |config|
22
+ # Allows RSpec to persist some state between runs in order to support
23
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
24
+ # you configure your source control system to ignore this file.
25
+ config.example_status_persistence_file_path = "spec/examples.txt"
26
+
27
+ # Disable RSpec exposing methods globally on `Module` and `main`
28
+ config.disable_monkey_patching!
29
+
30
+ config.expect_with :rspec do |c|
31
+ c.syntax = :expect
32
+ end
33
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ DefraRubyValidators.configure do |configuration|
4
+ configuration.companies_house_api_key = ENV["COMPANIES_HOUSE_API_KEY"]
5
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Support using the locale files within our tests (else we'd rely on loading the
4
+ # gem in a rails app to confirm these are being pulled through correctly.)
5
+ require "i18n"
6
+
7
+ I18n.load_path << Dir[File.expand_path("config/locales") + "/**/*.yml"]
8
+ I18n.default_locale = :en
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Stubbing HTTP requests
4
+ require "webmock/rspec"
5
+ # Auto generate fake responses for web-requests
6
+ require "vcr"
7
+
8
+ VCR.configure do |c|
9
+ c.cassette_library_dir = "spec/cassettes"
10
+ c.hook_into :webmock
11
+
12
+ c.ignore_hosts "127.0.0.1", "codeclimate.com"
13
+
14
+ SECONDS_IN_DAY = 24 * 60 * 60
15
+
16
+ c.default_cassette_options = { re_record_interval: (14 * SECONDS_IN_DAY) }
17
+
18
+ # Strip out authorization info
19
+ c.filter_sensitive_data("Basic <API_KEY>") do |interaction|
20
+ auth = interaction.request.headers["Authorization"]
21
+ auth.first if auth.nil? || auth.empty?
22
+ end
23
+ end
metadata ADDED
@@ -0,0 +1,260 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: defra_ruby_validators
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Defra
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-01-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activemodel
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rest-client
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: byebug
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: defra_ruby_style
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: dotenv
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: github_changelog_generator
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: i18n
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '3.0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '3.0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rubocop
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: simplecov
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: vcr
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '4.0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '4.0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: webmock
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: '3.4'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '3.4'
195
+ description: Package of validations commonly used in Defra Rails based digital services
196
+ email:
197
+ - alan.cruikshanks@environment-agency.gov.uk
198
+ executables: []
199
+ extensions: []
200
+ extra_rdoc_files: []
201
+ files:
202
+ - LICENSE
203
+ - README.md
204
+ - Rakefile
205
+ - bin/console
206
+ - bin/setup
207
+ - lib/defra_ruby_validators.rb
208
+ - lib/defra_ruby_validators/companies_house_number_validator.rb
209
+ - lib/defra_ruby_validators/companies_house_service.rb
210
+ - lib/defra_ruby_validators/engine.rb
211
+ - lib/defra_ruby_validators/validators.rb
212
+ - lib/defra_ruby_validators/version.rb
213
+ - spec/cassettes/company_no_inactive.yml
214
+ - spec/cassettes/company_no_not_found.yml
215
+ - spec/cassettes/company_no_valid.yml
216
+ - spec/defra_ruby_validators/companies_house_number_validator_spec.rb
217
+ - spec/defra_ruby_validators/companies_house_service_spec.rb
218
+ - spec/defra_ruby_validators/version_spec.rb
219
+ - spec/examples.txt
220
+ - spec/spec_helper.rb
221
+ - spec/support/defra_ruby_validators.rb
222
+ - spec/support/i18n.rb
223
+ - spec/support/vcr.rb
224
+ homepage: https://github.com/DEFRA/defra-ruby-validators
225
+ licenses:
226
+ - The Open Government Licence (OGL) Version 3
227
+ metadata:
228
+ allowed_push_host: https://rubygems.org
229
+ post_install_message:
230
+ rdoc_options: []
231
+ require_paths:
232
+ - lib
233
+ required_ruby_version: !ruby/object:Gem::Requirement
234
+ requirements:
235
+ - - ">="
236
+ - !ruby/object:Gem::Version
237
+ version: '0'
238
+ required_rubygems_version: !ruby/object:Gem::Requirement
239
+ requirements:
240
+ - - ">="
241
+ - !ruby/object:Gem::Version
242
+ version: '0'
243
+ requirements: []
244
+ rubyforge_project:
245
+ rubygems_version: 2.6.13
246
+ signing_key:
247
+ specification_version: 4
248
+ summary: Defra ruby on rails validations
249
+ test_files:
250
+ - spec/spec_helper.rb
251
+ - spec/defra_ruby_validators/companies_house_service_spec.rb
252
+ - spec/defra_ruby_validators/version_spec.rb
253
+ - spec/defra_ruby_validators/companies_house_number_validator_spec.rb
254
+ - spec/examples.txt
255
+ - spec/cassettes/company_no_not_found.yml
256
+ - spec/cassettes/company_no_valid.yml
257
+ - spec/cassettes/company_no_inactive.yml
258
+ - spec/support/i18n.rb
259
+ - spec/support/vcr.rb
260
+ - spec/support/defra_ruby_validators.rb