Commit 9d4432d9 9d4432d9644d0d948260eb286825560ec58d6e1d by Nicolas Perriault

added Casper#waitFor() and Casper#waitForSelector()

1 parent 6cbb22c8
1 .DS_Store 1 .DS_Store
2 *.xml 2 *.xml
3 *.png
......
...@@ -58,6 +58,8 @@ ...@@ -58,6 +58,8 @@
58 this.colorizer = new phantom.Casper.Colorizer(); 58 this.colorizer = new phantom.Casper.Colorizer();
59 this.currentUrl = 'about:blank'; 59 this.currentUrl = 'about:blank';
60 this.currentHTTPStatus = 200; 60 this.currentHTTPStatus = 200;
61 this.defaultWaitTimeout = 5000;
62 this.delayedExecution = false;
61 this.loadInProgress = false; 63 this.loadInProgress = false;
62 this.logLevels = ["debug", "info", "warning", "error"]; 64 this.logLevels = ["debug", "info", "warning", "error"];
63 this.logStyles = { 65 this.logStyles = {
...@@ -174,7 +176,7 @@ ...@@ -174,7 +176,7 @@
174 self.log(stepInfo + "done in " + time + "ms.", "info"); 176 self.log(stepInfo + "done in " + time + "ms.", "info");
175 self.step++; 177 self.step++;
176 } 178 }
177 if (typeof step !== "function") { 179 if (typeof step !== "function" && !self.delayedExecution) {
178 self.result.time = new Date().getTime() - self.startTime; 180 self.result.time = new Date().getTime() - self.startTime;
179 self.log("Done " + self.steps.length + " steps in " + self.result.time + 'ms.', "info"); 181 self.log("Done " + self.steps.length + " steps in " + self.result.time + 'ms.', "info");
180 clearInterval(self.checker); 182 clearInterval(self.checker);
...@@ -629,6 +631,64 @@ ...@@ -629,6 +631,64 @@
629 */ 631 */
630 thenOpenAndEvaluate: function(location, fn, replacements) { 632 thenOpenAndEvaluate: function(location, fn, replacements) {
631 return this.thenOpen(location).thenEvaluate(fn, replacements); 633 return this.thenOpen(location).thenEvaluate(fn, replacements);
634 },
635
636 /**
637 * Waits until a function returns true to process a next step.
638 *
639 * @param Function testFx A function to be evaluated for returning condition satisfecit
640 * @param Function then The next step to perform
641 * @param Number timeout The max amount of time to wait, in milliseconds
642 * @return Casper
643 */
644 waitFor: function(testFx, then, onTimeout, timeout) {
645 timeout = timeout ? timeout : this.defaultWaitTimeout;
646 if (typeof testFx !== "function") {
647 this.die("waitUntil() needs a test function");
648 }
649 if (typeof then !== "function") {
650 this.die("waitUntil() needs a next step definition");
651 }
652 this.delayedExecution = true;
653 var start = new Date().getTime();
654 var condition = false;
655 var interval = setInterval(function(self, testFx, onTimeout) {
656 if ((new Date().getTime() - start < timeout) && !condition) {
657 condition = testFx(self);
658 } else {
659 self.delayedExecution = false;
660 if (!condition) {
661 self.log("Casper.waitFor() timeout", "warning");
662 if (typeof onTimeout === "function") {
663 onTimeout(self);
664 } else {
665 self.die("Expired timeout, exiting.", "error");
666 }
667 clearInterval(interval);
668 } else {
669 self.log("waitFor() finished in " + (new Date().getTime() - start) + "ms.", "info");
670 self.then(then);
671 clearInterval(interval);
672 }
673 }
674 }, 100, this, testFx, onTimeout);
675 return this;
676 },
677
678 /**
679 * Waits until an element matching the provided CSS3 selector exists in
680 * remote DOM to process a next step.
681 *
682 * @param String selector A CSS3 selector
683 * @param Function then The next step to perform
684 * @param Number timeout The max amount of time to wait, in milliseconds
685 * @return Casper
686 */
687 waitForSelector: function(selector, then, onTimeout, timeout) {
688 timeout = timeout ? timeout : this.defaultWaitTimeout;
689 return this.waitFor(function(self) {
690 return self.exists(selector);
691 }, then, onTimeout, timeout);
632 } 692 }
633 }; 693 };
634 694
...@@ -1169,6 +1229,15 @@ ...@@ -1169,6 +1229,15 @@
1169 }; 1229 };
1170 1230
1171 /** 1231 /**
1232 * Adds a failed test entry to the stack.
1233 *
1234 * @param String message
1235 */
1236 this.fail = function(message) {
1237 this.assert(false, message);
1238 };
1239
1240 /**
1172 * Formats a message to highlight some parts of it. 1241 * Formats a message to highlight some parts of it.
1173 * 1242 *
1174 * @param String message 1243 * @param String message
...@@ -1192,6 +1261,15 @@ ...@@ -1192,6 +1261,15 @@
1192 }; 1261 };
1193 1262
1194 /** 1263 /**
1264 * Adds a successful test entry to the stack.
1265 *
1266 * @param String message
1267 */
1268 this.pass = function(message) {
1269 this.assert(true, message);
1270 };
1271
1272 /**
1195 * Render tests results, an optionnaly exit phantomjs. 1273 * Render tests results, an optionnaly exit phantomjs.
1196 * 1274 *
1197 * @param Boolean exit 1275 * @param Boolean exit
......
1 phantom.injectJs('casper.js');
2
3 var casper = new phantom.Casper({
4 logLevel: "debug",
5 verbose: true
6 });
7
8 casper.start('https://twitter.com/#!/twilio', function(self) {
9 self.waitForSelector('.tweet-row', function(self) {
10 self.captureSelector('twitter.png', 'html');
11 }, null, 12000);
12 });
13
14 casper.run(function(self) {
15 self.exit();
16 });
...\ No newline at end of file ...\ No newline at end of file
...@@ -136,6 +136,19 @@ casper.then(function(self) { ...@@ -136,6 +136,19 @@ casper.then(function(self) {
136 casper.options.verbose = true; 136 casper.options.verbose = true;
137 }); 137 });
138 138
139 // Casper.waitFor
140 casper.thenOpen('tests/site/waitFor.html', function(self) {
141 self.waitFor(function(self) {
142 return self.evaluate(function() {
143 return document.querySelectorAll('li').length === 4;
144 });
145 }, function(self) {
146 self.test.pass('Casper.waitFor() can wait for something to happen');
147 }, function(self) {
148 self.test.fail('Casper.waitFor() can wait for something to happen');
149 });
150 });
151
139 // run suite 152 // run suite
140 casper.run(function(self) { 153 casper.run(function(self) {
141 self.test.assertEquals(self.result.log.length, 3, 'log() logged messages'); 154 self.test.assertEquals(self.result.log.length, 3, 'log() logged messages');
......
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>waitFor test</title>
6 </head>
7 <body>
8 <img src="images/phantom.png"/>
9 <ul>
10 <li>one</li>
11 <li>two</li>
12 <li>three</li>
13 </ul>
14 <script>
15 setTimeout(function() {
16 var li = document.createElement('li')
17 li.appendChild(document.createTextNode('four'));
18 document.querySelector('ul').appendChild(li);
19 }, 2000);
20 </script>
21 </body>
22 </html>
...\ No newline at end of file ...\ No newline at end of file