user_device_spec.rb 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. require 'rails_helper'
  2. RSpec.describe UserDevice, type: :model do
  3. describe '.add' do
  4. let(:existing_record) { described_class.add(user_agent, ip, agent.id, fingerprint, type) }
  5. let(:ip) { '91.115.248.231' }
  6. let(:agent) { create(:agent_user) }
  7. context 'with existing record of type: "session"' do
  8. before { existing_record } # create existing record
  9. let(:user_agent) { 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36' }
  10. let(:fingerprint) { 'fingerprint1234' }
  11. let(:type) { 'session' }
  12. context 'when called with same parameters as existing record' do
  13. it 'returns the original record' do
  14. expect(described_class.add(user_agent, ip, agent.id, fingerprint, type))
  15. .to eq(existing_record)
  16. end
  17. end
  18. context 'when called with different IP from existing record' do
  19. let(:other_ip) { '176.198.137.254' }
  20. it 'returns a new record' do
  21. expect(described_class.add(user_agent, other_ip, agent.id, fingerprint, type))
  22. .to be_a(described_class)
  23. .and not_eq(existing_record)
  24. end
  25. end
  26. context 'when called with invalid IP, not matching existing record' do
  27. let(:other_ip) { 'foo' }
  28. it 'returns a new record' do
  29. expect(described_class.add(user_agent, other_ip, agent.id, fingerprint, type))
  30. .to be_a(described_class)
  31. .and not_eq(existing_record)
  32. end
  33. end
  34. context 'when called with different fingerprint from existing record' do
  35. let(:other_fingerprint) { 'fingerprintABCD' }
  36. it 'returns a new record' do
  37. expect(described_class.add(user_agent, ip, agent.id, other_fingerprint, type))
  38. .to be_a(described_class)
  39. .and not_eq(existing_record)
  40. end
  41. end
  42. context 'with recognized user_agent (Mac/Chrome)' do
  43. it 'assigns #user_agent attribute to given value' do
  44. expect(existing_record.user_agent).to eq(user_agent)
  45. end
  46. it 'derives #name attribute from given value' do
  47. expect(existing_record.name).to eq('Mac, Chrome')
  48. end
  49. it 'derives #browser attribute from given value' do
  50. expect(existing_record.browser).to eq('Chrome')
  51. end
  52. end
  53. context 'with recognized user_agent (iOS/Safari)' do
  54. let(:user_agent) { 'Mozilla/5.0 (iPhone; CPU iPhone OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H143 Safari/600.1.4' }
  55. it 'assigns #user_agent attribute to given value' do
  56. expect(existing_record.user_agent).to eq(user_agent)
  57. end
  58. it 'derives #name attribute from given value' do
  59. expect(existing_record.name).to eq('Ios, Safari')
  60. end
  61. it 'derives #browser attribute from given value' do
  62. expect(existing_record.browser).to eq('Safari')
  63. end
  64. end
  65. context 'with partially recognized user_agent (Mac/CalendarAgent)' do
  66. let(:user_agent) { 'Mac+OS+X/10.10.5 (14F27) CalendarAgent/316.1' }
  67. it 'assigns #user_agent and #browser attributes to given value' do
  68. expect([existing_record.user_agent, existing_record.browser])
  69. .to all(eq(user_agent))
  70. end
  71. it 'derives #name attribute from given value' do
  72. expect(existing_record.name).to eq("Mac, #{user_agent}")
  73. end
  74. end
  75. context 'with unrecognized user_agent' do
  76. let(:user_agent) { 'foo' }
  77. it 'assigns #user_agent, #name, and #browser attributes to given value' do
  78. expect([existing_record.user_agent, existing_record.name, existing_record.browser])
  79. .to all(eq(user_agent))
  80. end
  81. end
  82. end
  83. context 'with existing record of type: "basic_auth"' do
  84. before { existing_record } # create existing record
  85. let(:user_agent) { 'curl/7.43.0' }
  86. let(:fingerprint) { nil }
  87. let(:type) { 'basic_auth' }
  88. context 'when called with same parameters as existing record' do
  89. it 'returns the original record' do
  90. expect(described_class.add(user_agent, ip, agent.id, fingerprint, type))
  91. .to eq(existing_record)
  92. end
  93. end
  94. context 'when called with different IP from existing record' do
  95. let(:other_ip) { '176.198.137.254' }
  96. it 'returns a new record' do
  97. expect(described_class.add(user_agent, other_ip, agent.id, fingerprint, type))
  98. .to be_a(described_class)
  99. .and not_eq(existing_record)
  100. end
  101. end
  102. context 'when called with different type from existing record ("token_auth")' do
  103. let(:other_type) { 'token_auth' }
  104. it 'returns the original record' do
  105. expect(described_class.add(user_agent, ip, agent.id, fingerprint, other_type))
  106. .to eq(existing_record)
  107. end
  108. end
  109. context 'when called without existing record’s user agent' do
  110. let(:other_user_agent) { '' }
  111. it 'returns a new record' do
  112. expect(described_class.add(other_user_agent, ip, agent.id, fingerprint, type))
  113. .to be_a(described_class)
  114. .and not_eq(existing_record)
  115. end
  116. end
  117. context 'when existing record’s user agent is blank, and given is nil' do
  118. let(:user_agent) { '' }
  119. let(:other_user_agent) { nil }
  120. it 'returns the original record' do
  121. expect(described_class.add(other_user_agent, ip, agent.id, fingerprint, type))
  122. .to eq(existing_record)
  123. end
  124. end
  125. context 'when existing record and given args have nil user agent, but IPs don’t match' do
  126. let(:user_agent) { nil }
  127. let(:other_ip) { '176.198.137.254' }
  128. it 'returns a new record' do
  129. expect(described_class.add(user_agent, other_ip, agent.id, fingerprint, type))
  130. .to be_a(described_class)
  131. .and not_eq(existing_record)
  132. end
  133. end
  134. end
  135. context 'with exceedingly long fingerprint (161+ chars)' do
  136. let(:user_agent) { 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36' }
  137. let(:fingerprint) { 'x' * 161 }
  138. let(:type) { 'session' }
  139. it 'raises an error' do
  140. expect { described_class.add(user_agent, ip, agent.id, fingerprint, type) }
  141. .to raise_error(Exceptions::UnprocessableEntity)
  142. end
  143. end
  144. end
  145. describe '.action' do
  146. let(:user_device) { described_class.add(user_agent, ip, agent.id, fingerprint, type) }
  147. let(:user_agent) { 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36' }
  148. let(:ip) { '91.115.248.231' }
  149. let(:agent) { create(:agent_user) }
  150. let(:fingerprint) { 'fingerprint1234' }
  151. let(:type) { 'session' }
  152. context 'when called with parameters matching given user_device' do
  153. it 'returns the given user_device' do
  154. expect(described_class.action(user_device.id, user_agent, ip, agent.id, type))
  155. .to eq(user_device)
  156. end
  157. end
  158. context 'when called with different IP from given user_device' do
  159. let(:other_ip) { '176.198.137.254' }
  160. it 'returns a new user_device' do
  161. expect(described_class.action(user_device.id, user_agent, other_ip, agent.id, type))
  162. .to be_a(described_class)
  163. .and not_eq(user_device)
  164. end
  165. end
  166. context 'when called with invalid IP, not matching given user_device' do
  167. let(:other_ip) { 'foo' }
  168. it 'returns the given user_device' do
  169. expect(described_class.action(user_device.id, user_agent, other_ip, agent.id, type))
  170. .to eq(user_device)
  171. end
  172. it 'sets user_device.ip to the given (invalid) IP' do
  173. expect { described_class.action(user_device.id, user_agent, other_ip, agent.id, type) }
  174. .to change { user_device.reload.ip }.to(other_ip)
  175. end
  176. end
  177. end
  178. describe '#notification_send' do
  179. let(:user_device) { described_class.add(user_agent, ip, agent.id, fingerprint, type) }
  180. let(:user_agent) { 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36' }
  181. let(:ip) { '91.115.248.231' }
  182. let(:fingerprint) { 'fingerprint1234' }
  183. let(:type) { 'session' }
  184. context 'user with email address' do
  185. let(:agent) { create(:agent_user, email: 'somebody@example.com') }
  186. it 'returns true' do
  187. expect(user_device.notification_send('user_device_new_location'))
  188. .to eq(true)
  189. end
  190. end
  191. context 'user without email address' do
  192. let(:agent) { create(:agent_user, email: '') }
  193. it 'returns false' do
  194. expect(user_device.notification_send('user_device_new_location'))
  195. .to eq(false)
  196. end
  197. end
  198. end
  199. end