candy_check 0.1.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +2 -1
  3. data/.rubocop.yml +6 -0
  4. data/.ruby-version +1 -1
  5. data/.travis.yml +7 -10
  6. data/Guardfile +42 -0
  7. data/MIGRATION_GUIDE_0_2_0.md +141 -0
  8. data/README.md +85 -27
  9. data/Rakefile +1 -1
  10. data/candy_check.gemspec +32 -26
  11. data/lib/candy_check/app_store/receipt_collection.rb +4 -2
  12. data/lib/candy_check/app_store/subscription_verification.rb +25 -1
  13. data/lib/candy_check/app_store/verification.rb +1 -1
  14. data/lib/candy_check/app_store/verifier.rb +11 -11
  15. data/lib/candy_check/cli/app.rb +20 -33
  16. data/lib/candy_check/cli/commands/play_store.rb +12 -13
  17. data/lib/candy_check/play_store.rb +20 -10
  18. data/lib/candy_check/play_store/acknowledger.rb +19 -0
  19. data/lib/candy_check/play_store/android_publisher_service.rb +6 -0
  20. data/lib/candy_check/play_store/product_acknowledgements/acknowledgement.rb +45 -0
  21. data/lib/candy_check/play_store/product_acknowledgements/response.rb +24 -0
  22. data/lib/candy_check/play_store/product_purchases/product_purchase.rb +90 -0
  23. data/lib/candy_check/play_store/product_purchases/product_verification.rb +53 -0
  24. data/lib/candy_check/play_store/subscription_purchases/subscription_purchase.rb +154 -0
  25. data/lib/candy_check/play_store/subscription_purchases/subscription_verification.rb +55 -0
  26. data/lib/candy_check/play_store/verification_failure.rb +8 -6
  27. data/lib/candy_check/play_store/verifier.rb +24 -49
  28. data/lib/candy_check/version.rb +1 -1
  29. data/spec/app_store/client_spec.rb +2 -2
  30. data/spec/app_store/config_spec.rb +5 -5
  31. data/spec/app_store/receipt_collection_spec.rb +35 -8
  32. data/spec/app_store/receipt_spec.rb +16 -16
  33. data/spec/app_store/subscription_verification_spec.rb +49 -16
  34. data/spec/app_store/verifcation_failure_spec.rb +6 -6
  35. data/spec/app_store/verification_spec.rb +12 -12
  36. data/spec/app_store/verifier_spec.rb +36 -17
  37. data/spec/candy_check_spec.rb +3 -3
  38. data/spec/cli/app_spec.rb +10 -6
  39. data/spec/cli/commands/app_store_spec.rb +6 -6
  40. data/spec/cli/commands/play_store_spec.rb +10 -43
  41. data/spec/cli/commands/version_spec.rb +1 -1
  42. data/spec/cli/out_spec.rb +4 -4
  43. data/spec/fixtures/play_store/random_dummy_key.json +12 -0
  44. data/spec/fixtures/vcr_cassettes/play_store/product_acknowledgements/acknowledged.yml +105 -0
  45. data/spec/fixtures/vcr_cassettes/play_store/product_acknowledgements/already_acknowledged.yml +124 -0
  46. data/spec/fixtures/vcr_cassettes/play_store/product_acknowledgements/refunded.yml +122 -0
  47. data/spec/fixtures/vcr_cassettes/play_store/product_purchases/permission_denied.yml +196 -0
  48. data/spec/fixtures/vcr_cassettes/play_store/product_purchases/response_with_empty_body.yml +183 -0
  49. data/spec/fixtures/vcr_cassettes/play_store/product_purchases/valid_but_not_consumed.yml +122 -0
  50. data/spec/fixtures/vcr_cassettes/play_store/subscription_purchases/permission_denied.yml +196 -0
  51. data/spec/fixtures/vcr_cassettes/play_store/subscription_purchases/valid_but_expired.yml +127 -0
  52. data/spec/play_store/acknowledger_spec.rb +48 -0
  53. data/spec/play_store/product_acknowledgements/acknowledgement_spec.rb +54 -0
  54. data/spec/play_store/product_acknowledgements/response_spec.rb +66 -0
  55. data/spec/play_store/product_purchases/product_purchase_spec.rb +110 -0
  56. data/spec/play_store/product_purchases/product_verification_spec.rb +49 -0
  57. data/spec/play_store/subscription_purchases/subscription_purchase_spec.rb +237 -0
  58. data/spec/play_store/subscription_purchases/subscription_verification_spec.rb +65 -0
  59. data/spec/play_store/verification_failure_spec.rb +20 -20
  60. data/spec/play_store/verifier_spec.rb +32 -96
  61. data/spec/spec_helper.rb +31 -11
  62. data/spec/support/with_command.rb +0 -3
  63. metadata +167 -81
  64. data/lib/candy_check/play_store/client.rb +0 -126
  65. data/lib/candy_check/play_store/config.rb +0 -51
  66. data/lib/candy_check/play_store/discovery_repository.rb +0 -33
  67. data/lib/candy_check/play_store/receipt.rb +0 -81
  68. data/lib/candy_check/play_store/subscription.rb +0 -139
  69. data/lib/candy_check/play_store/subscription_verification.rb +0 -30
  70. data/lib/candy_check/play_store/verification.rb +0 -48
  71. data/spec/fixtures/api_cache.dump +0 -1
  72. data/spec/fixtures/play_store/api_cache.dump +0 -1
  73. data/spec/fixtures/play_store/auth_failure.txt +0 -18
  74. data/spec/fixtures/play_store/auth_success.txt +0 -20
  75. data/spec/fixtures/play_store/discovery.txt +0 -2841
  76. data/spec/fixtures/play_store/dummy.p12 +0 -0
  77. data/spec/fixtures/play_store/empty.txt +0 -17
  78. data/spec/fixtures/play_store/products_failure.txt +0 -29
  79. data/spec/fixtures/play_store/products_success.txt +0 -22
  80. data/spec/play_store/client_spec.rb +0 -125
  81. data/spec/play_store/config_spec.rb +0 -96
  82. data/spec/play_store/discovery_respository_spec.rb +0 -31
  83. data/spec/play_store/receipt_spec.rb +0 -88
  84. data/spec/play_store/subscription_spec.rb +0 -138
  85. data/spec/play_store/subscription_verification_spec.rb +0 -97
  86. data/spec/play_store/verification_spec.rb +0 -81
