snapshot 0.1.0 → 0.2.1.beta1

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: a66a1a9280b45c2ab1a4791bc85878ea76dc9929
4
- data.tar.gz: c0fdea38499e026ba90f5d50064308c1da2c488a
3
+ metadata.gz: 6c2536f41985227165492325889d7840b12dde0d
4
+ data.tar.gz: 35a2065343d4f96e79a1a47be751c44c466cc134
5
5
  SHA512:
6
- metadata.gz: 95c00e2071a985cb2430f42fded88f4b208ed94432df393b8637fca9c2e407b55c2c9cb89304f98fe9d4a5a2cf253152bbe0ea9640eabc56439d36ad08503190
7
- data.tar.gz: 6ea6bf77f028ed25ce463a2ab85c0164c2bf313426528c5463698154a93f0472260ec9265cfb598bd6f146fcf502f5358d297469f292b3e7b6ea57383924212e
6
+ metadata.gz: 41fa64e0018686214581fbb62e6cb17211b59954274cf77f24b746ba57cd2c8af31269fccbfadac6be89fc060d7aad8bb347d118d65472865d378f9b1d41822c
7
+ data.tar.gz: 94751b98456aa3a4e824cb37413a8c398b6643a0ef86134b3b3eb9a881a5e581da2bc64fc09448b3af042f5998d71ac822dd58fa012afa663b303d60e1b3eff4
data/README.md CHANGED
@@ -6,15 +6,27 @@ Snapshot - Create hundreds of iOS app screenshots
6
6
  ============
7
7
 
