peddler 2.1.0 → 2.4.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of peddler might be problematic. Click here for more details.

Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +43 -41
  3. data/lib/mws.rb +2 -1
  4. data/lib/mws/easy_ship.rb +3 -0
  5. data/lib/mws/easy_ship/client.rb +93 -0
  6. data/lib/mws/fulfillment_inbound_shipment/client.rb +2 -2
  7. data/lib/mws/fulfillment_outbound_shipment/client.rb +1 -1
  8. data/lib/mws/orders/client.rb +7 -9
  9. data/lib/mws/reports/client.rb +9 -0
  10. data/lib/mws/shipment_invoicing.rb +3 -0
  11. data/lib/mws/shipment_invoicing/client.rb +74 -0
  12. data/lib/peddler/client.rb +18 -15
  13. data/lib/peddler/errors/builder.rb +7 -2
  14. data/lib/peddler/errors/class_generator.rb +7 -2
  15. data/lib/peddler/errors/error.rb +6 -2
  16. data/lib/peddler/errors/parser.rb +1 -1
  17. data/lib/peddler/flat_file_parser.rb +6 -4
  18. data/lib/peddler/headers.rb +53 -1
  19. data/lib/peddler/marketplace.rb +24 -22
  20. data/lib/peddler/operation.rb +17 -11
  21. data/lib/peddler/parser.rb +1 -1
  22. data/lib/peddler/structured_list.rb +1 -1
  23. data/lib/peddler/vcr_matcher.rb +7 -7
  24. data/lib/peddler/version.rb +1 -1
  25. data/lib/peddler/xml_parser.rb +1 -1
  26. data/lib/peddler/xml_response_parser.rb +3 -2
  27. metadata +15 -150
  28. data/lib/mws/off_amazon_payments/client.rb +0 -362
  29. data/lib/mws/reports/parser.rb +0 -35
  30. data/test/credentials.rb +0 -23
  31. data/test/helper.rb +0 -15
  32. data/test/integration/test_errors.rb +0 -25
  33. data/test/integration/test_feeds.rb +0 -37
  34. data/test/integration/test_fulfillment_inbound_shipment.rb +0 -35
  35. data/test/integration/test_fulfillment_inventory.rb +0 -20
  36. data/test/integration/test_fulfillment_outbound_shipment.rb +0 -13
  37. data/test/integration/test_merchant_fulfillment.rb +0 -69
  38. data/test/integration/test_multibyte_queries.rb +0 -17
  39. data/test/integration/test_mws_headers.rb +0 -16
  40. data/test/integration/test_off_amazon_payments.rb +0 -13
  41. data/test/integration/test_orders.rb +0 -30
  42. data/test/integration/test_products.rb +0 -97
  43. data/test/integration/test_recommendations.rb +0 -20
  44. data/test/integration/test_reports.rb +0 -51
  45. data/test/integration/test_sellers.rb +0 -13
  46. data/test/integration/test_subscriptions.rb +0 -27
  47. data/test/integration_helper.rb +0 -53
  48. data/test/mws.yml +0 -36
  49. data/test/mws.yml.example +0 -32
  50. data/test/null_client.rb +0 -25
  51. data/test/recorder.rb +0 -39
  52. data/test/unit/mws/test_feeds_client.rb +0 -103
  53. data/test/unit/mws/test_finances_client.rb +0 -74
  54. data/test/unit/mws/test_fulfillment_inbound_shipment_client.rb +0 -426
  55. data/test/unit/mws/test_fulfillment_inventory_client.rb +0 -48
  56. data/test/unit/mws/test_fulfillment_outbound_shipment_client.rb +0 -202
  57. data/test/unit/mws/test_merchant_fulfillment_client.rb +0 -109
  58. data/test/unit/mws/test_off_amazon_payments_client.rb +0 -286
  59. data/test/unit/mws/test_orders_client.rb +0 -111
  60. data/test/unit/mws/test_products_client.rb +0 -248
  61. data/test/unit/mws/test_recommendations_client.rb +0 -62
  62. data/test/unit/mws/test_reports_client.rb +0 -209
  63. data/test/unit/mws/test_sellers_client.rb +0 -47
  64. data/test/unit/mws/test_subscriptions_client.rb +0 -182
  65. data/test/unit/peddler/errors/test_builder.rb +0 -65
  66. data/test/unit/peddler/errors/test_class_generator.rb +0 -18
  67. data/test/unit/peddler/errors/test_error.rb +0 -33
  68. data/test/unit/peddler/errors/test_parser.rb +0 -44
  69. data/test/unit/peddler/test_client.rb +0 -203
  70. data/test/unit/peddler/test_flat_file_parser.rb +0 -102
  71. data/test/unit/peddler/test_headers.rb +0 -55
  72. data/test/unit/peddler/test_marketplace.rb +0 -47
  73. data/test/unit/peddler/test_operation.rb +0 -87
  74. data/test/unit/peddler/test_parser.rb +0 -36
  75. data/test/unit/peddler/test_structured_list.rb +0 -39
  76. data/test/unit/peddler/test_vcr_matcher.rb +0 -55
  77. data/test/unit/peddler/test_xml_parser.rb +0 -37
  78. data/test/unit/peddler/test_xml_response_parser.rb +0 -39
  79. data/test/unit/test_mws.rb +0 -11
  80. data/test/vcr_cassettes/CartInformation.yml +0 -433
  81. data/test/vcr_cassettes/CustomerInformation.yml +0 -433
  82. data/test/vcr_cassettes/Errors.yml +0 -885
  83. data/test/vcr_cassettes/Feeds.yml +0 -9957
  84. data/test/vcr_cassettes/FulfillmentInboundShipment.yml +0 -6166
  85. data/test/vcr_cassettes/FulfillmentInventory.yml +0 -850
  86. data/test/vcr_cassettes/FulfillmentOutboundShipment.yml +0 -433
  87. data/test/vcr_cassettes/MWSHeaders.yml +0 -2964
  88. data/test/vcr_cassettes/MerchantFulfillment.yml +0 -753
  89. data/test/vcr_cassettes/MultibyteQueries.yml +0 -437
  90. data/test/vcr_cassettes/OffAmazonPayments.yml +0 -433
  91. data/test/vcr_cassettes/Orders.yml +0 -4740
  92. data/test/vcr_cassettes/PeddlerVCRMatcher.yml +0 -41
  93. data/test/vcr_cassettes/Products.yml +0 -7139
  94. data/test/vcr_cassettes/Recommendations.yml +0 -3145
  95. data/test/vcr_cassettes/Reports.yml +0 -5549
  96. data/test/vcr_cassettes/Sellers.yml +0 -433
  97. data/test/vcr_cassettes/Subscriptions.yml +0 -1529