@@ -8,64 +8,91 @@ describe CandyCheck::AppStore::ReceiptCollection do
8
8
  [{
9
9
  'expires_date' => '2014-04-15 12:52:40 Etc/GMT',
10
10
  'expires_date_pst' => '2014-04-15 05:52:40 America/Los_Angeles',
11
+ 'purchase_date' => '2014-04-14 12:52:40 Etc/GMT',
11
12
  'is_trial_period' => 'false'
12
13
  }, {
13
14
  'expires_date' => '2015-04-15 12:52:40 Etc/GMT',
14
15
  'expires_date_pst' => '2015-04-15 05:52:40 America/Los_Angeles',
16
+ 'purchase_date' => '2015-04-14 12:52:40 Etc/GMT',
15
17
  'is_trial_period' => 'false'
16
18
  }]
17
19
  end
18
20
 
19
21
  it 'is expired' do
20
- subject.expired?.must_be_true
22
+ _(subject.expired?).must_be_true
21
23
  end
22
24
 
23
25
  it 'is not a trial' do
24
- subject.trial?.must_be_false
26
+ _(subject.trial?).must_be_false
25
27
  end
26
28
 
27
29
  it 'has positive overdue days' do
28
30
  overdue = subject.overdue_days
29
- overdue.must_be_instance_of Fixnum
31
+ _(overdue).must_be_instance_of Fixnum
30
32
  assert overdue > 0
31
33
  end
32
34
 
33
35
  it 'has a last expires date' do
34
36
  expected = DateTime.new(2015, 4, 15, 12, 52, 40)
35
- subject.expires_at.must_equal expected
37
+ _(subject.expires_at).must_equal expected
36
38
  end
37
39
 
38
40
  it 'is expired? at same pointin time' do
