wraith 2.8.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 322bea139215b0b76a3fbee69b95ca2e715b2229
4
- data.tar.gz: d0c66b25dafb3df3fe601dad9a618c2e924c573c
3
+ metadata.gz: 9eb43d65349986285e6d089a4ed007f7d58247b6
4
+ data.tar.gz: 8a807791ed5348d4538495c6637ab1e2a6a11efd
5
5
  SHA512:
6
- metadata.gz: dd04184a6fc39dd9cedb1a8f099abb4567d740b3650b69ef31ef7c53eea2db97e8cb49e96eb29452e82dfb725695155458b4c3bd96924e3e73062d0e3e7933b2
7
- data.tar.gz: 22cd83978f44aecb5bbaaf9b72792d9114c6104c9bfd79e41bc884aeb9be49da52d1b9059ea6d723894bfe6983586f420b2df65355a7d23c63b3ba6e68550ab2
6
+ metadata.gz: 2460efd5b9be376c0fefeb69926d5c8d7cc05728718f8c2703f2cfb3c827825f701c0dea044424a99ba62ec8e9355fb956b71293e71d8ea9a06a500ea383bedd
7
+ data.tar.gz: 5a0fcdb92530cb4a46f34e57f90374c1ba229a634e5087d64d85386f1fd146b58bf00ce79d38b4fb15cced586f66faa3be1dcfe1f645fc51fbfb399d068a79ab
@@ -147,7 +147,9 @@ class Wraith::GalleryGenerator
147
147
  generate_html(@location, directories, slideshow_template, dest, with_path)
148
148
 
149
149
  puts "Gallery generated"
150
- check_failed_shots
150
+ failed = check_failed_shots
151
+ prompt_user_to_open_gallery dest
152
+ exit 1 if failed
151
153
  end
152
154
 
153
155
  def check_failed_shots
@@ -167,12 +169,17 @@ class Wraith::GalleryGenerator
167
169
  end
168
170
  end
169
171
 
170
- exit 1
172
+ return false
171
173
  else
172
174
  true
173
175
  end
174
176
  end
175
177
 
178
+ def prompt_user_to_open_gallery(dest)
179
+ puts "\nView the gallery in your browser:"
180
+ puts "\t file://" + `pwd`.chomp + '/' + dest
181
+ end
182
+
176
183
  class ErbBinding < OpenStruct
177
184
  def get_binding
178
185
  binding
