ronin-web-user_agents 0.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,414 @@
1
+ require 'spec_helper'
2
+ require 'ronin/web/user_agents/firefox'
3
+
4
+ describe Ronin::Web::UserAgents::Firefox do
5
+ describe ".build" do
6
+ let(:firefox_version) { '91.3.0' }
7
+ let(:gecko_version) { described_class::DESKTOP_GECKO_VERSION }
8
+
9
+ context "when given `os: :windows`" do
10
+ let(:os) { :windows }
11
+
12
+ context "but os_version: is not given" do
13
+ it do
14
+ expect {
15
+ subject.build(firefox_version: firefox_version, os: os)
16
+ }.to raise_error(ArgumentError,"os: #{os.inspect} also requires an os_version: value")
17
+ end
18
+ end
19
+
20
+ Ronin::Web::UserAgents::OS::Windows::VERSIONS.each do |version_id,version_string|
21
+ context "when given `os_version: #{version_id.inspect}`" do
22
+ let(:os_version) { version_id }
23
+ let(:windows_version) { version_string }
24
+
25
+ it "must include 'Windows NT #{version_string}' in the extensions" do
26
+ expect(
27
+ subject.build(
28
+ firefox_version: firefox_version,
29
+ os: os,
30
+ os_version: os_version
31
+ )
32
+ ).to eq("Mozilla/5.0 (Windows NT #{windows_version}; rv:#{firefox_version}) Gecko/#{gecko_version} Firefox/#{firefox_version}")
33
+ end
34
+
35
+ Ronin::Web::UserAgents::OS::Windows::ARCHES.each do |arch_id,arch_string|
36
+
37
+ context "and when `arch: #{arch_id.inspect}` is given" do
38
+ let(:arch) { arch_id }
39
+ let(:windows_arch) { arch_string }
40
+
41
+ if arch_id
42
+ it "must appned '#{arch_string}' after the Windows version" do
43
+ expect(
44
+ subject.build(
45
+ firefox_version: firefox_version,
46
+ os: os,
47
+ os_version: os_version,
48
+ arch: arch
49
+ )
50
+ ).to eq("Mozilla/5.0 (Windows NT #{windows_version}; #{windows_arch}; rv:#{firefox_version}) Gecko/#{gecko_version} Firefox/#{firefox_version}")
51
+ end
52
+
53
+ context "and when given the `firefox_version:` keyword argument" do
54
+ let(:firefox_version) { '1.2.3' }
55
+
56
+ it "must use the specified `firefox_version:` value" do
57
+ expect(
58
+ subject.build(
59
+ firefox_version: firefox_version,
60
+ os: os,
61
+ os_version: os_version,
62
+ arch: arch
63
+ )
64
+ ).to eq("Mozilla/5.0 (Windows NT #{windows_version}; #{windows_arch}; rv:#{firefox_version}) Gecko/#{gecko_version} Firefox/#{firefox_version}")
65
+ end
66
+ end
67
+ else # `arch: nil` edge-case
68
+ it "must not appned any additional fields" do
69
+ expect(
70
+ subject.build(
71
+ firefox_version: firefox_version,
72
+ os: os,
73
+ os_version: os_version,
74
+ arch: arch
75
+ )
76
+ ).to eq("Mozilla/5.0 (Windows NT #{windows_version}; rv:#{firefox_version}) Gecko/#{gecko_version} Firefox/#{firefox_version}")
77
+ end
78
+
79
+ context "and when given the `firefox_version:` keyword argument" do
80
+ let(:firefox_version) { '1.2.3' }
81
+
82
+ it "must use the specified `firefox_version:` value" do
83
+ expect(
84
+ subject.build(
85
+ firefox_version: firefox_version,
86
+ os: os,
87
+ os_version: os_version,
88
+ arch: arch
89
+ )
90
+ ).to eq("Mozilla/5.0 (Windows NT #{windows_version}; rv:#{firefox_version}) Gecko/#{gecko_version} Firefox/#{firefox_version}")
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ context "and when given the `firefox_version:` keyword argument" do
98
+ let(:firefox_version) { '1.2.3' }
99
+
100
+ it "must use the specified `firefox_version:` value" do
101
+ expect(
102
+ subject.build(
103
+ firefox_version: firefox_version,
104
+ os: os,
105
+ os_version: os_version
106
+ )
107
+ ).to eq("Mozilla/5.0 (Windows NT #{windows_version}; rv:#{firefox_version}) Gecko/#{gecko_version} Firefox/#{firefox_version}")
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ context "when given `os: :macos`" do
115
+ let(:os) { :macos }
116
+
117
+ context "and when given the `os_version:` keyword argument" do
118
+ let(:os_version) { '12.0.0' }
119
+
120
+ it "must include 'Macintosh; Intel Mac OS X.X.Y.Z' in the extensions" do
121
+ expect(
122
+ subject.build(
123
+ firefox_version: firefox_version,
124
+ os: os,
125
+ os_version: os_version
126
+ )
127
+ ).to eq("Mozilla/5.0 (Macintosh; Intel Mac OS X #{os_version}; rv:#{firefox_version}) Gecko/#{gecko_version} Firefox/#{firefox_version}")
128
+ end
129
+
130
+ context "and when given the `firefox_version:` keyword argument" do
131
+ let(:firefox_version) { '1.2.3' }
132
+
133
+ it "must use the specified `firefox_version:` value" do
134
+ expect(
135
+ subject.build(
136
+ firefox_version: firefox_version,
137
+ os: os,
138
+ os_version: os_version
139
+ )
140
+ ).to eq("Mozilla/5.0 (Macintosh; Intel Mac OS X #{os_version}; rv:#{firefox_version}) Gecko/#{gecko_version} Firefox/#{firefox_version}")
141
+ end
142
+ end
143
+ end
144
+
145
+ context "but `os_version:` is not given" do
146
+ it do
147
+ expect {
148
+ subject.build(firefox_version: firefox_version, os: os)
149
+ }.to raise_error(ArgumentError,"os: #{os.inspect} also requires an os_version: value")
150
+ end
151
+ end
152
+ end
153
+
154
+ context "when given `os: :linux`" do
155
+ let(:os) { :linux }
156
+
157
+ it "must add 'X11; Linux; rv:...' to the extensions" do
158
+ expect(
159
+ subject.build(
160
+ firefox_version: firefox_version,
161
+ os: os
162
+ )
163
+ ).to eq("Mozilla/5.0 (X11; Linux; rv:#{firefox_version}) Gecko/#{gecko_version} Firefox/#{firefox_version}")
164
+ end
165
+
166
+ Ronin::Web::UserAgents::OS::Linux::ARCHES.each do |arch_id,arch_string|
167
+ context "when given `arch: #{arch_id.inspect}`" do
168
+ let(:arch) { arch_id }
169
+ let(:linux_arch) { arch_string }
170
+
171
+ it "must add 'Linux #{arch_string}' to the extensions" do
172
+ expect(
173
+ subject.build(
174
+ firefox_version: firefox_version,
175
+ os: os,
176
+ arch: arch
177
+ )
178
+ ).to eq("Mozilla/5.0 (X11; Linux #{linux_arch}; rv:#{firefox_version}) Gecko/#{gecko_version} Firefox/#{firefox_version}")
179
+ end
180
+
181
+ Ronin::Web::UserAgents::OS::Linux::DISTROS.each do |distro_id,distro_string|
182
+ context "and when given `linux_distro: #{distro_id.inspect}" do
183
+ if distro_id
184
+ let(:linux_distro) { distro_string }
185
+
186
+ it "must add the '; #{distro_string}' to the extensions" do
187
+ expect(
188
+ subject.build(
189
+ firefox_version: firefox_version,
190
+ os: os,
191
+ linux_distro: linux_distro,
192
+ arch: arch
193
+ )
194
+ ).to eq("Mozilla/5.0 (X11; #{linux_distro}; Linux #{linux_arch}; rv:#{firefox_version}) Gecko/#{gecko_version} Firefox/#{firefox_version}")
195
+ end
196
+ else # `linux_distro: nil` edge-case
197
+ it "must omit the Linux Distro from the extensions" do
198
+ expect(
199
+ subject.build(
200
+ firefox_version: firefox_version,
201
+ os: os,
202
+ arch: arch
203
+ )
204
+ ).to eq("Mozilla/5.0 (X11; Linux #{linux_arch}; rv:#{firefox_version}) Gecko/#{gecko_version} Firefox/#{firefox_version}")
205
+ end
206
+ end
207
+ end
208
+ end
209
+
210
+ context "and when given the `firefox_version:` keyword argument" do
211
+ let(:firefox_version) { '1.2.3' }
212
+
213
+ it "must use the specified `firefox_version:` value" do
214
+ expect(
215
+ subject.build(
216
+ firefox_version: firefox_version,
217
+ os: os,
218
+ arch: arch
219
+ )
220
+ ).to eq("Mozilla/5.0 (X11; Linux #{linux_arch}; rv:#{firefox_version}) Gecko/#{gecko_version} Firefox/#{firefox_version}")
221
+ end
222
+ end
223
+ end
224
+ end
225
+ end
226
+
227
+ context "when given `os: :android`" do
228
+ let(:os) { :android }
229
+
230
+ it "must add 'Android; Mobile; rv:...' to the extensions" do
231
+ expect(
232
+ subject.build(
233
+ firefox_version: firefox_version,
234
+ os: os
235
+ )
236
+ ).to eq("Mozilla/5.0 (Android; Mobile; rv:#{firefox_version}) Gecko/#{firefox_version} Firefox/#{firefox_version}")
237
+ end
238
+
239
+ context "when `device_type: :mobile` is given" do
240
+ let(:device_type) { :mobile }
241
+
242
+ it "must add 'Android; Mobile; rv:...' to the extensions" do
243
+ expect(
244
+ subject.build(
245
+ firefox_version: firefox_version,
246
+ os: os,
247
+ device_type: device_type
248
+ )
249
+ ).to eq("Mozilla/5.0 (Android; Mobile; rv:#{firefox_version}) Gecko/#{firefox_version} Firefox/#{firefox_version}")
250
+ end
251
+ end
252
+
253
+ context "when `device_type: :tablet` is given" do
254
+ let(:device_type) { :tablet }
255
+
256
+ it "must add 'Android; Tablet; rv:...' to the extensions" do
257
+ expect(
258
+ subject.build(
259
+ firefox_version: firefox_version,
260
+ os: os,
261
+ device_type: device_type
262
+ )
263
+ ).to eq("Mozilla/5.0 (Android; Tablet; rv:#{firefox_version}) Gecko/#{firefox_version} Firefox/#{firefox_version}")
264
+ end
265
+ end
266
+
267
+ context "when `device_type: nil` is given" do
268
+ let(:device_type) { nil }
269
+
270
+ it "must add 'Android; Mobile; rv:...' to the extensions" do
271
+ expect(
272
+ subject.build(
273
+ firefox_version: firefox_version,
274
+ os: os,
275
+ device_type: device_type
276
+ )
277
+ ).to eq("Mozilla/5.0 (Android; Mobile; rv:#{firefox_version}) Gecko/#{firefox_version} Firefox/#{firefox_version}")
278
+ end
279
+ end
280
+ end
281
+
282
+ context "when given `os: :other`" do
283
+ let(:os) { :other }
284
+
285
+ it do
286
+ expect {
287
+ subject.build(firefox_version: firefox_version, os: os)
288
+ }.to raise_error(ArgumentError,"unsupported os: value (#{os.inspect})")
289
+ end
290
+ end
291
+ end
292
+
293
+ describe ".random" do
294
+ it "must return a random Chrome User-Agent string" do
295
+ expect(subject.random).to match(
296
+ %r{^Mozilla/5\.0 \([^\)]+\) Gecko/(?:20100101|\d+(?:\.\d+)*) Firefox/\d+(\.\d+)*$}
297
+ )
298
+ end
299
+
300
+ it "must generate a new random Chrome User-Agent string each time" do
301
+ expect(subject.random).to_not eq(subject.random)
302
+ end
303
+
304
+ context "when `os: :windows`" do
305
+ let(:os) { :windows }
306
+
307
+ it "must return a random Windows Chrome User-Agent string" do
308
+ expect(subject.random(os: os)).to match(
309
+ %r{^Mozilla/5\.0 \(Windows NT \d+(?:\.\d+)*(?:; (?:WOW64|Win64; x64))?; rv:\d+(?:\.\d+)*\) Gecko/(?:20100101|\d+(?:\.\d+)*) Firefox/\d+(\.\d+)*$}
310
+ )
311
+ end
312
+
313
+ context "and when given `os_version:`" do
314
+ let(:os_version) { 10 }
315
+
316
+ it "must return a random Windows Chrome User-Agent string for that version of Windows" do
317
+ expect(subject.random(os: os, os_version: os_version)).to match(
318
+ %r{^Mozilla/5\.0 \(Windows NT 10\.0(?:; (?:WOW64|Win64; x64))?; rv:\d+(?:\.\d+)*\) Gecko/(?:20100101|\d+(?:\.\d+)*) Firefox/\d+(\.\d+)*$}
319
+ )
320
+ end
321
+ end
322
+
323
+ context "and when given `arch: :wow64`" do
324
+ let(:arch) { :wow64 }
325
+
326
+ it "must return a random Windows Chrome User-Agent string for the WOW64 architecture" do
327
+ expect(subject.random(os: os, arch: arch)).to match(
328
+ %r{^Mozilla/5\.0 \(Windows NT \d+(?:\.\d+)*; WOW64; rv:\d+(?:\.\d+)*\) Gecko/(?:20100101|\d+(?:\.\d+)*) Firefox/\d+(\.\d+)*$}
329
+ )
330
+ end
331
+ end
332
+
333
+ context "and when given `arch: :win64`" do
334
+ let(:arch) { :win64 }
335
+
336
+ it "must return a random Windows Chrome User-Agent string for the WOW64 architecture" do
337
+ expect(subject.random(os: os, arch: arch)).to match(
338
+ %r{^Mozilla/5\.0 \(Windows NT \d+(?:\.\d+)*; Win64; x64; rv:\d+(?:\.\d+)*\) Gecko/(?:20100101|\d+(?:\.\d+)*) Firefox/\d+(\.\d+)*$}
339
+ )
340
+ end
341
+ end
342
+ end
343
+
344
+ context "when `os: :macos` is given" do
345
+ let(:os) { :macos }
346
+
347
+ it "must return a macOS Chrome User-Agent string" do
348
+ expect(subject.random(os: os)).to match(
349
+ %r{^Mozilla/5\.0 \(Macintosh; Intel Mac OS X \d+(\.\d+){1,2}; rv:\d+(?:\.\d+)*\) Gecko/(?:20100101|\d+(?:\.\d+)*) Firefox/\d+(\.\d+)*$}
350
+ )
351
+ end
352
+
353
+ context "and when `os_version:` is given" do
354
+ let(:os_version) { '10.11.12' }
355
+
356
+ it "must return a macOS Chrome User-Agent string for that macOS version" do
357
+ expect(subject.random(os: os, os_version: os_version)).to match(
358
+ %r{^Mozilla/5\.0 \(Macintosh; Intel Mac OS X 10\.11\.12; rv:\d+(?:\.\d+)*\) Gecko/(?:20100101|\d+(?:\.\d+)*) Firefox/\d+(\.\d+)*$}
359
+ )
360
+ end
361
+ end
362
+ end
363
+
364
+ context "when `os: :linux` is given" do
365
+ let(:os) { :linux }
366
+
367
+ it "must return a Linux Chrome User-Agent string" do
368
+ expect(subject.random(os: os)).to match(
369
+ %r{^Mozilla/5\.0 \(X11(?:; (?:Ubuntu|Fedora|Arch))?; Linux (?:x86_64|aarch64|i686)(?:; [a-z]+(?:-[A-Z]+)?)?; rv:\d+(?:\.\d+)*\) Gecko/(?:20100101|\d+(?:\.\d+)*) Firefox/\d+(\.\d+)*$}
370
+ )
371
+ end
372
+
373
+ context "and when `linux_distro:` is given" do
374
+ let(:linux_distro) { :ubuntu }
375
+
376
+ it "must return a Linux Chrome User-Agent string for that Linux Distro" do
377
+ expect(subject.random(os: os, linux_distro: linux_distro)).to match(
378
+ %r{^Mozilla/5\.0 \(X11; Ubuntu; Linux (?:x86_64|aarch64|i686)(?:; [a-z]+(?:-[A-Z]+)?)?; rv:\d+(?:\.\d+)*\) Gecko/(?:20100101|\d+(?:\.\d+)*) Firefox/\d+(\.\d+)*$}
379
+ )
380
+ end
381
+ end
382
+
383
+ context "and when `arch:` is given" do
384
+ let(:arch) { :arm64 }
385
+
386
+ it "must return a Linux Chrome User-Agent string for that architecture" do
387
+ expect(subject.random(os: os, arch: arch)).to match(
388
+ %r{^Mozilla/5\.0 \(X11(?:; (?:Ubuntu|Fedora|Arch))?; Linux aarch64(?:; [a-zA-Z-]+)?; rv:\d+(?:\.\d+)*\) Gecko/(?:20100101|\d+(?:\.\d+)*) Firefox/\d+(\.\d+)*$}
389
+ )
390
+ end
391
+ end
392
+ end
393
+
394
+ context "when `os: :android` is given" do
395
+ let(:os) { :android }
396
+
397
+ it "must return a Android Chrome User-Agent string" do
398
+ expect(subject.random(os: os)).to match(
399
+ %r{^Mozilla/5\.0 \(Android(?:; (?:Mobile|Tablet))?; rv:\d+(?:\.\d+)*\) Gecko/(?:20100101|\d+(?:\.\d+)*) Firefox/\d+(\.\d+)*$}
400
+ )
401
+ end
402
+
403
+ context "and when `device_type:` is given" do
404
+ let(:device_type) { :tablet }
405
+
406
+ it "must return a Linux Firefox User-Agent string with that device type" do
407
+ expect(subject.random(os: os, device_type: device_type)).to match(
408
+ %r{^Mozilla/5\.0 \(Android; Tablet; rv:\d+(?:\.\d+)*\) Gecko/(?:20100101|\d+(?:\.\d+)*) Firefox/\d+(\.\d+)*$}
409
+ )
410
+ end
411
+ end
412
+ end
413
+ end
414
+ end
@@ -0,0 +1,231 @@
1
+ require 'spec_helper'
2
+ require 'ronin/web/user_agents/google_bot'
3
+
4
+ describe Ronin::Web::UserAgents::GoogleBot do
5
+ describe ".build" do
6
+ context "whne given no keyword arguments" do
7
+ it "must return 'GoogleBot/#{described_class::VERSION} (+#{described_class::URL})'" do
8
+ expect(subject.build).to eq(
9
+ "GoogleBot/#{described_class::VERSION} (+#{described_class::URL})"
10
+ )
11
+ end
12
+
13
+ context "when given `crawler: :image`" do
14
+ it "must return 'Googlebot-Image/1.0'" do
15
+ expect(subject.build(crawler: :image)).to eq(
16
+ "Googlebot-Image/1.0"
17
+ )
18
+ end
19
+ end
20
+
21
+ context "when given `crawler: :video`" do
22
+ it "must return 'Googlebot-Video/1.0'" do
23
+ expect(subject.build(crawler: :video)).to eq(
24
+ "Googlebot-Video/1.0"
25
+ )
26
+ end
27
+ end
28
+
29
+ context "when given `crawler: :search`" do
30
+ it "must return 'GoogleBot/#{described_class::VERSION} (+http://www.google.com/bot.html)'" do
31
+ expect(subject.build(crawler: :search)).to eq(
32
+ "GoogleBot/#{described_class::VERSION} (+#{described_class::URL})"
33
+ )
34
+ end
35
+
36
+ context "and when also given `compatible: :desktop`" do
37
+ it "must return 'Mozilla/5.0 (compatible; GoogleBot/#{described_class::VERSION}; +#{described_class::URL})'" do
38
+ expect(
39
+ subject.build(
40
+ crawler: :search,
41
+ compatible: :desktop
42
+ )
43
+ ).to eq(
44
+ "Mozilla/5.0 (compatible; GoogleBot/#{described_class::VERSION}; +#{described_class::URL})"
45
+ )
46
+ end
47
+
48
+ context "and when also given the `chrome_version:` keyword argument" do
49
+ let(:chrome_version) { '1.2.3' }
50
+
51
+ it "must return 'Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; GoogleBot/#{described_class::VERSION}; +#{described_class::URL}) Chrome/... Safari/537.36'" do
52
+ expect(
53
+ subject.build(
54
+ crawler: :search,
55
+ compatible: :desktop,
56
+ chrome_version: chrome_version
57
+ )
58
+ ).to eq(
59
+ "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; GoogleBot/#{described_class::VERSION}; +#{described_class::URL}) Chrome/#{chrome_version} Safari/537.36"
60
+ )
61
+ end
62
+ end
63
+ end
64
+
65
+ context "and when also given `compatible: :mobile`" do
66
+ context "and the `chrome_version:` keyword argument is also given" do
67
+ let(:chrome_version) { '1.2.3' }
68
+
69
+ it "must return 'Mozilla/5.0 (Linux; Android #{described_class::ANDROID_VERSION}; #{described_class::ANDROID_DEVICE}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/... Mobile Safari/537.36 (compatible; GoogleBot/#{described_class::VERSION}; +#{described_class::URL})'" do
70
+ expect(
71
+ subject.build(
72
+ crawler: :search,
73
+ compatible: :mobile,
74
+ chrome_version: chrome_version
75
+ )
76
+ ).to eq(
77
+ "Mozilla/5.0 (Linux; Android #{described_class::ANDROID_VERSION}; #{described_class::ANDROID_DEVICE}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/#{chrome_version} Mobile Safari/537.36 (compatible; GoogleBot/#{described_class::VERSION}; +#{described_class::URL})"
78
+ )
79
+ end
80
+ end
81
+
82
+ context "but the `chrome_version:` keyword argument is not given" do
83
+ it do
84
+ expect {
85
+ subject.build(crawler: :search, compatible: :mobile)
86
+ }.to raise_error(ArgumentError,"compatible: :mobile also requires the chrome_version: keyword argument")
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ context "and when also given `compatible: :desktop`" do
94
+ it "must return 'Mozilla/5.0 (compatible; GoogleBot/#{described_class::VERSION}; +#{described_class::URL})'" do
95
+ expect(subject.build(compatible: :desktop)).to eq(
96
+ "Mozilla/5.0 (compatible; GoogleBot/#{described_class::VERSION}; +#{described_class::URL})"
97
+ )
98
+ end
99
+
100
+ context "and when also given the `chrome_version:` keyword argument" do
101
+ let(:chrome_version) { '1.2.3' }
102
+
103
+ it "must return 'Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; GoogleBot/#{described_class::VERSION}; +#{described_class::URL}) Chrome/... Safari/537.36'" do
104
+ expect(
105
+ subject.build(
106
+ compatible: :desktop,
107
+ chrome_version: chrome_version
108
+ )
109
+ ).to eq(
110
+ "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; GoogleBot/#{described_class::VERSION}; +#{described_class::URL}) Chrome/#{chrome_version} Safari/537.36"
111
+ )
112
+ end
113
+ end
114
+ end
115
+
116
+ context "and when also given `compatible: :mobile`" do
117
+ context "and the `chrome_version:` keyword argument is also given" do
118
+ let(:chrome_version) { '1.2.3' }
119
+
120
+ it "must return 'Mozilla/5.0 (Linux; Android #{described_class::ANDROID_VERSION}; #{described_class::ANDROID_DEVICE}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/... Mobile Safari/537.36 (compatible; GoogleBot/#{described_class::VERSION}; +#{described_class::URL})'" do
121
+ expect(
122
+ subject.build(
123
+ compatible: :mobile,
124
+ chrome_version: chrome_version
125
+ )
126
+ ).to eq(
127
+ "Mozilla/5.0 (Linux; Android #{described_class::ANDROID_VERSION}; #{described_class::ANDROID_DEVICE}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/#{chrome_version} Mobile Safari/537.36 (compatible; GoogleBot/#{described_class::VERSION}; +#{described_class::URL})"
128
+ )
129
+ end
130
+ end
131
+
132
+ context "but the `chrome_version:` keyword argument is not given" do
133
+ it do
134
+ expect {
135
+ subject.build(compatible: :mobile)
136
+ }.to raise_error(ArgumentError,"compatible: :mobile also requires the chrome_version: keyword argument")
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ describe ".random" do
143
+ let(:version_pattern) { Regexp.escape(described_class::VERSION) }
144
+ let(:url_pattern) { Regexp.escape(described_class::URL) }
145
+
146
+ let(:android_version_pattern) do
147
+ Regexp.escape(described_class::ANDROID_VERSION)
148
+ end
149
+
150
+ let(:android_device_pattern) do
151
+ Regexp.escape(described_class::ANDROID_DEVICE)
152
+ end
153
+
154
+ it "must return a random GoogleBot User-Agent string" do
155
+ expect(subject.random).to match(
156
+ %r{
157
+ ^(?:
158
+ Googlebot-Image/1\.0|
159
+ Googlebot-Video/1\.0|
160
+ Mozilla/5\.0\ AppleWebKit/537\.36\ \(KHTML,\ like\ Gecko;\ compatible;\ GoogleBot/#{version_pattern};\ \+#{url_pattern}\)\ Chrome/\d+(?:\.\d+)*\ Safari/537\.36|
161
+ Mozilla/5\.0\ \(compatible;\ GoogleBot/#{version_pattern};\ \+#{url_pattern}\)|
162
+ Mozilla/5\.0\ \(Linux;\ Android\ #{android_version_pattern};\ #{android_device_pattern}\)\ AppleWebKit/537\.36\ \(KHTML,\ like\ Gecko\)\ Chrome/\d+(?:\.\d+)*\ Mobile\ Safari/537\.36\ \(compatible;\ GoogleBot/#{version_pattern};\ \+#{url_pattern}\)|
163
+ GoogleBot/#{version_pattern}\ \(\+#{url_pattern}\)
164
+ )$
165
+ }x
166
+ )
167
+ end
168
+
169
+ context "when `crawler: :image` is given" do
170
+ it "must return 'Googlebot-Image/1.0'" do
171
+ expect(subject.build(crawler: :image)).to eq(
172
+ "Googlebot-Image/1.0"
173
+ )
174
+ end
175
+ end
176
+
177
+ context "when `crawler: :video` is given" do
178
+ it "must return 'Googlebot-Video/1.0'" do
179
+ expect(subject.build(crawler: :video)).to eq(
180
+ "Googlebot-Video/1.0"
181
+ )
182
+ end
183
+ end
184
+
185
+ context "when `crawler: :search ` is given" do
186
+ it "must return a random GoogleBot User-Agent string" do
187
+ expect(subject.random(crawler: :search)).to match(
188
+ %r{
189
+ ^(?:
190
+ Mozilla/5\.0\ AppleWebKit/537\.36\ \(KHTML,\ like\ Gecko;\ compatible;\ GoogleBot/#{version_pattern};\ \+#{url_pattern}\)\ Chrome/\d+(?:\.\d+)*\ Safari/537\.36|
191
+ Mozilla/5\.0\ \(compatible;\ GoogleBot/#{version_pattern};\ \+#{url_pattern}\)|
192
+ Mozilla/5\.0\ \(Linux;\ Android\ #{android_version_pattern};\ #{android_device_pattern}\)\ AppleWebKit/537\.36\ \(KHTML,\ like\ Gecko\)\ Chrome/\d+(?:\.\d+)*\ Mobile\ Safari/537\.36\ \(compatible;\ GoogleBot/#{version_pattern};\ \+#{url_pattern}\)|
193
+ GoogleBot/#{version_pattern}\ \(\+#{url_pattern}\)
194
+ )$
195
+ }x
196
+ )
197
+ end
198
+
199
+ context "and when `compatible: :desktop` is given" do
200
+ it "must return a random GoogleBot desktop compatible User-Agent string" do
201
+ expect(
202
+ subject.random(
203
+ crawler: :search,
204
+ compatible: :desktop
205
+ )
206
+ ).to match(
207
+ %r{
208
+ ^(?:
209
+ Mozilla/5\.0\ AppleWebKit/537\.36\ \(KHTML,\ like\ Gecko;\ compatible;\ GoogleBot/#{version_pattern};\ \+#{url_pattern}\)\ Chrome/\d+(?:\.\d+)*\ Safari/537\.36|
210
+ Mozilla/5\.0\ \(compatible;\ GoogleBot/#{version_pattern};\ \+#{url_pattern}\)
211
+ )$
212
+ }x
213
+ )
214
+ end
215
+ end
216
+
217
+ context "and when `compatible: :mobile` is given" do
218
+ it "must return a random GoogleBot mobile compatible User-Agent string" do
219
+ expect(
220
+ subject.random(
221
+ crawler: :search,
222
+ compatible: :mobile
223
+ )
224
+ ).to match(
225
+ %r{^Mozilla/5\.0 \(Linux;\ Android #{android_version_pattern}; #{android_device_pattern}\) AppleWebKit/537\.36 \(KHTML, like\ Gecko\) Chrome/\d+(?:\.\d+)*\ Mobile\ Safari/537\.36 \(compatible; GoogleBot/#{version_pattern}; \+#{url_pattern}\)$}
226
+ )
227
+ end
228
+ end
229
+ end
230
+ end
231
+ end