poltergeist 1.11.0 → 1.12.0

Sign up to get free protection for your applications and to get access to all the features.
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