8
8
  [![Twitter: @KauseFx](https://img.shields.io/badge/contact-@KrauseFx-blue.svg?style=flat)](https://twitter.com/KrauseFx)
9
- <!-- [![License](http://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/KrauseFx/deliver/blob/develop/LICENSE)
10
- [![Gem](https://img.shields.io/gem/v/deliver.svg?style=flat)](http://rubygems.org/gems/deliver)
11
- [![Build Status](https://img.shields.io/travis/KrauseFx/deliver/master.svg?style=flat)](https://travis-ci.org/KrauseFx/deliver) -->
9
+ [![License](http://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/KrauseFx/snapshot/blob/master/LICENSE)
10
+ [![Gem](https://img.shields.io/gem/v/snapshot.svg?style=flat)](http://rubygems.org/gems/snapshot)
12
11
 
13
- Taking perfect iOS screenshots is difficult. You usually want them to look the same in **all languages** on **all devices**.
12
+ You have an iPhone app. You support 20 languages. You updated the design. You want to release the update to the App Store.
13
+ *What's missing? *
14
14
 
15
- This easily results in over **300 screenshots** you have to create.
15
+ **New Screenshots**
16
16
 
17
- Uploading them is really easy, using [```deliver```](https://github.com/KrauseFx/deliver).
17
+ You want them to look **perfect** and **gorgeous**. They should show the same screens on all devices in all languages.
18
+
19
+ You have to manually create 20 (languages) x 4 (devices) x 5 (screenshots) = **400 screenshots**.
20
+
21
+ It's hard to get everything right!
22
+
23
+ - New screenshots with every (design) update
24
+ - No loading indicators
25
+ - Same content / screens
26
+ - [Clean Status Bar](#use-a-clean-status-bar)
27
+ - Uploading screenshots ([```deliver```](https://github.com/KrauseFx/deliver) is your friend)
28
+
29
+ This gem solves all those problems. It will run completely in the background - you can do something else, while your computer takes the screenshots for you.
18
30
 
19
31
  Follow the developer on Twitter: [@KrauseFx](https://twitter.com/KrauseFx)
20
32
 
@@ -41,11 +53,20 @@ Follow the developer on Twitter: [@KrauseFx](https://twitter.com/KrauseFx)
41
53
  ## Why?
42
54
  This gem automatically switches the language and device type and runs the automation script to take all screenshots.
43
55
 
44
- **Why use ```snapshot``` instead of....**
56
+ ### Why should I automate this process?
57
+ - It takes **hours** to take screenshots
58
+ - It is an integration test: You can test for UI elements and other things inside your scripts
59
+ - Be so nice, and provide new screenshots with every App Store update. Your customers deserve it
60
+ - You realise, there is a spelling mistake in one of the screens? Well, just correct it and re-run the script.
61
+ - You get a great overview of all your screens, running on all available simulators without the need to manually start it hundreds of times
62
+
63
+ ###Why use ```snapshot``` instead of....
64
+
65
+ I've been using many other solutions out there. Unfortunately none of them were perfect. The biggest issue was random timeouts of ```Instruments``` when starting the script. This problem is solved with ```snapshot```
45
66
 
46
67
  - **UI Automation in Instruments**: Instruments can only run your app on one device in one language. You have to manually switch it.
47
- - **[ui-screen-shooter](https://github.com/jonathanpenn/ui-screen-shooter)**: This ist the best alternative out there right now. It's based on AppleScript, you can not update it properly and there are quite some hacks in there. ```Snapshot``` uses a very similar technique - just in a clean and maintainable Ruby gem.
48
- - **[Subliminal](https://github.com/inkling/Subliminal)**: A good approach to write the interaction code in Objective C. Unfortunately it has a lot of open issues with the latest release of Xcode.
68
+ - **[ui-screen-shooter](https://github.com/jonathanpenn/ui-screen-shooter)**: This is the best alternative out there right now. It's based on AppleScript, you can not update it properly and there are quite some hacks in there. ```Snapshot``` uses a very similar technique - just in a clean and maintainable Ruby gem.
69
+ - **[Subliminal](https://github.com/inkling/Subliminal)**: A good approach to write the interaction code in Objective C. Unfortunately it has a lot of open issues with the latest release of Xcode. Also, it requires modifications of your Xcode project and schemes, which might break some other things.
49
70
 
50
71
  # Installation
51
72
 
@@ -68,21 +89,19 @@ Here a few links to get started:
68
89
  - [UI Automation: An Introduction (cocoamanifest.net)](http://cocoamanifest.net/articles/2011/05/uiautomation-an-introduction.html)
69
90
  - [Functional Testing UI Automation (mattmccomb.com)](http://www.mattmccomb.com/blog/2013/06/02/ios-functional-testing-with-uiautomation/)
70
91
 
71
- ## Record your first script
72
- Profile your app (CMD + I), choose ```Automation``` and click the Record button on the bottom of the window.
73
-
74
- This will get you started. Save the generated file with the extension ```js``` into your project root.
92
+ # Quick Start
75
93
 
76
- Add ```#import "SnapshotHelper.js"``` on the top of your file.
94
+ ## Record your first script
77
95
 
78
- Now you can use ```captureLocalizedScreenshot('0-name')``` to take a snapshot.
96
+ - Profile your app (CMD + I), choose ```Automation``` and click the Record button on the bottom of the window.
97
+ - This will get you started. Save the generated file with the extension ```js``` into your project root.
98
+ - Copy the ```SnapshotHelper.js``` file from the example folder to your project.
99
+ - Add ```#import "SnapshotHelper.js"``` on the top of your newly created JS file.
100
+ - Now you can use ```captureLocalizedScreenshot('0-name')``` to take a snapshot.
79
101
 
80
102
  You can take a look at the example project to play around with it.
81
103
 
82
- # Quick Start
83
-
84
-
85
- The guide will create all the necessary files for you, using the existing app metadata from iTunes Connect.
104
+ ## Start ```snapshot```
86
105
 
87
106
  - ```cd [your_project_folder]```
88
107
  - ```snapshot```
@@ -150,6 +169,12 @@ By default, ```snapshot``` will look for your project in the current directory.
150
169
  project_path "./my_project/Project.xcworkspace"
151
170
  ```
152
171
 
172
+ ### HTML Report Path
173
+ After all screenshots were created, a HTML file will be generated, to quickly get an overview of all screens on all devices. You can set a custom export path, to easily integrate the HTML report as ```Jenkins``` test result page.
174
+ ```ruby
175
+ html_path "~/Desktop/screens.html"
176
+ ```
177
+
153
178
  ### iOS Version
154
179
  I'll try to keep the script up to date. If you need to change the iOS version, you can do it like this:
155
180
 
data/bin/snapshot CHANGED
@@ -6,6 +6,7 @@ require 'snapshot'
6
6
  require 'commander/import'
7
7
  require 'snapshot/update_checker'
8
8
  require 'snapshot/dependency_checker'
9
+ require 'snapshot/snapfile_creator'
9
10
 
10
11
  HighLine.track_eof = false
11
12
 
@@ -27,8 +28,17 @@ default_command :run
27
28
 
28
29
  command :run do |c|
29
30
  c.syntax = 'snapshot'
30
- c.description = 'Run the script, to take all the screenshots.'
31
+ c.description = 'Run the script, to take all the screenshots'
31
32
  c.action do |args, options|
32
33
  Snapshot::Runner.new.work
33
34
  end
35
+ end
36
+
37
+ command :init do |c|
38
+ c.syntax = 'snapshot init'
39
+ c.description = "Creates a new Snapfile in the current directory"
40
+
41
+ c.action do |args, options|
42
+ Snapshot::SnapfileCreator.create('.')
43
+ end
34
44
  end
@@ -0,0 +1,33 @@
1
+ # Uncommend the lines below you want to change by removing the # in the beginning
2
+
3
+ # A list of devices you want to take the screenshots from
4
+ devices([
5
+ "iPhone 6",
6
+ "iPhone 6 Plus",
7
+ "iPhone 5",
8
+ "iPhone 4s"
9
+ ])
10
+
11
+ languages([
12
+ 'en-US',
13
+ 'de-DE',
14
+ 'it-IT'
15
+ ])
16
+
17
+ # Where should the resulting screenshots be stored?
18
+ screenshots_path "./screenshots"
19
+
20
+ # JavaScript UIAutomation file
21
+ # js_file './snapshot.js'
22
+
23
+ # The name of the project's scheme
24
+ # scheme 'SchemeName'
25
+
26
+ # Where is your project (or workspace)? Provide the full path here
27
+ # project_path './YourProject.xcworkspace'
28
+
29
+ # By default, the latest version should be used automatically. If you want to change it, do it here
30
+ # ios_version '8.1'
31
+
32
+ # The path, on which the HTML file should be exported to
33
+ # html_path './screenshots.html'
@@ -0,0 +1,55 @@
1
+ <html>
2
+ <head>
3
+ <style type="text/css">
4
+ * {
5
+ font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
6
+ font-weight: 300;
7
+ }
8
+ .language {
9
+
10
+ }
11
+ .deviceName {
12
+ padding-top: 20px;
13
+ font-size: 30px;
14
+ }
15
+ .screenshot {
16
+ cursor: pointer;
17
+ border: 1px #EEE solid;
18
+ }
19
+ td {
20
+ text-align: center;
21
+ }
22
+ </style>
23
+ </head>
24
+ <body>
25
+ <% divide_size_by = 5.0 %>
26
+ <% max_width = 180 %>
27
+
28
+
29
+ <% @data.each do |language, content| %>
30
+ <h1 class="language"><%= language %></h1>
31
+ <hr />
32
+ <table>
33
+ <% content.each do |device_name, screens| %>
34
+ <th colspan="<%= screens.count %>">
35
+ <h2 class="deviceName">
36
+ <%= device_name %>
37
+ </h2>
38
+ </th>
39
+ <tr>
40
+ <% screens.each do |screen_path| %>
41
+ <td>
42
+ <% screen_size = FastImage.size(screen_path) %>
43
+ <a href="<%= screen_path %>" target="_blank">
44
+ <img class="screenshot"
45
+ src="<%= screen_path %>",
46
+ style="width: <%= [(screen_size[0] / divide_size_by).round, max_width].min %>px;" />
47
+ </a>
48
+ </td>
49
+ <% end %>
50
+ </tr>
51
+ <% end %>
52
+ </table>
53
+ <% end %>
54
+ </body>
55
+ </head>
@@ -0,0 +1,54 @@
1
+ require 'erb'
2
+ require "fastimage"
3
+
4
+ module Snapshot
5
+ class ReportsGenerator
6
+ def generate
7
+ screens_path = SnapshotConfig.shared_instance.screenshots_path
8
+
9
+ @data = {}
10
+
11
+ Dir["#{screens_path}/*"].sort.each do |language_path|
12
+ language = language_path.split('/').last
13
+ Dir[[language_path, '*'].join('/')].sort.each do |screenshot|
14
+
15
+ available_devices.each do |key_name, output_name|
16
+
17
+ if screenshot.split('/').last.include?key_name
18
+ # This screenshot it from this device
19
+ @data[language] ||= {}
20
+ @data[language][output_name] ||= []
21
+ @data[language][output_name] << screenshot
22
+ break # to not include iPhone 6 and 6 Plus
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ html_path = [lib_path, "snapshot/page.html.erb"].join('/')
29
+ html = ERB.new(File.read(html_path)).result(binding) # http://www.rrn.dk/rubys-erb-templating-system
30
+
31
+
32
+ export_path = SnapshotConfig.shared_instance.html_path
33
+ File.write(export_path, html)
34
+
35
+ Helper.log.info "Successfully created HTML file with all the screenshots: #{export_path}".green
36
+ end
37
+
38
+ private
39
+ def lib_path
40
+ "./lib/"
41
+ end
42
+
43
+ def available_devices
44
+ # The order IS important, since those names are used to check for include?
45
+ # and the iPhone 6 is inlucded in the iPhone 6 Plus
46
+ {
47
+ 'iPhone6Plus' => "iPhone 6 Plus",
48
+ 'iPhone6' => "iPhone 6",
49
+ 'iPhone5' => "iPhone 5",
50
+ 'iPhone4' => "iPhone 4",
51
+ }
52
+ end
53
+ end
54
+ end
@@ -13,12 +13,13 @@ module Snapshot
13
13
 
14
14
  Builder.new.build_app
15
15
 
16
+ counter = 0
16
17
  SnapshotConfig.shared_instance.devices.each do |device|
17
18
  SnapshotConfig.shared_instance.languages.each do |language|
18
19
 
19
20
  begin
20
21
  run_tests(device, language)
21
- copy_screenshots(language)
22
+ counter += copy_screenshots(language)
22
23
  rescue Exception => ex
23
24
  Helper.log.error(ex)
24
25
  end
@@ -26,8 +27,9 @@ module Snapshot
26
27
  end
27
28
  end
28
29
 
29
- Helper.log.info "Successfully finished generating screenshots.".green
30
+ Helper.log.info "Successfully finished generating #{counter} screenshots.".green
30
31
  Helper.log.info "Check it out here: #{SnapshotConfig.shared_instance.screenshots_path}".green
32
+ ReportsGenerator.new.generate
31
33
  end
32
34
 
33
35
  def clean_old_traces
@@ -85,13 +87,13 @@ module Snapshot
85
87
 
86
88
  def copy_screenshots(language)
87
89
  resulting_path = [SnapshotConfig.shared_instance.screenshots_path, language].join('/')
88
- resulting_path.gsub!("~", ENV['HOME']) # some strange bug requires this
89
90
 
90
91
  FileUtils.mkdir_p resulting_path
91
92
 
92
93
  Dir.glob("#{TRACE_DIR}/**/*.png") do |file|
93
94
  FileUtils.cp_r(file, resulting_path + '/')
94
95
  end
96
+ return Dir.glob("#{TRACE_DIR}/**/*.png").count
95
97
  end
96
98
 
97
99
  def generate_test_command(device, language, app_path)
@@ -0,0 +1,24 @@
1
+ module Snapshot
2
+ class SnapfileCreator
3
+ # This method will take care of creating a Snapfile
4
+ def self.create(path)
5
+ path = [path, 'Snapfile'].join("/")
6
+
7
+ raise "Snapfile already exists at path '#{path}'. Run 'snapshot' to use Snapshot.".red if File.exists?(path)
8
+
9
+ template = File.read("#{gem_path}/lib/assets/SnapfileTemplate")
10
+ File.write(path, template)
11
+
12
+ puts "Successfully created new Snapfile at '#{path}'".green
13
+ end
14
+
15
+ private
16
+ def self.gem_path
17
+ if not Helper.is_test? and Gem::Specification::find_all_by_name('snapshot').any?
18
+ return Gem::Specification.find_by_name('snapshot').gem_dir
19
+ else
20
+ return './'
21
+ end
22
+ end
23
+ end
24
+ end
@@ -25,6 +25,9 @@ module Snapshot
25
25
  # @return (String) The path, in which the screenshots should be stored
26
26
  attr_accessor :screenshots_path
27
27
 
28
+ # @return (String) The path, in which the HTML file should be exported to
29
+ attr_accessor :html_path
30
+
28
31
 
29
32
  # A shared singleton
30
33
  def self.shared_instance
@@ -61,6 +64,8 @@ module Snapshot
61
64
 
62
65
  self.project_path = (Dir.glob("./*.xcworkspace").first rescue nil)
63
66
  self.project_path ||= (Dir.glob("./*.xcodeproj").first rescue nil)
67
+
68
+ self.html_path = './screenshots.html'
64
69
  end
65
70
 
66
71
  # Getters
@@ -72,11 +77,13 @@ module Snapshot
72
77
 
73
78
  # The JavaScript UIAutomation file
74
79
  def js_file
80
+ return manual_js_file if manual_js_file
81
+
75
82
  files = Dir.glob("./*.js").delete_if { |path| path.include?"SnapshotHelper.js" }
76
83
  if files.count == 1
77
84
  return files.first
78
85
  else
79
- raise "Could not determine which UIAutomation file to use. Please pass a path to your Javascript file using 'js_path'.".red
86
+ raise "Could not determine which UIAutomation file to use. Please pass a path to your Javascript file using 'js_file'.".red
80
87
  end
81
88
  end
82
89
 
@@ -32,15 +32,19 @@ module Snapshot
32
32
  when :js_file
33
33
  raise "js_file has to be an String".red unless value.kind_of?String
34
34
  raise "js_file at path '#{value}' not found".red unless File.exists?value
35
- @config.manual_js_file = value
35
+ @config.manual_js_file = value.gsub("~", ENV['HOME'])
36
36
  when :screenshots_path
37
37
  raise "screenshots_path has to be an String".red unless value.kind_of?String
38
- @config.screenshots_path = value
38
+ @config.screenshots_path = value.gsub("~", ENV['HOME'])
39
+ when :html_path
40
+ raise "html_path has to be an String".red unless value.kind_of?String
41
+ @config.html_path = value.gsub("~", ENV['HOME'])
42
+ @config.html_path = @config.html_path + "/screenshots.html" unless @config.html_path.include?".html"
39
43
  when :project_path
40
44
  raise "project_path has to be an String".red unless value.kind_of?String
41
45
 
42
46
  if File.exists?value and (value.end_with?".xcworkspace" or value.end_with?".xcodeproj")
43
- @config.project_path = value
47
+ @config.project_path = value.gsub("~", ENV['HOME'])
44
48
  else
45
49
  raise "The given project_path '#{value}' could not be found. Make sure to include the extension as well.".red
46
50
  end
@@ -1,3 +1,3 @@
1
1
  module Snapshot
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.1.beta1"
3
3
  end
data/lib/snapshot.rb CHANGED
@@ -6,6 +6,7 @@ require 'snapshot/runner'
6
6
  require 'snapshot/builder'
7
7
  require 'snapshot/snapshot_file'
8
8
  require 'snapshot/languages'
9
+ require 'snapshot/reports_generator'
9
10
 
10
11
  # Third Party code
11
12
  require 'colored'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snapshot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felix Krause
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-10 00:00:00.000000000 Z
11
+ date: 2014-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -39,47 +39,47 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: 1.6.21
41
41
  - !ruby/object:Gem::Dependency
42
- name: plist
42
+ name: colored
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 3.1.0
47
+ version: '0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 3.1.0
54
+ version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: colored
56
+ name: commander
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: 4.2.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: 4.2.0
69
69
  - !ruby/object:Gem::Dependency
70
- name: commander
70
+ name: fastimage
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 4.2.0
75
+ version: 1.6.3
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 4.2.0
82
+ version: 1.6.3
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: bundler
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -175,12 +175,16 @@ files:
175
175
  - LICENSE
176
176
  - README.md
177
177
  - bin/snapshot
178
+ - lib/assets/SnapfileTemplate
178
179
  - lib/snapshot.rb
179
180
  - lib/snapshot/builder.rb
180
181
  - lib/snapshot/dependency_checker.rb
181
182
  - lib/snapshot/helper.rb
182
183
  - lib/snapshot/languages.rb
184
+ - lib/snapshot/page.html.erb
185
+ - lib/snapshot/reports_generator.rb
183
186
  - lib/snapshot/runner.rb
187
+ - lib/snapshot/snapfile_creator.rb
184
188
  - lib/snapshot/snapshot_config.rb
185
189
  - lib/snapshot/snapshot_file.rb
186
190
  - lib/snapshot/update_checker.rb
@@ -189,8 +193,7 @@ homepage: http://felixkrause.at
189
193
  licenses:
190
194
  - MIT
191
195
  metadata: {}
192
- post_install_message: This gem requires phantomjs. Install it using 'brew update &&
193
- brew install phantomjs'
196
+ post_install_message:
194
197
  rdoc_options: []
195
198
  require_paths:
196
199
  - lib
@@ -198,12 +201,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
198
201
  requirements:
199
202
  - - ">="
200
203
  - !ruby/object:Gem::Version
201
- version: 1.9.3
204
+ version: 2.0.0
202
205
  required_rubygems_version: !ruby/object:Gem::Requirement
203
206
  requirements:
204
- - - ">="
207
+ - - ">"
205
208
  - !ruby/object:Gem::Version
206
- version: '0'
209
+ version: 1.3.1
207
210
  requirements: []
208
211
  rubyforge_project:
209
212
  rubygems_version: 2.2.2