39
41
  Timecop.freeze(Time.utc(2015, 4, 15, 12, 52, 40)) do
40
- subject.expired?.must_be_true
42
+ _(subject.expired?).must_be_true
41
43
  end
42
44
  end
43
45
  end
44
46
 
47
+ describe 'unordered receipts' do
48
+ let(:attributes) do
49
+ [{
50
+ 'expires_date' => '2015-04-15 12:52:40 Etc/GMT',
51
+ 'expires_date_pst' => '2015-04-15 05:52:40 America/Los_Angeles',
52
+ 'purchase_date' => '2015-04-14 12:52:40 Etc/GMT',
53
+ 'is_trial_period' => 'false'
54
+ }, {
55
+ 'expires_date' => '2014-04-15 12:52:40 Etc/GMT',
56
+ 'expires_date_pst' => '2014-04-15 05:52:40 America/Los_Angeles',
57
+ 'purchase_date' => '2014-04-14 12:52:40 Etc/GMT',
58
+ 'is_trial_period' => 'false'
59
+ }]
60
+ end
61
+
62
+ it 'the expires date is the latest one in time' do
63
+ expected = DateTime.new(2015, 4, 15, 12, 52, 40)
64
+ _(subject.expires_at).must_equal expected
65
+ end
66
+
67
+ end
68
+
45
69
  describe 'unexpired trial subscription' do
46
70
  two_days_from_now = DateTime.now + 2
47
71
 
48
72
  let(:attributes) do
49
73
  [{
50
74
  'expires_date' => '2016-04-15 12:52:40 Etc/GMT',
75
+ 'purchase_date' => '2016-04-15 12:52:40 Etc/GMT',
51
76
  'is_trial_period' => 'true'
52
77
  }, {
53
78
  'expires_date' =>
54
79
  two_days_from_now.strftime('%Y-%m-%d %H:%M:%S Etc/GMT'),
80
+ 'purchase_date' => '2016-04-15 12:52:40 Etc/GMT',
55
81
  'is_trial_period' => 'true'
56
82
  }]
57
83
  end
58
84
 
59
85
  it 'has not expired' do
60
- subject.expired?.must_be_false
86
+ _(subject.expired?).must_be_false
61
87
  end
62
88
 
63
89
  it 'it is a trial' do
64
- subject.trial?.must_be_true
90
+ _(subject.trial?).must_be_true
65
91
  end
66
92
 
67
93
  it 'expires in two days' do
68
- subject.overdue_days.must_equal(-2)
94
+ _(subject.overdue_days).must_equal(-2)
69
95
  end
70
96
  end
97
+
71
98
  end
@@ -31,62 +31,62 @@ describe CandyCheck::AppStore::Receipt do
31
31
 
32
32
  describe 'valid transaction' do
33
33
  it 'is valid' do
34
- subject.valid?.must_be_true
34
+ _(subject.valid?).must_be_true
35
35
  end
36
36
 
37
37
  it 'returns the item\'s id' do
38
- subject.item_id.must_equal 'some_item_id'
38
+ _(subject.item_id).must_equal 'some_item_id'
39
39
  end
40
40
 
41
41
  it 'returns the item\'s product_id' do
42
- subject.product_id.must_equal 'some_product'
42
+ _(subject.product_id).must_equal 'some_product'
43
43
  end
44
44
 
45
45
  it 'returns the quantity' do
46
- subject.quantity.must_equal 1
46
+ _(subject.quantity).must_equal 1
47
47
  end
48
48
 
49
49
  it 'returns the app version' do
50
- subject.app_version.must_equal '2.0'
50
+ _(subject.app_version).must_equal '2.0'
51
51
  end
52
52
 
53
53
  it 'returns the bundle identifier' do
54
- subject.bundle_identifier.must_equal 'some.test.app'
54
+ _(subject.bundle_identifier).must_equal 'some.test.app'
55
55
  end
56
56
 
57
57
  it 'returns the purchase date' do
58
58
  expected = DateTime.new(2015, 1, 9, 11, 40, 46)
59
- subject.purchase_date.must_equal expected
59
+ _(subject.purchase_date).must_equal expected
60
60
  end
61
61
 