@@ -1,102 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'helper'
4
- require 'peddler/flat_file_parser'
5
-
6
- class TestPeddlerFlatFileParser < MiniTest::Test
7
- def test_parsing_data
8
- body = build_body("Feed Processing Summary:\n\tNumber of records processed\t\t11006\n\tNumber of records successful\t\t11006\n\noriginal-record-number\tsku\terror-code\terror-type\terror-message\n1822\t85da472e-ba6c-11e3-95af-002590a74356\t5000\tWarning\tThe update for Sku '85da472e-ba6c-11e3-95af-002590a74356' was skipped because it is identical to the update in feed '9518995390'.\n",
9
- encoding: Encoding::ASCII_8BIT)
10
- parser = Peddler::FlatFileParser.new(build_mock_response(body), 'ISO-8859-1')
11
- assert_kind_of CSV::Table, parser.parse
12
- end
13
-
14
- def test_parsing_data_a_line_at_a_time
15
- body = build_body("Feed Processing Summary:\n\tNumber of records processed\t\t11006\n\tNumber of records successful\t\t11006\n\noriginal-record-number\tsku\terror-code\terror-type\terror-message\n1822\t85da472e-ba6c-11e3-95af-002590a74356\t5000\tWarning\tThe update for Sku '85da472e-ba6c-11e3-95af-002590a74356' was skipped because it is identical to the update in feed '9518995390'.\n",
16
- encoding: Encoding::ASCII_8BIT)
17
- parser = Peddler::FlatFileParser.new(build_mock_response(body), 'ISO-8859-1')
18
- counter = 0
19
- parser.parse { counter += 1 }
20
- assert counter.positive?
21
- end
22
-
23
- def test_the_work_around_empty_rows
24
- body = build_body("Feed Processing Summary:\n\tNumber of records processed\t\t2\n\tNumber of records successful\t\t2\n\nfoo\tbar\n1\ta\n\n2\tb\n",
25
- encoding: Encoding::ASCII_8BIT)
26
- parser = Peddler::FlatFileParser.new(build_mock_response(body), 'ISO-8859-1')
27
- assert_equal 3, parser.parse.count
28
- end
29
-
30
- def test_summary
31
- body = build_body("Feed Processing Summary:\n\tNumber of records processed\t\t11006\n\tNumber of records successful\t\t11006\n\noriginal-record-number\tsku\terror-code\terror-type\terror-message\n1822\t85da472e-ba6c-11e3-95af-002590a74356\t5000\tWarning\tThe update for Sku '85da472e-ba6c-11e3-95af-002590a74356' was skipped because it is identical to the update in feed '9518995390'.\n",
32
- encoding: Encoding::ASCII_8BIT)
33
- parser = Peddler::FlatFileParser.new(build_mock_response(body), 'ISO-8859-1')
34
- refute_empty parser.records_count
35
- end
36
-
37
- def test_summary_of_non_english_reports
38
- body = build_body("Riepilogo elaborazione feed:\n\tNumero record elaborati\t\t1\n\tNumero record elaborati con successo\t\t1\n\n",
39
- encoding: 'Cp1252')
40
- parser = Peddler::FlatFileParser.new(build_mock_response(body), 'ISO-8859-1')
41
- refute_empty parser.records_count
42
- end
43
-
44
- def test_validates
45
- body = build_body("Feed Processing Summary:\n\tNumber of records processed\t\t11006\n\tNumber of records successful\t\t11006\n\noriginal-record-number\tsku\terror-code\terror-type\terror-message\n1822\t85da472e-ba6c-11e3-95af-002590a74356\t5000\tWarning\tThe update for Sku '85da472e-ba6c-11e3-95af-002590a74356' was skipped because it is identical to the update in feed '9518995390'.\n",
46
- encoding: Encoding::ASCII_8BIT)
47
- parser = Peddler::FlatFileParser.new(build_mock_response(body), 'ISO-8859-1')
48
- assert parser.valid?
49
- end
50
-
51
- def test_handling_reports_without_a_summary
52
- response = OpenStruct.new(body: "Foo\nBar\n")
53
- parser = Peddler::FlatFileParser.new(response, 'ISO-8859-1')
54
- refute_empty parser.content
55
- end
56
-
57
- def test_handling_japanese_flat_files
58
- body = build_body("Foo\nこんにちは\n", encoding: Encoding::SHIFT_JIS)
59
- parser = Peddler::FlatFileParser.new(build_mock_response(body), Encoding::WINDOWS_31J)
60
- assert_equal 'こんにちは', parser.parse[0]['Foo']
61
- end
62
-
63
- def test_handling_japanese_curly_braces
64
- body = build_body("Foo\n〝\n", encoding: Encoding::WINDOWS_31J)
65
- parser = Peddler::FlatFileParser.new(build_mock_response(body), Encoding::WINDOWS_31J)
66
- assert_equal '〝', parser.parse[0]['Foo']
67
- end
68
-
69
- def test_handling_latin_1_flat_files
70
- body = build_body("Foo\n™\n", encoding: 'Cp1252')
71
- parser = Peddler::FlatFileParser.new(build_mock_response(body), Encoding::CP1252)
72
- assert_equal '™', parser.parse['Foo'][0]
73
- end
74
-
75
- def test_handling_undefined_characters
76
- body = +"Foo\n\xFF\n"
77
- body.force_encoding(Encoding::ASCII_8BIT)
78
- parser = Peddler::FlatFileParser.new(build_mock_response(body), Encoding::ASCII_8BIT)
79
- assert_equal '�', parser.parse['Foo'][0]
80
- end
81
-
82
- def test_handling_utf8_flat_files
83
- body = "Foo\nfür\n"
84
- parser = Peddler::FlatFileParser.new(build_mock_response(body, ascii: false), Encoding::CP1252)
85
- assert_equal 'für', parser.parse['Foo'][0]
86
- end
87
-
88
- private
89
-
90
- def build_body(str, encoding:)
91
- str.dup.encode(encoding)
92
- end
93
-
94
- def build_mock_response(body, ascii: true)
95
- body.force_encoding(Encoding::ASCII_8BIT) if ascii
96
- headers = {
97
- 'Content-MD5' => Digest::MD5.base64digest(body)
98
- }
99
-
100
- OpenStruct.new(body: body, headers: headers)
101
- end
102
- end
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'helper'
4
- require 'peddler/headers'
5
-
6
- class TestPeddlerHeaders < MiniTest::Test
7
- include ::Peddler::Headers
8
-
9
- attr_reader :headers
10
-
11
- def setup
12
- @headers = {
13
- 'x-mws-quota-max' => '200.0',
14
- 'x-mws-quota-remaining' => '200.0',
15
- 'x-mws-quota-resetsOn' => '2017-01-30T00:03:00.000Z',
16
- 'x-mws-request-id' => '123',
17
- 'x-mws-timestamp' => '2017-01-29T23:55:25.356Z',
18
- 'x-mws-response-context' => 'foo'
19
- }
20
- end
21
-
22
- def test_mws_quota_max
23
- assert_kind_of Integer, mws_quota_max
24
- end
25
-
26
- def test_mws_quota_remaining
27
- assert_kind_of Integer, mws_quota_remaining
28
- end
29
-
30
- def test_mws_quota_resets_on
31
- assert_kind_of Time, mws_quota_resets_on
32
- end
33
-
34
- def test_request_id
35
- assert mws_request_id
36
- end
37
-
38
- def test_timestamp
39
- assert_kind_of Time, mws_timestamp
40
- end
41
-
42
- def test_response_context
43
- assert mws_response_context
44
- end
45
-
46
- def test_handling_no_quota
47
- @headers = {}
48
- assert_nil mws_quota_max
49
- assert_nil mws_quota_remaining
50
- assert_nil mws_quota_resets_on
51
- assert_nil mws_request_id
52
- assert_nil mws_timestamp
53
- assert_nil mws_response_context
54
- end
55
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'helper'
4
- require 'peddler/marketplace'
5
-
6
- class TestPeddlerMarketplace < MiniTest::Test
7
- def setup
8
- @marketplace = Peddler::Marketplace.find('ATVPDKIKX0DER')
9
- end
10
-
11
- def test_country_code
12
- assert @marketplace.country_code
13
- end
14
-
15
- def test_host
16
- assert @marketplace.host
17
- end
18
-
19
- def test_encoding
20
- assert @marketplace.encoding
21
- end
22
-
23
- def test_guard_against_missing_country_code
24
- error = assert_raises ArgumentError do
25
- Peddler::Marketplace.find(nil)
26
- end
27
- assert_equal 'missing marketplace', error.message
28
- end
29
-
30
- def test_guard_against_invalid_country_code
31
- error = assert_raises ArgumentError do
32
- Peddler::Marketplace.find('FOO')
33
- end
34
- assert_equal '"FOO" is not a valid marketplace', error.message
35
- end
36
-
37
- class TestFindByCountryCode < TestPeddlerMarketplace
38
- def setup
39
- @marketplace = Peddler::Marketplace.find('US')
40
- end
41
-
42
- def test_translation_of_uk_to_gb
43
- marketplace = Peddler::Marketplace.find('UK')
44
- assert_equal 'GB', marketplace.country_code
45
- end
46
- end
47
- end
@@ -1,87 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'helper'
4
- require 'peddler/operation'
5
-
6
- class TestPeddlerOperation < MiniTest::Test
7
- def setup
8
- @operation = Peddler::Operation.new('Foo')
9
- end
10
-
11
- def test_that_it_converts_key_to_structured_list
12
- @operation.store('FooStatus', [1, 2])
13
- @operation.structure!('FooStatus', 'Foo')
14
- refute @operation.key?('FooStatus')
15
- assert_equal 1, @operation['FooStatus.Foo.1']
16
- assert_equal 2, @operation['FooStatus.Foo.2']
17
- end
18
-
19
- def test_that_it_converts_nested_keys_to_structured_list
20
- @operation.store('Foo.1.Status', [{ 'Baz' => 1 }])
21
- @operation.store('Foo.2.Status', [{ 'Baz' => 2 }])
22
- @operation.structure!('Status', 'Bar')
23
- refute @operation.key?('Foo.1.Status')
24
- refute @operation.key?('Foo.2.Status')
25
- assert_equal 1, @operation['Foo.1.Status.Bar.1.Baz']
26
- assert_equal 2, @operation['Foo.2.Status.Bar.1.Baz']
27
- end
28
-
29
- def test_that_store_camelizes_symbol_key
30
- @operation.store(:foo_bar, 'baz')
31
- assert @operation.key?('FooBar')
32
- refute @operation.key?(:foo_bar)
33
- end
34
-
35
- def test_that_store_wont_camelize_string_key
36
- @operation.store('foo_bar', 'baz')
37
- assert @operation.key?('foo_bar')
38
- refute @operation.key?('FooBar')
39
- end
40
-
41
- def test_that_store_wont_camelize_symbol_key_with_capital_letter
42
- @operation.store('MarketplaceId'.to_sym, '1')
43
- assert @operation.key?('MarketplaceId')
44
- end
45
-
46
- def test_that_store_upcases_sku
47
- @operation.store(:seller_sku, 'foo')
48
- assert @operation.key?('SellerSKU')
49
- refute @operation.key?(:seller_sku)
50
- end
51
-
52
- def test_that_store_upcases_cod
53
- @operation.store(:include_cod_fulfillment_preview, 'foo')
54
- assert @operation.key?('IncludeCODFulfillmentPreview')
55
- refute @operation.key?(:include_cod_fulfillment_preview)
56
- end
57
-
58
- def test_that_store_timestamps_time_values
59
- ts = Minitest::Mock.new
60
- ts.expect(:iso8601, 'foo')
61
- @operation.store('time', ts)
62
-
63
- assert_equal 'foo', @operation.fetch('time')
64
- end
65
-
66
- def test_stringifying_hash_values
67
- @operation.store('Foo', bar: 1)
68
- assert_equal 1, @operation.fetch('Foo.Bar')
69
- refute @operation.key?('Foo')
70
- end
71
-
72
- def test_stringifying_nested_hash_values
73
- @operation.store('Foo', bar: { baz: 1 })
74
- assert_equal 1, @operation.fetch('Foo.Bar.Baz')
75
- refute @operation.key?('Foo')
76
- end
77
-
78
- def test_stringifying_struct_values
79
- @operation.store('Foo', Struct.new(:bar, :baz).new(1, 2))
80
- assert_equal 1, @operation.fetch('Foo.Bar')
81
- assert_equal 2, @operation.fetch('Foo.Baz')
82
- end
83
-
84
- def test_that_update_returns_delegator
85
- assert_kind_of Peddler::Operation, @operation.add(foo: 'bar')
86
- end
87
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'helper'
4
- require 'peddler/parser'
5
-
6
- class TestPeddlerParser < MiniTest::Test
7
- def assert_parser(klass, *content_types, body: '')
8
- content_types.each do |content_type|
9
- res = OpenStruct.new(
10
- headers: { 'Content-Type' => content_type },
11
- body: body
12
- )
13
- parser = Peddler::Parser.new(res, 'Cp1252')
14
-
15
- assert_kind_of klass, parser
16
- end
17
- end
18
-
19
- def test_parsing_xml
20
- assert_parser Peddler::XMLParser,
21
- 'text/xml',
22
- 'text/xml; charset=UTF-8'
23
- end
24
-
25
- def test_parsing_incorrect_content_type
26
- assert_parser Peddler::XMLParser,
27
- 'xml; charset=UTF-8',
28
- body: '<?xml version="1.0"?><GetLowestOfferListingsForASINResponse>...'
29
- end
30
-
31
- def test_parsing_flat_files
32
- assert_parser Peddler::FlatFileParser,
33
- 'text/plain',
34
- 'application/octet-stream'
35
- end
36
- end
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'helper'
4
- require 'peddler/structured_list'
5
-
6
- class TestPeddlerStructuredList < MiniTest::Test
7
- def setup
8
- @list = Peddler::StructuredList.new('OrderStatus', 'Status')
9
- end
10
-
11
- def test_building_a_structured_list_for_a_single_value
12
- exp = { 'OrderStatus.Status.1' => 'foo' }
13
- assert_equal exp, @list.build('foo')
14
- end
15
-
16
- def test_building_a_structured_list_for_an_array_of_values
17
- exp = { 'OrderStatus.Status.1' => 'foo', 'OrderStatus.Status.2' => 'bar' }
18
- assert_equal exp, @list.build(%w[foo bar])
19
- end
20
-
21
- def test_flattening_nested_arrays_of_values
22
- exp = { 'OrderStatus.Status.1' => 'foo', 'OrderStatus.Status.2' => 'bar' }
23
- assert_equal exp, @list.build([%w[foo bar]])
24
- end
25
-
26
- def test_handling_single_key
27
- list = Peddler::StructuredList.new('Foo')
28
- exp = { 'Foo.1' => 'bar' }
29
-
30
- assert_equal exp, list.build('bar')
31
- end
32
-
33
- def test_handling_more_than_two_keys
34
- list = Peddler::StructuredList.new('QueryList', 'Query', '1', 'FilterOptions', 'FilterOption')
35
- exp = { 'QueryList.Query.1.FilterOptions.FilterOption.1' => 'foo' }
36
-
37
- assert_equal exp, list.build('foo')
38
- end
39
- end
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'helper'
4
- require 'null_client'
5
- require 'peddler/vcr_matcher'
6
- require 'recorder'
7
-
8
- class TestPeddlerVCRMatcher < MiniTest::Test
9
- include Recorder
10
- ::Peddler::VCRMatcher.ignore_seller!
11
-
12
- def setup
13
- VCR.insert_cassette(test_name)
14
- end
15
-
16
- def test_matching_recorded_post_without_body
17
- client.run
18
- end
19
-
20
- def test_wont_match_unrecorded_post_without_body
21
- client.operation.add(foo: 'bar')
22
- assert_raises(VCR::Errors::UnhandledHTTPRequestError) do
23
- client.run
24
- end
25
- end
26
-
27
- def test_matching_recorded_post_with_body
28
- client.body = 'content'
29
- client.run
30
- end
31
-
32
- def test_that_it_wont_match_unrecorded_post_with_different_query_and_same_body
33
- client.operation.add(foo: 'bar')
34
- client.body = 'content'
35
- assert_raises(VCR::Errors::UnhandledHTTPRequestError) do
36
- client.run
37
- end
38
- end
39
-
40
- def test_that_it_wont_match_unrecorded_post_with_same_query_and_different_body
41
- client.body = 'other content'
42
- assert_raises(VCR::Errors::UnhandledHTTPRequestError) do
43
- client.run
44
- end
45
- end
46
-
47
- def client
48
- @client ||= begin
49
- client = Class.new(Null::Client).new
50
- client.configure_with_mock_data!
51
- client.operation('Action')
52
- client
53
- end
54
- end
55
- end
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'helper'
4
- require 'peddler/xml_parser'
5
-
6
- class TestPeddlerXMLParser < MiniTest::Test
7
- Parser = Class.new(::Peddler::XMLParser)
8
-
9
- def setup
10
- body = '<Foo>Bar</Foo>'
11
-
12
- res = OpenStruct.new(
13
- body: body,
14
- headers: {
15
- 'Content-Type' => 'text/xml',
16
- 'Content-Length' => body.size.to_s
17
- }
18
- )
19
-
20
- @parser = Parser.new(res)
21
- end
22
-
23
- def test_that_it_does_not_implement_parsing
24
- assert_raises(NotImplementedError) do
25
- @parser.parse
26
- end
27
- end
28
-
29
- def test_digging_data
30
- @parser.instance_variable_set :@data, foo: { bar: :baz }
31
- assert_equal :baz, @parser.dig(:foo, :bar)
32
- end
33
-
34
- def test_validation
35
- assert @parser.valid?
36
- end
37
- end