defra_ruby_mocks 1.4.1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 37b80527c008c3d05100caffb316ae36fd75050a7d5612db07a180f163e3e17a
4
- data.tar.gz: 622dc9a174d7e0af97046b33a12164b37deec2d3574afebd42932b7c7b699171
3
+ metadata.gz: bc69209c2d4b90b3726d7486bb0f4f0f001d80aff649951f4e8eaa5e17e46cec
4
+ data.tar.gz: 2f8ca2c6731b2d0eae695e7aeae936c20288480bf758c4f16fcdcf3a27f70067
5
5
  SHA512:
6
- metadata.gz: ab9dec997252c0e656cb39c4364e9d2f28e28bfd707309178a3d0e17d3d3289241720cc4c78a1f542edef1545a5d30e43573aea389e6fc69ee33237e47414c95
7
- data.tar.gz: e3f3707826e51e569703a04aaaaeb4593f99db011331ffd73018909c8548f702cf317ccefe0f30308047b3734107b4ce292c8ef740fb362e9647834b3eb79e4c
6
+ metadata.gz: ed7a96c4eb66607adbe341b441181b339b60e28cf1d66e92e1eb6467606d82676110efc587d921a309fec419c472095a82c7b1b1bb8ebbff64740182c38723f4
7
+ data.tar.gz: f9b8847f14ac049e9b1cef302cfbe8893c6b56797e5f48e6b6548f939c16f923111c2f79be4023ab8c1c5a62aa91db10eebfc73b797de9feb7326798a65af215
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # Defra Ruby Mocks
2
2
 