62
62
  it 'returns the original purchase date' do
63
63
  expected = DateTime.new(2015, 1, 8, 11, 40, 46)
64
- subject.original_purchase_date.must_equal expected
64
+ _(subject.original_purchase_date).must_equal expected
65
65
  end
66
66
 
67
67
  it 'returns the transaction id' do
68
- subject.transaction_id.must_equal 'some_transaction_id'
68
+ _(subject.transaction_id).must_equal 'some_transaction_id'
69
69
  end
70
70
 
71
71
  it 'returns the original transaction id' do
72
- subject.original_transaction_id.must_equal 'some_original_transaction_id'
72
+ _(subject.original_transaction_id).must_equal 'some_original_transaction_id'
73
73
  end
74
74
 
75
75
  it 'return nil for cancellation date' do
76
- subject.cancellation_date.must_be_nil
76
+ _(subject.cancellation_date).must_be_nil
77
77
  end
78
78
 
79
79
  it 'returns raw attributes' do
80
- subject.attributes.must_be_same_as attributes
80
+ _(subject.attributes).must_be_same_as attributes
81
81
  end
82
82
 
83
83
  it 'returns the subscription expiration date' do
84
84
  expected = DateTime.new(2016, 6, 9, 13, 59, 40)
85
- subject.expires_date.must_equal expected
85
+ _(subject.expires_date).must_equal expected
86
86
  end
87
87
 
88
88
  it 'returns the trial status' do
89
- subject.is_trial_period.must_be_false
89
+ _(subject.is_trial_period).must_be_false
90
90
  end
91
91
  end
92
92
 
@@ -96,12 +96,12 @@ describe CandyCheck::AppStore::Receipt do
96
96
  end
97
97
 
98
98
  it 'isn\'t valid' do
99
- subject.valid?.must_be_false
99
+ _(subject.valid?).must_be_false
100
100
  end
101
101
 
102
102
  it 'return nil for cancellation date' do
103
103
  expected = DateTime.new(2015, 1, 12, 11, 40, 46)
104
- subject.cancellation_date.must_equal expected
104
+ _(subject.cancellation_date).must_equal expected
105
105
  end
106
106
  end
107
107
  end
@@ -11,26 +11,26 @@ describe CandyCheck::AppStore::SubscriptionVerification do
11
11
  it 'returns a verification failure for status != 0' do
12
12
  with_mocked_response('status' => 21_000) do |client, recorded|
13
13
  result = subject.call!
14
- client.receipt_data.must_equal data
15
- client.secret.must_equal secret
14
+ _(client.receipt_data).must_equal data
15
+ _(client.secret).must_equal secret
16
16
 
17
- recorded.first.must_equal [endpoint]
17
+ _(recorded.first).must_equal [endpoint]
18
18
 
19
- result.must_be_instance_of CandyCheck::AppStore::VerificationFailure
20
- result.code.must_equal 21_000
19
+ _(result).must_be_instance_of CandyCheck::AppStore::VerificationFailure
20
+ _(result.code).must_equal 21_000
21
21
  end
22
22
  end
23
23
 
24
24
  it 'returns a verification failure when receipt is missing' do
25
25
  with_mocked_response({}) do |client, recorded|
26
26
  result = subject.call!
27
- client.receipt_data.must_equal data
28
- client.secret.must_equal secret
27
+ _(client.receipt_data).must_equal data
28
+ _(client.secret).must_equal secret
29
29
 
30
- recorded.first.must_equal [endpoint]
30
+ _(recorded.first).must_equal [endpoint]
31
31
 
32
- result.must_be_instance_of CandyCheck::AppStore::VerificationFailure
33
- result.code.must_equal(-1)
32
+ _(result).must_be_instance_of CandyCheck::AppStore::VerificationFailure
33
+ _(result.code).must_equal(-1)
34
34
  end
35
35
  end
36
36
 
