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,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