pact 1.4.0.rc4 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. data/CHANGELOG.md +13 -0
  2. data/lib/pact/consumer/configuration/mock_service.rb +2 -1
  3. data/lib/pact/consumer/consumer_contract_builder.rb +2 -1
  4. data/lib/pact/version.rb +1 -1
  5. data/pact.gemspec +4 -3
  6. metadata +32 -205
  7. data/.gitignore +0 -29
  8. data/.rspec +0 -2
  9. data/.travis.yml +0 -8
  10. data/Gemfile +0 -9
  11. data/Gemfile.lock +0 -108
  12. data/README.md +0 -314
  13. data/Rakefile +0 -9
  14. data/config.ru +0 -3
  15. data/documentation/README.md +0 -13
  16. data/documentation/configuration.md +0 -166
  17. data/documentation/diff_formatter_embedded.png +0 -0
  18. data/documentation/diff_formatter_list.png +0 -0
  19. data/documentation/diff_formatter_unix.png +0 -0
  20. data/example/animal-service/Gemfile +0 -14
  21. data/example/animal-service/Gemfile.lock +0 -69
  22. data/example/animal-service/Rakefile +0 -5
  23. data/example/animal-service/config.ru +0 -3
  24. data/example/animal-service/db/animal_db.sqlite3 +0 -0
  25. data/example/animal-service/lib/animal_service/animal_repository.rb +0 -12
  26. data/example/animal-service/lib/animal_service/api.rb +0 -29
  27. data/example/animal-service/lib/animal_service/db.rb +0 -5
  28. data/example/animal-service/spec/service_consumers/pact_helper.rb +0 -11
  29. data/example/animal-service/spec/service_consumers/provider_states_for_zoo_app.rb +0 -26
  30. data/example/zoo-app/Gemfile +0 -12
  31. data/example/zoo-app/Gemfile.lock +0 -63
  32. data/example/zoo-app/Rakefile +0 -5
  33. data/example/zoo-app/doc/pacts/markdown/README.md +0 -3
  34. data/example/zoo-app/doc/pacts/markdown/Zoo App - Animal Service.md +0 -75
  35. data/example/zoo-app/lib/zoo_app/animal_service_client.rb +0 -31
  36. data/example/zoo-app/lib/zoo_app/models/alligator.rb +0 -17
  37. data/example/zoo-app/spec/pacts/zoo_app-animal_service.json +0 -67
  38. data/example/zoo-app/spec/service_providers/animal_service_client_spec.rb +0 -71
  39. data/example/zoo-app/spec/service_providers/pact_helper.rb +0 -15
  40. data/example/zoo-app/spec/spec_helper.rb +0 -6
  41. data/scratchpad.rb +0 -52
  42. data/spec/features/consumption_spec.rb +0 -114
  43. data/spec/features/production_spec.rb +0 -155
  44. data/spec/features/provider_states/zebras.rb +0 -28
  45. data/spec/integration/consumer_async_request_spec.rb +0 -46
  46. data/spec/integration/consumer_more_than_one_matching_interaction_spec.rb +0 -49
  47. data/spec/integration/consumer_no_matching_interaction_spec.rb +0 -53
  48. data/spec/integration/consumer_with_a_provider_state_spec.rb +0 -44
  49. data/spec/integration/consumer_with_form_hash_spec.rb +0 -62
  50. data/spec/integration/consumer_with_form_spec.rb +0 -50
  51. data/spec/integration/consumer_with_params_hash_spec.rb +0 -122
  52. data/spec/integration/pact/consumer_configuration_spec.rb +0 -66
  53. data/spec/integration/pact/provider_configuration_spec.rb +0 -25
  54. data/spec/lib/pact/cli_spec.rb +0 -47
  55. data/spec/lib/pact/configuration_spec.rb +0 -297
  56. data/spec/lib/pact/consumer/app_manager_spec.rb +0 -41
  57. data/spec/lib/pact/consumer/configuration_spec.rb +0 -57
  58. data/spec/lib/pact/consumer/consumer_contract_builder_spec.rb +0 -69
  59. data/spec/lib/pact/consumer/interaction_builder_spec.rb +0 -87
  60. data/spec/lib/pact/consumer/interactions_spec.rb +0 -64
  61. data/spec/lib/pact/consumer/mock_service/app_spec.rb +0 -52
  62. data/spec/lib/pact/consumer/mock_service/interaction_list_spec.rb +0 -78
  63. data/spec/lib/pact/consumer/mock_service/interaction_mismatch_spec.rb +0 -70
  64. data/spec/lib/pact/consumer/mock_service/interaction_replay_spec.rb +0 -12
  65. data/spec/lib/pact/consumer/mock_service/rack_request_helper_spec.rb +0 -88
  66. data/spec/lib/pact/consumer/mock_service/verification_get_spec.rb +0 -142
  67. data/spec/lib/pact/consumer/service_consumer_spec.rb +0 -11
  68. data/spec/lib/pact/doc/generator_spec.rb +0 -84
  69. data/spec/lib/pact/doc/interaction_view_model_spec.rb +0 -132
  70. data/spec/lib/pact/doc/markdown/consumer_contract_renderer_spec.rb +0 -29
  71. data/spec/lib/pact/doc/markdown/index_renderer_spec.rb +0 -29
  72. data/spec/lib/pact/provider/configuration/configuration_extension_spec.rb +0 -17
  73. data/spec/lib/pact/provider/configuration/pact_verification_spec.rb +0 -43
  74. data/spec/lib/pact/provider/configuration/service_provider_config_spec.rb +0 -21
  75. data/spec/lib/pact/provider/configuration/service_provider_dsl_spec.rb +0 -108
  76. data/spec/lib/pact/provider/configuration_spec.rb +0 -50
  77. data/spec/lib/pact/provider/matchers/messages_spec.rb +0 -116
  78. data/spec/lib/pact/provider/pact_helper_locator_spec.rb +0 -54
  79. data/spec/lib/pact/provider/print_missing_provider_states_spec.rb +0 -19
  80. data/spec/lib/pact/provider/request_spec.rb +0 -78
  81. data/spec/lib/pact/provider/rspec/formatter_rspec_2_spec.rb +0 -68
  82. data/spec/lib/pact/provider/rspec/formatter_rspec_3_spec.rb +0 -72
  83. data/spec/lib/pact/provider/rspec_spec.rb +0 -55
  84. data/spec/lib/pact/provider/state/provider_state_manager_spec.rb +0 -89
  85. data/spec/lib/pact/provider/state/provider_state_proxy_spec.rb +0 -80
  86. data/spec/lib/pact/provider/state/provider_state_spec.rb +0 -213
  87. data/spec/lib/pact/provider/world_spec.rb +0 -41
  88. data/spec/lib/pact/tasks/task_helper_spec.rb +0 -74
  89. data/spec/lib/pact/tasks/verification_task_spec.rb +0 -75
  90. data/spec/pact_specification/compliance-1.0.0.rb +0 -47
  91. data/spec/spec_helper.rb +0 -22
  92. data/spec/standalone/consumer_fail_test.rb +0 -55
  93. data/spec/standalone/consumer_pass_test.rb +0 -51
  94. data/spec/support/a_consumer-a_producer.json +0 -32
  95. data/spec/support/a_consumer-a_provider.json +0 -32
  96. data/spec/support/active_support_if_configured.rb +0 -6
  97. data/spec/support/app_for_config_ru.rb +0 -4
  98. data/spec/support/case-insensitive-response-header-matching.json +0 -21
  99. data/spec/support/case-insensitive-response-header-matching.rb +0 -15
  100. data/spec/support/consumer_contract_template.json +0 -24
  101. data/spec/support/factories.rb +0 -82
  102. data/spec/support/generated_index.md +0 -4
  103. data/spec/support/generated_markdown.md +0 -55
  104. data/spec/support/interaction_view_model.json +0 -63
  105. data/spec/support/interaction_view_model_with_terms.json +0 -50
  106. data/spec/support/markdown_pact.json +0 -48
  107. data/spec/support/missing_provider_states_output.txt +0 -25
  108. data/spec/support/options.json +0 -21
  109. data/spec/support/options_app.rb +0 -15
  110. data/spec/support/pact_helper.rb +0 -57
  111. data/spec/support/shared_examples_for_request.rb +0 -94
  112. data/spec/support/spec_support.rb +0 -20
  113. data/spec/support/stubbing.json +0 -22
  114. data/spec/support/stubbing_using_allow.rb +0 -29
  115. data/spec/support/term.json +0 -48
  116. data/spec/support/test_app_fail.json +0 -61
  117. data/spec/support/test_app_pass.json +0 -38
  118. data/spec/support/test_app_with_right_content_type_differ.json +0 -23
  119. data/tasks/pact-test.rake +0 -114
  120. data/tasks/spec.rake +0 -8
