casperjs 1.0.0.RC1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. data/CHANGELOG.md +179 -0
  2. data/LICENSE.md +19 -0
  3. data/README.md +30 -0
  4. data/bin/bootstrap.js +292 -0
  5. data/bin/usage.txt +10 -0
  6. data/casperjs.gemspec +21 -0
  7. data/modules/casper.js +1679 -0
  8. data/modules/cli.js +138 -0
  9. data/modules/clientutils.js +595 -0
  10. data/modules/colorizer.js +129 -0
  11. data/modules/events.js +247 -0
  12. data/modules/injector.js +93 -0
  13. data/modules/mouse.js +110 -0
  14. data/modules/querystring.js +187 -0
  15. data/modules/tester.js +807 -0
  16. data/modules/utils.js +429 -0
  17. data/modules/vendors/coffee-script.js +8 -0
  18. data/modules/xunit.js +123 -0
  19. data/package.json +35 -0
  20. data/rubybin/casperjs +57 -0
  21. data/samples/bbcshots.coffee +64 -0
  22. data/samples/bbcshots.js +80 -0
  23. data/samples/cliplay.coffee +19 -0
  24. data/samples/cliplay.js +21 -0
  25. data/samples/customevents.coffee +11 -0
  26. data/samples/customevents.js +13 -0
  27. data/samples/customlogging.coffee +33 -0
  28. data/samples/customlogging.js +42 -0
  29. data/samples/download.coffee +10 -0
  30. data/samples/download.js +11 -0
  31. data/samples/dynamic.coffee +60 -0
  32. data/samples/dynamic.js +65 -0
  33. data/samples/each.coffee +14 -0
  34. data/samples/each.js +17 -0
  35. data/samples/events.coffee +34 -0
  36. data/samples/events.js +41 -0
  37. data/samples/extends.coffee +29 -0
  38. data/samples/extends.js +37 -0
  39. data/samples/googlelinks.coffee +27 -0
  40. data/samples/googlelinks.js +33 -0
  41. data/samples/googlematch.coffee +47 -0
  42. data/samples/googlematch.js +65 -0
  43. data/samples/googlepagination.coffee +40 -0
  44. data/samples/googlepagination.js +51 -0
  45. data/samples/googletesting.coffee +17 -0
  46. data/samples/googletesting.js +23 -0
  47. data/samples/logcolor.coffee +10 -0
  48. data/samples/logcolor.js +11 -0
  49. data/samples/metaextract.coffee +23 -0
  50. data/samples/metaextract.js +29 -0
  51. data/samples/multirun.coffee +37 -0
  52. data/samples/multirun.js +56 -0
  53. data/samples/screenshot.coffee +28 -0
  54. data/samples/screenshot.js +33 -0
  55. data/samples/statushandlers.coffee +15 -0
  56. data/samples/statushandlers.js +19 -0
  57. data/samples/steptimeout.coffee +37 -0
  58. data/samples/steptimeout.js +45 -0
  59. data/samples/timeout.coffee +39 -0
  60. data/samples/timeout.js +47 -0
  61. data/tests/run.js +76 -0
  62. data/tests/site/alert.html +10 -0
  63. data/tests/site/click.html +40 -0
  64. data/tests/site/confirm.html +12 -0
  65. data/tests/site/elementattribute.html +6 -0
  66. data/tests/site/error.html +10 -0
  67. data/tests/site/form.html +26 -0
  68. data/tests/site/global.html +9 -0
  69. data/tests/site/images/phantom.png +0 -0
  70. data/tests/site/index.html +17 -0
  71. data/tests/site/mouse-events.html +47 -0
  72. data/tests/site/multiple-forms.html +16 -0
  73. data/tests/site/page1.html +8 -0
  74. data/tests/site/page2.html +8 -0
  75. data/tests/site/page3.html +8 -0
  76. data/tests/site/prompt.html +12 -0
  77. data/tests/site/resources.html +16 -0
  78. data/tests/site/result.html +11 -0
  79. data/tests/site/test.html +10 -0
  80. data/tests/site/visible.html +17 -0
  81. data/tests/site/waitFor.html +22 -0
  82. data/tests/suites/casper/agent.js +24 -0
  83. data/tests/suites/casper/capture.js +31 -0
  84. data/tests/suites/casper/click.js +61 -0
  85. data/tests/suites/casper/confirm.js +21 -0
  86. data/tests/suites/casper/elementattribute.js +8 -0
  87. data/tests/suites/casper/encode.js +20 -0
  88. data/tests/suites/casper/evaluate.js +27 -0
  89. data/tests/suites/casper/events.js +38 -0
  90. data/tests/suites/casper/exists.js +9 -0
  91. data/tests/suites/casper/fetchtext.js +9 -0
  92. data/tests/suites/casper/flow.coffee +38 -0
  93. data/tests/suites/casper/formfill.js +69 -0
  94. data/tests/suites/casper/global.js +9 -0
  95. data/tests/suites/casper/history.js +21 -0
  96. data/tests/suites/casper/hooks.js +41 -0
  97. data/tests/suites/casper/logging.js +38 -0
  98. data/tests/suites/casper/mouseevents.js +27 -0
  99. data/tests/suites/casper/onerror.js +19 -0
  100. data/tests/suites/casper/open.js +73 -0
  101. data/tests/suites/casper/prompt.js +17 -0
  102. data/tests/suites/casper/resources.coffee +24 -0
  103. data/tests/suites/casper/start.js +15 -0
  104. data/tests/suites/casper/steps.js +32 -0
  105. data/tests/suites/casper/viewport.js +11 -0
  106. data/tests/suites/casper/visible.js +17 -0
  107. data/tests/suites/casper/wait.js +27 -0
  108. data/tests/suites/casper/xpath.js +32 -0
  109. data/tests/suites/cli.js +125 -0
  110. data/tests/suites/clientutils.js +84 -0
  111. data/tests/suites/coffee.coffee +19 -0
  112. data/tests/suites/fs.js +36 -0
  113. data/tests/suites/http_status.js +28 -0
  114. data/tests/suites/injector.js +64 -0
  115. data/tests/suites/tester.js +121 -0
  116. data/tests/suites/utils.js +209 -0
  117. data/tests/suites/xunit.js +16 -0
  118. data/tests/testdir/01_a/abc.js +0 -0
  119. data/tests/testdir/01_a/def.js +0 -0
  120. data/tests/testdir/02_b/abc.js +0 -0
  121. data/tests/testdir/03_a.js +0 -0
  122. data/tests/testdir/03_b.js +0 -0
  123. data/tests/testdir/04/01_init.js +0 -0
  124. data/tests/testdir/04/02_do.js +0 -0
  125. metadata +192 -0
