poltergeist 1.11.0 → 1.12.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cc14ad1bf5ce9dacde0dfef301ec4fca4e46bd4d
4
- data.tar.gz: 41bb2dbf585f8c59b32eeb7b10e7289dae0d193e
3
+ metadata.gz: 62a6d774d0e6cf68f19667891d54f61c810e89f1
4
+ data.tar.gz: 19861cdfb3615834316772b64ee067be4efca384
5
5
  SHA512:
6
- metadata.gz: 48a9db9338cbca32461001b10787638bd486cbfe4f3ebf4ec5a080a20abbefc7a79b5ced7788e2d935d4f06d0dc86aae37325a3b0df53e3504d8bb1e77e61f05
7
- data.tar.gz: 2f75709c6262d5fd35075eadaa7a633f9ade052b68dc3a382ec5d6afeb5574d3a8d956d846caf07fc5de9c10a9a9b16d789065f67ba7ed6589adb2efcba4c666
6
+ metadata.gz: 3caef6797f238771788a78b0db80019e0f5559c2aef822e3bd102682ecd88a12160e39f6cf6c8a6dd58a4771cb501911fb99ac06d6464f1b8f0370b5dabae9cf
7
+ data.tar.gz: ad4321b2d883e7e2236ca800d401371a863027abe9b9a2c6807ae93c16898c77c9284844366504bec5b9f66d93c3d9c55a546af3ae1a79552b3ebe907dd6cb0b
@@ -23,8 +23,19 @@ module Capybara::Poltergeist
23
23
  def self.process_killer(pid)
24
24
  proc do
25
25
  begin
26
- Process.kill('KILL', pid)
26
+ if Capybara::Poltergeist.windows?
27
+ Process.kill('KILL', pid)
28
+ else
29
+ Process.kill('TERM', pid)
30
+ begin
31
+ Timeout.timeout(KILL_TIMEOUT) { Process.wait(pid) }
32
+ rescue Timeout::Error
33
+ Process.kill('KILL', pid)
34
+ Process.wait(pid)
35
+ end
36
+ end
27
37
  rescue Errno::ESRCH, Errno::ECHILD
38
+ # Zed's dead, baby
28
39
  end
29
40
  end
30
41
  end
@@ -41,15 +52,6 @@ module Capybara::Poltergeist
41
52
  @window_size = options[:window_size] || [1024, 768]
42
53
  @phantomjs_options = options[:phantomjs_options] || []
43
54
  @phantomjs_logger = options[:phantomjs_logger] || $stdout
44
-
45
- pid = Process.pid
46
- at_exit do
47
- # do the work in a separate thread, to avoid stomping on $!,
48
- # since other libraries depend on it directly.
49
- Thread.new do
50
- stop if Process.pid == pid
51
- end.join
52
- end
53
55
  end
54
56
 
55
57
  def start
@@ -111,21 +113,7 @@ module Capybara::Poltergeist
111
113
  end
112
114
 
113
115
  def kill_phantomjs
114
- begin
115
- if Capybara::Poltergeist.windows?
116
- Process.kill('KILL', pid)
117
- else
118
- Process.kill('TERM', pid)
119
- begin
120
- Timeout.timeout(KILL_TIMEOUT) { Process.wait(pid) }
121
- rescue Timeout::Error
122
- Process.kill('KILL', pid)
123
- Process.wait(pid)
124
- end
125
- end
126
- rescue Errno::ESRCH, Errno::ECHILD
127
- # Zed's dead, baby
128
- end
116
+ self.class.process_killer(pid).call
129
117
  @pid = nil
130
118
  end
131
119
 
@@ -1,10 +1,5 @@
1
1
  # This is injected into each page that is loaded
2
-
3
2
  class PoltergeistAgent
4
- # Since this code executes in the sites browser space - copy needed JSON functions
5
- # in case user code messes with JSON (early mootools for instance)
6
- @.JSON ||= { parse: JSON.parse, stringify: JSON.stringify }
7
-
8
3
  constructor: ->
9
4
  @elements = []
10
5
  @nodes = {}
@@ -15,19 +10,6 @@ class PoltergeistAgent
15
10
  catch error
