Commit 4dc8e4ca 4dc8e4ca8e91b44112af8f57c61554f6ef5ab80f by Nicolas Perriault

integrated PR #22 into modularization branch

1 parent 8c102519
...@@ -68,7 +68,6 @@ ...@@ -68,7 +68,6 @@
68 this.currentUrl = 'about:blank'; 68 this.currentUrl = 'about:blank';
69 this.currentHTTPStatus = 200; 69 this.currentHTTPStatus = 200;
70 this.defaultWaitTimeout = 5000; 70 this.defaultWaitTimeout = 5000;
71 this.delayedExecution = false;
72 this.history = []; 71 this.history = [];
73 this.loadInProgress = false; 72 this.loadInProgress = false;
74 this.logFormats = {}; 73 this.logFormats = {};
...@@ -81,14 +80,16 @@ ...@@ -81,14 +80,16 @@
81 }; 80 };
82 this.options = mergeObjects(this.defaults, options); 81 this.options = mergeObjects(this.defaults, options);
83 this.page = null; 82 this.page = null;
83 this.pendingWait = false;
84 this.requestUrl = 'about:blank'; 84 this.requestUrl = 'about:blank';
85 this.resources = [];
85 this.result = { 86 this.result = {
86 log: [], 87 log: [],
87 status: "success", 88 status: "success",
88 time: 0 89 time: 0
89 }; 90 };
90 this.started = false; 91 this.started = false;
91 this.step = 0; 92 this.step = -1;
92 this.steps = []; 93 this.steps = [];
93 this.test = new phantom.Casper.Tester(this); 94 this.test = new phantom.Casper.Tester(this);
94 }; 95 };
...@@ -188,11 +189,13 @@ ...@@ -188,11 +189,13 @@
188 * @param function onComplete An options callback to apply on completion 189 * @param function onComplete An options callback to apply on completion
189 */ 190 */
190 checkStep: function(self, onComplete) { 191 checkStep: function(self, onComplete) {
191 var step = self.steps[self.step]; 192 if (self.pendingWait || self.loadInProgress) {
192 if (!self.loadInProgress && isType(step, "function")) { 193 return;
193 self.runStep(step);
194 } 194 }
195 if (!isType(step, "function") && !self.delayedExecution) { 195 var step = self.steps[self.step++];
196 if (isType(step, "function")) {
197 self.runStep(step);
198 } else {
196 self.result.time = new Date().getTime() - self.startTime; 199 self.result.time = new Date().getTime() - self.startTime;
197 self.log("Done " + self.steps.length + " steps in " + self.result.time + 'ms.', "info"); 200 self.log("Done " + self.steps.length + " steps in " + self.result.time + 'ms.', "info");
198 clearInterval(self.checker); 201 clearInterval(self.checker);
...@@ -592,6 +595,24 @@ ...@@ -592,6 +595,24 @@
592 }, 595 },
593 596
594 /** 597 /**
598 * Checks if a given resource was loaded by the remote page.
599 *
600 * @param Function/String test A test function or string. In case a string is passed,
601 * @return Boolean
602 */
603 resourceExists: function(test) {
604 var testFn;
605 if (isType(test, "string")) {
606 testFn = function (res) {
607 return res.url.match(test);
608 };
609 } else {
610 testFn = test;
611 }
612 return this.resources.some(testFn);
613 },
614
615 /**
595 * Runs the whole suite of steps. 616 * Runs the whole suite of steps.
596 * 617 *
597 * @param function onComplete an optional callback 618 * @param function onComplete an optional callback
...@@ -615,7 +636,7 @@ ...@@ -615,7 +636,7 @@
615 */ 636 */
616 runStep: function(step) { 637 runStep: function(step) {
617 var skipLog = isType(step.options, "object") && step.options.skipLog === true; 638 var skipLog = isType(step.options, "object") && step.options.skipLog === true;
618 var stepInfo = "Step " + (this.step + 1) + "/" + this.steps.length; 639 var stepInfo = "Step " + (this.step) + "/" + this.steps.length;
619 var stepResult; 640 var stepResult;
620 if (!skipLog) { 641 if (!skipLog) {
621 this.log(stepInfo + ' ' + this.getCurrentUrl() + ' (HTTP ' + this.currentHTTPStatus + ')', "info"); 642 this.log(stepInfo + ' ' + this.getCurrentUrl() + ' (HTTP ' + this.currentHTTPStatus + ')', "info");
...@@ -721,7 +742,20 @@ ...@@ -721,7 +742,20 @@
721 if (!isType(step, "function")) { 742 if (!isType(step, "function")) {
722 throw "You can only define a step as a function"; 743 throw "You can only define a step as a function";
723 } 744 }
724 this.steps.push(step); 745 // check if casper is running
746 if (this.checker === null) {
747 // append step to the end of the queue
748 step.level = 0;
749 this.steps.push(step);
750 } else {
751 // insert substep a level deeper
752 step.level = this.steps[this.step - 1].level + 1;
753 var insertIndex = this.step;
754 while (this.steps[insertIndex] && step.level === this.steps[insertIndex].level) {
755 insertIndex++;
756 }
757 this.steps.splice(insertIndex, 0, step);
758 }
725 return this; 759 return this;
726 }, 760 },
727 761
...@@ -825,21 +859,25 @@ ...@@ -825,21 +859,25 @@
825 this.die("wait() a step definition must be a function"); 859 this.die("wait() a step definition must be a function");
826 } 860 }
827 return this.then(function(self) { 861 return this.then(function(self) {
828 self.delayedExecution = true; 862 self.waitStart();
829 var start = new Date().getTime(); 863 setTimeout(function() {
830 var interval = setInterval(function(self, then) { 864 self.log("wait() finished wating for " + timeout + "ms.", "info");
831 if (new Date().getTime() - start > timeout) { 865 if (then) {
832 self.delayedExecution = false; 866 then.call(self, self);
833 self.log("wait() finished wating for " + timeout + "ms.", "info"); 867 }
834 if (then) { 868 self.waitDone();
835 self.then(then); 869 }, timeout);
836 }
837 clearInterval(interval);
838 }
839 }, 100, self, then);
840 }); 870 });
841 }, 871 },
842 872
873 waitStart: function() {
874 this.pendingWait = true;
875 },
876
877 waitDone: function() {
878 this.pendingWait = false;
879 },
880
843 /** 881 /**
844 * Waits until a function returns true to process a next step. 882 * Waits until a function returns true to process a next step.
845 * 883 *
...@@ -857,32 +895,49 @@ ...@@ -857,32 +895,49 @@
857 if (then && !isType(then, "function")) { 895 if (then && !isType(then, "function")) {
858 this.die("waitFor() next step definition must be a function"); 896 this.die("waitFor() next step definition must be a function");
859 } 897 }
860 this.delayedExecution = true; 898 return this.then(function(self) {
861 var start = new Date().getTime(); 899 self.waitStart();
862 var condition = false; 900 var start = new Date().getTime();
863 var interval = setInterval(function(self, testFx, onTimeout) { 901 var condition = false;
864 if ((new Date().getTime() - start < timeout) && !condition) { 902 var interval = setInterval(function(self, testFx, onTimeout) {
865 condition = testFx(self); 903 if ((new Date().getTime() - start < timeout) && !condition) {
866 } else { 904 condition = testFx(self);
867 self.delayedExecution = false;
868 if (!condition) {
869 self.log("Casper.waitFor() timeout", "warning");
870 if (isType(onTimeout, "function")) {
871 onTimeout.call(self, self);
872 } else {
873 self.die("Expired timeout, exiting.", "error");
874 }
875 clearInterval(interval);
876 } else { 905 } else {
877 self.log("waitFor() finished in " + (new Date().getTime() - start) + "ms.", "info"); 906 self.waitDone();
878 if (then) { 907 if (!condition) {
879 self.then(then); 908 self.log("Casper.waitFor() timeout", "warning");
909 if (isType(onTimeout, "function")) {
910 onTimeout.call(self, self);
911 } else {
912 self.die("Expired timeout, exiting.", "error");
913 }
914 clearInterval(interval);
915 } else {
916 self.log("waitFor() finished in " + (new Date().getTime() - start) + "ms.", "info");
917 if (then) {
918 self.then(then);
919 }
920 clearInterval(interval);
880 } 921 }
881 clearInterval(interval);
882 } 922 }
883 } 923 }, 100, self, testFx, onTimeout);
884 }, 100, this, testFx, onTimeout); 924 });
885 return this; 925 },
926
927 /**
928 * Waits until a given resource is loaded
929 *
930 * @param String/Function test A function to test if the resource exists. A string will be matched against the resources url.
931 * @param Function then The next step to perform (optional)
932 * @param Function onTimeout A callback function to call on timeout (optional)
933 * @param Number timeout The max amount of time to wait, in milliseconds (optional)
934 * @return Casper
935 */
936 waitForResource: function(test, then, onTimeout, timeout) {
937 timeout = timeout ? timeout : this.defaultWaitTimeout;
938 return this.waitFor(function(self) {
939 return self.resourceExists(test);
940 }, then, onTimeout, timeout);
886 }, 941 },
887 942
888 /** 943 /**
......
...@@ -177,6 +177,16 @@ ...@@ -177,6 +177,16 @@
177 }; 177 };
178 178
179 /** 179 /**
180 * Asserts that the current page has a resource that matches the provided test
181 *
182 * @param Function/String test A test function that is called with every response
183 * @param String message Test description
184 */
185 this.assertResourceExists = function(test, message) {
186 return this.assert(casper.resourceExists(test), message);
187 };
188
189 /**
180 * Asserts that at least an element matching the provided CSS3 selector 190 * Asserts that at least an element matching the provided CSS3 selector
181 * exists in remote DOM. 191 * exists in remote DOM.
182 * 192 *
......
...@@ -70,6 +70,7 @@ function createPage(casper) { ...@@ -70,6 +70,7 @@ function createPage(casper) {
70 casper.log(msg, level, "remote"); 70 casper.log(msg, level, "remote");
71 }; 71 };
72 page.onLoadStarted = function() { 72 page.onLoadStarted = function() {
73 casper.resources = [];
73 casper.loadInProgress = true; 74 casper.loadInProgress = true;
74 }; 75 };
75 page.onLoadFinished = function(status) { 76 page.onLoadFinished = function(status) {
...@@ -119,6 +120,9 @@ function createPage(casper) { ...@@ -119,6 +120,9 @@ function createPage(casper) {
119 if (isType(casper.options.onResourceReceived, "function")) { 120 if (isType(casper.options.onResourceReceived, "function")) {
120 casper.options.onResourceReceived.call(casper, casper, resource); 121 casper.options.onResourceReceived.call(casper, casper, resource);
121 } 122 }
123 if (resource.stage === "end") {
124 casper.resources.push(resource);
125 }
122 if (resource.url === casper.requestUrl && resource.stage === "start") { 126 if (resource.url === casper.requestUrl && resource.stage === "start") {
123 casper.currentHTTPStatus = resource.status; 127 casper.currentHTTPStatus = resource.status;
124 if (isType(casper.options.httpStatusHandlers, "object") && resource.status in casper.options.httpStatusHandlers) { 128 if (isType(casper.options.httpStatusHandlers, "object") && resource.status in casper.options.httpStatusHandlers) {
......
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>CasperJS test resource</title>
6 <script>
7 setTimeout(function () {
8 document.querySelector("img").setAttribute("src","images/phantom.png");
9 }, 1000);
10 </script>
11 </head>
12 <body>
13 <img width="55" height="55" border="1">
14 </body>
15 </html>
...\ No newline at end of file ...\ No newline at end of file
1 do(casper) ->
2 step = 0
3
4 # testing resources
5 casper.start "tests/site/resources.html", ->
6 @test.assertEquals ++step, 1, "step 1"
7 @wait 400, ->
8 @test.assertEquals ++step, 2, "step 1.1"
9 @wait 200, ->
10 @test.assertEquals ++step, 3, "step 1.1.1"
11 @wait 200, ->
12 @test.assertEquals ++step, 4, "step 1.1.1.1"
13 @then ->
14 @test.assertEquals ++step, 5, "step 1.1.2.1"
15 @wait 400, ->
16 @test.assertEquals ++step, 6, "step 1.2"
17
18 casper.wait 200, ->
19 @test.assertEquals ++step, 7, "step 2"
20
21 casper.waitForSelector(
22 '#noneExistingSelector'
23 -> @test.fail "should run into timeout"
24 -> @test.assertEquals ++step, 8, "step 3 sucessfully timed out"
25 1000
26 )
27 casper.then ->
28 @test.assertEquals ++step, 9, "step 4"
29 @wait 300, ->
30 @test.assertEquals ++step, 10, "step 4.1"
31 @wait 300, ->
32 @test.assertEquals ++step, 11, "step 4.1.1"
33 @wait 100, ->
34 @test.assertEquals ++step, 12, "step 5.2"
35
36 casper.then ->
37 @test.assertEquals ++step, 13, "last step"
38
39 casper.run(-> @test.done())
...\ No newline at end of file ...\ No newline at end of file
1 do(casper) ->
2 casper.onError = ->
3 console.log 'err'
4 casper.start "tests/site/resources.html", ->
5 console.log 'loaded'
6 @test.assertEquals @resources.length, 1, "only one resource found"
7 @waitForResource "phantom.png", ->
8 @test.assertEquals(
9 @resources.length
10 2
11 "two resources found"
12 )
13 @test.assertResourceExists(
14 (res) -> res.url.match "phantom.png"
15 "phantom image found via test function"
16 )
17 @test.assertResourceExists(
18 "phantom.png"
19 "phantom image found via test string"
20 )
21
22 casper.run(-> @test.done())