passbook 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +5 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +53 -0
- data/LICENSE +22 -0
- data/README.md +237 -0
- data/Rakefile +35 -0
- data/VERSION +1 -0
- data/lib/passbook/pkpass.rb +142 -0
- data/lib/passbook/push_notification.rb +10 -0
- data/lib/passbook/version.rb +3 -0
- data/lib/passbook.rb +13 -0
- data/lib/rack/passbook_rack.rb +94 -0
- data/lib/rails/generators/passbook/config/config_generator.rb +16 -0
- data/lib/rails/generators/passbook/config/templates/initializer.rb +13 -0
- data/passbook-ios.gemspec +87 -0
- data/passbook.gemspec +87 -0
- data/spec/data/icon.png +0 -0
- data/spec/data/icon@2x.png +0 -0
- data/spec/data/logo.png +0 -0
- data/spec/data/logo@2x.png +0 -0
- data/spec/lib/passbook/pkpass_spec.rb +128 -0
- data/spec/lib/passbook/push_notification_spec.rb +22 -0
- data/spec/lib/rack/passbook_rack_spec.rb +196 -0
- data/spec/spec_helper.rb +9 -0
- metadata +220 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "passbook-ios"
|
8
|
+
s.version = "0.2.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Thomas Lauro", "Lance Gleason"]
|
12
|
+
s.date = "2013-01-06"
|
13
|
+
s.description = "This gem allows you to create IOS Passbooks. Unlike some, this works with Rails but does not require it."
|
14
|
+
s.email = ["thomas@lauro.fr", "lgleason@polyglotprogramminginc.com"]
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.md"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".travis.yml",
|
21
|
+
"Gemfile",
|
22
|
+
"Gemfile.lock",
|
23
|
+
"LICENSE",
|
24
|
+
"README.md",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"lib/passbook.rb",
|
28
|
+
"lib/passbook/pkpass.rb",
|
29
|
+
"lib/passbook/push_notification.rb",
|
30
|
+
"lib/passbook/version.rb",
|
31
|
+
"lib/rack/passbook_rack.rb",
|
32
|
+
"lib/rails/generators/passbook/config/config_generator.rb",
|
33
|
+
"lib/rails/generators/passbook/config/templates/initializer.rb",
|
34
|
+
"passbook-ios.gemspec",
|
35
|
+
"passbook.gemspec",
|
36
|
+
"spec/data/icon.png",
|
37
|
+
"spec/data/icon@2x.png",
|
38
|
+
"spec/data/logo.png",
|
39
|
+
"spec/data/logo@2x.png",
|
40
|
+
"spec/lib/passbook/pkpass_spec.rb",
|
41
|
+
"spec/lib/passbook/push_notification_spec.rb",
|
42
|
+
"spec/lib/rack/passbook_rack_spec.rb",
|
43
|
+
"spec/spec_helper.rb"
|
44
|
+
]
|
45
|
+
s.homepage = "http://github.com/frozon/passbook"
|
46
|
+
s.licenses = ["MIT"]
|
47
|
+
s.require_paths = ["lib"]
|
48
|
+
s.rubygems_version = "1.8.24"
|
49
|
+
s.summary = "A IOS Passbook generator."
|
50
|
+
|
51
|
+
if s.respond_to? :specification_version then
|
52
|
+
s.specification_version = 3
|
53
|
+
|
54
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
55
|
+
s.add_runtime_dependency(%q<rubyzip>, [">= 0"])
|
56
|
+
s.add_runtime_dependency(%q<grocer>, [">= 0"])
|
57
|
+
s.add_development_dependency(%q<rack-test>, [">= 0"])
|
58
|
+
s.add_development_dependency(%q<activesupport>, [">= 0"])
|
59
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
60
|
+
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
61
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
62
|
+
s.add_development_dependency(%q<rake>, [">= 0"])
|
63
|
+
s.add_development_dependency(%q<yard>, [">= 0"])
|
64
|
+
else
|
65
|
+
s.add_dependency(%q<rubyzip>, [">= 0"])
|
66
|
+
s.add_dependency(%q<grocer>, [">= 0"])
|
67
|
+
s.add_dependency(%q<rack-test>, [">= 0"])
|
68
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
69
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
70
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
71
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
72
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
73
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
74
|
+
end
|
75
|
+
else
|
76
|
+
s.add_dependency(%q<rubyzip>, [">= 0"])
|
77
|
+
s.add_dependency(%q<grocer>, [">= 0"])
|
78
|
+
s.add_dependency(%q<rack-test>, [">= 0"])
|
79
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
80
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
81
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
82
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
83
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
84
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
data/passbook.gemspec
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "passbook"
|
8
|
+
s.version = "0.2.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Thomas Lauro", "Lance Gleason"]
|
12
|
+
s.date = "2013-02-23"
|
13
|
+
s.description = "This gem allows you to create IOS Passbooks. Unlike some, this works with Rails but does not require it."
|
14
|
+
s.email = ["thomas@lauro.fr", "lgleason@polyglotprogramminginc.com"]
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.md"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".travis.yml",
|
21
|
+
"Gemfile",
|
22
|
+
"Gemfile.lock",
|
23
|
+
"LICENSE",
|
24
|
+
"README.md",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"lib/passbook.rb",
|
28
|
+
"lib/passbook/pkpass.rb",
|
29
|
+
"lib/passbook/push_notification.rb",
|
30
|
+
"lib/passbook/version.rb",
|
31
|
+
"lib/rack/passbook_rack.rb",
|
32
|
+
"lib/rails/generators/passbook/config/config_generator.rb",
|
33
|
+
"lib/rails/generators/passbook/config/templates/initializer.rb",
|
34
|
+
"passbook-ios.gemspec",
|
35
|
+
"passbook.gemspec",
|
36
|
+
"spec/data/icon.png",
|
37
|
+
"spec/data/icon@2x.png",
|
38
|
+
"spec/data/logo.png",
|
39
|
+
"spec/data/logo@2x.png",
|
40
|
+
"spec/lib/passbook/pkpass_spec.rb",
|
41
|
+
"spec/lib/passbook/push_notification_spec.rb",
|
42
|
+
"spec/lib/rack/passbook_rack_spec.rb",
|
43
|
+
"spec/spec_helper.rb"
|
44
|
+
]
|
45
|
+
s.homepage = "http://github.com/frozon/passbook"
|
46
|
+
s.licenses = ["MIT"]
|
47
|
+
s.require_paths = ["lib"]
|
48
|
+
s.rubygems_version = "1.8.24"
|
49
|
+
s.summary = "A IOS Passbook generator."
|
50
|
+
|
51
|
+
if s.respond_to? :specification_version then
|
52
|
+
s.specification_version = 3
|
53
|
+
|
54
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
55
|
+
s.add_runtime_dependency(%q<rubyzip>, [">= 0"])
|
56
|
+
s.add_runtime_dependency(%q<grocer>, [">= 0"])
|
57
|
+
s.add_development_dependency(%q<rack-test>, [">= 0"])
|
58
|
+
s.add_development_dependency(%q<activesupport>, [">= 0"])
|
59
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
60
|
+
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
61
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
62
|
+
s.add_development_dependency(%q<rake>, [">= 0"])
|
63
|
+
s.add_development_dependency(%q<yard>, [">= 0"])
|
64
|
+
else
|
65
|
+
s.add_dependency(%q<rubyzip>, [">= 0"])
|
66
|
+
s.add_dependency(%q<grocer>, [">= 0"])
|
67
|
+
s.add_dependency(%q<rack-test>, [">= 0"])
|
68
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
69
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
70
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
71
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
72
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
73
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
74
|
+
end
|
75
|
+
else
|
76
|
+
s.add_dependency(%q<rubyzip>, [">= 0"])
|
77
|
+
s.add_dependency(%q<grocer>, [">= 0"])
|
78
|
+
s.add_dependency(%q<rack-test>, [">= 0"])
|
79
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
80
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
81
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
82
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
83
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
84
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
data/spec/data/icon.png
ADDED
Binary file
|
Binary file
|
data/spec/data/logo.png
ADDED
Binary file
|
Binary file
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Passbook do
|
4
|
+
|
5
|
+
let (:content) {{
|
6
|
+
:formatVersion => 1,
|
7
|
+
:passTypeIdentifier => "pass.passbook.test",
|
8
|
+
:serialNumber => "001",
|
9
|
+
:teamIdentifier => ENV['APPLE_TEAM_ID'],
|
10
|
+
:relevantDate => "2012-10-02",
|
11
|
+
:locations => [ #TODO
|
12
|
+
{
|
13
|
+
:longitude => 2.35403,
|
14
|
+
:latitude => 48.893855
|
15
|
+
}
|
16
|
+
],
|
17
|
+
:organizationName => "WorldCo",
|
18
|
+
:description => "description",
|
19
|
+
:foregroundColor => "rgb(227,210,18)",
|
20
|
+
:backgroundColor => "rgb(60, 65, 76)",
|
21
|
+
:logoText => "Event",
|
22
|
+
:eventTicket => {
|
23
|
+
:primaryFields => [
|
24
|
+
{
|
25
|
+
:key => "date",
|
26
|
+
:label => "DATE",
|
27
|
+
:value => "date"
|
28
|
+
}
|
29
|
+
],
|
30
|
+
:backFields => [
|
31
|
+
{
|
32
|
+
:key => "description",
|
33
|
+
:label => "DESCRIPTION",
|
34
|
+
:value => "description"
|
35
|
+
},
|
36
|
+
{
|
37
|
+
:key => "aboutUs",
|
38
|
+
:label => "MORE",
|
39
|
+
:value => "about us"
|
40
|
+
}
|
41
|
+
]
|
42
|
+
}
|
43
|
+
}}
|
44
|
+
|
45
|
+
let (:pass) {Passbook::PKPass.new content.to_json}
|
46
|
+
|
47
|
+
context 'signatures' do
|
48
|
+
before do
|
49
|
+
Passbook.should_receive(:p12_password).and_return 'password'
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'p12_cert_and_key' do
|
53
|
+
context 'pem p12 certs' do
|
54
|
+
before do
|
55
|
+
Passbook.should_receive(:p12_key).twice.and_return 'my_p12_key'
|
56
|
+
Passbook.should_receive(:p12_certificate).and_return 'my_p12_certificate'
|
57
|
+
File.should_receive(:read).with('my_p12_key').and_return 'my_p12_key_file'
|
58
|
+
File.should_receive(:read).with('my_p12_certificate').and_return 'my_p12_certificate_file'
|
59
|
+
OpenSSL::PKey::RSA.should_receive(:new).with('my_p12_key_file', 'password').and_return 'my_rsa_key'
|
60
|
+
OpenSSL::X509::Certificate.should_receive(:new).with('my_p12_certificate_file').and_return 'my_ssl_p12_cert'
|
61
|
+
end
|
62
|
+
|
63
|
+
subject {pass.get_p12_cert_and_key}
|
64
|
+
its([:key]) {should eq 'my_rsa_key'}
|
65
|
+
its([:cert]) {should eq 'my_ssl_p12_cert'}
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'p12 files' do
|
69
|
+
let (:p12) { double('OpenSSL::PKCS12') }
|
70
|
+
let (:final_hash) {{:key => 'my_final_p12_key', :cert => 'my_final_p12_cert'}}
|
71
|
+
before do
|
72
|
+
p12.should_receive(:key).and_return final_hash[:key]
|
73
|
+
p12.should_receive(:certificate).and_return final_hash[:cert]
|
74
|
+
Passbook.should_receive(:p12_key).and_return nil
|
75
|
+
Passbook.should_receive(:p12_cert).and_return 'my_p12_cert'
|
76
|
+
File.should_receive(:read).with('my_p12_cert').and_return 'my_p12_cert_file'
|
77
|
+
OpenSSL::PKCS12.should_receive(:new).with('my_p12_cert_file', 'password').and_return p12
|
78
|
+
end
|
79
|
+
|
80
|
+
subject {pass.get_p12_cert_and_key}
|
81
|
+
its([:key]) {should eq final_hash[:key]}
|
82
|
+
its([:cert]) {should eq final_hash[:cert]}
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'outputs' do
|
88
|
+
let (:base_path) {'spec/data'}
|
89
|
+
let (:entries) {["pass.json", "manifest.json", "signature", "icon.png", "icon@2x.png", "logo.png", "logo@2x.png"]}
|
90
|
+
|
91
|
+
before :each do
|
92
|
+
pass.addFiles ["#{base_path}/icon.png","#{base_path}/icon@2x.png","#{base_path}/logo.png","#{base_path}/logo@2x.png"]
|
93
|
+
pass.should_receive(:createSignature).and_return('Signed by the Honey Badger')
|
94
|
+
@file_entries = []
|
95
|
+
Zip::ZipInputStream::open(zip_path) {|io|
|
96
|
+
while (entry = io.get_next_entry)
|
97
|
+
@file_entries << entry.name
|
98
|
+
end
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'zip file' do
|
103
|
+
let(:zip_path) {pass.file.path}
|
104
|
+
|
105
|
+
subject {entries}
|
106
|
+
it {should eq @file_entries}
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'StringIO' do
|
110
|
+
let (:temp_file) {Tempfile.new("pass.pkpass")}
|
111
|
+
let (:zip_path) {
|
112
|
+
zip_out = pass.stream
|
113
|
+
zip_out.class.should eq(Class::StringIO)
|
114
|
+
#creating file, re-reading zip to see if correctly formed
|
115
|
+
temp_file.write zip_out.string
|
116
|
+
temp_file.close
|
117
|
+
temp_file.path
|
118
|
+
}
|
119
|
+
|
120
|
+
subject {entries}
|
121
|
+
it {should eq @file_entries}
|
122
|
+
|
123
|
+
after do
|
124
|
+
temp_file.delete
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'grocer'
|
3
|
+
|
4
|
+
describe Passbook::PushNotification do
|
5
|
+
|
6
|
+
context 'send notification' do
|
7
|
+
let(:grocer_pusher) {double 'Grocer'}
|
8
|
+
let(:notification) {double 'Grocer::Notification'}
|
9
|
+
let(:notification_settings) {{:certificate => './notification_cert.pem', :gateway => 'honeybadger.apple.com'}}
|
10
|
+
|
11
|
+
before :each do
|
12
|
+
Passbook.should_receive(:notification_cert).and_return './notification_cert.pem'
|
13
|
+
Grocer::PassbookNotification.should_receive(:new).with(:device_token => 'my token').and_return notification
|
14
|
+
grocer_pusher.should_receive(:push).with(notification).and_return 55
|
15
|
+
Grocer.should_receive(:pusher).with(notification_settings).and_return grocer_pusher
|
16
|
+
Passbook.should_receive(:notification_gateway).and_return 'honeybadger.apple.com'
|
17
|
+
end
|
18
|
+
|
19
|
+
subject {Passbook::PushNotification.send_notification('my token')}
|
20
|
+
it {should eq 55}
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rack::PassbookRack do
|
4
|
+
|
5
|
+
let(:register_delete_path) {'/v1/devices/fe772e610be3efafb65ed77772ca311a/registrations/pass.com.polyglotprogramminginc.testpass/27-1'}
|
6
|
+
let(:register_delete_params) {{'deviceLibraryIdentifier' => 'fe772e610be3efafb65ed77772ca311a',
|
7
|
+
'passTypeIdentifier' => 'pass.com.polyglotprogramminginc.testpass',
|
8
|
+
'serialNumber' => '27-1'}}
|
9
|
+
let(:passes_for_device_path) {'/v1/devices/fe772e610be3efafb65ed77772ca311a/registrations/pass.com.polyglotprogramminginc.testpass'}
|
10
|
+
let(:passes_for_device_params) {{'deviceLibraryIdentifier' => 'fe772e610be3efafb65ed77772ca311a',
|
11
|
+
'passTypeIdentifier' => 'pass.com.polyglotprogramminginc.testpass'}}
|
12
|
+
let(:latest_pass_path) {'/v1/passes/pass.com.polyglotprogramminginc.testpass/27-1'}
|
13
|
+
let(:latest_pass_params) {{'passTypeIdentifier' => 'pass.com.polyglotprogramminginc.testpass',
|
14
|
+
'serialNumber' => '27-1'}}
|
15
|
+
let(:log_path) {'/v1/log'}
|
16
|
+
let(:push_token) {"8c56f2e787d9c089963960ace834bc2875e3f0cf7745da5b98d58bc6be05b4dc"}
|
17
|
+
|
18
|
+
context 'find method' do
|
19
|
+
let(:passbook_rack) {Rack::PassbookRack.new nil}
|
20
|
+
|
21
|
+
shared_examples_for 'a method that can handle non passbook urls' do
|
22
|
+
context 'incomplete passbook api path' do
|
23
|
+
subject {passbook_rack.find_method('/v1/devices/fe772e610be3efafb65ed77772ca311a/registrations')}
|
24
|
+
it {should eq nil}
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'no version api path' do
|
28
|
+
subject {passbook_rack.find_method('/devices/fe772e610be3efafb65ed77772ca311a/registrations')}
|
29
|
+
it {should eq nil}
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'no devices api path' do
|
33
|
+
subject {passbook_rack.find_method('/v1/fe772e610be3efafb65ed77772ca311a/registrations')}
|
34
|
+
it {should eq nil}
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'no registrations api path' do
|
38
|
+
subject {passbook_rack.find_method('/v1/devices/fe772e610be3efafb65ed77772ca311a')}
|
39
|
+
it {should eq nil}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'device register delete' do
|
44
|
+
context 'a valid path' do
|
45
|
+
subject {passbook_rack.find_method(register_delete_path)}
|
46
|
+
its([:method]) {should eq 'device_register_delete'}
|
47
|
+
its([:params]) {should eq(register_delete_params) }
|
48
|
+
end
|
49
|
+
|
50
|
+
it_behaves_like 'a method that can handle non passbook urls'
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'passes for device' do
|
55
|
+
subject {passbook_rack.find_method(passes_for_device_path)}
|
56
|
+
its([:method]) {should eq 'passes_for_device'}
|
57
|
+
its([:params]) {should eq passes_for_device_params }
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'latest pass' do
|
61
|
+
subject {passbook_rack.find_method(latest_pass_path)}
|
62
|
+
its([:method]) {should eq 'latest_pass'}
|
63
|
+
its([:params]) {should eq(latest_pass_params) }
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'latest pass' do
|
67
|
+
subject {passbook_rack.find_method(log_path)}
|
68
|
+
its([:method]) {should eq 'log'}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'rack middleware' do
|
73
|
+
|
74
|
+
context 'register pass' do
|
75
|
+
before do
|
76
|
+
Passbook::PassbookNotification.should_receive(:register_pass).
|
77
|
+
with(register_delete_params.merge!('pushToken' => push_token)).and_return({:status => 201})
|
78
|
+
post register_delete_path, {"pushToken" => push_token}.to_json
|
79
|
+
end
|
80
|
+
|
81
|
+
subject {last_response}
|
82
|
+
its(:status) {should eq 201}
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'passes for device' do
|
86
|
+
context 'with passes' do
|
87
|
+
let(:passes_for_device_response) {{'last_updated' => 1, 'serial_numbers' => [343, 234]}}
|
88
|
+
before do
|
89
|
+
Passbook::PassbookNotification.should_receive(:passes_for_device).
|
90
|
+
with(passes_for_device_params).and_return(passes_for_device_response)
|
91
|
+
get passes_for_device_path
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'status' do
|
95
|
+
subject {last_response.status}
|
96
|
+
it {should eq 200}
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'body' do
|
100
|
+
subject{JSON.parse(last_response.body)}
|
101
|
+
it {should eq passes_for_device_response}
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context 'without passes' do
|
106
|
+
before do
|
107
|
+
Passbook::PassbookNotification.should_receive(:passes_for_device).
|
108
|
+
with(passes_for_device_params).and_return(nil)
|
109
|
+
get passes_for_device_path
|
110
|
+
end
|
111
|
+
|
112
|
+
context 'status' do
|
113
|
+
subject {last_response.status}
|
114
|
+
it {should eq 204}
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'get latest pass' do
|
120
|
+
context 'valid pass' do
|
121
|
+
let(:raw_pass) {'some url encoded text'}
|
122
|
+
|
123
|
+
before do
|
124
|
+
Passbook::PassbookNotification.should_receive(:latest_pass).with(latest_pass_params).
|
125
|
+
and_return(raw_pass)
|
126
|
+
get latest_pass_path
|
127
|
+
end
|
128
|
+
|
129
|
+
subject {last_response}
|
130
|
+
its(:status) {should eq 200}
|
131
|
+
its(:header) {should eq({'Content-Type' => 'application/vnd.apple.pkpass',
|
132
|
+
'Content-Disposition' => 'attachment', 'filename' => '27-1.pkpass', 'Content-Length' => '21'})}
|
133
|
+
its(:body) {should eq raw_pass}
|
134
|
+
end
|
135
|
+
|
136
|
+
context 'no pass' do
|
137
|
+
before do
|
138
|
+
Passbook::PassbookNotification.should_receive(:latest_pass).with(latest_pass_params).
|
139
|
+
and_return(nil)
|
140
|
+
get latest_pass_path
|
141
|
+
end
|
142
|
+
|
143
|
+
subject {last_response}
|
144
|
+
its(:status) {should eq 204}
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context 'unregister pass' do
|
149
|
+
before do
|
150
|
+
Passbook::PassbookNotification.should_receive(:unregister_pass).
|
151
|
+
with(register_delete_params).and_return({:status => 200})
|
152
|
+
delete register_delete_path
|
153
|
+
end
|
154
|
+
|
155
|
+
subject {last_response}
|
156
|
+
its(:status) {should eq 200}
|
157
|
+
end
|
158
|
+
|
159
|
+
context 'log' do
|
160
|
+
let(:log_params) {{'logs' => ['some error']}}
|
161
|
+
before do
|
162
|
+
Passbook::PassbookNotification.should_receive(:log).
|
163
|
+
with(log_params)
|
164
|
+
post log_path, log_params.to_json
|
165
|
+
end
|
166
|
+
|
167
|
+
subject {last_response}
|
168
|
+
its(:status) {should eq 200}
|
169
|
+
end
|
170
|
+
|
171
|
+
context 'non passbook requests' do
|
172
|
+
before do
|
173
|
+
get '/foo'
|
174
|
+
end
|
175
|
+
|
176
|
+
subject {last_response}
|
177
|
+
its(:status) {should eq 200}
|
178
|
+
its(:body) {should eq 'test app'}
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
|
184
|
+
require 'rack/test'
|
185
|
+
include Rack::Test::Methods
|
186
|
+
|
187
|
+
def app
|
188
|
+
test_app = lambda do |env|
|
189
|
+
[200, {}, 'test app']
|
190
|
+
end
|
191
|
+
|
192
|
+
Rack::PassbookRack.new test_app
|
193
|
+
end
|
194
|
+
|
195
|
+
class Passbook::PassbookNotification
|
196
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
require 'json'
|
4
|
+
require 'simplecov'
|
5
|
+
require 'grocer/passbook_notification'
|
6
|
+
SimpleCov.start
|
7
|
+
|
8
|
+
Dir['lib/passbook/**/*.rb'].each {|f| require File.join(File.dirname(__FILE__), '..', f.gsub(/.rb/, ''))}
|
9
|
+
Dir['lib/rack/**/*.rb'].each {|f| require File.join(File.dirname(__FILE__), '..', f.gsub(/.rb/, ''))}
|