@@ -0,0 +1,129 @@
1
+ /*!
2
+ * Casper is a navigation utility for PhantomJS.
3
+ *
4
+ * Documentation: http://casperjs.org/
5
+ * Repository: http://github.com/n1k0/casperjs
6
+ *
7
+ * Copyright (c) 2011-2012 Nicolas Perriault
8
+ *
9
+ * Part of source code is Copyright Joyent, Inc. and other Node contributors.
10
+ *
11
+ * Permission is hereby granted, free of charge, to any person obtaining a
12
+ * copy of this software and associated documentation files (the "Software"),
13
+ * to deal in the Software without restriction, including without limitation
14
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15
+ * and/or sell copies of the Software, and to permit persons to whom the
16
+ * Software is furnished to do so, subject to the following conditions:
17
+ *
18
+ * The above copyright notice and this permission notice shall be included
19
+ * in all copies or substantial portions of the Software.
20
+ *
21
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27
+ * DEALINGS IN THE SOFTWARE.
28
+ *
29
+ */
30
+
31
+ /*global exports console require*/
32
+
33
+ var fs = require('fs');
34
+ var utils = require('utils');
35
+
36
+ exports.create = function create(type) {
37
+ "use strict";
38
+ if (!type) {
39
+ return;
40
+ }
41
+ if (!(type in exports)) {
42
+ throw new Error(utils.format('Unsupported colorizer type "%s"', type));
43
+ }
44
+ return new exports[type]();
45
+ };
46
+
47
+ /**
48
+ * This is a port of lime colorizer.
49
+ * http://trac.symfony-project.org/browser/tools/lime/trunk/lib/lime.php
50
+ *
51
+ * (c) Fabien Potencier, Symfony project, MIT license
52
+ */
53
+ var Colorizer = function Colorizer() {
54
+ "use strict";
55
+ var options = { bold: 1, underscore: 4, blink: 5, reverse: 7, conceal: 8 };
56
+ var foreground = { black: 30, red: 31, green: 32, yellow: 33, blue: 34, magenta: 35, cyan: 36, white: 37 };
57
+ var background = { black: 40, red: 41, green: 42, yellow: 43, blue: 44, magenta: 45, cyan: 46, white: 47 };
58
+ var styles = {
59
+ 'ERROR': { bg: 'red', fg: 'white', bold: true },
60
+ 'INFO': { fg: 'green', bold: true },
61
+ 'TRACE': { fg: 'green', bold: true },
62
+ 'PARAMETER': { fg: 'cyan' },
63
+ 'COMMENT': { fg: 'yellow' },
64
+ 'WARNING': { fg: 'red', bold: true },
65
+ 'GREEN_BAR': { fg: 'white', bg: 'green', bold: true },
66
+ 'RED_BAR': { fg: 'white', bg: 'red', bold: true },
67
+ 'INFO_BAR': { bg: 'cyan', fg: 'white', bold: true }
68
+ };
69
+
70
+ /**
71
+ * Adds a style to provided text.
72
+ *
73
+ * @param String text
74
+ * @param String styleName
75
+ * @return String
76
+ */
77
+ this.colorize = function colorize(text, styleName, pad) {
78
+ if (fs.isWindows() || !(styleName in styles)) {
79
+ return text;
80
+ }
81
+ return this.format(text, styles[styleName], pad);
82
+ };
83
+
84
+ /**
85
+ * Formats a text using a style declaration object.
86
+ *
87
+ * @param String text
88
+ * @param Object style
89
+ * @return String
90
+ */
91
+ this.format = function format(text, style, pad) {
92
+ if (fs.isWindows() || !utils.isObject(style)) {
93
+ return text;
94
+ }
95
+ var codes = [];
96
+ if (style.fg && foreground[style.fg]) {
97
+ codes.push(foreground[style.fg]);
98
+ }
99
+ if (style.bg && background[style.bg]) {
100
+ codes.push(background[style.bg]);
101
+ }
102
+ for (var option in options) {
103
+ if (style[option] === true) {
104
+ codes.push(options[option]);
105
+ }
106
+ }
107
+ // pad
108
+ if (typeof pad === "number" && text.length < pad) {
109
+ text += new Array(pad - text.length + 1).join(' ');
110
+ }
111
+ return "\u001b[" + codes.join(';') + 'm' + text + "\u001b[0m";
112
+ };
113
+ };
114
+ exports.Colorizer = Colorizer;
115
+
116
+ /**
117
+ * Dummy colorizer. Does basically nothing.
118
+ *
119
+ */
120
+ var Dummy = function Dummy() {
121
+ "use strict";
122
+ this.colorize = function colorize(text, styleName, pad) {
123
+ return text;
124
+ };
125
+ this.format = function format(text, style, pad){
126
+ return text;
127
+ };
128
+ };
129
+ exports.Dummy = Dummy;
@@ -0,0 +1,247 @@
1
+ // Copyright Joyent, Inc. and other Node contributors.
2
+ //
3
+ // Permission is hereby granted, free of charge, to any person obtaining a
4
+ // copy of this software and associated documentation files (the
5
+ // "Software"), to deal in the Software without restriction, including
6
+ // without limitation the rights to use, copy, modify, merge, publish,
7
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ // persons to whom the Software is furnished to do so, subject to the
9
+ // following conditions:
10
+ //
11
+ // The above copyright notice and this permission notice shall be included
12
+ // in all copies or substantial portions of the Software.
13
+ //
14
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ var isArray = Array.isArray;
23
+
24
+ function EventEmitter() {
25
+ this._filters = {};
26
+ }
27
+ exports.EventEmitter = EventEmitter;
28
+
29
+ // By default EventEmitters will print a warning if more than
30
+ // 10 listeners are added to it. This is a useful default which
31
+ // helps finding memory leaks.
32
+ //
33
+ // Obviously not all Emitters should be limited to 10. This function allows
34
+ // that to be increased. Set to zero for unlimited.
35
+ var defaultMaxListeners = 10;
36
+ EventEmitter.prototype.setMaxListeners = function(n) {
37
+ if (!this._events) this._events = {};
38
+ this._maxListeners = n;
39
+ };
40
+
41
+
42
+ EventEmitter.prototype.emit = function() {
43
+ var type = arguments[0];
44
+ // If there is no 'error' event listener then throw.
45
+ if (type === 'error') {
46
+ if (!this._events || !this._events.error ||
47
+ (isArray(this._events.error) && !this._events.error.length))
48
+ {
49
+ if (arguments[1] instanceof Error) {
50
+ throw arguments[1]; // Unhandled 'error' event
51
+ } else {
52
+ throw new CasperError("Uncaught, unspecified 'error' event.");
53
+ }
54
+ return false;
55
+ }
56
+ }
57
+
58
+ if (!this._events) return false;
59
+ var handler = this._events[type];
60
+ if (!handler) return false;
61
+
62
+ if (typeof handler == 'function') {
63
+ switch (arguments.length) {
64
+ // fast cases
65
+ case 1:
66
+ handler.call(this);
67
+ break;
68
+ case 2:
69
+ handler.call(this, arguments[1]);
70
+ break;
71
+ case 3:
72
+ handler.call(this, arguments[1], arguments[2]);
73
+ break;
74
+ // slower
75
+ default:
76
+ var l = arguments.length;
77
+ var args = new Array(l - 1);
78
+ for (var i = 1; i < l; i++) args[i - 1] = arguments[i];
79
+ handler.apply(this, args);
80
+ }
81
+ return true;
82
+
83
+ } else if (isArray(handler)) {
84
+ var l = arguments.length;
85
+ var args = new Array(l - 1);
86
+ for (var i = 1; i < l; i++) args[i - 1] = arguments[i];
87
+
88
+ var listeners = handler.slice();
89
+ for (var i = 0, l = listeners.length; i < l; i++) {
90
+ listeners[i].apply(this, args);
91
+ }
92
+ return true;
93
+
94
+ } else {
95
+ return false;
96
+ }
97
+ };
98
+
99
+ // EventEmitter is defined in src/node_events.cc
100
+ // EventEmitter.prototype.emit() is also defined there.
101
+ EventEmitter.prototype.addListener = function(type, listener) {
102
+ if ('function' !== typeof listener) {
103
+ throw new CasperError('addListener only takes instances of Function');
104
+ }
105
+
106
+ if (!this._events) this._events = {};
107
+
108
+ // To avoid recursion in the case that type == "newListeners"! Before
109
+ // adding it to the listeners, first emit "newListeners".
110
+ this.emit('newListener', type, listener);
111
+
112
+ if (!this._events[type]) {
113
+ // Optimize the case of one listener. Don't need the extra array object.
114
+ this._events[type] = listener;
115
+ } else if (isArray(this._events[type])) {
116
+
117
+ // If we've already got an array, just append.
118
+ this._events[type].push(listener);
119
+
120
+ // Check for listener leak
121
+ if (!this._events[type].warned) {
122
+ var m;
123
+ if (this._maxListeners !== undefined) {
124
+ m = this._maxListeners;
125
+ } else {
126
+ m = defaultMaxListeners;
127
+ }
128
+
129
+ if (m && m > 0 && this._events[type].length > m) {
130
+ this._events[type].warned = true;
131
+ console.error('(node) warning: possible EventEmitter memory ' +
132
+ 'leak detected. %d listeners added. ' +
133
+ 'Use emitter.setMaxListeners() to increase limit.',
134
+ this._events[type].length);
135
+ console.trace();
136
+ }
137
+ }
138
+ } else {
139
+ // Adding the second element, need to change to array.
140
+ this._events[type] = [this._events[type], listener];
141
+ }
142
+
143
+ return this;
144
+ };
145
+
146
+ EventEmitter.prototype.on = EventEmitter.prototype.addListener;
147
+
148
+ EventEmitter.prototype.once = function(type, listener) {
149
+ if ('function' !== typeof listener) {
150
+ throw new CasperError('.once only takes instances of Function');
151
+ }
152
+
153
+ var self = this;
154
+ function g() {
155
+ self.removeListener(type, g);
156
+ listener.apply(this, arguments);
157
+ };
158
+
159
+ g.listener = listener;
160
+ self.on(type, g);
161
+
162
+ return this;
163
+ };
164
+
165
+ EventEmitter.prototype.removeListener = function(type, listener) {
166
+ if ('function' !== typeof listener) {
167
+ throw new CasperError('removeListener only takes instances of Function');
168
+ }
169
+
170
+ // does not use listeners(), so no side effect of creating _events[type]
171
+ if (!this._events || !this._events[type]) return this;
172
+
173
+ var list = this._events[type];
174
+
175
+ if (isArray(list)) {
176
+ var position = -1;
177
+ for (var i = 0, length = list.length; i < length; i++) {
178
+ if (list[i] === listener ||
179
+ (list[i].listener && list[i].listener === listener))
180
+ {
181
+ position = i;
182
+ break;
183
+ }
184
+ }
185
+
186
+ if (position < 0) return this;
187
+ list.splice(position, 1);
188
+ if (list.length == 0)
189
+ delete this._events[type];
190
+ } else if (list === listener ||
191
+ (list.listener && list.listener === listener))
192
+ {
193
+ delete this._events[type];
194
+ }
195
+
196
+ return this;
197
+ };
198
+
199
+ EventEmitter.prototype.removeAllListeners = function(type) {
200
+ if (arguments.length === 0) {
201
+ this._events = {};
202
+ return this;
203
+ }
204
+
205
+ // does not use listeners(), so no side effect of creating _events[type]
206
+ if (type && this._events && this._events[type]) this._events[type] = null;
207
+ return this;
208
+ };
209
+
210
+ EventEmitter.prototype.listeners = function(type) {
211
+ if (!this._events) this._events = {};
212
+ if (!this._events[type]) this._events[type] = [];
213
+ if (!isArray(this._events[type])) {
214
+ this._events[type] = [this._events[type]];
215
+ }
216
+ return this._events[type];
217
+ };
218
+
219
+ // Added for CasperJS: filters a value attached to an event
220
+ EventEmitter.prototype.filter = function() {
221
+ var type = arguments[0];
222
+ if (!this._filters) {
223
+ this._filters = {};
224
+ return;
225
+ }
226
+
227
+ var filter = this._filters[type];
228
+ if (typeof filter !== 'function') {
229
+ return;
230
+ }
231
+ return filter.apply(this, Array.prototype.splice.call(arguments, 1));
232
+ };
233
+
234
+ EventEmitter.prototype.setFilter = function(type, filterFn) {
235
+ if (!this._filters) {
236
+ this._filters = {};
237
+ }
238
+ if ('function' !== typeof filterFn) {
239
+ throw new CasperError('setFilter only takes instances of Function');
240
+ }
241
+ if (!this._filters[type]) {
242
+ this._filters[type] = filterFn;
243
+ return true;
244
+ }
245
+ // TODO: process multiple filters? in which order? disallow?
246
+ return false;
247
+ };
@@ -0,0 +1,93 @@
1
+ /*!
2
+ * Casper is a navigation utility for PhantomJS.
3
+ *
4
+ * Documentation: http://casperjs.org/
5
+ * Repository: http://github.com/n1k0/casperjs
6
+ *
7
+ * Copyright (c) 2011-2012 Nicolas Perriault
8
+ *
9
+ * Part of source code is Copyright Joyent, Inc. and other Node contributors.
10
+ *
11
+ * Permission is hereby granted, free of charge, to any person obtaining a
12
+ * copy of this software and associated documentation files (the "Software"),
13
+ * to deal in the Software without restriction, including without limitation
14
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15
+ * and/or sell copies of the Software, and to permit persons to whom the
16
+ * Software is furnished to do so, subject to the following conditions:
17
+ *
18
+ * The above copyright notice and this permission notice shall be included
19
+ * in all copies or substantial portions of the Software.
20
+ *
21
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27
+ * DEALINGS IN THE SOFTWARE.
28
+ *
29
+ */
30
+
31
+ /*global CasperError console encodeURIComponent escape exports require*/
32
+
33
+ var utils = require('utils');
34
+
35
+ exports.create = function create(fn) {
36
+ "use strict";
37
+ return new FunctionArgsInjector(fn);
38
+ };
39
+
40
+ /**
41
+ * Function argument injector.
42
+ *
43
+ * FIXME: use new Function() instead of eval()
44
+ */
45
+ var FunctionArgsInjector = function FunctionArgsInjector(fn) {
46
+ "use strict";
47
+ if (!utils.isFunction(fn)) {
48
+ throw new CasperError("FunctionArgsInjector() can only process functions");
49
+ }
50
+ this.fn = fn;
51
+
52
+ this.extract = function extract(fn) {
53
+ var match = /^function\s?(\w+)?\s?\((.*)\)\s?\{([\s\S]*)\}/i.exec(fn.toString().trim());
54
+ if (match && match.length > 1) {
55
+ var args = match[2].split(',').map(function _map(arg) {
56
+ return arg.replace(new RegExp(/\/\*+.*\*\//ig), "").trim();
57
+ }).filter(function _filter(arg) {
58
+ return arg;
59
+ }) || [];
60
+ return {
61
+ name: match[1] ? match[1].trim() : null,
62
+ args: args,
63
+ body: match[3] ? match[3].trim() : ''
64
+ };
65
+ }
66
+ };
67
+
68
+ this.process = function process(values) {
69
+ var fnObj = this.extract(this.fn);
70
+ if (!utils.isObject(fnObj)) {
71
+ throw new CasperError("Unable to process function " + this.fn.toString());
72
+ }
73
+ var inject = this.getArgsInjectionString(fnObj.args, values);
74
+ var newFn = new Function([inject, fnObj.body].join('\n'));
75
+ newFn.name = fnObj.name || '';
76
+ return newFn;
77
+ };
78
+
79
+ this.getArgsInjectionString = function getArgsInjectionString(args, values) {
80
+ values = typeof values === "object" ? values : {};
81
+ var jsonValues = escape(encodeURIComponent(JSON.stringify(values)));
82
+ var inject = [
83
+ 'var __casper_params__ = JSON.parse(decodeURIComponent(unescape(\'' + jsonValues + '\')));'
84
+ ];
85
+ args.forEach(function _forEach(arg) {
86
+ if (arg in values) {
87
+ inject.push('var ' + arg + '=__casper_params__["' + arg + '"];');
88
+ }
89
+ });
90
+ return inject.join('\n') + '\n';
91
+ };
92
+ };
93
+ exports.FunctionArgsInjector = FunctionArgsInjector;