device_detector 1.0.1 → 1.0.2

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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -5
  3. data/CHANGELOG.md +3 -1
  4. data/README.md +5 -5
  5. data/Rakefile +16 -12
  6. data/lib/device_detector.rb +15 -0
  7. data/lib/device_detector/memory_cache.rb +21 -14
  8. data/lib/device_detector/os.rb +6 -3
  9. data/lib/device_detector/version.rb +3 -1
  10. data/regexes/bots.yml +73 -7
  11. data/regexes/client/browsers.yml +80 -2
  12. data/regexes/client/feed_readers.yml +7 -7
  13. data/regexes/client/libraries.yml +13 -1
  14. data/regexes/client/mediaplayers.yml +9 -5
  15. data/regexes/client/mobile_apps.yml +21 -0
  16. data/regexes/device/mobiles.yml +5616 -402
  17. data/regexes/device/televisions.yml +1 -1
  18. data/regexes/oss.yml +71 -13
  19. data/spec/device_detector/memory_cache_spec.rb +51 -19
  20. data/spec/device_detector_spec.rb +26 -55
  21. data/spec/fixtures/client/browser.yml +221 -96
  22. data/spec/fixtures/client/feed_reader.yml +0 -6
  23. data/spec/fixtures/client/library.yml +25 -1
  24. data/spec/fixtures/client/mediaplayer.yml +0 -12
  25. data/spec/fixtures/client/mobile_app.yml +24 -0
  26. data/spec/fixtures/detector/bots.yml +168 -3
  27. data/spec/fixtures/detector/desktop.yml +1422 -1422
  28. data/spec/fixtures/detector/feature_phone.yml +21 -1
  29. data/spec/fixtures/detector/feed_reader.yml +18 -5
  30. data/spec/fixtures/detector/mediaplayer.yml +33 -3
  31. data/spec/fixtures/detector/mobile_apps.yml +55 -6
  32. data/spec/fixtures/detector/phablet.yml +924 -164
  33. data/spec/fixtures/detector/smartphone-1.yml +4654 -4655
  34. data/spec/fixtures/detector/smartphone-10.yml +12362 -0
  35. data/spec/fixtures/detector/smartphone-11.yml +7639 -0
  36. data/spec/fixtures/detector/smartphone-2.yml +4232 -4247
  37. data/spec/fixtures/detector/smartphone-3.yml +4348 -4237
  38. data/spec/fixtures/detector/smartphone-4.yml +4110 -4103
  39. data/spec/fixtures/detector/smartphone-5.yml +5651 -2716
  40. data/spec/fixtures/detector/smartphone-6.yml +9896 -0
  41. data/spec/fixtures/detector/smartphone-7.yml +9899 -0
  42. data/spec/fixtures/detector/smartphone-8.yml +9945 -0
  43. data/spec/fixtures/detector/smartphone-9.yml +9916 -0
  44. data/spec/fixtures/detector/smartphone.yml +4114 -4013
  45. data/spec/fixtures/detector/tablet-1.yml +3857 -3857
  46. data/spec/fixtures/detector/tablet-2.yml +6681 -1787
  47. data/spec/fixtures/detector/tablet-3.yml +5134 -0
  48. data/spec/fixtures/detector/tablet.yml +3383 -3406
  49. data/spec/fixtures/detector/tv.yml +338 -24
  50. data/spec/fixtures/detector/unknown.yml +0 -120
  51. data/spec/fixtures/parser/oss.yml +135 -0
  52. metadata +17 -3
@@ -293,4 +293,4 @@ Videoweb:
293
293
  - regex: '(tv2n)'
294
294
  model: '$1'
295
295
  - regex: '(videowebtv)'
296
- model: 'VideoWeb TV'
296
+ model: 'VideoWeb TV'
@@ -65,6 +65,13 @@
65
65
  name: 'Windows IoT'
66
66
  version: '10'
67
67
 
68
+ ##########
69
+ # KaiOS
70
+ ##########
71
+ - regex: 'KAIOS(?:/(\d+[\.\d]+))?'
72
+ name: 'KaiOS'
73
+ version: '$1'
74
+
68
75
  ##########