@@ -38,17 +38,50 @@ describe CandyCheck::AppStore::SubscriptionVerification do
38
38
  response = {
39
39
  'status' => 0,
40
40
  'latest_receipt_info' => [
41
- { 'item_id' => 'some_id' },
42
- { 'item_id' => 'some_other_id' }
41
+ { 'item_id' => 'some_id', 'purchase_date' => '2016-04-15 12:52:40 Etc/GMT' },
42
+ { 'item_id' => 'some_other_id', 'purchase_date' => '2016-04-15 12:52:40 Etc/GMT' }
43
43
  ]
44
44
  }
45
45
  with_mocked_response(response) do
46
46
  result = subject.call!
47
- result.must_be_instance_of CandyCheck::AppStore::ReceiptCollection
48
- result.receipts.must_be_instance_of Array
47
+ _(result).must_be_instance_of CandyCheck::AppStore::ReceiptCollection
48
+ _(result.receipts).must_be_instance_of Array
49
+ _(result.receipts.size).must_equal(2)
49
50
  last = result.receipts.last
50
- last.must_be_instance_of CandyCheck::AppStore::Receipt
51
- last.item_id.must_equal('some_other_id')
51
+ _(last).must_be_instance_of CandyCheck::AppStore::Receipt
52
+ _(last.item_id).must_equal('some_other_id')
53
+ end
54
+ end
55
+
56
+ describe 'filtered product_ids' do
57
+ subject do
58
+ CandyCheck::AppStore::SubscriptionVerification.new(
59
+ endpoint,
60
+ data,
61
+ secret,
62
+ product_ids
63
+ )
64
+ end
65
+ let(:product_ids) { ['product_1'] }
66
+
67
+ it 'returns only filtered reciepts when specifc product_ids are reqested' do
68
+ response = {
69
+ 'status' => 0,
70
+ 'latest_receipt_info' => [
71
+ { 'item_id' => 'some_id', 'product_id' => 'product_1', 'purchase_date' => '2016-04-15 12:52:40 Etc/GMT' },
72
+ { 'item_id' => 'some_other_id', 'product_id' => 'product_1', 'purchase_date' => '2016-04-15 12:52:40 Etc/GMT' },
73
+ { 'item_id' => 'some_id', 'product_id' => 'product_2', 'purchase_date' => '2016-04-15 12:52:40 Etc/GMT' }
74
+ ]
75
+ }
76
+ with_mocked_response(response) do
77
+ result = subject.call!
78
+ _(result).must_be_instance_of CandyCheck::AppStore::ReceiptCollection
79
+ _(result.receipts).must_be_instance_of Array
80
+ _(result.receipts.size).must_equal(2)
81
+ last = result.receipts.last
82
+ _(last).must_be_instance_of CandyCheck::AppStore::Receipt
83
+ _(last.item_id).must_equal('some_other_id')
84
+ end
52
85
  end
53
86
  end
54
87
 
@@ -9,20 +9,20 @@ describe CandyCheck::AppStore::VerificationFailure do
9
9
  it 'fetched an failure with message for every known code' do
10
10
  known.each do |code|
11
11
  got = subject.fetch(code)
12
- got.code.must_equal code
13
- got.message.wont_equal 'Unknown error'
12
+ _(got.code).must_equal code
13
+ _(got.message).wont_equal 'Unknown error'
14
14
  end
15
15
  end
16
16
 
17
17
  it 'fetched an failure for unknown codes' do
18
18
  got = subject.fetch(1234)
19
- got.code.must_equal 1234
20
- got.message.must_equal 'Unknown error'
19
+ _(got.code).must_equal 1234
20
+ _(got.message).must_equal 'Unknown error'
21
21
  end
22
22
 
23
23
  it 'fetched an failure for nil code' do
24
24
  got = subject.fetch(nil)
25
- got.code.must_equal(-1)
26
- got.message.must_equal 'Unknown error'
25
+ _(got.code).must_equal(-1)
26
+ _(got.message).must_equal 'Unknown error'
27
27
  end
28
28
  end
@@ -9,26 +9,26 @@ describe CandyCheck::AppStore::Verification do
9
9
  it 'returns a verification failure for status != 0' do
10
10
  with_mocked_response('status' => 21_000) do |client, recorded|
11
11
  result = subject.call!
12
- client.receipt_data.must_equal data
13
- client.secret.must_equal secret
12
+ _(client.receipt_data).must_equal data
13
+ _(client.secret).must_equal secret
14
14
 