3
- [![Build Status](https://travis-ci.com/DEFRA/defra-ruby-mocks.svg?branch=master)](https://travis-ci.com/DEFRA/defra-ruby-mocks)
3
+ ![Build Status](https://github.com/DEFRA/defra-ruby-mocks/workflows/CI/badge.svg?branch=main)
4
4
  [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=DEFRA_defra-ruby-mocks&metric=sqale_rating)](https://sonarcloud.io/dashboard?id=DEFRA_defra-ruby-mocks)
5
5
  [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=DEFRA_defra-ruby-mocks&metric=coverage)](https://sonarcloud.io/dashboard?id=DEFRA_defra-ruby-mocks)
6
- [![security](https://hakiri.io/github/DEFRA/defra-ruby-mocks/master.svg)](https://hakiri.io/github/DEFRA/defra-ruby-mocks/master)
6
+ [![security](https://hakiri.io/github/DEFRA/defra-ruby-mocks/main.svg)](https://hakiri.io/github/DEFRA/defra-ruby-mocks/main)
7
7
  [![Licence](https://img.shields.io/badge/Licence-OGLv3-blue.svg)](http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3)
8
8
 
9
9
  A Rails Engine used by the [Ruby services team](https://github.com/DEFRA/ruby-services-team) in their digital services.
@@ -21,7 +21,7 @@ Things to note
21
21
 
22
22
  Make sure you already have:
23
23
 
24
- - Ruby 2.4.2
24
+ - Ruby 2.7.1
25
25
  - [Bundler](http://bundler.io/) – for installing Ruby gems
26
26
 
27
27
  ## Mounting the engine
@@ -71,14 +71,38 @@ The project currently mocks the following services.
71
71
 
72
72
  When mounted into an app you can make requests to `/mocks/company/[company number]` to get a response that matches what our apps expect.
73
73
 
74
- This is an important distinction to note. When our apps like the [Waste Exemptions front office](https://github.com/DEFRA/waste-exemptions-front-office) make a real request to Companies House, they get a lot more information back in the JSON reponse. However the only thing they are interested in is the value of `"company_status"`.
74
+ This is an important distinction to note. When our apps like the [Waste Exemptions front office](https://github.com/DEFRA/waste-exemptions-front-office) make a real request to Companies House, they get a lot more information back in the JSON reponse. However the only things they are interested in are the value of `"company_name"`, `"company_status"`, `"company_type"` and `"registered_office"`, .
75
75
 
76
- So rather than maintain a lot of unused JSON data, the mock just returns that bit of the JSON.
76
+ So rather than maintain a lot of unused JSON data, the mock just returns those bits of the JSON.
77
77
 
78
78
  ```bash
79
79
  curl http://localhost:3000/mocks/company/SC123456
80
80
  {
81
- "company_status": "active"
81
+ "company_name": "Acme Industries",
82
+ "company_status": "active",
83
+ "company_type": "ltd",
84
+ "registered_office_address": {
85
+ "address_line_1": "10 Downing St",
86
+ "address_line_2": "Horizon House",
87
+ "locality": "Bristol",
88
+ "postal_code": "BS1 5AH"
89
+ }
90
+ }
91
+ ```
92
+
93
+ Additionally, an Officers endpoint is available at `/mocks/company/[company number]/officers`. This returns a list of partial Officer data, eg:
94
+ ```bash
95
+ curl http://localhost:3000/mocks/company/SC123456/officers
96
+ {
97
+ "items": [
98
+ {
99
+ "name": "APPLE, Alice",
100
+ "officer_role": "director"
101
+ },
102
+ {
103
+ "name": "BANANA, Bob",
104
+ "officer_role": "director"
105
+ },...
82
106
  }
83
107
  ```
84
108
 
@@ -99,6 +123,11 @@ The exceptions to this are the 'special' numbers listed below. Use them if you a
99
123
  - `33333333` will return `"open"`
100
124
  - `22222222` will return `"closed"`
101
125
 
126
+ Additionally, an `"active"` LLP company can be retrieved by using the following registration numbers:
127
+
128
+ - `XX999999`
129
+ - `YY999999`
130
+
102
131
  The list of possible statuses was taken from
103
132
 
104
133
  - [Companies House API](https://developer.companieshouse.gov.uk/api/docs/company/company_number/companyProfile-resource.html)
@@ -122,6 +151,30 @@ This Worldpay mock replicates those 2 interactions with the following urls
122
151
  - `../worldpay/payments-service`
123
152
  - `../worldpay/dispatcher`
124
153
 
154
+ ##### Cancelled payments
155
+
156
+ The engine has the ability to mock a user cancelling a payment when on the Worldpay site. To have the mock return a cancelled payment response just ensure the registration's company name includes the word `cancel` (case doesn't matter).
157
+
158
+ If it does the engine will redirect back to the cancelled url instead of the success url provided, plus set the payment status to `CANCELLED`.
159
+
160
+ This allows us to test how the application handles Worldpay responding with a cancelled payment response.
161
+
162
+ ##### Errored payments
163
+
164
+ The engine has the ability to Worldpay erroring during a payment. To have the mock return an errored payment response just ensure the registration's company name includes the word `error` (case doesn't matter).
165
+
166
+ If it does the engine will redirect back to the error url instead of the success url provided, plus set the payment status to `ERROR`.
167
+
168
+ This allows us to test how the application handles Worldpay responding with an errored payment response.
169
+
170
+ ##### Pending payments
171
+
172
+ The engine has the ability to also mock Worldpay marking a payment as pending. To have the mock return a payment pending response just ensure the registration's company name includes the word `pending` (case doesn't matter).
173
+
174
+ If it does the engine will redirect back to the pending url instead of the success url provided, plus set the payment status to `SENT_FOR_AUTHORISATION`.
175
+
176
+ This allows us to test how the application handles Worldpay responding with a payment pending response.
177
+
125
178
  ##### Refused payments
126
179
 
127
180
  The engine has the ability to also mock Worldpay refusing a payment. To have the mock refuse payment just ensure the registration's company name includes the word `reject` (case doesn't matter).
@@ -6,13 +6,20 @@ module DefraRubyMocks
6
6
  before_action :set_default_response_format
7
7
 
8
8
  def show
9
- @status = CompaniesHouseService.run(params[:id])
9
+ service = CompaniesHouseService.run(params[:id])
10
+
11
+ @company_status = service.company_status
12
+ @company_type = service.company_type
10
13
 
11
14
  respond_to :json
12
15
  rescue NotFoundError
13
16
  render "not_found", status: 404
14
17
  end
15
18
 
19
+ def officers
20
+ respond_to :json
21
+ end
22
+
16
23
  private
17
24
 
18
25
  def set_default_response_format
@@ -10,14 +10,18 @@ module DefraRubyMocks
10
10
 
11
11
  render_payment_response if @values[:request_type] == :payment
12
12
  render_refund_response if @values[:request_type] == :refund
13
- rescue StandardError
13
+ rescue StandardError => e
14
+ Rails.logger.error("MOCKS: Worldpay payments service error: #{e.message}")
14
15
  head 500
15
16
  end
16
17
 
17
18
  def dispatcher
18
19
  @response = WorldpayResponseService.run(
19
20
  success_url: params[:successURL],
20
- failure_url: params[:failureURL]
21
+ failure_url: params[:failureURL],
22
+ pending_url: params[:pendingURL],
23
+ cancel_url: params[:cancelURL],
24
+ error_url: params[:errorURL]
21
25
  )
22
26
 
23
27
  if @response.status == :STUCK
@@ -25,7 +29,8 @@ module DefraRubyMocks
25
29
  else
26
30
  redirect_to @response.url
27
31
  end
28
- rescue StandardError
32
+ rescue StandardError => e
33
+ Rails.logger.error("MOCKS: Worldpay dispatcher error: #{e.message}")
29
34
  head 500
30
35
  end
31
36
 
@@ -2,8 +2,14 @@
2
2
 
3
3
  module DefraRubyMocks
4
4
  class BaseService
5
- def self.run(attrs = nil)
6
- new.run(attrs)
5
+ def self.run(options = nil)
6
+ if options && !options.is_a?(Hash)
7
+ new.run(options)
8
+ elsif options
9
+ new.run(**options)
10
+ else
11
+ new.run
12
+ end
7
13
  end
8
14
  end
9
15
  end
@@ -31,15 +31,22 @@ module DefraRubyMocks
31
31
  }
32
32
  end
33
33
 
34
+ def self.llp_company_numbers
35
+ %w[XX999999 YY999999]
36
+ end
37
+
34
38
  def run(company_number)
35
39
  raise NotFoundError unless valid_company_number?(company_number)
36
40
  raise NotFoundError if company_number == NOT_FOUND
37
41
 
38
- return specials[company_number] if specials.key?(company_number)
42
+ @company_status = specials[company_number] || "active"
43
+ @company_type = llps.include?(company_number) ? "llp" : "ltd"
39
44
 
40
- "active"
45
+ self
41
46
  end
42
47
 
48
+ attr_reader :company_status, :company_type
49
+
43
50
  private
44
51
 
45
52
  def valid_company_number?(company_number)
@@ -50,5 +57,8 @@ module DefraRubyMocks
50
57
  self.class.special_company_numbers
51
58
  end
52
59
 
60
+ def llps
61
+ self.class.llp_company_numbers
62
+ end
53
63
  end
54
64
  end
@@ -3,11 +3,19 @@
3
3
  module DefraRubyMocks
4
4
  class WorldpayResponseService < BaseService
5
5
 
6
- def run(success_url:, failure_url:)
7
- parse_reference(success_url)
6
+ def run(success_url:, failure_url:, pending_url:, cancel_url:, error_url:)
7
+ urls = {
8
+ success: success_url,
9
+ failure: failure_url,
10
+ pending: pending_url,
11
+ cancel: cancel_url,
12
+ error: error_url
13
+ }
14
+
15
+ parse_reference(urls[:success])
8
16
  @resource = WorldpayResourceService.run(reference: @reference)
9
17
 
10
- generate_response(success_url, failure_url)
18
+ generate_response(urls)
11
19
  end
12
20
 
13
21
  private
@@ -59,27 +67,44 @@ module DefraRubyMocks
59
67
  def payment_status
60
68
  return :REFUSED if @resource.company_name.include?("reject")
61
69
  return :STUCK if @resource.company_name.include?("stuck")
70
+ return :SENT_FOR_AUTHORISATION if @resource.company_name.include?("pending")
71
+ return :CANCELLED if @resource.company_name.include?("cancel")
72
+ return :ERROR if @resource.company_name.include?("error")
62
73
 
63
74
  :AUTHORISED
64
75
  end
65
76
 
77
+ def url(payment_status, urls)
78
+ return urls[:failure] if %i[REFUSED STUCK].include?(payment_status)
79
+ return urls[:pending] if payment_status == :SENT_FOR_AUTHORISATION
80
+ return urls[:cancel] if payment_status == :CANCELLED
81
+ return urls[:error] if payment_status == :ERROR
82
+
83
+ urls[:success]
84
+ end
85
+
86
+ # Generate a mac that matches what Worldpay would generate
87
+ #
88
+ # For whatever reason, if the payment is cancelled by the user Worldpay does
89
+ # not include the payment status in the mac it generates. Plus the order of
90
+ # things in the array is important.
66
91
  def generate_mac(status)
67
92
  data = [
68
93
  order_key,
69
94
  order_value,
70
- "GBP",
71
- status,
72
- DefraRubyMocks.configuration.worldpay_mac_secret
95
+ "GBP"
73
96
  ]
97
+ data << status unless status == :CANCELLED
98
+ data << DefraRubyMocks.configuration.worldpay_mac_secret
74
99
 
75
100
  Digest::MD5.hexdigest(data.join).to_s
76
101
  end
77
102
 
78
- def generate_response(success_url, failure_url)
103
+ def generate_response(urls)
79
104
  status = payment_status
80
105
 
81
106
  WorldpayResponse.new(
82
- status == :AUTHORISED ? success_url : failure_url,
107
+ url(status, urls),
83
108
  @url_format == :new ? "?" : "&",
84
109
  order_key,
85
110
  generate_mac(status),
@@ -0,0 +1,26 @@
1
+ // https://developer-specs.company-information.service.gov.uk/companies-house-public-data-api/resources/officerlist
2
+ {
3
+ "items": [
4
+ {
5
+ "name": "APPLE, Alice",
6
+ "officer_role": "director"
7
+ },
8
+ {
9
+ "name": "BANANA, Bob",
10
+ "officer_role": "director"
11
+ },
12
+ {
13
+ "name": "CARROT, Charlie",
14
+ "officer_role": "director",
15
+ "resigned_on": "2020-01-21"
16
+ },
17
+ {
18
+ "name": "DONUT, Dave Dickie",
19
+ "officer_role": "llp-member"
20
+ },
21
+ {
22
+ "name": "ENDIVE, Eve Marie",
23
+ "officer_role": "llp-designated-member"
24
+ }
25
+ ]
26
+ }
@@ -1,3 +1,12 @@
1
+ // https://developer-specs.company-information.service.gov.uk/companies-house-public-data-api/resources/companyprofile
1
2
  {
2
- "company_status": "<%= @status %>"
3
+ "company_name": "Acme Industries",
4
+ "company_status": "<%= @company_status %>",
5
+ "type": "<%= @company_type %>",
6
+ "registered_office_address": {
7
+ "address_line_1": "10 Downing St",
8
+ "address_line_2": "Horizon House",
9
+ "locality": "Bristol",
10
+ "postal_code": "BS1 5AH"
11
+ }
3
12
  }
data/config/routes.rb CHANGED
@@ -6,6 +6,11 @@ DefraRubyMocks::Engine.routes.draw do
6
6
  as: "company",
7
7
  constraints: ->(_request) { DefraRubyMocks.configuration.enabled? }
8
8
 
9
+ get "/company/:id/officers",
10
+ to: "company#officers",
11
+ as: "company_officers",
12
+ constraints: ->(_request) { DefraRubyMocks.configuration.enabled? }
13
+
9
14
  get "/worldpay/payments-service",
10
15
  to: "worldpay#payments_service",
11
16
  as: "worldpay_payments_service",
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DefraRubyMocks
4
- VERSION = "1.4.1"
4
+ VERSION = "2.2.0"
5
5
  end