69
76
  # Custom Android Roms
70
77
  ##########
@@ -84,10 +91,14 @@
84
91
  name: 'MocorDroid'
85
92
  version: '$1'
86
93
 
94
+ - regex: 'Fire OS(?:/(\d+[\.\d]*))?'
95
+ name: 'Fire OS'
96
+ version: '$1'
97
+
87
98
  ##########
88
99
  # Android
89
100
  ##########
90
- - regex: '(?:(?:Orca-)?Android|Adr)[ /](?:[a-z]+ )?(\d+[\.\d]+)'
101
+ - regex: '(?:(?:Orca-)?Android|Adr)[ /](?:[a-z]+ )?(\d+[\.\d]*)'
91
102
  name: 'Android'
92
103
  version: '$1'
93
104
 
@@ -96,6 +107,10 @@
96
107
  name: 'Android'
97
108
  version: ''
98
109
 
110
+ - regex: '(?:TwitterAndroid).*[ /](?:[a-z]+ )?(\d+[\.\d]*)'
111
+ name: 'Android'
112
+ version: '$1'
113
+
99
114
  - regex: 'BeyondPod|AntennaPod|Podkicker|DoggCatcher|Player FM|okhttp|Podcatcher Deluxe'
100
115
  name: 'Android'
101
116
  version: ''
@@ -249,12 +264,59 @@
249
264
  - regex: 'Windows'
250
265
  name: 'Windows'
251
266
  version: ''
252
-
253
-
267
+
268
+
269
+ ##########
270
+ # Haiku OS
271
+ ##########
272
+ - regex: 'Haiku'
273
+ name: 'Haiku OS'
274
+ version: ''
275
+
254
276
 
255
277
  ##########
256
278
  # iOS
257
279
  ##########
280
+ - regex: 'CFNetwork/889'
281
+ name: 'iOS'
282
+ version: '11.1'
283
+
284
+ - regex: 'CFNetwork/887.*(x86_64)'
285
+ name: 'Mac'
286
+ version: '10.13'
287
+
288
+ - regex: 'CFNetwork/887'
289
+ name: 'iOS'
290
+ version: '11.0'
291
+
292
+ - regex: 'CFNetwork/811.*(x86_64)'
293
+ name: 'Mac'
294
+ version: '10.12'
295
+
296
+ - regex: 'CFNetwork/811'
297
+ name: 'iOS'
298
+ version: '10.3'
299
+
300
+ - regex: 'CFNetwork/808\.3'
301
+ name: 'iOS'
302
+ version: '10.3'
303
+
304
+ - regex: 'CFNetwork/808\.2'
305
+ name: 'iOS'
306
+ version: '10.2'
307
+
308
+ - regex: 'CFNetwork/808\.1'
309
+ name: 'iOS'
310
+ version: '10.1'
311
+
312
+ - regex: 'CFNetwork/808\.0'
313
+ name: 'iOS'
314
+ version: '10.0'
315
+
316
+ - regex: 'CFNetwork/808'
317
+ name: 'iOS'
318
+ version: '10'
319
+
258
320
  - regex: 'CFNetwork/758\.4\.3'
259
321
  name: 'iOS'
260
322
  version: '9.3.2'
@@ -355,7 +417,7 @@
355
417
  name: 'iOS'
356
418
  version: '$1'
357
419
 
358
- - regex: 'Podcasts/(?:[\d\.]+)|Instacast(?:HD)?/(?:\d\.[\d\.abc]+)|Pocket Casts, iOS|Overcast|Castro|Podcat|i[cC]atcher'
420
+ - regex: 'Podcasts/(?:[\d\.]+)|Instacast(?:HD)?/(?:\d\.[\d\.abc]+)|Pocket Casts, iOS|Overcast|Castro|Podcat|i[cC]atcher|RSSRadio/'
359
421
  name: 'iOS'
360
422
  version: ''
361
423
 
@@ -368,6 +430,10 @@
368
430
  # Mac
369
431
  ##########
370
432
 
433
+ - regex: 'CFNetwork/807'
434
+ name: 'Mac'
435
+ version: '10.12'
436
+
371
437
  - regex: 'CFNetwork/760'
