added Casper#getCurrentUrl() & onLoadError callback option + tests
Showing
4 changed files
with
83 additions
and
23 deletions
... | @@ -33,6 +33,7 @@ | ... | @@ -33,6 +33,7 @@ |
33 | * logLevel | String | "error" | Logging level (see logLevels for available values) | 33 | * logLevel | String | "error" | Logging level (see logLevels for available values) |
34 | * onDie | function | null | A function to be called when Casper#die() is called | 34 | * onDie | function | null | A function to be called when Casper#die() is called |
35 | * onError | function | null | A function to be called when an "error" level event occurs | 35 | * onError | function | null | A function to be called when an "error" level event occurs |
36 | * onLoadError | function | null | A function to be called when a requested resource cannot be loaded | ||
36 | * onPageInitialized | function | null | A function to be called after WebPage instance has been initialized | 37 | * onPageInitialized | function | null | A function to be called after WebPage instance has been initialized |
37 | * page | WebPage | null | An existing WebPage instance | 38 | * page | WebPage | null | An existing WebPage instance |
38 | * pageSettings | Object | {} | PhantomJS's WebPage settings object | 39 | * pageSettings | Object | {} | PhantomJS's WebPage settings object |
... | @@ -56,6 +57,7 @@ | ... | @@ -56,6 +57,7 @@ |
56 | logLevel: "error", | 57 | logLevel: "error", |
57 | onDie: null, | 58 | onDie: null, |
58 | onError: null, | 59 | onError: null, |
60 | onLoadError: null, | ||
59 | onPageInitialized: null, | 61 | onPageInitialized: null, |
60 | page: null, | 62 | page: null, |
61 | pageSettings: { userAgent: DEFAULT_USER_AGENT }, | 63 | pageSettings: { userAgent: DEFAULT_USER_AGENT }, |
... | @@ -64,6 +66,7 @@ | ... | @@ -64,6 +66,7 @@ |
64 | }; | 66 | }; |
65 | // local properties | 67 | // local properties |
66 | this.checker = null; | 68 | this.checker = null; |
69 | this.currentUrl = 'about:blank'; | ||
67 | this.currentHTTPStatus = 200; | 70 | this.currentHTTPStatus = 200; |
68 | this.loadInProgress = false; | 71 | this.loadInProgress = false; |
69 | this.logLevels = ["debug", "info", "warning", "error"]; | 72 | this.logLevels = ["debug", "info", "warning", "error"]; |
... | @@ -358,6 +361,17 @@ | ... | @@ -358,6 +361,17 @@ |
358 | }, | 361 | }, |
359 | 362 | ||
360 | /** | 363 | /** |
364 | * Retrieve current document url. | ||
365 | * | ||
366 | * @return String | ||
367 | */ | ||
368 | getCurrentUrl: function() { | ||
369 | return decodeURIComponent(this.evaluate(function() { | ||
370 | return document.location.href; | ||
371 | })); | ||
372 | }, | ||
373 | |||
374 | /** | ||
361 | * Logs a message. | 375 | * Logs a message. |
362 | * | 376 | * |
363 | * @param String message The message to log | 377 | * @param String message The message to log |
... | @@ -568,14 +582,8 @@ | ... | @@ -568,14 +582,8 @@ |
568 | * @return Boolean | 582 | * @return Boolean |
569 | */ | 583 | */ |
570 | this.click = function(selector) { | 584 | this.click = function(selector) { |
571 | try { | 585 | var elem = document.querySelector(selector); |
572 | var elem = document.querySelector(selector); | ||
573 | } catch (e) { | ||
574 | console.log('invalid selector: ' + selector); | ||
575 | return false; | ||
576 | } | ||
577 | if (!elem) { | 586 | if (!elem) { |
578 | console.log('selector "' + selector + '" did not find any matching element'); | ||
579 | return false; | 587 | return false; |
580 | } | 588 | } |
581 | var evt = document.createEvent("MouseEvents"); | 589 | var evt = document.createEvent("MouseEvents"); |
... | @@ -694,6 +702,34 @@ | ... | @@ -694,6 +702,34 @@ |
694 | }; | 702 | }; |
695 | 703 | ||
696 | /** | 704 | /** |
705 | * Finds all DOM elements matching by the provided selector. | ||
706 | * | ||
707 | * @param String selector CSS3 selector | ||
708 | * @return NodeList|undefined | ||
709 | */ | ||
710 | this.findAll = function(selector) { | ||
711 | try { | ||
712 | return document.querySelectorAll(selector); | ||
713 | } catch (e) { | ||
714 | console.log('findAll(): invalid selector provided "' + selector + '":' + e); | ||
715 | } | ||
716 | }; | ||
717 | |||
718 | /** | ||
719 | * Finds a DOM element by the provided selector. | ||
720 | * | ||
721 | * @param String selector CSS3 selector | ||
722 | * @return HTMLElement|undefined | ||
723 | */ | ||
724 | this.findOne = function(selector) { | ||
725 | try { | ||
726 | return document.querySelector(selector); | ||
727 | } catch (e) { | ||
728 | console.log('findOne(): invalid selector provided "' + selector + '":' + e); | ||
729 | } | ||
730 | }; | ||
731 | |||
732 | /** | ||
697 | * Downloads a resource behind an url and returns its base64-encoded | 733 | * Downloads a resource behind an url and returns its base64-encoded |
698 | * contents. | 734 | * contents. |
699 | * | 735 | * |
... | @@ -822,6 +858,9 @@ | ... | @@ -822,6 +858,9 @@ |
822 | } | 858 | } |
823 | message += ': ' + casper.requestUrl; | 859 | message += ': ' + casper.requestUrl; |
824 | casper.log(message, "warning"); | 860 | casper.log(message, "warning"); |
861 | if (typeof(casper.options.onLoadError) === "function") { | ||
862 | casper.options.onLoadError(casper, casper.requestUrl, status); | ||
863 | } | ||
825 | } | 864 | } |
826 | if (casper.options.clientScripts) { | 865 | if (casper.options.clientScripts) { |
827 | for (var i = 0; i < casper.options.clientScripts.length; i++) { | 866 | for (var i = 0; i < casper.options.clientScripts.length; i++) { |
... | @@ -842,15 +881,16 @@ | ... | @@ -842,15 +881,16 @@ |
842 | utils: encodeURIComponent(phantom.Casper.ClientUtils.toString()) | 881 | utils: encodeURIComponent(phantom.Casper.ClientUtils.toString()) |
843 | })); | 882 | })); |
844 | if (!injected) { | 883 | if (!injected) { |
845 | casper.log('Failed to inject Casper client-side utilities!', "warning"); | 884 | casper.log("Failed to inject Casper client-side utilities!", "warning"); |
846 | } else { | 885 | } else { |
847 | casper.log('Successfully injected Casper client-side utilities', "debug"); | 886 | casper.log("Successfully injected Casper client-side utilities", "debug"); |
848 | } | 887 | } |
849 | casper.loadInProgress = false; | 888 | casper.loadInProgress = false; |
850 | }; | 889 | }; |
851 | page.onResourceReceived = function(resource) { | 890 | page.onResourceReceived = function(resource) { |
852 | if (resource.url === casper.requestUrl) { | 891 | if (resource.url === casper.requestUrl) { |
853 | casper.currentHTTPStatus = resource.status; | 892 | casper.currentHTTPStatus = resource.status; |
893 | casper.currentUrl = resource.url; | ||
854 | } | 894 | } |
855 | }; | 895 | }; |
856 | return page; | 896 | return page; | ... | ... |
... | @@ -35,6 +35,20 @@ phantom.Casper.extend({ | ... | @@ -35,6 +35,20 @@ phantom.Casper.extend({ |
35 | return this.assertEquals(this.evaluate(fn), expected, message); | 35 | return this.assertEquals(this.evaluate(fn), expected, message); |
36 | }, | 36 | }, |
37 | 37 | ||
38 | assertMatch: function(subject, pattern, message) { | ||
39 | return this.assert(pattern.test(subject), message); | ||
40 | }, | ||
41 | |||
42 | assertTitle: function(expected, message) { | ||
43 | return this.assertEvalEquals(function() { | ||
44 | return document.title; | ||
45 | }, expected, message); | ||
46 | }, | ||
47 | |||
48 | assertUrlMatch: function(pattern, message) { | ||
49 | return this.assertMatch(this.getCurrentUrl(), pattern, message); | ||
50 | }, | ||
51 | |||
38 | renderResults: function() { | 52 | renderResults: function() { |
39 | this.echo("=========================================="); | 53 | this.echo("=========================================="); |
40 | var total = testResults.passed + testResults.failed, | 54 | var total = testResults.passed + testResults.failed, | ... | ... |
... | @@ -26,9 +26,7 @@ casper.options.verbose = true; | ... | @@ -26,9 +26,7 @@ casper.options.verbose = true; |
26 | 26 | ||
27 | // Casper#start() | 27 | // Casper#start() |
28 | casper.start('tests/site/index.html', function(self) { | 28 | casper.start('tests/site/index.html', function(self) { |
29 | self.assertEvalEquals(function() { | 29 | self.assertTitle('CasperJS test index', 'start() casper can start itself an open an url'); |
30 | return document.title; | ||
31 | }, 'CasperJS test index', 'start() casper can start itself an open an url'); | ||
32 | self.assertEval(function() { | 30 | self.assertEval(function() { |
33 | return typeof(__utils__) === "object"; | 31 | return typeof(__utils__) === "object"; |
34 | }, 'start() injects ClientUtils instance within remote DOM'); | 32 | }, 'start() injects ClientUtils instance within remote DOM'); |
... | @@ -41,9 +39,7 @@ casper.assert(casper.steps.length === 1, 'start() can add a new navigation step' | ... | @@ -41,9 +39,7 @@ casper.assert(casper.steps.length === 1, 'start() can add a new navigation step' |
41 | 39 | ||
42 | // Casper#then() | 40 | // Casper#then() |
43 | casper.then(function(self) { | 41 | casper.then(function(self) { |
44 | self.assertEvalEquals(function() { | 42 | self.assertTitle('CasperJS test target', 'click() casper can click on a text link and react when it is loaded 1/2'); |
45 | return document.title; | ||
46 | }, 'CasperJS test target', 'click() casper can click on a text link and react when it is loaded 1/2'); | ||
47 | self.click('a[href="form.html"]'); | 43 | self.click('a[href="form.html"]'); |
48 | }); | 44 | }); |
49 | 45 | ||
... | @@ -51,14 +47,13 @@ casper.assert(casper.steps.length === 2, 'then() adds a new navigation step'); | ... | @@ -51,14 +47,13 @@ casper.assert(casper.steps.length === 2, 'then() adds a new navigation step'); |
51 | 47 | ||
52 | // Casper#fill() | 48 | // Casper#fill() |
53 | casper.then(function(self) { | 49 | casper.then(function(self) { |
54 | self.assertEvalEquals(function() { | 50 | self.assertTitle('CasperJS test form', 'click() casper can click on a text link and react when it is loaded 2/2'); |
55 | return document.title; | 51 | self.fill('form[action="result.html"]', { |
56 | }, 'CasperJS test form', 'click() casper can click on a text link and react when it is loaded 2/2'); | ||
57 | self.fill('form[action="form.html"]', { | ||
58 | email: 'chuck@norris.com', | 52 | email: 'chuck@norris.com', |
59 | content: 'Am watching thou', | 53 | content: 'Am watching thou', |
60 | check: true, | 54 | check: true, |
61 | choice: 'no', | 55 | choice: 'no', |
56 | topic: 'bar', | ||
62 | file: phantom.libraryPath + '/README.md' | 57 | file: phantom.libraryPath + '/README.md' |
63 | }); | 58 | }); |
64 | self.assertEvalEquals(function() { | 59 | self.assertEvalEquals(function() { |
... | @@ -68,6 +63,9 @@ casper.then(function(self) { | ... | @@ -68,6 +63,9 @@ casper.then(function(self) { |
68 | return document.querySelector('textarea[name="content"]').value; | 63 | return document.querySelector('textarea[name="content"]').value; |
69 | }, 'Am watching thou', 'fill() can fill a textarea form field'); | 64 | }, 'Am watching thou', 'fill() can fill a textarea form field'); |
70 | self.assertEvalEquals(function() { | 65 | self.assertEvalEquals(function() { |
66 | return document.querySelector('select[name="topic"]').value; | ||
67 | }, 'bar', 'fill() can pick a value from a select form field'); | ||
68 | self.assertEvalEquals(function() { | ||
71 | return document.querySelector('input[name="check"]').checked; | 69 | return document.querySelector('input[name="check"]').checked; |
72 | }, true, 'fill() can check a form checkbox'); | 70 | }, true, 'fill() can check a form checkbox'); |
73 | self.assertEvalEquals(function() { | 71 | self.assertEvalEquals(function() { |
... | @@ -79,9 +77,17 @@ casper.then(function(self) { | ... | @@ -79,9 +77,17 @@ casper.then(function(self) { |
79 | self.assertEvalEquals(function() { | 77 | self.assertEvalEquals(function() { |
80 | return document.querySelector('input[name="file"]').files.length === 1; | 78 | return document.querySelector('input[name="file"]').files.length === 1; |
81 | }, true, 'fill() can select a file to upload'); | 79 | }, true, 'fill() can select a file to upload'); |
82 | self.evaluate(function() { | 80 | self.click('input[type="submit"]'); |
83 | document.querySelector('form[action="form.html"]').submit(); | 81 | }); |
84 | }) | 82 | |
83 | // Casper#click() | ||
84 | casper.then(function(self) { | ||
85 | self.assertTitle('CasperJS test form result', 'click() casper can click on a submit button'); | ||
86 | self.assertUrlMatch(/email=chuck@norris.com/, 'fill() input[type=email] field was submitted'); | ||
87 | self.assertUrlMatch(/content=Am\+watching\+thou/, 'fill() textarea field was submitted'); | ||
88 | self.assertUrlMatch(/check=on/, 'fill() input[type=checkbox] field was submitted'); | ||
89 | self.assertUrlMatch(/choice=no/, 'fill() input[type=radio] field was submitted'); | ||
90 | self.assertUrlMatch(/topic=bar/, 'fill() select field was submitted'); | ||
85 | }); | 91 | }); |
86 | 92 | ||
87 | casper.run(function(self) { | 93 | casper.run(function(self) { | ... | ... |
... | @@ -5,7 +5,7 @@ | ... | @@ -5,7 +5,7 @@ |
5 | <title>CasperJS test form</title> | 5 | <title>CasperJS test form</title> |
6 | </head> | 6 | </head> |
7 | <body> | 7 | <body> |
8 | <form action="form.html" enctype="multipart/form-data"> | 8 | <form action="result.html" enctype="multipart/form-data"> |
9 | <input type="text" name="email" placeholder="email" /> | 9 | <input type="text" name="email" placeholder="email" /> |
10 | <textarea name="content"></textarea> | 10 | <textarea name="content"></textarea> |
11 | <select name="topic"> | 11 | <select name="topic"> | ... | ... |
-
Please register or sign in to post a comment