casperjs 1.0.0.RC1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,35 @@
1
+ {
2
+ "name": "casperjs",
3
+ "description": "Navigation scripting & testing utility for PhantomJS",
4
+ "version": "1.0.0-RC1",
5
+ "keywords": [
6
+ "phantomjs",
7
+ "javascript"
8
+ ],
9
+ "maintainers": [
10
+ {
11
+ "name": "Nicolas Perriault",
12
+ "email": "nperriault@gmail.com",
13
+ "web": "http://www.akei.com"
14
+ }
15
+ ],
16
+ "dependencies": {
17
+ "http://www.phantomjs.org/": "1.5"
18
+ },
19
+ "bugs": {
20
+ "url": "https://github.com/n1k0/casperjs/issues"
21
+ },
22
+ "repositories": [
23
+ {
24
+ "type": "git",
25
+ "url": "git://github.com/n1k0/casperjs.git"
26
+ }
27
+ ],
28
+ "licenses": [
29
+ {
30
+ "name": "MIT",
31
+ "url": "http://www.opensource.org/licenses/mit-license.php"
32
+ }
33
+ ],
34
+ "homepage": "http://casperjs.org"
35
+ }
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+ # Ruby Wrapper for CasperJs
3
+ # by hannyu
4
+
5
+
6
+ CASPER_PATH = File.dirname(File.dirname(File.expand_path(__FILE__)))
7
+
8
+ PHANTOMJS_NATIVE_ARGS = [
9
+ '--cookies-file',
10
+ '--config',
11
+ '--debug',
12
+ '--disk-cache',
13
+ '--ignore-ssl-errors',
14
+ '--load-images',
15
+ '--load-plugins',
16
+ '--local-storage-path',
17
+ '--local-storage-quota',
18
+ '--local-to-remote-url-access',
19
+ '--max-disk-cache-size',
20
+ '--output-encoding',
21
+ '--proxy',
22
+ '--proxy-auth',
23
+ '--proxy-type',
24
+ '--remote-debugger-port',
25
+ '--remote-debugger-autorun',
26
+ '--script-encoding',
27
+ '--web-security',
28
+ ]
29
+
30
+ CASPER_ARGS = []
31
+ PHANTOMJS_ARGS = []
32
+ ARGV.each do |arg|
33
+ is_found = false
34
+ PHANTOMJS_NATIVE_ARGS.each do |pna|
35
+ if arg.start_with? pna
36
+ PHANTOMJS_ARGS << arg
37
+ is_found = true
38
+ break
39
+ end
40
+ end
41
+ CASPER_ARGS << arg if not is_found
42
+ end
43
+
44
+ CASPER_COMMAND = []
45
+ CASPER_COMMAND << (ENV["PHANTOMJS_EXECUTABLE"] || "phantomjs")
46
+ CASPER_COMMAND.concat PHANTOMJS_ARGS
47
+ CASPER_COMMAND << File.join(CASPER_PATH, "bin", "bootstrap.js")
48
+ CASPER_COMMAND << "--casper-path=#{CASPER_PATH}"
49
+ CASPER_COMMAND << "--cli"
50
+ CASPER_COMMAND.concat CASPER_ARGS
51
+
52
+ if system(CASPER_COMMAND.join(" ")).nil?
53
+ puts "Fatal: Did you install phantomjs?"
54
+ end
55
+
56
+ exit $?.exitstatus
57
+
@@ -0,0 +1,64 @@
1
+ ###
2
+ Create a mosaic image from all headline photos on BBC homepage
3
+ ###
4
+
5
+ casper = require("casper").create()
6
+ nbLinks = 0
7
+ currentLink = 1
8
+ images = []
9
+
10
+ # helper to hide some element from remote DOM
11
+ casper.hide = (selector) ->
12
+ @evaluate (selector) ->
13
+ document.querySelector(selector).style.display = "none"
14
+ , selector: selector
15
+
16
+ casper.start "http://www.bbc.co.uk/", ->
17
+ nbLinks = @evaluate ->
18
+ return __utils__.findAll('#promo2_carousel_items_items li').length
19
+ @echo "#{nbLinks} items founds"
20
+ # hide navigation arrows
21
+ @hide ".nav_left"
22
+ @hide ".nav_right"
23
+ @mouse.move "#promo2_carousel"
24
+ @waitUntilVisible ".autoplay.nav_pause", ->
25
+ @echo "Moving over pause button"
26
+ @mouse.move ".autoplay.nav_pause"
27
+ @click ".autoplay.nav_pause"
28
+ @echo "Clicked on pause button"
29
+ @waitUntilVisible ".autoplay.nav_play", ->
30
+ @echo "Carousel has been paused"
31
+ # hide play button
32
+ @hide ".autoplay"
33
+
34
+ # Capture carrousel area
35
+ next = ->
36
+ image = "bbcshot#{currentLink}.png"
37
+ images.push image
38
+ @echo "Processing image #{currentLink}"
39
+ @captureSelector image, '.carousel_viewport'
40
+ if currentLink < nbLinks
41
+ @click ".carousel_itemList_li[rel='#{currentLink}']"
42
+ @wait 1000, ->
43
+ @then next
44
+ currentLink++
45
+ else
46
+ @then buildPage
47
+
48
+ # Building resulting page and image
49
+ buildPage = ->
50
+ @echo "Build result page"
51
+ fs = require "fs"
52
+ @viewport 624, 400
53
+ pageHtml = "<html><body style='background:black;margin:0;padding:0'>"
54
+ images.forEach (image) ->
55
+ pageHtml += "<img src='file://#{fs.workingDirectory}/#{image}'><br>"
56
+ pageHtml += "</body></html>"
57
+ fs.write "result.html", pageHtml, 'w'
58
+ @thenOpen "file://#{fs.workingDirectory}/result.html", ->
59
+ @echo "Resulting image saved to result.png"
60
+ @capture "result.png"
61
+
62
+ casper.then next
63
+
64
+ casper.run()
@@ -0,0 +1,80 @@
1
+ /*
2
+ * Create a mosaic image from all headline photos on BBC homepage
3
+ */
4
+
5
+ var casper = require("casper").create();
6
+ var nbLinks = 0;
7
+ var currentLink = 1;
8
+ var images = [];
9
+ var buildPage, next;
10
+
11
+ // helper to hide some element from remote DOM
12
+ casper.hide = function(selector) {
13
+ this.evaluate(function(selector) {
14
+ document.querySelector(selector).style.display = "none";
15
+ }, {
16
+ selector: selector
17
+ });
18
+ };
19
+
20
+ casper.start("http://www.bbc.co.uk/", function() {
21
+ nbLinks = this.evaluate(function() {
22
+ return __utils__.findAll('#promo2_carousel_items_items li').length;
23
+ });
24
+ this.echo(nbLinks + " items founds");
25
+ // hide navigation arrows
26
+ this.hide(".nav_left");
27
+ this.hide(".nav_right");
28
+ this.mouse.move("#promo2_carousel");
29
+ this.waitUntilVisible(".autoplay.nav_pause", function() {
30
+ this.echo("Moving over pause button");
31
+ this.mouse.move(".autoplay.nav_pause");
32
+ this.click(".autoplay.nav_pause");
33
+ this.echo("Clicked on pause button");
34
+ this.waitUntilVisible(".autoplay.nav_play", function() {
35
+ this.echo("Carousel has been paused");
36
+ // hide play button
37
+ this.hide(".autoplay");
38
+ });
39
+ });
40
+ });
41
+
42
+ // Capture carrousel area
43
+ next = function() {
44
+ var image;
45
+ image = "bbcshot" + currentLink + ".png";
46
+ images.push(image);
47
+ this.echo("Processing image " + currentLink);
48
+ this.captureSelector(image, '.carousel_viewport');
49
+ if (currentLink < nbLinks) {
50
+ this.click(".carousel_itemList_li[rel='" + currentLink + "']");
51
+ this.wait(1000, function() {
52
+ this.then(next);
53
+ currentLink++;
54
+ });
55
+ } else {
56
+ this.then(buildPage);
57
+ }
58
+ };
59
+
60
+ // Building resulting page and image
61
+ buildPage = function() {
62
+ var fs, pageHtml;
63
+ this.echo("Build result page");
64
+ fs = require("fs");
65
+ this.viewport(624, 400);
66
+ pageHtml = "<html><body style='background:black;margin:0;padding:0'>";
67
+ images.forEach(function(image) {
68
+ pageHtml += "<img src='file://" + fs.workingDirectory + "/" + image + "'><br>";
69
+ });
70
+ pageHtml += "</body></html>";
71
+ fs.write("result.html", pageHtml, 'w');
72
+ this.thenOpen("file://" + fs.workingDirectory + "/result.html", function() {
73
+ this.echo("Resulting image saved to result.png");
74
+ this.capture("result.png");
75
+ });
76
+ };
77
+
78
+ casper.then(next);
79
+
80
+ casper.run();
@@ -0,0 +1,19 @@
1
+ casper = require("casper").create()
2
+ dump = require("utils").dump
3
+
4
+ # removing default options passed by the Python executable
5
+ casper.cli.drop "cli"
6
+ casper.cli.drop "casper-path"
7
+
8
+ if casper.cli.args.length is 0 and Object.keys(casper.cli.options).length is 0
9
+ casper
10
+ .echo("Pass some args and options to see how they are handled by CasperJS")
11
+ .exit(1)
12
+
13
+ casper.echo "Casper CLI passed args:"
14
+ dump casper.cli.args
15
+
16
+ casper.echo "Casper CLI passed options:"
17
+ dump casper.cli.options
18
+
19
+ casper.exit()
@@ -0,0 +1,21 @@
1
+ var casper = require("casper").create();
2
+ var dump = require("utils").dump;
3
+
4
+ // removing default options passed by the Python executable
5
+ casper.cli.drop("cli");
6
+ casper.cli.drop("casper-path");
7
+
8
+ if (casper.cli.args.length === 0 && Object.keys(casper.cli.options).length === 0) {
9
+ casper
10
+ .echo("Pass some args and options to see how they are handled by CasperJS")
11
+ .exit(1)
12
+ ;
13
+ }
14
+
15
+ casper.echo("Casper CLI passed args:");
16
+ dump(casper.cli.args);
17
+
18
+ casper.echo("Casper CLI passed options:");
19
+ dump(casper.cli.options);
20
+
21
+ casper.exit();
@@ -0,0 +1,11 @@
1
+ casper = require("casper").create()
2
+
3
+ # listening to a custom event
4
+ casper.on "google.loaded", (title) ->
5
+ @echo "Google page title is #{title}"
6
+
7
+ casper.start "http://google.com/", ->
8
+ # emitting a custom event
9
+ @emit "google.loaded", @getTitle()
10
+
11
+ casper.run()
@@ -0,0 +1,13 @@
1
+ var casper = require("casper").create();
2
+
3
+ // listening to a custom event
4
+ casper.on("google.loaded", function(title) {
5
+ this.echo("Google page title is " + title);
6
+ });
7
+
8
+ casper.start("http://google.com/", function() {
9
+ // emitting a custom event
10
+ this.emit("google.loaded", this.getTitle());
11
+ });
12
+
13
+ casper.run();
@@ -0,0 +1,33 @@
1
+ ###
2
+ A basic custom logging implementation. The idea is to (extremely) verbosely
3
+ log every received resource.
4
+ ###
5
+
6
+ casper = require("casper").create
7
+ ###
8
+ Every time a resource is received, a new log entry is added to the stack
9
+ at the 'verbose' level.
10
+
11
+ @param Object resource A phantomjs resource object
12
+ ###
13
+ onResourceReceived: (self, resource) ->
14
+ infos = []
15
+ props = [
16
+ "url"
17
+ "status"
18
+ "statusText"
19
+ "redirectURL"
20
+ "bodySize"
21
+ ]
22
+ infos.push resource[prop] for prop in props
23
+ infos.push "[#{header.name}: #{header.value}]" for header in resource.headers
24
+ @log infos.join(", "), "verbose"
25
+ verbose: true # we want to see the log printed out to the console
26
+ logLevel: "verbose" # of course we want to see logs to our new level :)
27
+
28
+ # add a new 'verbose' logging level at the lowest priority
29
+ casper.logLevels = ["verbose"].concat casper.logLevels
30
+
31
+ # test our new logger with google
32
+ casper.start("http://www.google.com/").run ->
33
+ @exit()
@@ -0,0 +1,42 @@
1
+ /*
2
+ * A basic custom logging implementation. The idea is to (extremely) verbosely
3
+ * log every received resource.
4
+ */
5
+
6
+ var casper = require("casper").create({
7
+ /*
8
+ Every time a resource is received, a new log entry is added to the stack at
9
+ the 'verbose' level.
10
+ */
11
+ onResourceReceived: function(self, resource) {
12
+ var header, infos, prop, props, _i, _j, _len, _len1, _ref;
13
+ infos = [];
14
+ props = [
15
+ "url",
16
+ "status",
17
+ "statusText",
18
+ "redirectURL",
19
+ "bodySize"
20
+ ];
21
+ for (_i = 0, _len = props.length; _i < _len; _i++) {
22
+ prop = props[_i];
23
+ infos.push(resource[prop]);
24
+ }
25
+ _ref = resource.headers;
26
+ for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
27
+ header = _ref[_j];
28
+ infos.push("[" + header.name + ": " + header.value + "]");
29
+ }
30
+ this.log(infos.join(", "), "verbose");
31
+ },
32
+ verbose: true,
33
+ logLevel: "verbose"
34
+ });
35
+
36
+ // add a new 'verbose' logging level at the lowest priority
37
+ casper.logLevels = ["verbose"].concat(casper.logLevels);
38
+
39
+ // test our new logger with google
40
+ casper.start("http://www.google.com/").run(function() {
41
+ this.exit();
42
+ });
@@ -0,0 +1,10 @@
1
+ ###
2
+ Download the google logo image onto the local filesystem
3
+ ###
4
+
5
+ casper = require("casper").create()
6
+
7
+ casper.start "http://www.google.fr/", ->
8
+ @echo @download "http://www.google.fr/images/srpr/logo3w.png", "logo.png"
9
+
10
+ casper.run()
@@ -0,0 +1,11 @@
1
+ /*
2
+ * download the google logo image onto the local filesystem
3
+ */
4
+
5
+ var casper = require("casper").create();
6
+
7
+ casper.start("http://www.google.fr/", function() {
8
+ this.download("http://www.google.fr/images/srpr/logo3w.png", "logo.png");
9
+ });
10
+
11
+ casper.run();
@@ -0,0 +1,60 @@
1
+ casper = require("casper").create
2
+ verbose: true
3
+
4
+ # The base links array
5
+ links = [
6
+ "http://google.com/"
7
+ "http://yahoo.com/"
8
+ "http://bing.com/"
9
+ ]
10
+
11
+ currentLink = 0;
12
+
13
+ # If we don't set a limit, it could go on forever
14
+ upTo = ~~casper.cli.get(0) || 10
15
+
16
+ ###
17
+ Get the links, and add them to the links array
18
+ (It could be done all in one step, but it is intentionally splitted)
19
+ ###
20
+ addLinks = (link) ->
21
+ @then ->
22
+ found = @evaluate searchLinks
23
+ @echo "#{found.length} links found on #{link}"
24
+ links = links.concat found
25
+
26
+ ###
27
+ Fetch all <a> elements from the page and return
28
+ the ones which contains a href starting with 'http://'
29
+ ###
30
+ searchLinks = ->
31
+ filter = Array::filter
32
+ map = Array::map
33
+ map.call filter.call(document.querySelectorAll("a"), (a) ->
34
+ (/^http:\/\/.*/i).test a.getAttribute("href")
35
+ ), (a) ->
36
+ a.getAttribute "href"
37
+
38
+ # Just opens the page and prints the title
39
+ start = (link) ->
40
+ @start link, ->
41
+ @echo "Page title: #{ @getTitle() }"
42
+
43
+ # As long as it has a next link, and is under the maximum limit, will keep running
44
+ check = ->
45
+ if links[currentLink] && currentLink < upTo
46
+ @echo "--- Link #{currentLink} ---"
47
+ start.call @, links[currentLink]
48
+ addLinks.call @, links[currentLink]
49
+ currentLink++
50
+ @run check
51
+ else
52
+ @echo "All done."
53
+ @exit()
54
+
55
+ casper.start()
56
+
57
+ casper.then ->
58
+ @echo "Starting"
59
+
60
+ casper.run check