372
438
  name: 'Mac'
373
439
  version: '10.11'
@@ -408,7 +474,7 @@
408
474
  name: 'Mac'
409
475
  version: '10.2'
410
476
 
411
- - regex: 'Mac OS X(?: (?:Version )?(\d+(?:[_\.]\d+)+))?'
477
+ - regex: 'Mac[ +]OS[ +]X(?:[ /](?:Version )?(\d+(?:[_\.]\d+)+))?'
412
478
  name: 'Mac'
413
479
  version: '$1'
414
480
 
@@ -458,14 +524,6 @@
458
524
  version: ''
459
525
 
460
526
 
461
- ##########
462
- # Haiku OS
463
- ##########
464
- - regex: 'Haiku'
465
- name: 'Haiku OS'
466
- version: ''
467
-
468
-
469
527
  ##########
470
528
  # BeOS
471
529
  ##########
@@ -1,15 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../spec_helper'
2
4
 
3
5
  describe DeviceDetector::MemoryCache do
4
-
5
6
  let(:subject) { DeviceDetector::MemoryCache.new(config) }
6
7
 
7
8
  let(:config) { {} }
8
9
 
9
10
  describe '#set' do
10
-
11
11
  describe 'string key' do
12
-
13
12
  let(:key) { 'string' }
14
13
 
15
14
  it 'sets the value under the key' do
@@ -18,26 +17,63 @@ describe DeviceDetector::MemoryCache do
18
17
  subject.data[key].must_equal 'value'
19
18
  end
20
19
 
20
+ it 'returns the value' do
21
+ subject.set(key, 'value').must_equal 'value'
22
+ subject.set(key, false).must_equal false
23
+ assert_nil subject.set(key, nil)
24
+ end
21
25
  end
22
26
 
23
27
  describe 'array key' do
24
-
25
- let(:key) { ['string1', 'string2'] }
28
+ let(:key) { %w[string1 string2] }
26
29
 
27
30
  it 'sets the value under the key' do
28
31
  subject.set(key, 'value')
29
32
 
30
33
  subject.data[String(key)].must_equal 'value'
31
34
  end
35
+ end
36
+
37
+ describe 'nil value' do
38
+ let(:key) { 'string' }
39
+ let(:internal_value) { DeviceDetector::MemoryCache::STORES_NIL_VALUE }
40
+
41
+ it 'sets the value under the key' do
42
+ subject.set(key, nil)
32
43
 
44
+ subject.data[String(key)].must_equal internal_value
45
+ assert_nil subject.get(key)
46
+ end
47
+
48
+ it 'sets the value under the key' do
49
+ subject.get_or_set(key, nil)
50
+
51
+ subject.data[String(key)].must_equal internal_value
52
+ assert_nil subject.get(key)
53
+ end
33
54
  end
34
55
 
56
+ describe 'false value' do
57
+ let(:key) { 'string' }
58
+
59
+ it 'sets the value under the key' do
60
+ subject.set(key, false)
61
+
62
+ subject.data[String(key)].must_equal false
63
+ subject.get(key).must_equal false
64
+ end
65
+
66
+ it 'sets the value under the key' do
67
+ subject.get_or_set(key, false)
68
+
69
+ subject.data[String(key)].must_equal false
70
+ subject.get(key).must_equal false
71
+ end
72
+ end
35
73
  end
36
74
 
37
75
  describe '#get' do
38
-
39
76
  describe 'string key' do
40
-
41
77
  let(:key) { 'string' }
42
78
 
43
79
  it 'gets the value for the key' do
@@ -45,29 +81,23 @@ describe DeviceDetector::MemoryCache do
45
81
 
46
82
  subject.get(key).must_equal 'value'
47
83
  end
48
-
49
84
  end
50
85
 
51
86
  describe 'array key' do
52
-
53
- let(:key) { ['string1', 'string2'] }
87
+ let(:key) { %w[string1 string2] }
54
88
 
55
89
  it 'gets the value for the key' do
56
90
  subject.data[String(key)] = 'value'
57
91
 
58
92
  subject.get(key).must_equal 'value'
59
93
  end
60
-
61
94
  end