16
11
  { error: { message: error.toString(), stack: error.stack } }
17
12
 
18
- @stringify: (object) ->
19
- try
20
- PoltergeistAgent.JSON.stringify object, (key, value) ->
21
- if Array.isArray(this[key])
22
- return this[key]
23
- else
24
- return value
25
- catch error
26
- if error instanceof TypeError
27
- '"(cyclic structure)"'
28
- else
29
- throw error
30
-
31
13
  # Somehow PhantomJS returns all characters(brackets, etc) properly encoded
32
14
  # except whitespace character in pathname part of the location. This hack
33
15
  # is intended to fix this up.
@@ -194,7 +176,7 @@ class PoltergeistAgent.Node
194
176
  if name == 'checked' || name == 'selected'
195
177
  @element[name]
196
178
  else
197
- @element.getAttribute(name)
179
+ @element.getAttribute(name) ? undefined
198
180
 
199
181
  scrollIntoView: ->
200
182
  @element.scrollIntoViewIfNeeded()
@@ -1,18 +1,13 @@
1
1
  var PoltergeistAgent;
2
2
 
3
3
  PoltergeistAgent = (function() {
4
- PoltergeistAgent.JSON || (PoltergeistAgent.JSON = {
5
- parse: JSON.parse,
6
- stringify: JSON.stringify
7
- });
8
-
9
4
  function PoltergeistAgent() {
10
5
  this.elements = [];
11
6
  this.nodes = {};
12
7
  }
13
8
 
14
9
  PoltergeistAgent.prototype.externalCall = function(name, args) {
15
- var error, error1;
10
+ var error;
16
11
  try {
17
12
  return {
18
13
  value: this[name].apply(this, args)
@@ -28,32 +23,12 @@ PoltergeistAgent = (function() {
28
23
  }
29
24
  };
30
25
 
31
- PoltergeistAgent.stringify = function(object) {
32
- var error, error1;
33
- try {
34
- return PoltergeistAgent.JSON.stringify(object, function(key, value) {
35
- if (Array.isArray(this[key])) {
36
- return this[key];
37
- } else {
38
- return value;
39
- }
40
- });
41
- } catch (error1) {
42
- error = error1;
43
- if (error instanceof TypeError) {
44
- return '"(cyclic structure)"';
45
- } else {
46
- throw error;
47
- }
48
- }
49
- };
50
-
51
26
  PoltergeistAgent.prototype.currentUrl = function() {
52
27
  return window.location.href.replace(/\ /g, '%20');
53
28
  };
54
29
 
55
30
  PoltergeistAgent.prototype.find = function(method, selector, within) {
56
- var el, error, error1, i, j, len, results, results1, xpath;
31
+ var el, error, i, j, len, results, results1, xpath;
57
32
  if (within == null) {
58
33
  within = document;
59
34
  }
@@ -296,10 +271,11 @@ PoltergeistAgent.Node = (function() {
296
271
  };
297
272
 
298
273
  Node.prototype.getAttribute = function(name) {
274
+ var ref;
299
275
  if (name === 'checked' || name === 'selected') {
300
276
  return this.element[name];
301
277
  } else {
302
- return this.element.getAttribute(name);
278
+ return (ref = this.element.getAttribute(name)) != null ? ref : void 0;
303
279
  }
304
280
  };
305
281
 
@@ -29,7 +29,7 @@ Poltergeist.Cmd = (function() {
29
29
  };
30
30
 
31
31
  Cmd.prototype.run = function(browser) {
32
- var error, error1;
32
+ var error;
33
33
  this.browser = browser;
34
34
  try {
35
35
  return this.browser.runCommand(this);
@@ -28,11 +28,15 @@ Poltergeist.WebPage = (function() {
28
28
  this._tempHeaders = {};
29
29
  this._blockedUrls = [];
30
30
  this._requestedResources = {};
31
+ this._responseHeaders = [];
31
32
  ref = WebPage.CALLBACKS;
32
33
  for (i = 0, len = ref.length; i < len; i++) {
33
34
  callback = ref[i];
34
35
  this.bindCallback(callback);
35
36
  }
37
+ if (phantom.version.major < 2) {
38
+ this._overrideNativeEvaluate();
39
+ }
36
40
  }
37
41
 
38
42
  ref = WebPage.COMMANDS;
@@ -498,32 +502,20 @@ Poltergeist.WebPage = (function() {
498
502
  };
499
503
 
500
504
  WebPage.prototype.evaluate = function() {
501
- var args, fn;
505
+ var args, fn, ref2;
502
506
  fn = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
503
507
  this.injectAgent();
504
- return JSON.parse(this.sanitize(this["native"]().evaluate("function() { return PoltergeistAgent.stringify(" + (this.stringifyCall(fn, args)) + ") }")));
505
- };
506
-
507
- WebPage.prototype.sanitize = function(potential_string) {
508
- if (typeof potential_string === "string") {
509
- return potential_string.replace("\n", "\\n").replace("\r", "\\r");
510
- } else {
511
- return potential_string;
512
- }
508
+ return (ref2 = this["native"]()).evaluate.apply(ref2, ["function() { var _result = " + (this.stringifyCall(fn)) + "; return (_result == null) ? undefined : _result; }"].concat(slice.call(args)));
513
509
  };
514
510
 
515
511
  WebPage.prototype.execute = function() {
516
- var args, fn;
512
+ var args, fn, ref2;
517
513
  fn = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
518
- return this["native"]().evaluate("function() { " + (this.stringifyCall(fn, args)) + " }");
514
+ return (ref2 = this["native"]()).evaluate.apply(ref2, ["function() { " + (this.stringifyCall(fn)) + " }"].concat(slice.call(args)));
519
515
  };
520
516
 
521
- WebPage.prototype.stringifyCall = function(fn, args) {
522
- if (args.length === 0) {
523
- return "(" + (fn.toString()) + ")()";
524
- } else {
525
- return "(" + (fn.toString()) + ").apply(this, PoltergeistAgent.JSON.parse(" + (JSON.stringify(JSON.stringify(args))) + "))";
526
- }
517
+ WebPage.prototype.stringifyCall = function(fn) {
518
+ return "(" + (fn.toString()) + ").apply(this, arguments)";
527
519
  };
528
520
 
529
521
  WebPage.prototype.bindCallback = function(name) {
@@ -590,6 +582,92 @@ Poltergeist.WebPage = (function() {
590
582
  }
591
583
  };
592
584
 
585
+ WebPage.prototype._overrideNativeEvaluate = function() {
586
+ return this._native.evaluate = function (func, args) {
587
+ function quoteString(str) {
588
+ var c, i, l = str.length, o = '"';
589
+ for (i = 0; i < l; i += 1) {
590
+ c = str.charAt(i);
591
+ if (c >= ' ') {
592
+ if (c === '\\' || c === '"') {
593
+ o += '\\';
594
+ }
595
+ o += c;
596
+ } else {
597
+ switch (c) {
598
+ case '\b':
599
+ o += '\\b';
600
+ break;
601
+ case '\f':
602
+ o += '\\f';
603
+ break;
604
+ case '\n':
605
+ o += '\\n';
606
+ break;
607
+ case '\r':
608
+ o += '\\r';
609
+ break;
610
+ case '\t':
611
+ o += '\\t';
612
+ break;
613
+ default:
614
+ c = c.charCodeAt();
615
+ o += '\\u00' + Math.floor(c / 16).toString(16) +
616
+ (c % 16).toString(16);
617
+ }
618
+ }
619
+ }
620
+ return o + '"';
621
+ }
622
+
623
+ function detectType(value) {
624
+ var s = typeof value;
625
+ if (s === 'object') {
626
+ if (value) {
627
+ if (value instanceof Array) {
628
+ s = 'array';
629
+ } else if (value instanceof RegExp) {
630
+ s = 'regexp';
631
+ } else if (value instanceof Date) {
632
+ s = 'date';
633
+ }
634
+ } else {
635
+ s = 'null';
636
+ }
637
+ }
638
+ return s;
639
+ }
640
+
641
+ var str, arg, argType, i, l;
642
+ if (!(func instanceof Function || typeof func === 'string' || func instanceof String)) {
643
+ throw "Wrong use of WebPage#evaluate";
644
+ }
645
+ str = 'function() { return (' + func.toString() + ')(';
646
+ for (i = 1, l = arguments.length; i < l; i++) {
647
+ arg = arguments[i];
648
+ argType = detectType(arg);
649
+
650
+ switch (argType) {
651
+ case "object": //< for type "object"
652
+ case "array": //< for type "array"
653
+ str += JSON.stringify(arg) + ","
654
+ break;
655
+ case "date": //< for type "date"
656
+ str += "new Date(" + JSON.stringify(arg) + "),"
657
+ break;
658
+ case "string": //< for type "string"
659
+ str += quoteString(arg) + ',';
660
+ break;
661
+ default: // for types: "null", "number", "function", "regexp", "undefined"
662
+ str += arg + ',';
663
+ break;
664
+ }
665
+ }
666
+ str = str.replace(/,$/, '') + '); }';
667
+ return this.evaluateJavaScript(str);
668
+ };;
669
+ };
670
+
593
671
  return WebPage;
594
672
 
595
673
  })();
@@ -27,10 +27,14 @@ class Poltergeist.WebPage
27
27
  @_tempHeaders = {}
28
28
  @_blockedUrls = []
29
29
  @_requestedResources = {}
30
+ @_responseHeaders = []
30
31
 
31
32
  for callback in WebPage.CALLBACKS
32
33
  this.bindCallback(callback)
33
34
 
35
+ if phantom.version.major < 2
36
+ @._overrideNativeEvaluate()
37
+
34
38
  for command in @COMMANDS
35
39
  do (command) =>
36
40
  this.prototype[command] =
@@ -341,25 +345,14 @@ class Poltergeist.WebPage
341
345
 
342
346
  evaluate: (fn, args...) ->
343
347
  this.injectAgent()
344
- JSON.parse this.sanitize(this.native().evaluate("function() { return PoltergeistAgent.stringify(#{this.stringifyCall(fn, args)}) }"))
345
-
346
- sanitize: (potential_string) ->
347
- if typeof(potential_string) == "string"
348
- # JSON doesn't like \r or \n in strings unless escaped
349
- potential_string.replace("\n","\\n").replace("\r","\\r")
350
- else
351
- potential_string
348
+ this.native().evaluate("function() { var _result = #{this.stringifyCall(fn)};
349
+ return (_result == null) ? undefined : _result; }", args...)
352
350
 
353
351
  execute: (fn, args...) ->
354
- this.native().evaluate("function() { #{this.stringifyCall(fn, args)} }")
352
+ this.native().evaluate("function() { #{this.stringifyCall(fn)} }", args...)
355
353
 
356
- stringifyCall: (fn, args) ->
357
- if args.length == 0
358
- "(#{fn.toString()})()"
359
- else
360
- # The JSON.stringify happens twice because the second time we are essentially
361
- # escaping the string.
362
- "(#{fn.toString()}).apply(this, PoltergeistAgent.JSON.parse(#{JSON.stringify(JSON.stringify(args))}))"
354
+ stringifyCall: (fn) ->
355
+ "(#{fn.toString()}).apply(this, arguments)"
363
356
 
364
357
  bindCallback: (name) ->
365
358
  @native()[name] = =>
@@ -406,3 +399,90 @@ class Poltergeist.WebPage
406
399
  clearMemoryCache()
407
400
  else
408
401
  throw new Poltergeist.UnsupportedFeature("clearMemoryCache is supported since PhantomJS 2.0.0")
402
+
403
+ _overrideNativeEvaluate: ->
404
+ # PhantomJS 1.9.x WebPage#evaluate depends on the browser context JSON, this replaces it
405
+ # with the evaluate from 2.1.1 which uses the PhantomJS JSON
406
+ @_native.evaluate = `function (func, args) {
407
+ function quoteString(str) {
408
+ var c, i, l = str.length, o = '"';
409
+ for (i = 0; i < l; i += 1) {
410
+ c = str.charAt(i);
411
+ if (c >= ' ') {
412
+ if (c === '\\' || c === '"') {
413
+ o += '\\';
414
+ }
415
+ o += c;
416
+ } else {
417
+ switch (c) {
418
+ case '\b':
419
+ o += '\\b';
420
+ break;
421
+ case '\f':
422
+ o += '\\f';
423
+ break;
424
+ case '\n':
425
+ o += '\\n';
426
+ break;
427
+ case '\r':
428
+ o += '\\r';
429
+ break;
430
+ case '\t':
431
+ o += '\\t';
432
+ break;
433
+ default:
434
+ c = c.charCodeAt();
435
+ o += '\\u00' + Math.floor(c / 16).toString(16) +
436
+ (c % 16).toString(16);
437
+ }
438
+ }
439
+ }
440
+ return o + '"';
441
+ }
442
+
443
+ function detectType(value) {
444
+ var s = typeof value;
445
+ if (s === 'object') {
446
+ if (value) {
447
+ if (value instanceof Array) {
448
+ s = 'array';
449
+ } else if (value instanceof RegExp) {
450
+ s = 'regexp';
451
+ } else if (value instanceof Date) {
452
+ s = 'date';
453
+ }
454
+ } else {
455
+ s = 'null';
456
+ }
457
+ }
458
+ return s;
459
+ }
460
+
461
+ var str, arg, argType, i, l;
462
+ if (!(func instanceof Function || typeof func === 'string' || func instanceof String)) {
463
+ throw "Wrong use of WebPage#evaluate";
464
+ }
465
+ str = 'function() { return (' + func.toString() + ')(';
466
+ for (i = 1, l = arguments.length; i < l; i++) {
467
+ arg = arguments[i];
468
+ argType = detectType(arg);
469
+
470
+ switch (argType) {
471
+ case "object": //< for type "object"
472
+ case "array": //< for type "array"
473
+ str += JSON.stringify(arg) + ","
474
+ break;
475
+ case "date": //< for type "date"
476
+ str += "new Date(" + JSON.stringify(arg) + "),"
477
+ break;
478
+ case "string": //< for type "string"
479
+ str += quoteString(arg) + ',';
480
+ break;
481
+ default: // for types: "null", "number", "function", "regexp", "undefined"
482
+ str += arg + ',';
483
+ break;
484
+ }
485
+ }
486
+ str = str.replace(/,$/, '') + '); }';
487
+ return this.evaluateJavaScript(str);
488
+ };`
@@ -1,5 +1,5 @@
1
1
  module Capybara
2
2
  module Poltergeist
3
- VERSION = "1.11.0"
3
+ VERSION = "1.12.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: poltergeist
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.11.0
4
+ version: 1.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Leighton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-10 00:00:00.000000000 Z
11
+ date: 2016-12-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capybara
@@ -72,28 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 3.4.0
75
+ version: 3.5.0
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 3.4.0
83
- - !ruby/object:Gem::Dependency
84
- name: rspec-core
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "!="
88
- - !ruby/object:Gem::Version
89
- version: 3.4.0
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "!="
95
- - !ruby/object:Gem::Version
96
- version: 3.4.0
82
+ version: 3.5.0
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: sinatra
99
85
  requirement: !ruby/object:Gem::Requirement
@@ -190,14 +176,14 @@ dependencies:
190
176
  requirements:
191
177
  - - "~>"
192
178
  - !ruby/object:Gem::Version
193
- version: 1.10.0
179
+ version: 1.11.1
194
180
  type: :development
195
181
  prerelease: false
196
182
  version_requirements: !ruby/object:Gem::Requirement
197
183
  requirements:
198
184
  - - "~>"
199
185
  - !ruby/object:Gem::Version
200
- version: 1.10.0
186
+ version: 1.11.1
201
187
  - !ruby/object:Gem::Dependency
202
188
  name: listen
203
189
  requirement: !ruby/object:Gem::Requirement
@@ -287,7 +273,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
287
273
  version: '0'
288
274
  requirements: []
289
275
  rubyforge_project:
290
- rubygems_version: 2.5.1
276
+ rubygems_version: 2.5.2
291
277
  signing_key:
292
278
  specification_version: 4
293
279
  summary: PhantomJS driver for Capybara