crusade_rails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +3 -0
  4. data/Rakefile +48 -0
  5. data/app/assets/javascripts/crusade.js +15 -0
  6. data/app/assets/javascripts/crusade_rails/configuration.js.coffee.erb +4 -0
  7. data/app/assets/javascripts/crusade_rails/crusade.js.coffee +46 -0
  8. data/app/assets/javascripts/crusade_rails/notification_permission.js.coffee +13 -0
  9. data/app/assets/stylesheets/crusade_rails/application.css +13 -0
  10. data/app/controllers/crusade_rails/apns/v1/log_controller.rb +13 -0
  11. data/app/controllers/crusade_rails/apns/v1/push_package_controller.rb +23 -0
  12. data/app/controllers/crusade_rails/apns/v1/subscription_controller.rb +37 -0
  13. data/app/controllers/crusade_rails/application_controller.rb +14 -0
  14. data/app/helpers/crusade_rails/application_helper.rb +4 -0
  15. data/app/models/crusade_rails/user_subscription.rb +4 -0
  16. data/app/services/crusade_rails/notification_service.rb +36 -0
  17. data/app/services/crusade_rails/user_subscription_service.rb +36 -0
  18. data/app/views/layouts/crusade_rails/application.html.erb +14 -0
  19. data/config/initializers/teaspoon.rb +65 -0
  20. data/config/routes.rb +15 -0
  21. data/db/migrate/20130917203302_create_crusade_rails_user_subscriptions.rb +12 -0
  22. data/lib/crusade_rails/configuration_loader.rb +33 -0
  23. data/lib/crusade_rails/engine.rb +9 -0
  24. data/lib/crusade_rails/version.rb +3 -0
  25. data/lib/crusade_rails.rb +4 -0
  26. data/lib/generators/crusade/install/USAGE +9 -0
  27. data/lib/generators/crusade/install/install_generator.rb +17 -0
  28. data/lib/generators/crusade/install/templates/configuration.yml +23 -0
  29. data/lib/generators/crusade/install/templates/initializer.rb +2 -0
  30. data/lib/tasks/crusade_rails_tasks.rake +4 -0
  31. data/test/controllers/apns/v1/log_controller_test.rb +35 -0
  32. data/test/controllers/apns/v1/push_package_controller_test.rb +41 -0
  33. data/test/controllers/apns/v1/subscription_controller_test.rb +61 -0
  34. data/test/crusade_rails_test.rb +7 -0
  35. data/test/dummy/README.rdoc +28 -0
  36. data/test/dummy/Rakefile +6 -0
  37. data/test/dummy/app/assets/javascripts/application.js +13 -0
  38. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  39. data/test/dummy/app/controllers/application_controller.rb +5 -0
  40. data/test/dummy/app/helpers/application_helper.rb +2 -0
  41. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  42. data/test/dummy/bin/bundle +3 -0
  43. data/test/dummy/bin/rails +4 -0
  44. data/test/dummy/bin/rake +4 -0
  45. data/test/dummy/config/application.rb +23 -0
  46. data/test/dummy/config/boot.rb +5 -0
  47. data/test/dummy/config/certificate.p12 +0 -0
  48. data/test/dummy/config/crusade.yml +23 -0
  49. data/test/dummy/config/crusade_absolute.yml +13 -0
  50. data/test/dummy/config/database.yml +25 -0
  51. data/test/dummy/config/environment.rb +5 -0
  52. data/test/dummy/config/environments/development.rb +29 -0
  53. data/test/dummy/config/environments/production.rb +80 -0
  54. data/test/dummy/config/environments/test.rb +36 -0
  55. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  56. data/test/dummy/config/initializers/crusade.rb +2 -0
  57. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  58. data/test/dummy/config/initializers/inflections.rb +16 -0
  59. data/test/dummy/config/initializers/mime_types.rb +5 -0
  60. data/test/dummy/config/initializers/secret_token.rb +12 -0
  61. data/test/dummy/config/initializers/session_store.rb +3 -0
  62. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  63. data/test/dummy/config/locales/en.yml +23 -0
  64. data/test/dummy/config/routes.rb +3 -0
  65. data/test/dummy/config.ru +4 -0
  66. data/test/dummy/db/development.sqlite3 +0 -0
  67. data/test/dummy/db/migrate/20130921092524_create_crusade_rails_user_subscriptions.crusade_rails.rb +13 -0
  68. data/test/dummy/db/schema.rb +34 -0
  69. data/test/dummy/db/test.sqlite3 +0 -0
  70. data/test/dummy/lib/icon.iconset/icon_128x128.png +0 -0
  71. data/test/dummy/lib/icon.iconset/icon_128x128@2x.png +0 -0
  72. data/test/dummy/lib/icon.iconset/icon_16x16.png +0 -0
  73. data/test/dummy/lib/icon.iconset/icon_16x16@2x.png +0 -0
  74. data/test/dummy/lib/icon.iconset/icon_32x32.png +0 -0
  75. data/test/dummy/lib/icon.iconset/icon_32x32@2x.png +0 -0
  76. data/test/dummy/log/development.log +9000 -0
  77. data/test/dummy/log/test.log +18388 -0
  78. data/test/dummy/public/404.html +58 -0
  79. data/test/dummy/public/422.html +58 -0
  80. data/test/dummy/public/500.html +57 -0
  81. data/test/dummy/public/favicon.ico +0 -0
  82. data/test/dummy/tmp/cache/assets/development/sprockets/0330051201f83b2ff3843e3c6747e79d +0 -0
  83. data/test/dummy/tmp/cache/assets/development/sprockets/0534641409a2140bc6e7ebc3ffb3a54d +0 -0
  84. data/test/dummy/tmp/cache/assets/development/sprockets/108a4cc5d6041a541455f23f064f718f +0 -0
  85. data/test/dummy/tmp/cache/assets/development/sprockets/10b6d318fbf01394655188cb55968932 +0 -0
  86. data/test/dummy/tmp/cache/assets/development/sprockets/1903ce46cdbce5cbddb3f58cacb00c89 +0 -0
  87. data/test/dummy/tmp/cache/assets/development/sprockets/19e13c514bd0c76f667eacd20d91d72c +0 -0
  88. data/test/dummy/tmp/cache/assets/development/sprockets/1d295354fabfd91032e5c51cf32fe192 +0 -0
  89. data/test/dummy/tmp/cache/assets/development/sprockets/24efeb1e9e576159a181fb53b3f114a7 +0 -0
  90. data/test/dummy/tmp/cache/assets/development/sprockets/27cb4afd1625534b2a374a81b9df26de +0 -0
  91. data/test/dummy/tmp/cache/assets/development/sprockets/28fcfef8d3cf8654ba549bc1761e83e4 +0 -0
  92. data/test/dummy/tmp/cache/assets/development/sprockets/2969a922d5c2342a65712f8bd9cc99a6 +0 -0
  93. data/test/dummy/tmp/cache/assets/development/sprockets/2de3b3bd851fd121492b6d4ac403e556 +0 -0
  94. data/test/dummy/tmp/cache/assets/development/sprockets/2e0be385ec13186af8c1ea31b03b96fd +0 -0
  95. data/test/dummy/tmp/cache/assets/development/sprockets/2e465486b1a6c8f2d49a4ed114d70396 +0 -0
  96. data/test/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  97. data/test/dummy/tmp/cache/assets/development/sprockets/3125a19a8cea48c16b56e8b59a5c5294 +0 -0
  98. data/test/dummy/tmp/cache/assets/development/sprockets/3cc705332293b3c69203db8a96e9d830 +0 -0
  99. data/test/dummy/tmp/cache/assets/development/sprockets/3cd8491f62d0bb72dc92a13205463599 +0 -0
  100. data/test/dummy/tmp/cache/assets/development/sprockets/3cde555d17b62d65401cc9272bae6e08 +0 -0
  101. data/test/dummy/tmp/cache/assets/development/sprockets/556f3a4cc7bf634157a1bcb26a3d2b6d +0 -0
  102. data/test/dummy/tmp/cache/assets/development/sprockets/5f268780e6c88d505c5593761755010a +0 -0
  103. data/test/dummy/tmp/cache/assets/development/sprockets/6701d9e3411fdcd8e5e547bdec87cb66 +0 -0
  104. data/test/dummy/tmp/cache/assets/development/sprockets/6b77a9aa8954a56d3da421ee8f0813e8 +0 -0
  105. data/test/dummy/tmp/cache/assets/development/sprockets/6f19bfcf39fc6e2ba42b315015e41741 +0 -0
  106. data/test/dummy/tmp/cache/assets/development/sprockets/72194bfe82d488c5e022c9046c0581c5 +0 -0
  107. data/test/dummy/tmp/cache/assets/development/sprockets/732aa0a732c68b36c462c1aa61e9c5db +0 -0
  108. data/test/dummy/tmp/cache/assets/development/sprockets/742719bcba2beaa6ee593b3c6eabe40b +0 -0
  109. data/test/dummy/tmp/cache/assets/development/sprockets/753c20567a3407e94309e3a586ba70c1 +0 -0
  110. data/test/dummy/tmp/cache/assets/development/sprockets/76d2c2ca1f8747e7c285677d59d1f9d9 +0 -0
  111. data/test/dummy/tmp/cache/assets/development/sprockets/8674169919e38981b419dbd475a583aa +0 -0
  112. data/test/dummy/tmp/cache/assets/development/sprockets/8770d1f7ac46ca50bf453462671ea0b9 +0 -0
  113. data/test/dummy/tmp/cache/assets/development/sprockets/8b4c20d1cbaeadc08407a48823e8c7c3 +0 -0
  114. data/test/dummy/tmp/cache/assets/development/sprockets/8d66da576394374d14318805fe809466 +0 -0
  115. data/test/dummy/tmp/cache/assets/development/sprockets/9aacc018015dba444d327301c20b63c5 +0 -0
  116. data/test/dummy/tmp/cache/assets/development/sprockets/9bf8f0dcacf365b365a44fc7acaf5b33 +0 -0
  117. data/test/dummy/tmp/cache/assets/development/sprockets/9f6a5c70035131b2862f0cf1b1ffba5f +0 -0
  118. data/test/dummy/tmp/cache/assets/development/sprockets/aa3a6aa3669f27355e35fd070b5ec5cc +0 -0
  119. data/test/dummy/tmp/cache/assets/development/sprockets/b0f0a9774bdd9aba74bc3dbaa280abd2 +0 -0
  120. data/test/dummy/tmp/cache/assets/development/sprockets/b116102c65d66d0bac493130339e906f +0 -0
  121. data/test/dummy/tmp/cache/assets/development/sprockets/b3c46efa2d626eb47c04b3299485ada2 +0 -0
  122. data/test/dummy/tmp/cache/assets/development/sprockets/b60162f01dfafeaa2fd08552bee0d7b7 +0 -0
  123. data/test/dummy/tmp/cache/assets/development/sprockets/ba4082b2576e0439500c1de73f75e722 +0 -0
  124. data/test/dummy/tmp/cache/assets/development/sprockets/bd98cfe5b883a49d02e51dff15eb2d62 +0 -0
  125. data/test/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  126. data/test/dummy/tmp/cache/assets/development/sprockets/d0ba95da0d65927f38a86ec70536acfa +0 -0
  127. data/test/dummy/tmp/cache/assets/development/sprockets/ddcd3a7d9f01da29b22f5bb8894c9e9d +0 -0
  128. data/test/dummy/tmp/cache/assets/development/sprockets/dfb8f1f4a35d49c4853bb839dd074b03 +0 -0
  129. data/test/dummy/tmp/cache/assets/development/sprockets/edb1e911142e4ffa330d5f54129ae937 +0 -0
  130. data/test/dummy/tmp/cache/assets/development/sprockets/f3676986bcff0feb06ca29fc36c62054 +0 -0
  131. data/test/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  132. data/test/dummy/tmp/cache/assets/development/sprockets/f8e371443421803a78fdbe7fb29531b7 +0 -0
  133. data/test/dummy/tmp/cache/assets/development/sprockets/f9b223cb5385faca472d99ad42c60776 +0 -0
  134. data/test/dummy/tmp/cache/assets/development/sprockets/fcd414d106937117c1f77dafcb48d32d +0 -0
  135. data/test/dummy/tmp/cache/assets/development/sprockets/ff6fd5ae68516118b84d0dc0485e4456 +0 -0
  136. data/test/fixtures/crusade_rails/default_routes.rb +6 -0
  137. data/test/generators/install_generator_test.rb +66 -0
  138. data/test/integration/configuration_loader_test.rb +56 -0
  139. data/test/integration/push_package_integration_test.rb +14 -0
  140. data/test/javascripts/support/jquery.js +9790 -0
  141. data/test/javascripts/support/safari.coffee +7 -0
  142. data/test/javascripts/test_helper.coffee +25 -0
  143. data/test/javascripts/unit/configuration_test.js.coffee +11 -0
  144. data/test/javascripts/unit/crusade_test.js.coffee +102 -0
  145. data/test/javascripts/unit/notification_permission_test.js.coffee +49 -0
  146. data/test/routes/apns_routes_test.rb +39 -0
  147. data/test/services/notification_service_test.rb +69 -0
  148. data/test/services/user_subscription_service_test.rb +104 -0
  149. data/test/support/fake_push_notification.rb +24 -0
  150. data/test/teaspoon_env.rb +33 -0
  151. data/test/test_helper.rb +27 -0
  152. metadata +468 -0