@@ -1,46 +0,0 @@
1
- require 'spec_helper'
2
- require 'pact/consumer'
3
- require 'pact/consumer/rspec'
4
- load 'pact/consumer/world.rb'
5
-
6
- describe "A service consumer side of a pact", :pact => true do
7
-
8
- context "with an asynchronous interaction with provider" do
9
- before do
10
- Pact.clear_configuration
11
-
12
- Pact.service_consumer "Consumer" do
13
- has_pact_with "Zebra Service" do
14
- mock_service :zebra_service do
15
- verify true
16
- port 1239
17
- end
18
- end
19
- end
20
- end
21
-
22
- it "goes like this" do
23
- zebra_service.
24
- given(:the_zebras_are_here).
25
- upon_receiving("a retrieve Mallory request").
26
- with({
27
- method: :get,
28
- path: '/mallory'
29
- }).
30
- will_respond_with({status: 200})
31
-
32
- async_interaction { Net::HTTP.get_response(URI('http://localhost:1239/mallory')) }
33
-
34
- zebra_service.wait_for_interactions wait_max_seconds: 1, poll_interval: 0.1
35
- end
36
-
37
- def async_interaction
38
- Thread.new do
39
- sleep 0.2
40
- yield
41
- end
42
- end
43
-
44
- end
45
-
46
- end
@@ -1,49 +0,0 @@
1
- require 'pact/consumer'
2
- require 'pact/consumer/rspec'
3
- load 'pact/consumer/world.rb'
4
-
5
- describe "A service consumer side of a pact", :pact => true do
6
-
7
- context "with more than one matching interaction found" do
8
- let(:expected_response) do
9
- {"message"=>"Multiple interaction found for GET /path", "matching_interactions"=>[{"description"=>"a request", "request"=>{"method"=>"get", "path"=>"/path", "body"=>{"a"=>"some body"}, "headers"=>{"Content-Type"=>"application/json"}}}, {"description"=>"an identical request", "request"=>{"method"=>"get", "path"=>"/path", "body"=>{"a"=>"some body"}, "headers"=>{"Content-Type"=>"application/json"}}}]}
10
- end
11
-
12
- it "returns an error" do
13
- Pact.clear_configuration
14
- Pact.clear_consumer_world
15
-
16
- Pact.service_consumer "Consumer" do
17
- has_pact_with "Mary Service" do
18
- mock_service :mary_service do
19
- verify false
20
- port 1237
21
- end
22
- end
23
- end
24
-
25
- mary_service
26
- .given("something")
27
- .upon_receiving("a request")
28
- .with(method: 'get', path: '/path', body: {a: 'some body'}, headers: {'Content-Type' => 'application/json'})
29
- .will_respond_with(status: 200)
30
-
31
-
32
- mary_service
33
- .upon_receiving("an identical request")
34
- .with(method: 'get', path: '/path', body: {a: 'some body'}, headers: {'Content-Type' => 'application/json'})
35
- .will_respond_with(status: 200)
36
-
37
- uri = URI('http://localhost:1237/path')
38
- post_req = Net::HTTP::Get.new(uri.path)
39
- post_req['Content-Type'] = "application/json"
40
- post_req.body = {a: "some body"}.to_json
41
- response = Net::HTTP.start(uri.hostname, uri.port) do |http|
42
- http.request post_req
43
- end
44
-
45
- expect(JSON.load(response.body)).to eq expected_response
46
- end
47
-
48
- end
49
- end
@@ -1,53 +0,0 @@
1
- require 'pact/consumer'
2
- require 'pact/consumer/rspec'
3
- load 'pact/consumer/world.rb'
4
-
5
- describe "A service consumer side of a pact", :pact => true do
6
- context "with no matching interaction found" do
7
-
8
- let(:expected_response) do
9
- {
10
- "message"=>"No interaction found for GET /path",
11
- "interaction_diffs"=>[{
12
- "description" => "a request that will not be properly matched",
13
- "provider_state" => "something",
14
- "body"=>{
15
- "a"=>{
16
- "EXPECTED"=>"some body",
17
- "ACTUAL"=>"not matching body"
18
- }
19
- }
20
- }]
21
- }
22
- end
23
-
24
- it "returns an error" do
25
- Pact.clear_configuration
26
-
27
- Pact.service_consumer "Consumer" do
28
- has_pact_with "Mary Service" do
29
- mock_service :mary_service do
30
- verify false
31
- port 1236
32
- end
33
- end
34
- end
35
-
36
- mary_service
37
- .given("something")
38
- .upon_receiving("a request that will not be properly matched")
39
- .with(method: 'get', path: '/path', body: {a: 'some body'}, headers: {'Content-Type' => 'application/json'})
40
- .will_respond_with(status: 200)
41
-
42
- uri = URI('http://localhost:1236/path')
43
- post_req = Net::HTTP::Get.new(uri.path)
44
- post_req['Content-Type'] = "application/json"
45
- post_req.body = {a: "not matching body"}.to_json
46
- response = Net::HTTP.start(uri.hostname, uri.port) do |http|
47
- http.request post_req
48
- end
49
-
50
- expect(JSON.load(response.body)).to eq expected_response
51
- end
52
- end
53
- end
@@ -1,44 +0,0 @@
1
- require 'pact/consumer'
2
- require 'pact/consumer/rspec'
3
- load 'pact/consumer/world.rb'
4
- require 'faraday'
5
-
6
- describe "A service consumer side of a pact", :pact => true do
7
- context "with a provider state" do
8
- before do
9
- Pact.clear_configuration
10
-
11
- Pact.service_consumer "Consumer" do
12
- has_pact_with "Zebra Service" do
13
- mock_service :zebra_service do
14
- verify false
15
- port 1235
16
- end
17
- end
18
- end
19
- end
20
-
21
- let(:body) { 'That is some good Mallory.' }
22
-
23
- it "goes like this" do
24
- zebra_service.
25
- given(:the_zebras_are_here).
26
- upon_receiving("a retrieve Mallory request").with({
27
- method: :get,
28
- path: '/mallory',
29
- headers: {'Accept' => 'text/html'}
30
- }).
31
- will_respond_with({
32
- status: 200,
33
- headers: { 'Content-Type' => 'text/html' },
34
- body: Pact::Term.new(matcher: /Mallory/, generate: body)
35
- })
36
-
37
- response = Faraday.get(zebra_service.mock_service_base_url + "/mallory", nil, {'Accept' => 'text/html'})
38
- expect(response.body).to eq body
39
-
40
- interactions = Pact::ConsumerContract.from_json(zebra_service.write_pact).interactions
41
- expect(interactions.first.provider_state).to eq("the_zebras_are_here")
42
- end
43
- end
44
- end
@@ -1,62 +0,0 @@
1
- require 'spec_helper'
2
- require 'net/http'
3
- require 'pact/consumer'
4
- require 'pact/consumer/rspec'
5
- require 'faraday'
6
- load 'pact/consumer/world.rb'
7
-
8
- describe "A service consumer side of a pact", :pact => true do
9
-
10
- let(:body) { 'That is some good Mallory.' }
11
-
12
- context 'submitting a form specified as a Hash' do
13
-
14
- before :all do
15
- Pact.clear_configuration
16
-
17
- Pact.service_consumer "Consumer" do
18
- has_pact_with "Zebra Service" do
19
- mock_service :zebra_service_4 do
20
- port 1245
21
- end
22
- end
23
- end
24
- end
25
-
26
- before do
27
-
28
- zebra_service_4.
29
- given("the zebras like using forms").
30
- upon_receiving("a create Mallory request").with({
31
- method: :post,
32
- path: '/mallory',
33
- headers: {'Content-Type' => 'application/x-www-form-urlencoded'},
34
- body: {
35
- param1: Pact::Term.new(generate: 'woger', matcher: /w/),
36
- param2: 'penguin'
37
- }
38
- }).
39
- will_respond_with({
40
- status: 200
41
- })
42
-
43
- end
44
-
45
- let(:url) { zebra_service_4.mock_service_base_url + "/mallory" }
46
- let(:response) { Faraday.post url, param2: 'penguin', param1: 'wiffle' }
47
- let(:pact_json) { response; zebra_service_4.write_pact }
48
-
49
- it "matches form data" do
50
- expect(response.status).to eq 200
51
- end
52
-
53
- it "does not include any Pact::Terms" do
54
- expect(pact_json).to_not include "Pact::Term"
55
- end
56
-
57
- it "includes the reified form" do
58
- expect(pact_json).to include "param1=woger"
59
- end
60
-
61
- end
62
- end
@@ -1,50 +0,0 @@
1
- require 'spec_helper'
2
- require 'net/http'
3
- require 'pact/consumer'
4
- require 'pact/consumer/rspec'
5
- require 'faraday'
6
- load 'pact/consumer/world.rb'
7
-
8
- describe "A service consumer side of a pact", :pact => true do
9
-
10
- let(:body) { 'That is some good Mallory.' }
11
-
12
- context 'submitting a form' do
13
-
14
- before :all do
15
- Pact.clear_configuration
16
-
17
- Pact.service_consumer "Consumer" do
18
- has_pact_with "Zebra Service" do
19
- mock_service :zebra_service_3 do
20
- port 1243
21
- end
22
- end
23
- end
24
- end
25
-
26
- before do
27
-
28
- zebra_service_3.
29
- given("the zebras like using forms").
30
- upon_receiving("a create Mallory request").with({
31
- method: :post,
32
- path: '/mallory',
33
- headers: {'Content-Type' => 'application/x-www-form-urlencoded'},
34
- body: "param1=wiffle&param2=penguin"
35
- }).
36
- will_respond_with({
37
- status: 200
38
- })
39
-
40
- end
41
-
42
- let(:url) { zebra_service_3.mock_service_base_url + "/mallory" }
43
-
44
- it "matches form data" do
45
- response = Faraday.post url, param2: 'penguin', param1: 'wiffle'
46
- expect(response.status).to eq 200
47
- end
48
-
49
- end
50
- end
@@ -1,122 +0,0 @@
1
- require 'spec_helper'
2
- require 'net/http'
3
- require 'pact/consumer'
4
- require 'pact/consumer/rspec'
5
- require 'faraday'
6
- load 'pact/consumer/world.rb'
7
-
8
- describe "A service consumer side of a pact", :pact => true do
9
-
10
- # Helper to make Faraday requests.
11
- # Faraday::FlatParamsEncoder may only be needed with our current version of Faraday 0.9
12
- # and ensures that when there are multiple parameters of the same name, they are encoded properly. e.g. colour=blue&colour=green
13
- def faraday_mallory(base_url,params, headers = {})
14
- (Faraday.new base_url, :request => {
15
- :params_encoder => Faraday::FlatParamsEncoder,
16
- }).get '/mallory', params, {'Accept' => 'application/json'}.merge(headers)
17
- end
18
-
19
- let(:body) { 'That is some good Mallory.' }
20
-
21
- context 'When expecting multiple instances of the same parameter in the query' do
22
-
23
- before :all do
24
- Pact.clear_configuration
25
-
26
- Pact.service_consumer "Consumer" do
27
- has_pact_with "Zebra Service" do
28
- mock_service :zebra_service2 do
29
- verify false
30
- port 1241
31
- end
32
- end
33
- end
34
- end
35
-
36
- before do
37
-
38
- zebra_service2.
39
- given(:the_zebras_are_here).
40
- upon_receiving("a retrieve Mallory request").with({
41
- method: :get,
42
- path: '/mallory',
43
- headers: {'Accept' => 'application/json'},
44
- query: {colour: 'brown', size: ['small', 'large']}
45
- }).
46
- will_respond_with({
47
- status: 200,
48
- headers: { 'Content-Type' => 'application/json' },
49
- body: Pact::Term.new(matcher: /Mallory/, generate: body)
50
- })
51
-
52
- end
53
-
54
- it "matches when all instances are provided" do
55
- response= faraday_mallory(zebra_service2.mock_service_base_url, { size: ['small','large'], colour: 'brown'})
56
- expect(response.body).to eq body
57
-
58
- interactions = Pact::ConsumerContract.from_json(zebra_service2.write_pact).interactions
59
- expect(interactions.first.provider_state).to eq("the_zebras_are_here")
60
- end
61
-
62
- it "does not match when only the first instance is provided" do
63
- response = Faraday.get(zebra_service2.mock_service_base_url + "/mallory?colour=brown&size=small", nil, {'Accept' => 'application/json'})
64
- expect(response.body).not_to eq body
65
- end
66
-
67
- it "does not match when only the last instance is provided" do
68
- response = Faraday.get(zebra_service2.mock_service_base_url + "/mallory?colour=brown&size=large", nil, {'Accept' => 'application/json'})
69
- expect(response.body).not_to eq body
70
- end
71
-
72
- it "does not match when they are out of order" do
73
- response= faraday_mallory(zebra_service2.mock_service_base_url, { size: ['large','small'], colour: 'brown'})
74
- expect(response.body).not_to eq body
75
- end
76
- end
77
-
78
- context "and a complex request matching Pact Terms and multiple instances of the same parameter" do
79
-
80
- before :all do
81
- Pact.clear_configuration
82
- Pact.service_consumer "Consumer" do
83
- has_pact_with "Zebra Service" do
84
- mock_service :zebra_service do
85
- verify false
86
- port 1242
87
- end
88
- end
89
- end
90
- end
91
-
92
- before do
93
- zebra_service.
94
- given(:the_zebras_are_here).
95
- upon_receiving("a retrieve Mallory request").
96
- with({
97
- method: :get,
98
- path: '/mallory',
99
- headers: {'Accept' => 'application/json', 'Content-Type' => 'application/x-www-form-urlencoded'},
100
- query: { size: ['small',Pact::Term.new(matcher: /med.*/, generate: 'medium'),'large'], colour: 'brown', weight: '5'}
101
- }).
102
- will_respond_with({
103
- status: 200,
104
- headers: { 'Content-Type' => 'application/json' },
105
- body: Pact::Term.new(matcher: /Mallory/, generate: body)
106
- })
107
- end
108
-
109
- let(:response) do
110
- faraday_mallory(
111
- zebra_service.mock_service_base_url,
112
- { weight: 5, size: ['small','medium','large'], colour: 'brown'},
113
- {'Content-Type' => 'application/x-www-form-urlencoded'}
114
- )
115
- end
116
-
117
- it "goes like this" do
118
- expect(response.body).to eq body
119
- end
120
-
121
- end
122
- end
@@ -1,66 +0,0 @@
1
- require 'spec_helper'
2
- require 'pact/configuration'
3
- require 'pact/consumer/configuration'
4
-
5
- describe "consumer side" do
6
- describe "configure" do
7
-
8
- class TestHelper
9
- include Pact::Consumer::ConsumerContractBuilders
10
- end
11
-
12
- let(:application) { double("App")}
13
- let(:world) { Pact::Consumer::World.new }
14
-
15
- before do
16
- Pact.clear_configuration
17
- Pact::Consumer::AppManager.instance.clear_all
18
- # Don't want processes actually spawning
19
- allow_any_instance_of(Pact::Consumer::AppRegistration).to receive(:spawn)
20
- allow(Pact).to receive(:consumer_world).and_return(world)
21
-
22
- my_app = application
23
-
24
- Pact.service_consumer "My Consumer" do
25
- app my_app
26
- port 1111
27
-
28
- has_pact_with "My Service" do
29
- mock_service :my_service do
30
- port 1234
31
- standalone true
32
- end
33
- end
34
-
35
- has_pact_with "My Other Service" do
36
- mock_service :my_other_service do
37
- port 1235
38
- standalone false
39
- end
40
- end
41
- end
42
-
43
- end
44
-
45
- describe "providers" do
46
-
47
- subject { TestHelper.new.my_service }
48
-
49
- it "should have defined methods in MockServices for the providers" do
50
- expect(subject).to be_instance_of(Pact::Consumer::ConsumerContractBuilder)
51
- end
52
-
53
- context "when standalone is true" do
54
- it "is not registerd with the AppManager" do
55
- expect(Pact::Consumer::AppManager.instance.app_registered_on?(1234)).to eq false
56
- end
57
- end
58
-
59
- context "when standalone is false" do
60
- it "should register the MockServices on their given ports if they are not" do
61
- expect(Pact::Consumer::AppManager.instance.app_registered_on?(1235)).to eq true
62
- end
63
- end
64
- end
65
- end
66
- end