poltergeist 0.6.0 → 0.7.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.
@@ -1,54 +1,37 @@
1
- var __slice = Array.prototype.slice, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
1
+ var __slice = [].slice;
2
+
2
3
  Poltergeist.Node = (function() {
3
- var name, _fn, _i, _len, _ref;
4
- Node.DELEGATES = ['text', 'getAttribute', 'value', 'set', 'setAttribute', 'isObsolete', 'removeAttribute', 'isMultiple', 'select', 'tagName', 'find', 'isVisible', 'position', 'trigger', 'parentId', 'clickTest'];
4
+ var name, _fn, _i, _len, _ref,
5
+ _this = this;
6
+
7
+ Node.DELEGATES = ['text', 'getAttribute', 'value', 'set', 'setAttribute', 'isObsolete', 'removeAttribute', 'isMultiple', 'select', 'tagName', 'find', 'isVisible', 'position', 'trigger', 'parentId', 'clickTest', 'scrollIntoView', 'isDOMEqual'];
8
+
5
9
  function Node(page, id) {
6
10
  this.page = page;
7
11
  this.id = id;
8
12
  }
13
+
9
14
  Node.prototype.parent = function() {
10
15
  return new Poltergeist.Node(this.page, this.parentId());
11
16
  };
17
+
12
18
  _ref = Node.DELEGATES;
13
- _fn = __bind(function(name) {
14
- return this.prototype[name] = function() {
15
- var arguments, _ref2;
16
- _ref2 = arguments, arguments = 1 <= _ref2.length ? __slice.call(_ref2, 0) : [];
17
- return this.page.nodeCall(this.id, name, arguments);
19
+ _fn = function(name) {
20
+ return Node.prototype[name] = function() {
21
+ var args;
22
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
23
+ return this.page.nodeCall(this.id, name, args);
18
24
  };
19
- }, Node);
25
+ };
20
26
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
21
27
  name = _ref[_i];
22
28
  _fn(name);
23
29
  }
24
- Node.prototype.clickPosition = function(scrollIntoView) {
25
- var adjust, dimensions, document, middle, pos, scroll, viewport;
26
- if (scrollIntoView == null) {
27
- scrollIntoView = true;
28
- }
29
- dimensions = this.page.validatedDimensions();
30
- document = dimensions.document;
31
- viewport = dimensions.viewport;
30
+
31
+ Node.prototype.clickPosition = function() {
32
+ var middle, pos, viewport;
33
+ viewport = this.page.viewportSize();
32
34
  pos = this.position();
33
- scroll = {
34
- left: dimensions.left,
35
- top: dimensions.top
36
- };
37
- adjust = function(coord, measurement) {
38
- if (pos[coord] < 0) {
39
- return scroll[coord] = Math.max(0, scroll[coord] + pos[coord] - (viewport[measurement] / 2));
40
- } else if (pos[coord] >= viewport[measurement]) {
41
- return scroll[coord] = Math.min(document[measurement] - viewport[measurement], scroll[coord] + pos[coord] - viewport[measurement] + (viewport[measurement] / 2));
42
- }
43
- };
44
- if (scrollIntoView) {
45
- adjust('left', 'width');
46
- adjust('top', 'height');
47
- if (scroll.left !== dimensions.left || scroll.top !== dimensions.top) {
48
- this.page.setScrollPosition(scroll);
49
- pos = this.position();
50
- }
51
- }
52
35
  middle = function(start, end, size) {
53
36
  return start + ((Math.min(end, size) - start) / 2);
54
37
  };
@@ -57,23 +40,33 @@ Poltergeist.Node = (function() {
57
40
  y: middle(pos.top, pos.bottom, viewport.height)
58
41
  };
59
42
  };
43
+
60
44
  Node.prototype.click = function() {
61
45
  var pos, test;
46
+ this.scrollIntoView();
62
47
  pos = this.clickPosition();
63
48
  test = this.clickTest(pos.x, pos.y);
64
49
  if (test.status === 'success') {
65
50
  return this.page.sendEvent('click', pos.x, pos.y);
66
51
  } else {
67
- return new Poltergeist.ClickFailed(test.selector, pos);
52
+ throw new Poltergeist.ClickFailed(test.selector, pos);
68
53
  }
69
54
  };
55
+
70
56
  Node.prototype.dragTo = function(other) {
71
57
  var otherPosition, position;
58
+ this.scrollIntoView();
72
59
  position = this.clickPosition();
73
- otherPosition = other.clickPosition(false);
60
+ otherPosition = other.clickPosition();
74
61
  this.page.sendEvent('mousedown', position.x, position.y);
75
62
  this.page.sendEvent('mousemove', otherPosition.x, otherPosition.y);
76
63
  return this.page.sendEvent('mouseup', otherPosition.x, otherPosition.y);
77
64
  };
65
+
66
+ Node.prototype.isEqual = function(other) {
67
+ return this.page === other.page && this.isDOMEqual(other.id);
68
+ };
69
+
78
70
  return Node;
79
- }).call(this);
71
+
72
+ }).call(this);
@@ -1,17 +1,24 @@
1
- var __slice = Array.prototype.slice, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
1
+ var __slice = [].slice;
2
+
2
3
  Poltergeist.WebPage = (function() {
3
- var command, delegate, _fn, _fn2, _i, _j, _len, _len2, _ref, _ref2;
4
- WebPage.CALLBACKS = ['onAlert', 'onConsoleMessage', 'onLoadFinished', 'onInitialized', 'onLoadStarted', 'onResourceRequested', 'onResourceReceived', 'onError'];
4
+ var command, delegate, _fn, _fn1, _i, _j, _len, _len1, _ref, _ref1,
5
+ _this = this;
6
+
7
+ WebPage.CALLBACKS = ['onAlert', 'onConsoleMessage', 'onLoadFinished', 'onInitialized', 'onLoadStarted', 'onResourceRequested', 'onResourceReceived', 'onError', 'onNavigationRequested', 'onUrlChanged'];
8
+
5
9
  WebPage.DELEGATES = ['open', 'sendEvent', 'uploadFile', 'release', 'render'];
10
+
6
11
  WebPage.COMMANDS = ['currentUrl', 'find', 'nodeCall', 'pushFrame', 'popFrame', 'documentSize'];
7
- function WebPage() {
12
+
13
+ function WebPage(width, height) {
8
14
  var callback, _i, _len, _ref;
9
15
  this["native"] = require('webpage').create();
10
16
  this._source = "";
11
17
  this._errors = [];
18
+ this._networkTraffic = {};
12
19
  this.setViewportSize({
13
- width: 1024,
14
- height: 768
20
+ width: width,
21
+ height: height
15
22
  });
16
23
  _ref = WebPage.CALLBACKS;
17
24
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
@@ -20,28 +27,31 @@ Poltergeist.WebPage = (function() {
20
27
  }
21
28
  this.injectAgent();
22
29
  }
30
+
23
31
  _ref = WebPage.COMMANDS;
24
- _fn = __bind(function(command) {
25
- return this.prototype[command] = function() {
26
- var arguments, _ref2;
27
- _ref2 = arguments, arguments = 1 <= _ref2.length ? __slice.call(_ref2, 0) : [];
28
- return this.runCommand(command, arguments);
32
+ _fn = function(command) {
33
+ return WebPage.prototype[command] = function() {
34
+ var args;
35
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
36
+ return this.runCommand(command, args);
29
37
  };
30
- }, WebPage);
38
+ };
31
39
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
32
40
  command = _ref[_i];
33
41
  _fn(command);
34
42
  }
35
- _ref2 = WebPage.DELEGATES;
36
- _fn2 = __bind(function(delegate) {
37
- return this.prototype[delegate] = function() {
43
+
44
+ _ref1 = WebPage.DELEGATES;
45
+ _fn1 = function(delegate) {
46
+ return WebPage.prototype[delegate] = function() {
38
47
  return this["native"][delegate].apply(this["native"], arguments);
39
48
  };
40
- }, WebPage);
41
- for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
42
- delegate = _ref2[_j];
43
- _fn2(delegate);
49
+ };
50
+ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
51
+ delegate = _ref1[_j];
52
+ _fn1(delegate);
44
53
  }
54
+
45
55
  WebPage.prototype.onInitializedNative = function() {
46
56
  this._source = null;
47
57
  this.injectAgent();
@@ -50,64 +60,118 @@ Poltergeist.WebPage = (function() {
50
60
  top: 0
51
61
  });
52
62
  };
63
+
53
64
  WebPage.prototype.injectAgent = function() {
54
- if (this.evaluate(function() {
65
+ if (this["native"].evaluate(function() {
55
66
  return typeof __poltergeist;
56
67
  }) === "undefined") {
57
68
  this["native"].injectJs("" + phantom.libraryPath + "/agent.js");
58
69
  return this.nodes = {};
59
70
  }
60
71
  };
72
+
61
73
  WebPage.prototype.onConsoleMessageNative = function(message) {
62
74
  if (message === '__DOMContentLoaded') {
63
75
  this._source = this["native"].content;
64
76
  return false;
65
77
  }
66
78
  };
79
+
80
+ WebPage.prototype.onLoadStartedNative = function() {
81
+ return this.requestId = this.lastRequestId;
82
+ };
83
+
67
84
  WebPage.prototype.onLoadFinishedNative = function() {
68
85
  return this._source || (this._source = this["native"].content);
69
86
  };
70
- WebPage.prototype.onConsoleMessage = function(message, line, file) {
71
- if (!(this._errors.length && this._errors[this._errors.length - 1].message === message)) {
72
- return console.log(message);
73
- }
87
+
88
+ WebPage.prototype.onConsoleMessage = function(message) {
89
+ return console.log(message);
74
90
  };
91
+
75
92
  WebPage.prototype.onErrorNative = function(message, stack) {
93
+ var stackString;
94
+ stackString = message;
95
+ stack.forEach(function(frame) {
96
+ stackString += "\n";
97
+ stackString += " at " + frame.file + ":" + frame.line;
98
+ if (frame["function"] && frame["function"] !== '') {
99
+ return stackString += " in " + frame["function"];
100
+ }
101
+ });
76
102
  return this._errors.push({
77
103
  message: message,
78
- stack: stack
104
+ stack: stackString
79
105
  });
80
106
  };
107
+
108
+ WebPage.prototype.onResourceRequestedNative = function(request) {
109
+ this.lastRequestId = request.id;
110
+ return this._networkTraffic[request.id] = {
111
+ request: request,
112
+ responseParts: []
113
+ };
114
+ };
115
+
116
+ WebPage.prototype.onResourceReceivedNative = function(response) {
117
+ this._networkTraffic[response.id].responseParts.push(response);
118
+ if (this.requestId === response.id) {
119
+ if (response.redirectURL) {
120
+ return this.requestId = response.id;
121
+ } else {
122
+ return this._statusCode = response.status;
123
+ }
124
+ }
125
+ };
126
+
127
+ WebPage.prototype.networkTraffic = function() {
128
+ return this._networkTraffic;
129
+ };
130
+
81
131
  WebPage.prototype.content = function() {
82
132
  return this["native"].content;
83
133
  };
134
+
84
135
  WebPage.prototype.source = function() {
85
136
  return this._source;
86
137
  };
138
+
87
139
  WebPage.prototype.errors = function() {
88
140
  return this._errors;
89
141
  };
142
+
90
143
  WebPage.prototype.clearErrors = function() {
91
144
  return this._errors = [];
92
145
  };
146
+
147
+ WebPage.prototype.statusCode = function() {
148
+ return this._statusCode;
149
+ };
150
+
93
151
  WebPage.prototype.viewportSize = function() {
94
152
  return this["native"].viewportSize;
95
153
  };
154
+
96
155
  WebPage.prototype.setViewportSize = function(size) {
97
156
  return this["native"].viewportSize = size;
98
157
  };
158
+
99
159
  WebPage.prototype.scrollPosition = function() {
100
160
  return this["native"].scrollPosition;
101
161
  };
162
+
102
163
  WebPage.prototype.setScrollPosition = function(pos) {
103
164
  return this["native"].scrollPosition = pos;
104
165
  };
166
+
105
167
  WebPage.prototype.clipRect = function() {
106
168
  return this["native"].clipRect;
107
169
  };
170
+
108
171
  WebPage.prototype.setClipRect = function(rect) {
109
172
  return this["native"].clipRect = rect;
110
173
  };
174
+
111
175
  WebPage.prototype.dimensions = function() {
112
176
  var scroll, viewport;
113
177
  scroll = this.scrollPosition();
@@ -121,12 +185,11 @@ Poltergeist.WebPage = (function() {
121
185
  document: this.documentSize()
122
186
  };
123
187
  };
188
+
124
189
  WebPage.prototype.validatedDimensions = function() {
125
- var dimensions, document, orig_left, orig_top;
190
+ var dimensions, document;
126
191
  dimensions = this.dimensions();
127
192
  document = dimensions.document;
128
- orig_left = dimensions.left;
129
- orig_top = dimensions.top;
130
193
  if (dimensions.right > document.width) {
131
194
  dimensions.left = Math.max(0, dimensions.left - (dimensions.right - document.width));
132
195
  dimensions.right = document.width;
@@ -135,28 +198,30 @@ Poltergeist.WebPage = (function() {
135
198
  dimensions.top = Math.max(0, dimensions.top - (dimensions.bottom - document.height));
136
199
  dimensions.bottom = document.height;
137
200
  }
138
- if (dimensions.left !== orig_left || dimensions.top !== orig_top) {
139
- this.setScrollPosition({
140
- left: dimensions.left,
141
- top: dimensions.top
142
- });
143
- }
201
+ this.setScrollPosition({
202
+ left: dimensions.left,
203
+ top: dimensions.top
204
+ });
144
205
  return dimensions;
145
206
  };
207
+
146
208
  WebPage.prototype.get = function(id) {
147
209
  var _base;
148
210
  return (_base = this.nodes)[id] || (_base[id] = new Poltergeist.Node(this, id));
149
211
  };
212
+
150
213
  WebPage.prototype.evaluate = function() {
151
214
  var args, fn;
152
215
  fn = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
153
- return JSON.parse(this["native"].evaluate("function() { return JSON.stringify(" + (this.stringifyCall(fn, args)) + ") }"));
216
+ return JSON.parse(this["native"].evaluate("function() { return PoltergeistAgent.stringify(" + (this.stringifyCall(fn, args)) + ") }"));
154
217
  };
218
+
155
219
  WebPage.prototype.execute = function() {
156
220
  var args, fn;
157
221
  fn = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
158
222
  return this["native"].evaluate("function() { " + (this.stringifyCall(fn, args)) + " }");
159
223
  };
224
+
160
225
  WebPage.prototype.stringifyCall = function(fn, args) {
161
226
  if (args.length === 0) {
162
227
  return "(" + (fn.toString()) + ")()";
@@ -164,6 +229,7 @@ Poltergeist.WebPage = (function() {
164
229
  return "(" + (fn.toString()) + ").apply(this, JSON.parse(" + (JSON.stringify(JSON.stringify(args))) + "))";
165
230
  }
166
231
  };
232
+
167
233
  WebPage.prototype.bindCallback = function(name) {
168
234
  var that;
169
235
  that = this;
@@ -177,12 +243,23 @@ Poltergeist.WebPage = (function() {
177
243
  }
178
244
  };
179
245
  };
180
- WebPage.prototype.runCommand = function(name, arguments) {
246
+
247
+ WebPage.prototype.runCommand = function(name, args) {
181
248
  var result;
182
- result = this.evaluate(function(name, arguments) {
183
- return __poltergeist.externalCall(name, arguments);
184
- }, name, arguments);
185
- return result && result.value;
249
+ result = this.evaluate(function(name, args) {
250
+ return __poltergeist.externalCall(name, args);
251
+ }, name, args);
252
+ if (result.error != null) {
253
+ if (result.error.message === 'PoltergeistAgent.ObsoleteNode') {
254
+ throw new Poltergeist.ObsoleteNode;
255
+ } else {
256
+ throw new Poltergeist.JavascriptError([result.error]);
257
+ }
258
+ } else {
259
+ return result.value;
260
+ }
186
261
  };
262
+
187
263
  return WebPage;
188
- }).call(this);
264
+
265
+ }).call(this);
@@ -1,6 +1,6 @@
1
1
  class Poltergeist
2
- constructor: (port) ->
3
- @browser = new Poltergeist.Browser(this)
2
+ constructor: (port, width, height) ->
3
+ @browser = new Poltergeist.Browser(this, width, height)
4
4
  @connection = new Poltergeist.Connection(this, port)
5
5
 
6
6
  # The QtWebKit bridge doesn't seem to like Function.prototype.bind
@@ -11,7 +11,14 @@ class Poltergeist
11
11
 
12
12
  runCommand: (command) ->
13
13
  @running = true
14
- @browser[command.name].apply(@browser, command.args)
14
+
15
+ try
16
+ @browser[command.name].apply(@browser, command.args)
17
+ catch error
18
+ if error instanceof Poltergeist.Error
19
+ this.sendError(error)
20
+ else
21
+ this.sendError(new Poltergeist.BrowserError(error.toString(), error.stack))
15
22
 
16
23
  sendResponse: (response) ->
17
24
  this.send(response: response)
@@ -23,25 +30,6 @@ class Poltergeist
23
30
  args: error.args && error.args() || [error.toString()]
24
31
  )
25
32
 
26
- # This is a bit of a mess. We can't wrap the runCommand code in
27
- # a try ... catch, because that will prevent stack traces being
28
- # reported, and there is no error.stack property.
29
- #
30
- # And thrown errors get toString() called, which becomes the
31
- # value of the message variable here. So we can basically only
32
- # use strings as exceptions at the moment, which means we throw
33
- # exceptions with extra data and then retrieve it here.
34
- #
35
- # The solution will be for PhantomJS to support an e.stack
36
- # property on exceptions.
37
- #
38
- # See http://code.google.com/p/phantomjs/issues/detail?id=166.
39
- onError: (message, stack) =>
40
- if message == 'PoltergeistAgent.ObsoleteNode'
41
- this.sendError(new Poltergeist.ObsoleteNode)
42
- else
43
- this.sendError(new Poltergeist.BrowserError(message, stack))
44
-
45
33
  send: (data) ->
46
34
  # Prevents more than one response being sent for a single
47
35
  # command. This can happen in some scenarios where an error
@@ -84,4 +72,4 @@ phantom.injectJs("#{phantom.libraryPath}/node.js")
84
72
  phantom.injectJs("#{phantom.libraryPath}/connection.js")
85
73
  phantom.injectJs("#{phantom.libraryPath}/browser.js")
86
74
 
87
- new Poltergeist(phantom.args[0])
75
+ new Poltergeist(phantom.args[0], phantom.args[1], phantom.args[2])