62
-
63
95
  end
64
96
 
65
97
  describe '#get_or_set' do
66
-
67
98
  let(:key) { 'string' }
68
99
 
69
100
  describe 'value already present' do
70
-
71
101
  it 'gets the value for the key from cache' do
72
102
  subject.data[key] = 'value'
73
103
 
@@ -80,10 +110,13 @@ describe DeviceDetector::MemoryCache do
80
110
  block_called.must_equal false
81
111
  end
82
112
 
113
+ it 'returns the value' do
114
+ subject.data[key] = 'value2'
115
+ subject.get_or_set(key, 'value').must_equal 'value2'
116
+ end
83
117
  end
84
118
 
85
119
  describe 'value not yet present' do
86
-
87
120
  it 'evaluates the block and sets the result' do
88
121
  block_called = false
89
122
  subject.get_or_set(key) do
@@ -94,12 +127,13 @@ describe DeviceDetector::MemoryCache do
94
127
  subject.data[key].must_equal true
95
128
  end
96
129
 
130
+ it 'returns the value' do
131
+ subject.get_or_set(key, 'value').must_equal 'value'
132
+ end
97
133
  end
98
-
99
134
  end
100
135
 
101
136
  describe 'cache purging' do
102
-
103
137
  let(:config) { { max_cache_keys: 3 } }
104
138
 
105
139
  it 'purges the cache when key size arrives at max' do
@@ -110,7 +144,5 @@ describe DeviceDetector::MemoryCache do
110
144
 
111
145
  subject.data.keys.size.must_equal 3
112
146
  end
113
-
114
147
  end
115
-
116
148
  end
@@ -1,218 +1,189 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'spec_helper'
2
4
 
3
5
  describe DeviceDetector do
4
-
5
6
  subject { DeviceDetector.new(user_agent) }
6
7
 
7
- alias :client :subject
8
+ alias_method :client, :subject
8
9
 
9
10
  describe 'known user agent' do
10
-
11
11
  describe 'desktop chrome browser' do