@@ -0,0 +1,7 @@
1
+ @mockSafariPushNotification = ->
2
+ window.safari =
3
+ pushNotification:
4
+ fakeResult:
5
+ permission: 'default'
6
+ permission: (permissionData) -> console.log 'permission'
7
+ requestPermission: (url, pushId, userData, callback) -> callback(window.safari.pushNotification.fakeResult)
@@ -0,0 +1,25 @@
1
+ # Teaspoon includes some support files, but you can use anything from your own support path too.
2
+ # require support/jasmine-jquery
3
+ # require support/sinon
4
+ # require support/your-support-file
5
+ #
6
+ # Deferring execution
7
+ # If you're using CommonJS, RequireJS or some other asynchronous library you can defer execution. Call Teaspoon.execute()
8
+ # after everything has been loaded. Simple example of a timeout:
9
+ #
10
+ # Teaspoon.defer = true
11
+ # setTimeout(Teaspoon.execute, 1000)
12
+ #
13
+ # Matching files
14
+ # By default Teaspoon will look for files that match _spec.{js,js.coffee,.coffee}. Add a filename_spec.js file in your
15
+ # spec path and it'll be included in the default suite automatically. If you want to customize suites, check out the
16
+ # configuration in config/initializers/teaspoon.rb
17
+ #
18
+ # Manifest
19
+ # If you'd rather require your spec files manually (to control order for instance) you can disable the suite matcher in
20
+ # the configuration and use this file as a manifest.
21
+ #
22
+ # For more information: http://github.com/modeset/teaspoon
23
+ #
24
+ # You can require javascript files here. A good place to start is by requiring your application.js.
25
+ #= require application
@@ -0,0 +1,11 @@
1
+
2
+ describe 'configuration', ->
3
+
4
+ it 'attaches the configuration on the window', ->
5
+ expect(window.crusade).toBeDefined()
6
+
7
+ it 'sets the push_id', ->
8
+ expect(window.crusade.pushId).toEqual 'web.com.example.push.id'
9
+
10
+ it 'sets the webservice url', ->
11
+ expect(window.crusade.webserviceUrl).toEqual 'https://www.example.com/push'
@@ -0,0 +1,102 @@
1
+
2
+ describe 'Crusade', ->
3
+ subject = null
4
+
5
+ beforeEach ->
6
+ subject = new Crusade()
7
+
8
+ describe 'request push notification permission', ->
9
+ callback = null
10
+ permissionResult = null
11
+
12
+ beforeEach ->
13
+ mockSafariPushNotification()
14
+
15
+ callback = (permission) -> permissionResult = permission
16
+
17
+ describe 'the user was already requested', ->
18
+ afterEach ->
19
+ expect(window.safari.pushNotification.permission).toHaveBeenCalledWith 'web.com.example.push.id'
20
+
21
+
22
+ describe 'the user granted the permission', ->
23
+ it 'executes the success function if the user has already granted the permission', ->
24
+ spyOn(window.safari.pushNotification, 'permission').andReturn({permission: 'granted', deviceToken: 'deviceToken'})
25
+
26
+ subject.requestPermission('userId').granted(callback)
27
+
28
+ expect(permissionResult.permission).toEqual 'granted'
29
+
30
+ it 'wraps the safari permission into a crusade permission', ->
31
+ spyOn(window.safari.pushNotification, 'permission').andReturn({permission: 'granted', deviceToken: 'deviceToken'})
32
+
33
+ subject.requestPermission('userId').granted(callback)
34
+
35
+ expect(permissionResult).toEqual jasmine.any(NotificationPermission)
36
+
37
+ describe 'the user denied the permission', ->
38
+ it 'executes the error function if the user has already denied the permission', ->
39
+ spyOn(window.safari.pushNotification, 'permission').andReturn({permission: 'denied'})
40
+
41
+ subject.requestPermission('userId').denied(callback)
42
+
43
+ expect(permissionResult.permission).toEqual 'denied'
44
+
45
+ describe 'the user has never been requested', ->
46
+ permissionCallback = null
47
+
48
+ beforeEach ->
49
+ spyOn(window.safari.pushNotification, 'permission').andReturn({permission: 'default'})
50
+
51
+ permissionCallback = (permission) -> callback(permission)
52
+
53
+ afterEach ->
54
+ expect(window.safari.pushNotification.requestPermission).toHaveBeenCalledWith 'https://www.example.com/push',
55
+ 'web.com.example.push.id'
56
+ {userId: 'userId'}
57
+ jasmine.any(Function)
58
+
59
+ describe 'the user denies the permission', ->
60
+ it 'executes the success function if the user has already granted the permission', ->
61
+ window.safari.pushNotification.fakeResult = { permission: 'granted', deviceToken: 'deviceToken' }
62
+ spyOn(window.safari.pushNotification, 'requestPermission').andCallThrough()
63
+
64
+ subject.requestPermission('userId').granted(callback)
65
+
66
+ expect(permissionResult.permission).toEqual 'granted'
67
+
68
+ it 'wraps the safari permission into a crusade permission', ->
69
+ window.safari.pushNotification.fakeResult = { permission: 'granted', deviceToken: 'deviceToken' }
70
+ spyOn(window.safari.pushNotification, 'requestPermission').andCallThrough()
71
+
72
+ subject.requestPermission('userId').granted(callback)
73
+
74
+ expect(permissionResult).toEqual jasmine.any(NotificationPermission)
75
+
76
+ describe 'the user grants the permission', ->
77
+ it 'executes the error function if the user has already denied the permission', ->
78
+ window.safari.pushNotification.fakeResult = { permission: 'denied' }
79
+ spyOn(window.safari.pushNotification, 'requestPermission').andCallThrough()
80
+
81
+ subject.requestPermission('userId').denied(callback)
82
+
83
+ expect(permissionResult.permission).toEqual 'denied'
84
+
85
+ describe 'checkPermission', ->
86
+ afterEach ->
87
+ expect(window.safari.pushNotification.permission).toHaveBeenCalledWith 'web.com.example.push.id'
88
+
89
+
90
+ it 'returns the result of the current permission', ->
91
+ spyOn(window.safari.pushNotification, 'permission').andReturn({permission: 'granted', deviceToken: 'deviceToken'})
92
+
93
+ permissionResult = subject.checkPermission()
94
+
95
+ expect(permissionResult.permission).toEqual 'granted'
96
+
97
+ it 'wraps the safari permission into a crusade permission', ->
98
+ spyOn(window.safari.pushNotification, 'permission').andReturn({permission: 'granted', deviceToken: 'deviceToken'})
99
+
100
+ permissionResult = subject.checkPermission()
101
+
102
+ expect(permissionResult).toEqual jasmine.any(NotificationPermission)
@@ -0,0 +1,49 @@
1
+
2
+ describe 'NotificationPermission', ->
3
+ subject = null
4
+
5
+ describe 'constructor', ->
6
+ safariPermission = {}
7
+
8
+ it 'copies the permission', ->
9
+ safariPermission = { permission: "granted" }
10
+
11
+ subject = new NotificationPermission(safariPermission)
12
+
13
+ expect(subject.permission).toEqual "granted"
14
+
15
+ it 'copies the deviceToken', ->
16
+ safariPermission = { deviceToken: "1234q" }
17
+
18
+ subject = new NotificationPermission(safariPermission)
19
+
20
+ expect(subject.deviceToken).toEqual "1234q"
21
+
22
+ describe 'no safariPermission', ->
23
+ beforeEach ->
24
+ subject = new NotificationPermission()
25
+
26
+ it 'has a default permission', ->
27
+ expect(subject.permission).toEqual "default"
28
+
29
+ it 'does not have deviceToken', ->
30
+ expect(subject.deviceToken).toBeNull()
31
+
32
+ describe 'isGranted', ->
33
+ beforeEach ->
34
+ subject = new NotificationPermission()
35
+
36
+ it 'is granted if the permission is "granted"', ->
37
+ subject.permission = 'granted'
38
+
39
+ expect(subject.isGranted()).toBe(true)
40
+
41
+ it 'is not granted if the permission is "default"', ->
42
+ subject.permission = 'default'
43
+
44
+ expect(subject.isGranted()).toBe(false)
45
+
46
+ it 'is not granted if the permission is "denied"', ->
47
+ subject.permission = 'denied'
48
+
49
+ expect(subject.isGranted()).toBe(false)
@@ -0,0 +1,39 @@
1
+ require 'test_helper'
2
+
3
+ describe 'APNS routes Integration Test' do
4
+ it 'routes the push package creation' do
5
+ assert_regonize_route 'post', '/apns/v1/pushPackages/web.com.example.push.id',
6
+ controller: 'crusade_rails/apns/v1/push_package',
7
+ action: 'create'
8
+ end
9
+
10
+ it 'routes the push notification subscription' do
11
+ assert_regonize_route 'post', '/apns/v1/devices/1234a/registrations/web.com.example.push.id',
12
+ controller: 'crusade_rails/apns/v1/subscription',
13
+ action: 'create'
14
+ end
15
+
16
+ it 'routes the push notification unsubscription' do
17
+ assert_regonize_route 'delete', '/apns/v1/devices/1234a/registrations/web.com.example.push.id',
18
+ controller: 'crusade_rails/apns/v1/subscription',
19
+ action: 'delete'
20
+ end
21
+
22
+ it 'routes the logs' do
23
+ assert_regonize_route 'post', '/apns/v1/log',
24
+ controller: 'crusade_rails/apns/v1/log', action: 'create'
25
+ end
26
+
27
+
28
+ def engine_routes
29
+ CrusadeRails::Engine.routes
30
+ end
31
+
32
+ def assert_regonize_route(method, path, controller)
33
+ recognize = engine_routes.recognize_path path, method: method
34
+ recognize.wont_be_nil "#{method} #{path} is not recognized"
35
+
36
+ controller[:controller].must_equal recognize[:controller]
37
+ controller[:action].must_equal recognize[:action]
38
+ end
39
+ end
@@ -0,0 +1,69 @@
1
+ require 'test_helper'
2
+
3
+ describe CrusadeRails::NotificationService do
4
+ let(:fake_push_notification) { FakePushNotification.new }
5
+
6
+ subject { CrusadeRails::NotificationService.new fake_push_notification }
7
+
8
+ describe 'default constructor' do
9
+ it 'sets a crusade apns push notification' do
10
+ service = CrusadeRails::NotificationService.new
11
+
12
+ service.push_notification.is_a?(Crusade::APNS::PushNotification).must_be_true
13
+ end
14
+
15
+ it 'sets correctly the configuration' do
16
+ service = CrusadeRails::NotificationService.new
17
+
18
+ service.push_notification.configuration.must_be_same_as Rails.application.config.crusade
19
+ end
20
+ end
21
+
22
+ describe 'send_notification' do
23
+ let(:attr) { { title: 'the title', body: 'the body' } }
24
+ let(:user_id) { 1234 }
25
+
26
+ let(:subscription) { CrusadeRails::UserSubscription.new(user_id: 1234, device_token: 'aaaa', active: true) }
27
+
28
+ before do
29
+ CrusadeRails::UserSubscription.stubs(:where).returns([])
30
+ CrusadeRails::UserSubscription.stubs(:where).with(user_id: user_id).returns([subscription])
31
+ end
32
+
33
+ describe 'notification active' do
34
+ before { subject.send_notification user_id, attr }
35
+ let(:last_sent) { fake_push_notification.last_notification }
36
+
37
+ it 'sends a push notification' do
38
+ fake_push_notification.sent?.must_be_true
39
+ end
40
+
41
+ it 'converts the push notification' do
42
+ last_sent.title.must_equal 'the title'
43
+ last_sent.body.must_equal 'the body'
44
+ end
45
+
46
+ it 'sents to the correct device' do
47
+ last_sent.device_token.must_equal 'aaaa'
48
+ end
49
+ end
50
+
51
+ describe 'no notification for the user' do
52
+ it 'does not send any notification' do
53
+ subject.send_notification 'unknown', attr
54
+
55
+ fake_push_notification.sent?.must_be_false
56
+ end
57
+ end
58
+
59
+ describe 'notification inactive' do
60
+ before { subscription.active = false }
61
+
62
+ it 'does not send any notification' do
63
+ subject.send_notification user_id, attr
64
+
65
+ fake_push_notification.sent?.must_be_false
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,104 @@
1
+ require 'test_helper'
2
+
3
+ describe CrusadeRails::UserSubscriptionService do
4
+ before { CrusadeRails::UserSubscription.delete_all }
5
+ after { CrusadeRails::UserSubscription.delete_all }
6
+
7
+ let(:user_id) { 123 }
8
+
9
+ describe 'register' do
10
+ subject { CrusadeRails::UserSubscriptionService.new }
11
+
12
+ let(:registration) { subject.register user_id, user_token }
13
+ let(:user_token) { '1234a' }
14
+ let(:subscription) { CrusadeRails::UserSubscription.where(user_id: user_id).first }
15
+
16
+ before { registration }
17
+
18
+ it 'registers the user id' do
19
+ subscription.user_id.must_equal user_id
20
+ end
21
+
22
+ it 'registers the user token' do
23
+ subscription.user_token.must_equal user_token
24
+ end
25
+
26
+ it 'creates a subscription entry' do
27
+ subscription.wont_be_nil
28
+ end
29
+
30
+ it 'does no contains a device token' do
31
+ subscription.device_token.must_be_nil
32
+ end
33
+
34
+ it 'is not activated' do
35
+ subscription.active?.must_be_false
36
+ end
37
+
38
+ it 'returns true when the registration is successfull' do
39
+ registration.must_be_true
40
+ end
41
+ end
42
+
43
+ describe 'subscribe' do
44
+ let(:user_token) { '1234' }
45
+ let(:device_token) { 'abcd' }
46
+
47
+ subject { CrusadeRails::UserSubscriptionService.new}
48
+
49
+ describe 'no previous subscription' do
50
+ before do
51
+ CrusadeRails::UserSubscription.new(user_id: user_id, user_token: user_token).save!
52
+
53
+ subject.subscribe user_token, device_token
54
+ end
55
+
56
+ let(:subscription) { CrusadeRails::UserSubscription.where(user_id: user_id).first }
57
+
58
+ it 'sets the device token' do
59
+ subscription.device_token.must_equal device_token
60
+ end
61
+
62
+ it 'activates the subscription' do
63
+ subscription.active?.must_be_true
64
+ end
65
+
66
+ it { subject.subscribe(user_token, device_token).must_be_true }
67
+ end
68
+
69
+ describe 'previous subscription' do
70
+ end
71
+
72
+ describe 'subscription not found' do
73
+ end
74
+ end
75
+
76
+ describe 'unsubscribe' do
77
+ let(:user_token) { '1234' }
78
+ let(:device_token) { 'abcd' }
79
+
80
+ subject { CrusadeRails::UserSubscriptionService.new}
81
+
82
+ describe 'no previous subscription' do
83
+ before do
84
+ CrusadeRails::UserSubscription.new(user_id: user_id, user_token: user_token, active: true).save!
85
+
86
+ subject.unsubscribe user_token, device_token
87
+ end
88
+
89
+ let(:subscription) { CrusadeRails::UserSubscription.where(user_id: user_id).first }
90
+
91
+ it 'unactivate the subscription' do
92
+ subscription.active?.must_be_false
93
+ end
94
+
95
+ it { subject.unsubscribe(user_token, device_token).must_be_true }
96
+ end
97
+
98
+ describe 'previous subscription' do
99
+ end
100
+
101
+ describe 'subscription not found' do
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,24 @@
1
+
2
+ class FakePushNotification
3
+ attr_reader :sent, :configuration
4
+
5
+ def initialize
6
+ reset
7
+ end
8
+
9
+ def send notification
10
+ @sent << notification
11
+ end
12
+
13
+ def reset
14
+ @sent = []
15
+ end
16
+
17
+ def sent?
18
+ @sent.size > 0
19
+ end
20
+
21
+ def last_notification
22
+ @sent.last
23
+ end
24
+ end
@@ -0,0 +1,33 @@
1
+ # This file allows you to override various Teaspoon configuration directives when running from the command line. It is not
2
+ # required from within the Rails environment, so overriding directives that have been defined within the initializer
3
+ # is not possible.
4
+ #
5
+ # Set RAILS_ROOT and load the environment.
6
+ ENV["RAILS_ROOT"] = File.expand_path("../../", __FILE__)
7
+ require File.expand_path("../../test/dummy/config/environment", __FILE__)
8
+
9
+ # Provide default configuration.
10
+ #
11
+ # You can override various configuration directives defined here by using arguments with the teaspoon command.
12
+ #
13
+ # teaspoon --driver=selenium --suppress-log
14
+ # rake teaspoon DRIVER=selenium SUPPRESS_LOG=false
15
+ Teaspoon.setup do |config|
16
+ # Driver / Server
17
+ #config.driver = "phantomjs" # available: phantomjs, selenium
18
+ #config.server = nil # defaults to Rack::Server
19
+
20
+ # Behaviors
21
+ #config.server_timeout = 20 # timeout for starting the server
22
+ #config.server_port = nil # defaults to any open port unless specified
23
+ #config.fail_fast = true # abort after the first failing suite
24
+
25
+ # Output
26
+ #config.formatters = "dot" # available: dot, tap, tap_y, swayze_or_oprah
27
+ #config.suppress_log = false # suppress logs coming from console[log/error/debug]
28
+ #config.color = true
29
+
30
+ # Coverage (requires istanbul -- https://github.com/gotwarlost/istanbul)
31
+ #config.coverage = true
32
+ #config.coverage_reports = "text,html,cobertura"
33
+ end
@@ -0,0 +1,27 @@
1
+ # Configure Rails Environment
2
+ ENV["RAILS_ENV"] = "test"
3
+
4
+ require File.expand_path("../dummy/config/environment.rb", __FILE__)
5
+
6
+ require "rails/test_help"
7
+ require "minitest/spec"
8
+ require "minitest/rails"
9
+ require "minitest/mock"
10
+ require "minitest/great_expectations"
11
+
12
+ require "mocha"
13
+
14
+ module ActiveRecord::TestFixtures
15
+ def before_setup
16
+ super
17
+ end
18
+
19
+ def after_teardown
20
+ super
21
+ end
22
+ end
23
+
24
+ Rails.backtrace_cleaner.remove_silencers!
25
+
26
+ # Load support files
27
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }