dvla-atlas 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -0
  3. data/Gemfile +3 -0
  4. data/LICENSE +21 -0
  5. data/README.md +153 -0
  6. data/lib/dvla/atlas/artefacts.rb +52 -0
  7. data/lib/dvla/atlas/holder.rb +22 -0
  8. data/lib/dvla/atlas/test_artefactory.rb +13 -0
  9. data/lib/dvla/atlas/version.rb +5 -0
  10. data/lib/dvla/atlas.rb +23 -0
  11. data/sorbet/config +3 -0
  12. data/sorbet/rbi/annotations/activesupport.rbi +128 -0
  13. data/sorbet/rbi/annotations/rainbow.rbi +269 -0
  14. data/sorbet/rbi/gems/activesupport@7.0.3.1.rbi +14 -0
  15. data/sorbet/rbi/gems/ast@2.4.2.rbi +584 -0
  16. data/sorbet/rbi/gems/concurrent-ruby@1.2.0.rbi +8 -0
  17. data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +1079 -0
  18. data/sorbet/rbi/gems/i18n@1.12.0.rbi +8 -0
  19. data/sorbet/rbi/gems/json@2.6.3.rbi +1541 -0
  20. data/sorbet/rbi/gems/minitest@5.17.0.rbi +8 -0
  21. data/sorbet/rbi/gems/netrc@0.11.0.rbi +158 -0
  22. data/sorbet/rbi/gems/parallel@1.22.1.rbi +277 -0
  23. data/sorbet/rbi/gems/parser@3.2.0.0.rbi +6963 -0
  24. data/sorbet/rbi/gems/pastel@0.8.0.rbi +8 -0
  25. data/sorbet/rbi/gems/rack@3.0.4.1.rbi +5166 -0
  26. data/sorbet/rbi/gems/rainbow@3.1.1.rbi +8 -0
  27. data/sorbet/rbi/gems/rbi@0.0.16.rbi +3008 -0
  28. data/sorbet/rbi/gems/regexp_parser@2.6.2.rbi +8 -0
  29. data/sorbet/rbi/gems/rexml@3.2.5.rbi +8 -0
  30. data/sorbet/rbi/gems/rspec-core@3.12.0.rbi +10783 -0
  31. data/sorbet/rbi/gems/rspec-expectations@3.12.2.rbi +8106 -0
  32. data/sorbet/rbi/gems/rspec-mocks@3.12.3.rbi +5301 -0
  33. data/sorbet/rbi/gems/rspec-support@3.12.0.rbi +1617 -0
  34. data/sorbet/rbi/gems/rspec@3.12.0.rbi +88 -0
  35. data/sorbet/rbi/gems/rubocop-ast@1.24.1.rbi +8 -0
  36. data/sorbet/rbi/gems/rubocop-performance@1.15.2.rbi +8 -0
  37. data/sorbet/rbi/gems/rubocop-rails@2.17.4.rbi +8 -0
  38. data/sorbet/rbi/gems/rubocop@1.44.1.rbi +8 -0
  39. data/sorbet/rbi/gems/ruby-progressbar@1.11.0.rbi +8 -0
  40. data/sorbet/rbi/gems/spoom@1.1.15.rbi +2383 -0
  41. data/sorbet/rbi/gems/tapioca@0.10.5.rbi +3204 -0
  42. data/sorbet/rbi/gems/thor@1.2.1.rbi +3923 -0
  43. data/sorbet/rbi/gems/tty-color@0.6.0.rbi +8 -0
  44. data/sorbet/rbi/gems/tty-config@0.6.0.rbi +8 -0
  45. data/sorbet/rbi/gems/tty-cursor@0.7.1.rbi +8 -0
  46. data/sorbet/rbi/gems/tty-prompt@0.23.1.rbi +8 -0
  47. data/sorbet/rbi/gems/tty-reader@0.9.0.rbi +8 -0
  48. data/sorbet/rbi/gems/tty-screen@0.8.1.rbi +8 -0
  49. data/sorbet/rbi/gems/tzinfo@2.0.6.rbi +8 -0
  50. data/sorbet/rbi/gems/unicode-display_width@2.4.2.rbi +8 -0
  51. data/sorbet/rbi/gems/unparser@0.6.7.rbi +4515 -0
  52. data/sorbet/rbi/gems/webrick@1.7.0.rbi +2555 -0
  53. data/sorbet/rbi/gems/wisper@2.0.1.rbi +8 -0
  54. data/sorbet/rbi/gems/yard-sorbet@0.8.0.rbi +441 -0
  55. data/sorbet/rbi/gems/yard@0.9.28.rbi +17803 -0
  56. data/sorbet/rbi/todo.rbi +7 -0
  57. data/sorbet/tapioca/config.yml +13 -0
  58. data/sorbet/tapioca/require.rb +4 -0
  59. metadata +172 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 109ee9046094b99c7ccb3fc7b188fcca9240a61ae2d5c2091c4257483b447746