@@ -0,0 +1,45 @@
1
+ module.exports = function (commandLineDimensions) {
2
+ // remove quotes from dimensions string
3
+ commandLineDimensions = commandLineDimensions.replace(/'/gi, '');
4
+
5
+ function getWidthAndHeight(dimensions) {
6
+ dimensions = /(\d*)x?((\d*))?/i.exec(dimensions);
7
+ return {
8
+ 'viewportWidth': parseInt(dimensions[1]),
9
+ 'viewportHeight': parseInt(dimensions[2] || 1500)
10
+ };
11
+ }
12
+
13
+ var multipleDimensions = commandLineDimensions.split(','),
14
+ dimensionsToPass;
15
+
16
+ if (multipleDimensions.length > 1) {
17
+ dimensionsToPass = multipleDimensions.map(function (cliDimensions) {
18
+ return getWidthAndHeight(cliDimensions);
19
+ });
20
+ }
21
+ else {
22
+ dimensionsToPass = getWidthAndHeight(commandLineDimensions);
23
+ }
24
+
25
+ return {
26
+ dimensions: dimensionsToPass,
27
+ takingMultipleScreenshots: function (dimensions) {
28
+ return dimensions.length && dimensions.length > 1;
29
+ },
30
+ replaceImageNameWithDimensions: function (image_name, currentDimensions) {
31
+ // shots/clickable_guide__after_click/MULTI_casperjs_english.png
32
+ // ->
33
+ // shots/clickable_guide__after_click/1024x359_casperjs_english.png
34
+ var dirs = image_name.split('/'),
35
+ filename = dirs[dirs.length - 1],
36
+ filenameParts = filename.split('_'),
37
+ newFilename;
38
+
39
+ filenameParts[0] = currentDimensions.viewportWidth + 'x' + currentDimensions.viewportHeight;
40
+ dirs.pop(); // remove MULTI_casperjs_english.png
41
+ newFilename = dirs.join('/') + '/' + filenameParts.join('_');
42
+ return newFilename;
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,112 @@
1
+ module.exports = function (config) {
2
+
3
+ // config
4
+ var systemArgs = config.systemArgs,
5
+ javascriptEnabled = config.javascriptEnabled;
6
+
7
+ // modules
8
+ var page = require('webpage').create(),
9
+ helper = require('./_helper.js')(systemArgs[2]);
10
+
11
+ // command line arguments
12
+ var url = systemArgs[1],
13
+ dimensions = helper.dimensions,
14
+ image_name = systemArgs[3],
15
+ selector = systemArgs[4],
16
+ globalBeforeCaptureJS = systemArgs[5],
17
+ pathBeforeCaptureJS = systemArgs[6],
18
+ dimensionsProcessed = 0,
19
+ currentDimensions;
20
+
21
+ globalBeforeCaptureJS = globalBeforeCaptureJS === 'false' ? false : globalBeforeCaptureJS;
22
+ pathBeforeCaptureJS = pathBeforeCaptureJS === 'false' ? false : pathBeforeCaptureJS;
23
+
24
+ var current_requests = 0;
25
+ var last_request_timeout;
26
+ var final_timeout;
27
+
28
+ if (helper.takingMultipleScreenshots(dimensions)) {
29
+ currentDimensions = dimensions[0];
30
+ image_name = helper.replaceImageNameWithDimensions(image_name, currentDimensions);
31
+ }
32
+ else {
33
+ currentDimensions = dimensions;
34
+ }
35
+
36
+ page.viewportSize = { width: currentDimensions.viewportWidth, height: currentDimensions.viewportHeight};
37
+ page.settings = { loadImages: true, javascriptEnabled: javascriptEnabled };
38
+
39
+ // If you want to use additional phantomjs commands, place them here
40
+ page.settings.userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.17';
41
+
42
+ page.onResourceRequested = function(req) {
43
+ current_requests += 1;
44
+ };
45
+
46
+ page.onResourceReceived = function(res) {
47
+ if (res.stage === 'end') {
48
+ current_requests -= 1;
49
+ debounced_render();
50
+ }
51
+ };
52
+
53
+ page.open(url, function(status) {
54
+ if (status !== 'success') {
55
+ console.log('Error with page ' + url);
56
+ phantom.exit();
57
+ }
58
+ });
59
+
60
+ function runSetupJavaScriptThenCaptureImage() {
61
+ if (globalBeforeCaptureJS) {
62
+ require(globalBeforeCaptureJS)(page);
63
+ }
64
+ if (pathBeforeCaptureJS) {
65
+ require(pathBeforeCaptureJS)(page);
66
+ }
67
+ captureImage();
68
+ }
69
+
70
+ function captureImage() {
71
+
72
+ console.log('Snapping ' + url + ' at: ' + currentDimensions.viewportWidth + 'x' + currentDimensions.viewportHeight);
73
+ page.clipRect = {
74
+ top: 0,
75
+ left: 0,
76
+ height: currentDimensions.viewportHeight,
77
+ width: currentDimensions.viewportWidth
78
+ };
79
+ page.render(image_name);
80
+
81
+ dimensionsProcessed++;
82
+ if (helper.takingMultipleScreenshots(dimensions) && dimensionsProcessed < dimensions.length) {
83
+ currentDimensions = dimensions[dimensionsProcessed];
84
+ image_name = helper.replaceImageNameWithDimensions(image_name, currentDimensions);
85
+ setTimeout(captureImage, 1000);
86
+ }
87
+ else {
88
+ // prevent CI from failing from 'Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL' errors
89
+ // see https://github.com/n1k0/casperjs/issues/1068
90
+ setTimeout(function(){
91
+ phantom.exit();
92
+ }, 10);
93
+ }
94
+ }
95
+
96
+ function debounced_render() {
97
+ clearTimeout(last_request_timeout);
98
+ clearTimeout(final_timeout);
99
+
100
+ // If there's no more ongoing resource requests, wait for 1 second before
101
+ // rendering, just in case the page kicks off another request
102
+ if (current_requests < 1) {
103
+ clearTimeout(final_timeout);
104
+ last_request_timeout = setTimeout(runSetupJavaScriptThenCaptureImage, 1000);
105
+ }
106
+
107
+ // Sometimes, straggling requests never make it back, in which
108
+ // case, timeout after 5 seconds and render the page anyway
109
+ final_timeout = setTimeout(runSetupJavaScriptThenCaptureImage, 5000);
110
+ }
111
+
112
+ }
@@ -0,0 +1,81 @@
1
+ // modules
2
+ var system = require('system'),
3
+ casper = require('casper').create(),
4
+ helper = requireRelative('_helper.js')(casper.cli.get(1));
5
+
6
+ // command line arguments
7
+ var url = casper.cli.get(0),
8
+ dimensions = helper.dimensions,
9
+ image_name = casper.cli.get(2),
10
+ selector = casper.cli.get(3),
11
+ globalBeforeCaptureJS = casper.cli.get(4),
12
+ pathBeforeCaptureJS = casper.cli.get(5),
13
+ dimensionsProcessed = 0,
14
+ currentDimensions;
15
+
16
+ // functions
17
+ function requireRelative(file) {
18
+ // PhantomJS will automatically `require` relatively, but CasperJS needs some extra help. Hence this function.
19
+ // 'templates/javascript/casper.js' -> 'templates/javascript'
20
+ var currentFilePath = system.args[3].split('/');
21
+ currentFilePath.pop();
22
+ var fs = require('fs');
23
+ currentFilePath = fs.absolute(currentFilePath.join('/'));
24
+ return require(currentFilePath + '/' + file);
25
+ }
26
+ function snap() {
27
+ console.log('Snapping ' + url + ' at: ' + currentDimensions.viewportWidth + 'x' + currentDimensions.viewportHeight);
28
+
29
+ if (!selector) {
30
+ this.capture(image_name);
31
+ }
32
+ else {
33
+ this.captureSelector(image_name, selector);
34
+ }
35
+
36
+ dimensionsProcessed++;
37
+ if (helper.takingMultipleScreenshots(dimensions) && dimensionsProcessed < dimensions.length) {
38
+ currentDimensions = dimensions[dimensionsProcessed];
39
+ image_name = helper.replaceImageNameWithDimensions(image_name, currentDimensions);
40
+ casper.viewport(currentDimensions.viewportWidth, currentDimensions.viewportHeight);
41
+ casper.wait(300, function then () {
42
+ snap.bind(this)();
43
+ });
44
+ }
45
+ }
46
+
47
+ if (helper.takingMultipleScreenshots(dimensions)) {
48
+ currentDimensions = dimensions[0];
49
+ image_name = helper.replaceImageNameWithDimensions(image_name, currentDimensions);
50
+ }
51
+ else {
52
+ currentDimensions = dimensions;
53
+ }
54
+
55
+ // Casper can now do its magic
56
+ casper.start();
57
+ casper.open(url);
58
+ casper.viewport(currentDimensions.viewportWidth, currentDimensions.viewportHeight);
59
+ casper.then(function() {
60
+ if (globalBeforeCaptureJS) {
61
+ require('./' + globalBeforeCaptureJS)(this);
62
+ }
63
+ });
64
+ casper.then(function() {
65
+ if (pathBeforeCaptureJS) {
66
+ require('./' + pathBeforeCaptureJS)(this);
67
+ }
68
+ });
69
+ // waits for all images to download before taking screenshots
70
+ // (broken images are a big cause of Wraith failures!)
71
+ // Credit: http://reff.it/8m3HYP
72
+ casper.waitFor(function() {
73
+ return this.evaluate(function() {
74
+ var images = document.getElementsByTagName('img');
75
+ return Array.prototype.every.call(images, function(i) { return i.complete; });
76
+ });
77
+ }, function then () {
78
+ snap.bind(this)();
79
+ });
80
+
81
+ casper.run();
File without changes
@@ -5,8 +5,8 @@ require "shellwords"
5
5
  class Wraith::SaveImages
6
6
  attr_reader :wraith, :history, :meta
7
7
 
8
- def initialize(config, history = false)
9
- @wraith = Wraith::Wraith.new(config)
8
+ def initialize(config, history = false, yaml_passed = false)
9
+ @wraith = Wraith::Wraith.new(config, yaml_passed)
10
10
  @history = history
11
11
  @meta = SaveMetadata.new(@wraith, history)
12
12
  end
@@ -21,26 +21,51 @@ class Wraith::SaveImages
21
21
  end
22
22
 
23
23
  def save_images
24
+ jobs = define_jobs
25
+ parallel_task(jobs)
26
+ end
27
+
28
+ def define_jobs
24
29
  jobs = []
25
30
  check_paths.each do |label, options|
26
31
  settings = CaptureOptions.new(options, wraith)
27
32
 
28
- wraith.widths.each do |width|
29
- base_file_name = meta.file_names(width, label, meta.base_label)
30
- compare_file_name = meta.file_names(width, label, meta.compare_label)
31
-
32
- jobs << [label, settings.path, width, settings.base_url, base_file_name, settings.selector, wraith.before_capture, settings.before_capture]
33
- jobs << [label, settings.path, width, settings.compare_url, compare_file_name, settings.selector, wraith.before_capture, settings.before_capture] unless settings.compare_url.nil?
33
+ if wraith.resize
34
+ jobs = jobs + define_individual_job(label, settings, wraith.widths)
35
+ else
36
+ wraith.widths.each do |width|
37
+ jobs = jobs + define_individual_job(label, settings, width)
38
+ end
34
39
  end
35
40
  end
36
- parallel_task(jobs)
41
+ jobs
42
+ end
43
+
44
+ def define_individual_job(label, settings, width)
45
+ base_file_name = meta.file_names(width, label, meta.base_label)
46
+ compare_file_name = meta.file_names(width, label, meta.compare_label)
47
+
48
+ jobs = []
49
+ jobs << [label, settings.path, prepare_widths_for_cli(width), settings.base_url, base_file_name, settings.selector, wraith.before_capture, settings.before_capture]
50
+ jobs << [label, settings.path, prepare_widths_for_cli(width), settings.compare_url, compare_file_name, settings.selector, wraith.before_capture, settings.before_capture] unless settings.compare_url.nil?
51
+
52
+ jobs
53
+ end
54
+
55
+ def prepare_widths_for_cli(width)
56
+ if width.kind_of? Array
57
+ # prepare for the command line. [30,40,50] => "'30','40','50'"
58
+ width = width.map{ |i| "'#{i}'" }.join(',')
59
+ end
60
+ width
37
61
  end
38
62
 
39
63
  def capture_page_image(browser, url, width, file_name, selector, global_before_capture, path_before_capture)
40
- command = "#{browser} #{wraith.phantomjs_options} '#{wraith.snap_file}' '#{url}' '#{width}' '#{file_name}' '#{selector}' '#{global_before_capture}' '#{path_before_capture}'"
64
+
65
+ command = "#{browser} #{wraith.phantomjs_options} '#{wraith.snap_file}' '#{url}' \"#{width}\" '#{file_name}' '#{selector}' '#{global_before_capture}' '#{path_before_capture}'"
41
66
 
42
67
  # @TODO - uncomment the following line when we add a verbose mode
43
- # puts command
68
+ #puts command
44
69
  run_command command
45
70
  end
46
71
 
@@ -68,6 +93,10 @@ class Wraith::SaveImages
68
93
  max_attempts.times do |i|
69
94
  capture_page_image meta.engine, url, width, filename, selector, global_before_capture, path_before_capture
70
95
 
96
+ if wraith.resize
97
+ return # @TODO - need to check if the image was generated, as per the reload example below
98
+ end
99
+
71
100
  return if File.exist? filename
72
101
 
73
102
  puts "Failed to capture image #{filename} on attempt number #{i + 1} of #{max_attempts}"
@@ -142,12 +171,11 @@ class SaveMetadata
142
171
  history ? "_latest" : ""
143
172
  end
144
173
 
145
- def engine_label
146
- wraith.engine.key(engine)
147
- end
148
-
149
174
  def file_names(width, label, domain_label)
150
- "#{wraith.directory}/#{label}/#{width}_#{engine_label}_#{domain_label}.png"
175
+ if width.kind_of? Array
176
+ width = 'MULTI'
177
+ end
178
+ "#{wraith.directory}/#{label}/#{width}_#{engine}_#{domain_label}.png"
151
179
  end
152
180
 
153
181
  def base_label
@@ -159,6 +187,6 @@ class SaveMetadata
159
187
  end
160
188
 
161
189
  def engine
162
- wraith.engine.each { |_label, browser| return browser }
190
+ wraith.engine
163
191
  end
164
192
  end
@@ -1,3 +1,3 @@
1
1
  module Wraith
2
- VERSION = "2.8.1"
2
+ VERSION = "3.0.0"
3
3
  end
data/lib/wraith/wraith.rb CHANGED
@@ -3,15 +3,20 @@ require "yaml"
3
3
  class Wraith::Wraith
4
4
  attr_accessor :config
5
5
 
6
- def initialize(config_name)
6
+ def initialize(config, yaml_passed = false)
7
+ @config = yaml_passed ? config : open_config_file(config)
8
+ rescue
9
+ puts "unable to find config at #{config}"
10
+ exit 1
11
+ end
12
+
13
+ def open_config_file(config_name)
7
14
  if File.exist?(config_name) && File.extname(config_name) == ".yaml"
8
- @config = YAML.load(File.open(config_name))
15
+ config = File.open config_name
9
16
  else
10
- @config = YAML.load(File.open("configs/#{config_name}.yaml"))
17
+ config = File.open "configs/#{config_name}.yaml"
11
18
  end
12
- rescue
13
- puts "unable to find config at #{config_name}"
14
- exit 1
19
+ YAML.load config
15
20
  end
16
21
 
17
22
  def directory
@@ -23,8 +28,30 @@ class Wraith::Wraith
23
28
  @config["history_dir"]
24
29
  end
25
30
 
31
+ def engine
32
+ engine = @config["browser"]
33
+ # Legacy support for those using the old style "browser: \n phantomjs: 'casperjs'" configs
34
+ if engine.is_a? Hash
35
+ engine = engine.values.first
36
+ end
37
+ engine
38
+ end
39
+
26
40
  def snap_file
27
- @config["snap_file"] ? @config["snap_file"] : File.expand_path("lib/wraith/javascript/snap.js")
41
+ @config["snap_file"] || snap_file_from_engine(engine)
42
+ end
43
+
44
+ def snap_file_from_engine(engine)
45
+ path_to_js_templates = File.dirname(__FILE__) + '/javascript'
46
+ case engine
47
+ when "phantomjs"
48
+ path_to_js_templates + "/phantom.js"
49
+ when "casperjs"
50
+ path_to_js_templates + "/casper.js"
51
+ # @TODO - add a SlimerJS option
52
+ else
53
+ abort "Wraith does not recognise the browser engine '#{engine}'"
54
+ end
28
55
  end
29
56
 
30
57
  def before_capture
@@ -35,6 +62,11 @@ class Wraith::Wraith
35
62
  @config["screen_widths"]
36
63
  end
37
64
 
65
+ def resize
66
+ # @TODO make this default to true, once it's been tested a bit more thoroughly
67
+ @config["resize_or_reload"] ? (@config["resize_or_reload"] == "resize") : false
68
+ end
69
+
38
70
  def domains
39
71
  @config["domains"]
40
72
  end
@@ -75,10 +107,6 @@ class Wraith::Wraith
75
107
  @config["paths"]
76
108
  end
77
109
 
78
- def engine
79
- @config["browser"]
80
- end
81
-
82
110
  def fuzz
83
111
  @config["fuzz"]
84
112
  end