snapshot 0.1.0 → 0.2.1.beta1

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