15
- recorded.first.must_equal [endpoint]
15
+ _(recorded.first).must_equal [endpoint]
16
16
 
17
- result.must_be_instance_of CandyCheck::AppStore::VerificationFailure
18
- result.code.must_equal 21_000
17
+ _(result).must_be_instance_of CandyCheck::AppStore::VerificationFailure
18
+ _(result.code).must_equal 21_000
19
19
  end
20
20
  end
21
21
 
22
22
  it 'returns a verification failure when receipt is missing' do
23
23
  with_mocked_response({}) do |client, recorded|
24
24
  result = subject.call!
25
- client.receipt_data.must_equal data
26
- client.secret.must_equal secret
25
+ _(client.receipt_data).must_equal data
26
+ _(client.secret).must_equal secret
27
27
 
28
- recorded.first.must_equal [endpoint]
28
+ _(recorded.first).must_equal [endpoint]
29
29
 
30
- result.must_be_instance_of CandyCheck::AppStore::VerificationFailure
31
- result.code.must_equal(-1)
30
+ _(result).must_be_instance_of CandyCheck::AppStore::VerificationFailure
31
+ _(result.code).must_equal(-1)
32
32
  end
33
33
  end
34
34
 
@@ -36,8 +36,8 @@ describe CandyCheck::AppStore::Verification do
36
36
  response = { 'status' => 0, 'receipt' => { 'item_id' => 'some_id' } }
37
37
  with_mocked_response(response) do
38
38
  result = subject.call!
39
- result.must_be_instance_of CandyCheck::AppStore::Receipt
40
- result.item_id.must_equal('some_id')
39
+ _(result).must_be_instance_of CandyCheck::AppStore::Receipt
40
+ _(result.item_id).must_equal('some_id')
41
41
  end
42
42
  end
43
43
 
@@ -18,7 +18,7 @@ describe CandyCheck::AppStore::Verifier do
18
18
  end
19
19
 
20
20
  it 'holds the config' do
21
- subject.config.must_be_same_as config
21
+ _(subject.config).must_be_same_as config
22
22
  end
23
23
 
24
24
  describe 'sandbox' do
@@ -26,7 +26,7 @@ describe CandyCheck::AppStore::Verifier do
26
26
 
27
27
  it 'uses sandbox endpoint without retry on success' do
28
28
  with_mocked_verifier(receipt) do
29
- subject.verify(data, secret).must_be_same_as receipt
29
+ _(subject.verify(data, secret)).must_be_same_as receipt
30
30
  assert_recorded([sandbox_endpoint, data, secret])
31
31
  end
32
32
  end
@@ -34,7 +34,7 @@ describe CandyCheck::AppStore::Verifier do
34
34
  it 'only uses sandbox endpoint for normal failures' do
35
35
  failure = get_failure(21_000)
36
36
  with_mocked_verifier(failure) do
37
- subject.verify(data, secret).must_be_same_as failure
37
+ _(subject.verify(data, secret)).must_be_same_as failure
38
38
  assert_recorded([sandbox_endpoint, data, secret])
39
39
  end
40
40
  end
@@ -42,7 +42,7 @@ describe CandyCheck::AppStore::Verifier do
42
42
  it 'retries production endpoint for redirect error' do
43
43
  failure = get_failure(21_008)
44
44
  with_mocked_verifier(failure, receipt) do