4
+ data.tar.gz: 0776f0ab8215402924da52459e1336869dcc0bb9cce5288575c71e6a77e22dc0
5
+ SHA512:
6
+ metadata.gz: 511df857b1ae53375702fa50b65335a98d31a6bb8c163802cac77451cb152fc517770272378c10901a294e4e77d8234add7ae3795679a15e2aa7b0bfc750cd71
7
+ data.tar.gz: 9312d564d9a86db24cdac3646645fb2fbca4ea996be8c96eaa3902defd6f3036134d5cf5de29d386dce2a7dea10ef7f0cd1ae77a09db6579cca929d4ba560d8d
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.2.2
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 HM Government (Driver and Vehicle Licensing Agency)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,153 @@
1
+ # Atlas
2
+
3
+ Atlas provides a wrapper around the `World` functionality provided by Cucumber.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'dvla-atlas'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle install
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install dvla-atlas
20
+
21
+
22
+ ## World overview
23
+
24
+ World is a [feature of Cucumber](https://github.com/cucumber/cucumber-ruby/blob/main/features/docs/writing_support_code/world.feature) that allows the user to influence the context within which test steps are run. By default, at the start of each scenario Cucumber calls `Object.new` and mixes in the RSpec assertions to get the context within which the test steps will be executed. Calling `World` allows this to be changed in one of two ways.
25
+
26
+ The first is by defining additional methods within a module and then mixing that into the object that the tests are run in the context of. For example, suppose we define the following module `Helper`:
27
+
28
+ ```ruby
29
+ module Helper
30
+ def foo
31
+ 'foo'
32
+ end
33
+ end
34
+ ```
35
+
36
+ If this module is then passed into World (`World(Helper)`), all steps that are run in that test pack will be able to call the method `foo` directly.
37
+
38
+ The second way to use World is to provide it with a block of code. This block will be called at the start of each Scenario, with the returned value being used in place of `Object.new`. For example, suppose we define the following class `Base`:
39
+
40
+ ```ruby
41
+ class Base
42
+ def initialize(base_value)
43
+ @base_value = base_value
44
+ end
45
+
46
+ def add_to_base_value(value_to_add)
47
+ value_to_add + @base_value
48
+ end
49
+
50
+ def set_base_value(new_base_value)
51
+ @base_value = new_base_value
52
+ end
53
+ end
54
+ ```
55
+
56
+ The above can be used as the context for all tests with the following code:
57
+
58
+ ```ruby
59
+ World do
60
+ Base.new(2)
61
+ end
62
+ ```
63
+
64
+ As this is run for each new scenario, the block will be run again and so the internal `base_value` will start off as 2 for each new test.
65
+
66
+ ## Using Atlas
67
+
68
+ ### Adding it to your tests
69
+
70
+ Atlas functions by providing the base class (in this instance called `TestArtefactory`) for tests to run in the context of. This features a single method called `artefacts` that returns an artefacts object upon which you can define variables that you wish to share across steps within the same scenario. Once you got the gem installed you can add the following to your `env.rb` file (or equivalent):
71
+
72
+ ```ruby
73
+ World do
74
+ DVLA::Atlas.base_world
75
+ end
76
+ ```
77
+
78
+ However, the generated artefacts does not currently have any fields
79
+
80
+ ### Adding fields to your artefact
81
+
82
+ For example, if you wanted all scenarios to have access to the string `foo` this could be set up in the following way when creating World:
83
+
84
+ ```ruby
85
+ World do
86
+ world = DVLA::Atlas.base_world
87
+ world.artefacts.define_fields(foo: 'foo')
88
+ world
89
+ end
90
+ ```
91
+
92
+ This would allow any test step to make the following call and retrieve the value of 'foo' in the following way:
93
+
94
+ ```ruby
95
+ artefacts.foo
96
+ ```
97
+
98
+ Additionally, a setter for that variable will also exist, so a test could assign a different value to foo for the rest of the scenario if required, such as:
99
+
100
+ ```ruby
101
+ artefacts.foo = 'bar'
102
+ ```
103
+
104
+ It is also possible to create a variable in artefacts without assigning any value to it. For example, you could have the initial call to World that looks like this:
105
+
106
+ ```ruby
107
+ World do
108
+ world = DVLA::Atlas.base_world
109
+ world.artefacts.define_fields('current_url')
110
+ world
111
+ end
112
+ ```
113
+
114
+ This would guarantee that `current_url` is accessible by all test steps, even if it does not start with a value.
115
+
116
+ ### Exposing your own helper methods
117
+
118
+ If you've got some of your own helper methods you'd like to make available, you can define them in a module and mix that in with the world. You'd do that in the following way:
119
+
120
+ ```ruby
121
+ World do
122
+ world = DVLA::Atlas.base_world
123
+ world.artefacts.define_fields('current_url', 'username', 'password')
124
+ world
125
+ end
126
+
127
+ module Helpers
128
+ def double(value)
129
+ value * 2
130
+ end
131
+ end
132
+
133
+ World(Helpers)
134
+ ```
135
+
136
+ As well as the fields `current_url`, `username` and `password`, this would provide all test steps with access to the method `double`
137
+
138
+ ### Accessing the artefact outside the scope of the test steps
139
+
140
+ If you need access to the artefact from somewhere other than directly in the steps and it is not feasible to pass it in from step method then it can be configured to be accessible globally. That is achieved by adding a call into `make_artefacts_global` when configuring World:
141
+
142
+ ```ruby
143
+ World do
144
+ world = DVLA::Atlas.base_world
145
+ world.artefacts.define_fields('current_url', 'username', 'password')
146
+ DVLA::Atlas.make_artefacts_global(world.artefacts)
147
+ world
148
+ end
149
+ ```
150
+
151
+ ## Development
152
+
153
+ Atlas is quite lightweight. The functionality that deals with the creation of properties in with the test artefact is located within `artefacts.rb`. This project uses [Sorbet](https://sorbet.org/) for type checking. When making changes, don't forget to add tests.
@@ -0,0 +1,52 @@
1
+ #typed: strict
2
+
3
+ require 'sorbet-runtime'
4
+
5
+ module DVLA
6
+ module Atlas
7
+ class Artefacts
8
+ extend T::Sig
9
+
10
+ sig { params(vargs: String, kwargs: T.untyped).void }
11
+ def define_fields(*vargs, **kwargs)
12
+ vargs.each do |attr|
13
+ initialise_fields(attr)
14
+ end
15
+
16
+ kwargs.each_pair do |key, value|
17
+ initialise_fields(key)
18
+ send(:"#{key}=", value) # As an initial value has been passed for this field, we want to set it using the newly defined setter
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ sig { params(name: T.any(String, Symbol)).void }
25
+ def initialise_fields(name)
26
+ # Create the history of the newly defined field. This will start out empty. There is no public way to set this so
27
+ # no need to expose it by defining a method.
28
+ instance_variable_set("@#{name}_history", [])
29
+
30
+ # Create the getter for the new field, and ensure that it is run upon call if it is a proc.
31
+ define_singleton_method :"#{name}" do
32
+ value = instance_variable_get("@#{name}")
33
+ value.respond_to?(:call) ? value.call : value
34
+ end
35
+
36
+ # Define a getter for the history of the new field
37
+ define_singleton_method :"#{name}_history" do
38
+ instance_variable_get("@#{name}_history")
39
+ end
40
+
41
+ # Define the setter for the new field. This also pushes the current value of the field into the history unless
42
+ # it is currently nil and the history is empty. This is to prevent each history list starting with a nil entry
43
+ # as all fields are nil when defined.
44
+ define_singleton_method :"#{name}=" do |arg|
45
+ current_value = send(:"#{name}")
46
+ send(:"#{name}_history").push(current_value) unless send(:"#{name}_history").empty? && current_value.nil?
47
+ instance_variable_set("@#{name}", arg)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,22 @@
1
+ #typed: strict
2
+
3
+ require 'singleton'
4
+
5
+ module DVLA
6
+ module Atlas
7
+ class Holder
8
+ extend T::Sig
9
+ include Singleton
10
+
11
+ sig { returns(DVLA::Atlas::Artefacts) }
12
+ attr_accessor :artefacts
13
+
14
+ # The below is required by Sorbet. While the flow of the code within Atlas won't allow for :artefacts to be called
15
+ # externally before something is assigned to it, Sorbet requires that it is initialized using T.let.
16
+ sig { void }
17
+ def initialize
18
+ @artefacts = T.let(DVLA::Atlas::Artefacts.new, DVLA::Atlas::Artefacts)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,13 @@
1
+ #typed: strict
2
+
3
+ module DVLA
4
+ module Atlas
5
+ class TestArtefactory
6
+ extend T::Sig
7
+ sig { returns(DVLA::Atlas::Artefacts) }
8
+ def artefacts
9
+ @artefacts ||= T.let(Artefacts.new, T.nilable(DVLA::Atlas::Artefacts))
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ module DVLA
2
+ module Atlas
3
+ VERSION = '1.0.0'.freeze
4
+ end
5
+ end
data/lib/dvla/atlas.rb ADDED
@@ -0,0 +1,23 @@
1
+ # typed: strict
2
+
3
+ require 'dvla/atlas/artefacts'
4
+ require 'dvla/atlas/holder'
5
+ require 'dvla/atlas/test_artefactory'
6
+ require 'sorbet-runtime'
7
+
8
+ module DVLA
9
+ module Atlas
10
+ extend T::Sig
11
+
12
+ sig { returns(DVLA::Atlas::TestArtefactory) }
13
+ def self.base_world
14
+ TestArtefactory.new
15
+ end
16
+
17
+ sig { params(artefacts: DVLA::Atlas::Artefacts).void }
18
+ def self.make_artefacts_global(artefacts)
19
+ DVLA::Atlas::Holder.instance.artefacts = artefacts
20
+ Object.send(:define_method, :artefacts) { DVLA::Atlas::Holder.instance.artefacts }
21
+ end
22
+ end
23
+ end
data/sorbet/config ADDED
@@ -0,0 +1,3 @@
1
+ --dir
2
+ .
3
+ --ignore=vendor/
@@ -0,0 +1,128 @@
1
+ # typed: strict
2
+
3
+ # DO NOT EDIT MANUALLY
4
+ # This file was pulled from a central RBI files repository.
5
+ # Please run `bin/tapioca annotations` to update it.
6
+
7
+ module ActiveSupport::Testing::Declarative
8
+ sig { params(name: String, block: T.proc.bind(T.untyped).void).void }
9
+ def test(name, &block); end
10
+ end
11
+
12
+ class ActiveSupport::EnvironmentInquirer
13
+ sig { returns(T::Boolean) }
14
+ def development?; end
15
+
16
+ sig { returns(T::Boolean) }
17
+ def production?; end
18
+
19
+ sig { returns(T::Boolean) }
20
+ def test?; end
21
+
22
+ # @method_missing: delegated to String through ActiveSupport::StringInquirer
23
+ sig { returns(T::Boolean) }
24
+ def staging?; end
25
+ end
26
+
27
+ module ActiveSupport::Testing::SetupAndTeardown::ClassMethods
28
+ sig { params(args: T.untyped, block: T.nilable(T.proc.bind(T.untyped).void)).void }
29
+ def setup(*args, &block); end
30
+
31
+ sig { params(args: T.untyped, block: T.nilable(T.proc.bind(T.untyped).void)).void }
32
+ def teardown(*args, &block); end
33
+ end
34
+
35
+ class ActiveSupport::TestCase
36
+ sig { params(args: T.untyped, block: T.nilable(T.proc.bind(T.attached_class).void)).void }
37
+ def self.setup(*args, &block); end
38
+
39
+ sig { params(args: T.untyped, block: T.nilable(T.proc.bind(T.attached_class).void)).void }
40
+ def self.teardown(*args, &block); end
41
+
42
+ sig { params(name: String, block: T.proc.bind(T.attached_class).void).void }
43
+ def self.test(name, &block); end
44
+ end
45
+
46
+ class Object
47
+ sig { returns(T::Boolean) }
48
+ def blank?; end
49
+
50
+ sig { returns(T::Boolean) }
51
+ def present?; end
52
+ end
53
+
54
+ class Hash
55
+ sig { returns(T::Boolean) }
56
+ def extractable_options?; end
57
+ end
58
+
59
+ class Array
60
+ sig { params(position: Integer).returns(T.self_type) }
61
+ def from(position); end
62
+
63
+ sig { params(position: Integer).returns(T.self_type) }
64
+ def to(position); end
65
+
66
+ sig { params(elements: T.untyped).returns(T::Array[T.untyped]) }
67
+ def including(*elements); end
68
+
69
+ sig { params(elements: T.untyped).returns(T.self_type) }
70
+ def excluding(*elements); end
71
+
72
+ sig { params(elements: T.untyped).returns(T.self_type) }
73
+ def without(*elements); end
74
+
75
+ sig { returns(T.nilable(Elem)) }
76
+ def second; end
77
+
78
+ sig { returns(T.nilable(Elem)) }
79
+ def third; end
80
+
81
+ sig { returns(T.nilable(Elem)) }
82
+ def fourth; end
83
+
84
+ sig { returns(T.nilable(Elem)) }
85
+ def fifth; end
86
+
87
+ sig { returns(T.nilable(Elem)) }
88
+ def forty_two; end
89
+
90
+ sig { returns(T.nilable(Elem)) }
91
+ def third_to_last; end
92
+
93
+ sig { returns(T.nilable(Elem)) }
94
+ def second_to_last; end
95
+
96
+ sig { params(options: T::Hash[T.untyped, T.untyped]).returns(String) }
97
+ def to_sentence(options = {}); end
98
+
99
+ sig { params(format: Symbol).returns(String) }
100
+ def to_fs(format = :default); end
101
+
102
+ sig { params(format: Symbol).returns(String) }
103
+ def to_formatted_s(format = :default); end
104
+
105
+ sig { returns(String) }
106
+ def to_xml; end
107
+
108
+ sig { returns(T::Hash[T.untyped, T.untyped]) }
109
+ def extract_options!; end
110
+
111
+ sig { type_parameters(:FillType).params(number: Integer, fill_with: T.type_parameter(:FillType), block: T.nilable(T.proc.params(group: T::Array[T.any(Elem, T.type_parameter(:FillType))]).void)).returns(T::Array[T::Array[T.any(Elem, T.type_parameter(:FillType))]]) }
112
+ def in_groups(number, fill_with = T.unsafe(nil), &block); end
113
+
114
+ sig { type_parameters(:FillType).params(number: Integer, fill_with: T.type_parameter(:FillType), block: T.nilable(T.proc.params(group: T::Array[T.any(Elem, T.type_parameter(:FillType))]).void)).returns(T::Array[T::Array[T.any(Elem, T.type_parameter(:FillType))]]) }
115
+ def in_groups_of(number, fill_with = T.unsafe(nil), &block); end
116
+
117
+ sig { params(value: T.untyped, block: T.nilable(T.proc.params(element: Elem).returns(T.untyped))).returns(T::Array[T::Array[Elem]]) }
118
+ def split(value = nil, &block); end
119
+
120
+ sig { params(object: T.untyped).returns(T::Array[T.untyped]) }
121
+ def self.wrap(object); end
122
+
123
+ sig { returns(T.untyped) }
124
+ def extract!; end
125
+
126
+ sig { returns(ActiveSupport::ArrayInquirer) }
127
+ def inquiry; end
128
+ end