passbook 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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/, ''))}
|