Chris@0
|
1 var __slice = [].slice;
|
Chris@0
|
2
|
Chris@0
|
3 Poltergeist.Node = (function () {
|
Chris@0
|
4 var name, _fn, _i, _len, _ref;
|
Chris@0
|
5 var xpathStringLiteral;
|
Chris@0
|
6
|
Chris@0
|
7 Node.DELEGATES = ['allText', 'visibleText', 'getAttribute', 'value', 'set', 'checked',
|
Chris@0
|
8 'setAttribute', 'isObsolete', 'removeAttribute', 'isMultiple',
|
Chris@0
|
9 'select', 'tagName', 'find', 'getAttributes', 'isVisible',
|
Chris@0
|
10 'position', 'trigger', 'input', 'parentId', 'parentIds', 'mouseEventTest',
|
Chris@0
|
11 'scrollIntoView', 'isDOMEqual', 'isDisabled', 'deleteText', 'selectRadioValue',
|
Chris@0
|
12 'containsSelection', 'allHTML', 'changed', 'getXPathForElement', 'deselectAllOptions'];
|
Chris@0
|
13
|
Chris@0
|
14 function Node(page, id) {
|
Chris@0
|
15 this.page = page;
|
Chris@0
|
16 this.id = id;
|
Chris@0
|
17 }
|
Chris@0
|
18
|
Chris@0
|
19 /**
|
Chris@0
|
20 * Returns the parent Node of this Node
|
Chris@0
|
21 * @return {Poltergeist.Node}
|
Chris@0
|
22 */
|
Chris@0
|
23 Node.prototype.parent = function () {
|
Chris@0
|
24 return new Poltergeist.Node(this.page, this.parentId());
|
Chris@0
|
25 };
|
Chris@0
|
26
|
Chris@0
|
27 _ref = Node.DELEGATES;
|
Chris@0
|
28
|
Chris@0
|
29 _fn = function (name) {
|
Chris@0
|
30 return Node.prototype[name] = function () {
|
Chris@0
|
31 var args = [];
|
Chris@0
|
32 if (arguments.length >= 1) {
|
Chris@0
|
33 args = __slice.call(arguments, 0)
|
Chris@0
|
34 }
|
Chris@0
|
35 return this.page.nodeCall(this.id, name, args);
|
Chris@0
|
36 };
|
Chris@0
|
37 };
|
Chris@0
|
38
|
Chris@0
|
39 //Adding all the delegates from the agent Node to this Node
|
Chris@0
|
40 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
Chris@0
|
41 name = _ref[_i];
|
Chris@0
|
42 _fn(name);
|
Chris@0
|
43 }
|
Chris@0
|
44
|
Chris@0
|
45 xpathStringLiteral = function (s) {
|
Chris@0
|
46 if (s.indexOf('"') === -1)
|
Chris@0
|
47 return '"' + s + '"';
|
Chris@0
|
48 if (s.indexOf("'") === -1)
|
Chris@0
|
49 return "'" + s + "'";
|
Chris@0
|
50 return 'concat("' + s.replace(/"/g, '",\'"\',"') + '")';
|
Chris@0
|
51 };
|
Chris@0
|
52
|
Chris@0
|
53 /**
|
Chris@0
|
54 * Gets an x,y position tailored for mouse event actions
|
Chris@0
|
55 * @return {{x, y}}
|
Chris@0
|
56 */
|
Chris@0
|
57 Node.prototype.mouseEventPosition = function () {
|
Chris@0
|
58 var middle, pos, viewport;
|
Chris@0
|
59
|
Chris@0
|
60 viewport = this.page.viewportSize();
|
Chris@0
|
61 pos = this.position();
|
Chris@0
|
62 middle = function (start, end, size) {
|
Chris@0
|
63 return start + ((Math.min(end, size) - start) / 2);
|
Chris@0
|
64 };
|
Chris@0
|
65
|
Chris@0
|
66 return {
|
Chris@0
|
67 x: middle(pos.left, pos.right, viewport.width),
|
Chris@0
|
68 y: middle(pos.top, pos.bottom, viewport.height)
|
Chris@0
|
69 };
|
Chris@0
|
70 };
|
Chris@0
|
71
|
Chris@0
|
72 /**
|
Chris@0
|
73 * Executes a phantomjs native mouse event
|
Chris@0
|
74 * @param name
|
Chris@0
|
75 * @return {{x, y}}
|
Chris@0
|
76 */
|
Chris@0
|
77 Node.prototype.mouseEvent = function (name) {
|
Chris@0
|
78 var pos, test;
|
Chris@0
|
79
|
Chris@0
|
80 this.scrollIntoView();
|
Chris@0
|
81 pos = this.mouseEventPosition();
|
Chris@0
|
82 test = this.mouseEventTest(pos.x, pos.y);
|
Chris@0
|
83
|
Chris@0
|
84 if (test.status === 'success') {
|
Chris@0
|
85 if (name === 'rightclick') {
|
Chris@0
|
86 this.page.mouseEvent('click', pos.x, pos.y, 'right');
|
Chris@0
|
87 this.trigger('contextmenu');
|
Chris@0
|
88 } else {
|
Chris@0
|
89 this.page.mouseEvent(name, pos.x, pos.y);
|
Chris@0
|
90 }
|
Chris@0
|
91 return pos;
|
Chris@0
|
92 } else {
|
Chris@0
|
93 throw new Poltergeist.MouseEventFailed(name, test.selector, pos);
|
Chris@0
|
94 }
|
Chris@0
|
95 };
|
Chris@0
|
96
|
Chris@0
|
97 /**
|
Chris@0
|
98 * Executes a mouse based drag from one node to another
|
Chris@0
|
99 * @param other
|
Chris@0
|
100 * @return {{x, y}}
|
Chris@0
|
101 */
|
Chris@0
|
102 Node.prototype.dragTo = function (other) {
|
Chris@0
|
103 var otherPosition, position;
|
Chris@0
|
104
|
Chris@0
|
105 this.scrollIntoView();
|
Chris@0
|
106 position = this.mouseEventPosition();
|
Chris@0
|
107 otherPosition = other.mouseEventPosition();
|
Chris@0
|
108 this.page.mouseEvent('mousedown', position.x, position.y);
|
Chris@0
|
109 return this.page.mouseEvent('mouseup', otherPosition.x, otherPosition.y);
|
Chris@0
|
110 };
|
Chris@0
|
111
|
Chris@0
|
112 /**
|
Chris@0
|
113 * Checks if one node is equal to another
|
Chris@0
|
114 * @param other
|
Chris@0
|
115 * @return {boolean}
|
Chris@0
|
116 */
|
Chris@0
|
117 Node.prototype.isEqual = function (other) {
|
Chris@0
|
118 return this.page === other.page && this.isDOMEqual(other.id);
|
Chris@0
|
119 };
|
Chris@0
|
120
|
Chris@0
|
121
|
Chris@0
|
122 /**
|
Chris@0
|
123 * The value to select
|
Chris@0
|
124 * @param value
|
Chris@0
|
125 * @param multiple
|
Chris@0
|
126 */
|
Chris@0
|
127 Node.prototype.select_option = function (value, multiple) {
|
Chris@0
|
128 var tagName = this.tagName().toLowerCase();
|
Chris@0
|
129
|
Chris@0
|
130 if (tagName === "select") {
|
Chris@0
|
131 var escapedOption = xpathStringLiteral(value);
|
Chris@0
|
132 // The value of an option is the normalized version of its text when it has no value attribute
|
Chris@0
|
133 var optionQuery = ".//option[@value = " + escapedOption + " or (not(@value) and normalize-space(.) = " + escapedOption + ")]";
|
Chris@0
|
134 var ids = this.find("xpath", optionQuery);
|
Chris@0
|
135 var polterNode = this.page.get(ids[0]);
|
Chris@0
|
136
|
Chris@0
|
137 if (multiple || !this.getAttribute('multiple')) {
|
Chris@0
|
138 if (!polterNode.getAttribute('selected')) {
|
Chris@0
|
139 polterNode.select(value);
|
Chris@0
|
140 this.trigger('click');
|
Chris@0
|
141 this.input();
|
Chris@0
|
142 }
|
Chris@0
|
143 return true;
|
Chris@0
|
144 }
|
Chris@0
|
145
|
Chris@0
|
146 this.deselectAllOptions();
|
Chris@0
|
147 polterNode.select(value);
|
Chris@0
|
148 this.trigger('click');
|
Chris@0
|
149 this.input();
|
Chris@0
|
150 return true;
|
Chris@0
|
151 } else if (tagName === "input" && this.getAttribute("type").toLowerCase() === "radio") {
|
Chris@0
|
152 return this.selectRadioValue(value);
|
Chris@0
|
153 }
|
Chris@0
|
154
|
Chris@0
|
155 throw new Poltergeist.BrowserError("The element is not a select or radio input");
|
Chris@0
|
156
|
Chris@0
|
157 };
|
Chris@0
|
158
|
Chris@0
|
159 return Node;
|
Chris@0
|
160
|
Chris@0
|
161 }).call(this);
|