poltergeist 0.6.0 → 0.7.0

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