45
- subject.verify(data, secret).must_be_same_as receipt
45
+ _(subject.verify(data, secret)).must_be_same_as receipt
46
46
  assert_recorded(
47
47
  [sandbox_endpoint, data, secret],
48
48
  [production_endpoint, data, secret]
@@ -56,7 +56,7 @@ describe CandyCheck::AppStore::Verifier do
56
56
 
57
57
  it 'uses production endpoint without retry on success' do
58
58
  with_mocked_verifier(receipt) do
59
- subject.verify(data, secret).must_be_same_as receipt
59
+ _(subject.verify(data, secret)).must_be_same_as receipt
60
60
  assert_recorded([production_endpoint, data, secret])
61
61
  end
62
62
  end
@@ -64,7 +64,7 @@ describe CandyCheck::AppStore::Verifier do
64
64
  it 'only uses production endpoint for normal failures' do
65
65
  failure = get_failure(21_000)
66
66
  with_mocked_verifier(failure) do
67
- subject.verify(data, secret).must_be_same_as failure
67
+ _(subject.verify(data, secret)).must_be_same_as failure
68
68
  assert_recorded([production_endpoint, data, secret])
69
69
  end
70
70
  end
@@ -72,7 +72,7 @@ describe CandyCheck::AppStore::Verifier do
72
72
  it 'retries production endpoint for redirect error' do
73
73
  failure = get_failure(21_007)
74
74
  with_mocked_verifier(failure, receipt) do
75
- subject.verify(data, secret).must_be_same_as receipt
75
+ _(subject.verify(data, secret)).must_be_same_as receipt
76
76
  assert_recorded(
77
77
  [production_endpoint, data, secret],
78
78
  [sandbox_endpoint, data, secret]
@@ -86,31 +86,41 @@ describe CandyCheck::AppStore::Verifier do
86
86
 
87
87
  it 'uses production endpoint without retry on success' do
88
88
  with_mocked_verifier(receipt_collection) do
89
- subject.verify_subscription(
89
+ _(subject.verify_subscription(
90
90
  data, secret
91
- ).must_be_same_as receipt_collection
92
- assert_recorded([production_endpoint, data, secret])
91
+ )).must_be_same_as receipt_collection
92
+ assert_recorded([production_endpoint, data, secret, nil])
93
93
  end
94
94
  end
95
95
 
96
96
  it 'only uses production endpoint for normal failures' do
97
97
  failure = get_failure(21_000)
98
98
  with_mocked_verifier(failure) do
99
- subject.verify_subscription(data, secret).must_be_same_as failure
100
- assert_recorded([production_endpoint, data, secret])
99
+ _(subject.verify_subscription(data, secret)).must_be_same_as failure
100
+ assert_recorded([production_endpoint, data, secret, nil])
101
101
  end
102
102
  end
103
103
 
104
104
  it 'retries production endpoint for redirect error' do
105
105
  failure = get_failure(21_007)
106
106
  with_mocked_verifier(failure, receipt) do
107
- subject.verify_subscription(data, secret).must_be_same_as receipt
107
+ _(subject.verify_subscription(data, secret)).must_be_same_as receipt
108
108
  assert_recorded(
109
- [production_endpoint, data, secret],
110
- [sandbox_endpoint, data, secret]
109
+ [production_endpoint, data, secret, nil],
110
+ [sandbox_endpoint, data, secret, nil]
111
111
  )
112
112
  end
113
113
  end
114
+
115
+ it 'passed the product_ids' do
116
+ product_ids = ['product_1']
117
+ with_mocked_verifier(receipt_collection) do
118
+ _(subject.verify_subscription(
119
+ data, secret, product_ids
120
+ )).must_be_same_as receipt_collection
121
+ assert_recorded([production_endpoint, data, secret, product_ids])
122
+ end
123
+ end
114
124
  end
115
125
 
116
126
  private
@@ -127,15 +137,24 @@ describe CandyCheck::AppStore::Verifier do
127
137
  end
128
138
 
129
139
  def assert_recorded(*calls)
130
- @recorded.must_equal calls
140
+ _(@recorded).must_equal calls
131
141
  end
132
142
 
133
143
  def get_failure(code)
134
144
  CandyCheck::AppStore::VerificationFailure.fetch(code)
135
145
  end
136
146
 
137
- DummyAppStoreVerification = Struct.new(:endpoint, :data, :secret) do
147
+ class DummyAppStoreVerification
148
+ attr_reader :endpoint, :data, :secret, :product_ids
138
149
  attr_accessor :results
150
+
151
+ def initialize(endpoint, data, secret, product_ids = nil)
152
+ @endpoint = endpoint
153
+ @data = data
154
+ @secret = secret
155
+ @product_ids = product_ids
156
+ end
157
+
139
158
  def call!
140
159
  results.shift
141
160
  end