12
-
13
12
  let(:user_agent) { 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.69' }
14
13
 
15
14
  describe '#name' do
16
-
17
15
  it 'returns the name' do
18
16
  client.name.must_equal 'Chrome'
19
17
  end
20
-
21
18
  end
22
19
 
23
20
  describe '#full_version' do
24
-
25
21
  it 'returns the full version' do
26
22
  client.full_version.must_equal '30.0.1599.69'
27
23
  end
24
+ end
28
25
 
26
+ describe '#os_family' do
27
+ it 'returns the operating system name' do
28
+ client.os_family.must_equal 'Mac'
29
+ end
29
30
  end
30
31
 
31
32
  describe '#os_name' do
32
-
33
33
  it 'returns the operating system name' do
34
34
  client.os_name.must_equal 'Mac'
35
35
  end
36
-
37
36
  end
38
37
 
39
38
  describe '#os_full_version' do
40
-
41
39
  it 'returns the operating system full version' do
42
40
  client.os_full_version.must_equal '10.8.5'
43
41
  end
44
-
45
42
  end
46
43
 
47
44
  describe '#known?' do
48
-
49
45
  it 'returns true' do
50
46
  client.known?.must_equal true
51
47
  end
52
-
53
48
  end
54
49
 
55
50
  describe '#bot?' do
56
-
57
51
  it 'returns false' do
58
52
  client.bot?.must_equal false
59
53
  end
60
-
61
54
  end
62
55
 
63
56
  describe '#bot_name' do
64
-
65
57
  it 'returns nil' do
66
58
  client.bot_name.must_be_nil
67
59
  end
60
+ end
61
+ end
68
62
 
63
+ describe 'ubuntu linux' do
64
+ let(:user_agent) do
65
+ 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36'
66
+ end
67
+
68
+ describe '#os_family' do
69
+ it 'returns the operating system name' do
70
+ client.os_family.must_equal 'GNU/Linux'
71
+ end
69
72
  end
70
73
 
74
+ describe '#os_name' do
75
+ it 'returns the operating system name' do
76
+ client.os_name.must_equal 'Ubuntu'
77
+ end
78
+ end
71
79
  end
72
80
 
73
81
  describe 'firefox mobile phone' do
74
-
75
- let(:user_agent) {'Mozilla/5.0 (Android 7.0; Mobile; rv:53.0) Gecko/53.0 Firefox/53.0'}
82
+ let(:user_agent) { 'Mozilla/5.0 (Android 7.0; Mobile; rv:53.0) Gecko/53.0 Firefox/53.0' }
76
83
 
77
84
  it 'detects smartphone' do
78
85
  client.device_type.must_equal 'smartphone'
79
86
  end
80
-
81
87
  end
82
88
 
83
89
  describe 'firefox mobile tablet' do
84
-
85
- let(:user_agent) {'Mozilla/5.0 (Android 6.0.1; Tablet; rv:47.0) Gecko/47.0 Firefox/47.0'}
90
+ let(:user_agent) { 'Mozilla/5.0 (Android 6.0.1; Tablet; rv:47.0) Gecko/47.0 Firefox/47.0' }
86
91
 
87
92
  it 'detects tablet' do
88
93
  client.device_type.must_equal 'tablet'
89
94
  end
90
-
91
95
  end
92
-
93
96
  end
94
97
 
95
98
  describe 'unknown user agent' do
96
-
97
99
  let(:user_agent) { 'garbage123' }
98
100
 
99
101
  describe '#name' do
100
-
101
102
  it 'returns nil' do
102
103
  client.name.must_be_nil
103
104
  end
104
-
105
105
  end
106
106
 
107
107
  describe '#full_version' do
108
-
109
108
  it 'returns nil' do
110
109
  client.full_version.must_be_nil
111
110
  end
112
-
113
111
  end
114
112
 
115
113
  describe '#os_name' do
116
-
117
114
  it 'returns nil' do
118
115
  client.os_name.must_be_nil
119
116
  end
120
-
121
117
  end
122
118
 
123
119
  describe '#os_full_version' do
124
-
125
120
  it 'returns nil' do
126
121
  client.os_full_version.must_be_nil
127
122
  end
128
-
129
123
  end
130
124
 
131
125
  describe '#known?' do
132
-
133
126
  it 'returns false' do
134
127
  client.known?.must_equal false
135
128
  end
136
-
137
129
  end
138
130
 
139
131
  describe '#bot?' do
140
-
141
132
  it 'returns false' do
142
133
  client.bot?.must_equal false
143
134
  end
144
-
145
135
  end
146
136
 
147
137
  describe '#bot_name' do
148
-
149
138
  it 'returns nil' do
150
139
  client.bot_name.must_be_nil
151
140
  end
152
-
153
141
  end
154
-
155
142
  end
156
143
 
157
144
  describe 'bot' do
158
-
159
145
  let(:user_agent) { 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)' }
160
146
 
161
147
  describe '#name' do
162
-
163
148
  it 'returns nil' do
164
149
  client.name.must_be_nil
165
150
  end
166
-
167
151
  end
168
152
 
169
153
  describe '#full_version' do
170
-
171
154
  it 'returns nil' do
172
155
  client.full_version.must_be_nil
173
156
  end
174
-
175
157
  end
176
158
 
177
159
  describe '#os_name' do
178
-
179
160
  it 'returns nil' do
180
161
  client.os_name.must_be_nil
181
162
  end
182
-
183
163
  end
184
164
 
185
165
  describe '#os_full_version' do
186
-
187
166
  it 'returns nil' do
188
167
  client.os_full_version.must_be_nil
189
168
  end
190
-
191
169
  end
192
170
 
193
171
  describe '#known?' do
194
-
195
172
  it 'returns false' do
196
173
  client.known?.must_equal false
197
174
  end
198
-
199
175
  end
200
176
 
201
177
  describe '#bot?' do
202
-
203
178
  it 'returns true' do
204
179
  client.bot?.must_equal true
205
180
  end
206
-
207
181
  end
208
182
 
209
183
  describe '#bot_name' do
210
-
211
184
  it 'returns the name of the bot' do
212
185
  client.bot_name.must_equal 'Googlebot'
213
186
  end
214
-
215
187
  end
216
-
217
188
  end
218
189
  end