second_curtain 0.1.5 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MDk0OGYxZjA4ZGJjODZkZjY0MWI3ZjljMjViNTVjYWRiMTk2MTUzZA==
4
+ ZmUyZjgyMzZjMWNmMzE2NDY3ZDk2NWIyYmQwOWJkNTFjYWFlNDYwNw==
5
5
  data.tar.gz: !binary |-
6
- MGE5NTRhNmU3ZmE1NjdlNTg2ZmQ5MTViZTUzMjkxYjhjYzdlMzhhNA==
6
+ ZjYyZTc1NDRiOTA5NzAzOGUzMzU5ZjBhZWZlNzEzOGNkNDRlMTg0YQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- OWUxY2EyZjc0NTBjMDUyNDAxNjA5N2U4MWYwNzA5MGE1NzI3MDI4YjU1MDIw
10
- YjhjNjczZGYzZGM0YTcwZGEzOWZlZDdiYWY5ZjIwYWQ1ZWZkZTA2ZDdkODVh
11
- MmZmNTkzMzMwYTlhOGQ2NDcyNWQxZjBmYTFiNzY2MzhlYzgxODk=
9
+ N2RjOWMyMDc0MjE3NjJiZmI3MTgzOGNjM2I4N2FhZTRhZjRiNDMwMDJmNzlm
10
+ Y2M0MTcwZDkxYjhkZTk4MGZiYjdhYjNmMGM0N2Q1MWZlYWExM2FhNTgwYTE0
11
+ ZGM0YzIxNjFmOGRlNjEzZmMwYjc4N2Y5ZWQ2YjJiZmViYTNhNmM=
12
12
  data.tar.gz: !binary |-
13
- ODNkOWNhZmQ3MDM0MDcwNzFiMWRhNGZmZjQ0ODIzNWI4YWQyODg3ODYyZGEx
14
- YTZmZDk1N2JhNmQzOTJlNWNhYmMyYzYzN2U2MGE1Y2MyMzNkNTJhYjM0ZmJm
15
- ODdjNTc2NDA4Mzk0MmUxNDNhYmUxNmI0MWVjZjk5MTk0NTBiNmE=
13
+ YTFhOGJhOTExOWFmY2I4NzE5YmU3M2M0ODZjYzRkMjY0MmRkODM2YjRmZWZl
14
+ Y2VlNTRkZDUxYTc1OWQ4OTFjYzZkYTY2NmNhOWZjOWE5Zjk3OWUyM2YzZDk3
15
+ MTMxNjM3Yzk2YmRhYTA2ZjZlNGZhNjkzMGIyZjhjOGMzZWFhZDQ=
data/bin/second_curtain CHANGED
@@ -2,56 +2,51 @@
2
2
 
3
3
  require 'second_curtain'
4
4
 
5
- input = []
5
+ parser = Parser.new()
6
6
 
7
7
  ARGF.each_line do |line|
8
- input.push(line)
8
+ parser.parse_line(line)
9
9
  print line
10
10
  end
11
11
 
12
- bucket_name = ENV['UPLOAD_IOS_SNAPSHOT_BUCKET_NAME']
12
+ if parser.has_failing_commands
13
+ bucket_name = ENV['UPLOAD_IOS_SNAPSHOT_BUCKET_NAME']
13
14
 
14
- if bucket_name == nil
15
- abort "error: Second Curtain bucket name must be specified in environment UPLOAD_IOS_SNAPSHOT_BUCKET_NAME variable"
16
- end
17
-
18
- aws_key = ENV['AWS_ACCESS_KEY_ID']
19
- aws_secret = ENV['AWS_SECRET_ACCESS_KEY']
20
- if aws_key == nil || aws_secret == nil
21
- abort "error: Second Curtain AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY must be defined as environment variables"
22
- end
15
+ if bucket_name == nil
16
+ abort "error: Second Curtain bucket name must be specified in environment UPLOAD_IOS_SNAPSHOT_BUCKET_NAME variable"
17
+ end
23
18
 
24
- path_prefix = ENV['UPLOAD_IOS_SNAPSHOT_BUCKET_PREFIX'] || '/'
25
- if !path_prefix.end_with?('/')
26
- path_prefix += '/'
27
- end
19
+ aws_key = ENV['AWS_ACCESS_KEY_ID']
20
+ aws_secret = ENV['AWS_SECRET_ACCESS_KEY']
21
+ if aws_key == nil || aws_secret == nil
22
+ abort "error: Second Curtain AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY must be defined as environment variables"
23
+ end
28
24
 
29
- folder_name = ENV['UPLOAD_IOS_SNAPSHOT_FOLDER_NAME']
30
- if !folder_name
31
- folder_name = ENV['TRAVIS_JOB_ID']
32
- end
25
+ path_prefix = ENV['UPLOAD_IOS_SNAPSHOT_BUCKET_PREFIX'] || '/'
26
+ if !path_prefix.end_with?('/')
27
+ path_prefix += '/'
28
+ end
33
29
 
34
- if !folder_name
35
- now = DateTime.now()
36
- folder_name = now.strftime('%Y-%m-%d--%H-%M')
37
- end
30
+ folder_name = ENV['UPLOAD_IOS_SNAPSHOT_FOLDER_NAME']
31
+ if !folder_name
32
+ folder_name = ENV['TRAVIS_JOB_ID']
33
+ end
38
34
 
39
- s3 = AWS::S3.new
40
- bucket = s3.buckets[bucket_name]
41
- manager = UploadManager.new(bucket, path_prefix)
42
-
43
- input.each do |line|
44
- if line.start_with?('ksdiff')
45
- parts = line.split(/"/)
46
- if (parts.count >= 4)
47
- expected_path = parts[1]
48
- actual_path = parts[3]
49
- manager.enqueue_upload(expected_path, actual_path)
50
- end
35
+ if !folder_name
36
+ now = DateTime.now()
37
+ folder_name = now.strftime('%Y-%m-%d--%H-%M')
51
38
  end
52
- end
53
39
 
54
- failures_address = manager.upload(folder_name)
55
- if failures_address
56
- $stderr.puts ("Failures: " + failures_address)
40
+ s3 = AWS::S3.new
41
+ bucket = s3.buckets[bucket_name]
42
+ manager = UploadManager.new(bucket, path_prefix)
43
+
44
+ parser.failing_commands.each do |command|
45
+ manager.enqueue_upload(command.before_path, command.after_path)
46
+ end
47
+
48
+ failures_address = manager.upload(folder_name)
49
+ if failures_address
50
+ $stderr.puts ("Failures: " + failures_address)
51
+ end
57
52
  end
@@ -1,2 +1,6 @@
1
1
  require 'second_curtain/upload'
2
2
  require 'second_curtain/upload_manager'
3
+ require 'second_curtain/parser'
4
+ require 'second_curtain/kaleidoscope_command'
5
+ require 'second_curtain/xcode_test_case'
6
+ require 'second_curtain/test_suite'
@@ -0,0 +1,18 @@
1
+ class KaleidoscopeCommand
2
+ attr_accessor :fails
3
+ attr_accessor :before_path
4
+ attr_accessor :after_path
5
+
6
+ def self.command_from_line(line)
7
+ components = line.split("\"")
8
+ if components.count >= 4
9
+ KaleidoscopeCommand.new(components[1], components[3])
10
+ end
11
+ end
12
+
13
+ def initialize(before_path, after_path)
14
+ @before_path = before_path
15
+ @after_path = after_path
16
+ end
17
+ end
18
+
@@ -0,0 +1,51 @@
1
+ require 'second_curtain/xcode_test_case'
2
+ require 'second_curtain/test_suite'
3
+ require 'second_curtain/kaleidoscope_command'
4
+
5
+ # Lifted from https://github.com/orta/Snapshots/blob/master/SnapshotDiffs/ORLogReader.m
6
+
7
+ class Parser
8
+ def initialize
9
+ @test_suites = []
10
+ end
11
+
12
+ def parse_line(line)
13
+ if line.include?("Test Suite")
14
+ test_suite = TestSuite.suite_from_line(line)
15
+ @test_suites.push test_suite unless test_suite == nil
16
+ end
17
+
18
+ if line.include?("Test Case") && latest_test_suite
19
+ if line.include?("started.")
20
+ test_case = XcodeTestCase.test_case_from_line(line)
21
+ latest_test_suite.test_cases.push test_case unless test_case == nil
22
+ elsif line.include?("' failed (")
23
+ latest_test_suite.latest_test_case.latest_command.fails = true
24
+ end
25
+ end
26
+
27
+ if line.include?("ksdiff") && latest_test_suite
28
+ command_string = extract_command_string_from_line(line)
29
+ command = KaleidoscopeCommand.command_from_line(command_string)
30
+ if command != nil
31
+ latest_test_suite.latest_test_case.add_command command
32
+ end
33
+ end
34
+ end
35
+
36
+ def latest_test_suite
37
+ @test_suites.last
38
+ end
39
+
40
+ def extract_command_string_from_line(line)
41
+ return line.split("diff:\n").last
42
+ end
43
+
44
+ def failing_commands
45
+ @test_suites.map { |e| e.test_cases }.flatten.map { |e| e.commands }.flatten.select { |e| e.fails }
46
+ end
47
+
48
+ def has_failing_commands
49
+ failing_commands.count > 0
50
+ end
51
+ end
@@ -0,0 +1,176 @@
1
+ <html>
2
+ <head>
3
+ <style>
4
+ html {
5
+ background-color:#FFFAFC;
6
+ font-family: 'Josefin Sans', sans-serif;
7
+ color:#BE99CC;
8
+ }
9
+
10
+ nav {
11
+ height:60px;
12
+ background-color:white;
13
+ }
14
+
15
+ nav h1 {
16
+ display:inline-block;
17
+ margin-top:6px;
18
+ }
19
+
20
+ nav ul {
21
+ margin-top:18px;
22
+ display:inline-block;
23
+ float:right;
24
+ }
25
+
26
+ nav ul li {
27
+ float:right;
28
+ margin-left:30px;
29
+ }
30
+
31
+ nav ul li a {
32
+ text-decoration: none;
33
+ }
34
+
35
+ h1 {
36
+ font-weight: 400;
37
+ font-size:48px;
38
+ }
39
+
40
+ h2, nav ul, h3 {
41
+ font-weight: 300;
42
+ font-size:24px;
43
+ }
44
+
45
+ .content {
46
+ width:1200px;
47
+ margin:0 auto;
48
+ }
49
+
50
+ img.before {
51
+ border: 2px solid #9FCC99;
52
+ }
53
+
54
+ img.after {
55
+ border: 2px solid #CC7B7B;
56
+ background-color:green;
57
+ pointer-events:none;
58
+ }
59
+
60
+ article.content {
61
+ margin:36px auto;
62
+ }
63
+
64
+ section img {
65
+ background-repeat: repeat-x repeat-y;
66
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAeUlEQVRYCe3TIQ7AIBBE0QXRut7/mlSVGorE/22C+KtAzIa8DKW3Z0TiHNeZuC2ipm77YZkPpKgKKkgFaN4OKkgFaN4OKkgFaN4OKkgFaL6MOXTJmn/vvl7x2U9CCRVUkArQvB1UkArQvB1UkArQvB1UkArQ/PYd/AC9pgss8BZEQAAAAABJRU5ErkJggg==);
67
+ }
68
+
69
+ section div.onion {
70
+ position: relative;
71
+ }
72
+
73
+ section div.onion p {
74
+ text-align:center;
75
+ position:absolute;
76
+ top:600px;
77
+ left:0px;
78
+ width:100%;
79
+ }
80
+
81
+ section div.onion img {
82
+ position:absolute;
83
+ top:1px;
84
+ left:1;
85
+ max-height:520px;
86
+ }
87
+
88
+ section {
89
+ background-color:white;
90
+ height:660px;
91
+ }
92
+
93
+ </style>
94
+ <link href='http://fonts.googleapis.com/css?family=Josefin+Sans:300,400' rel='stylesheet' type='text/css'>
95
+ <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
96
+ </head>
97
+
98
+ <body>
99
+ <nav>
100
+ <div class="content">
101
+ <h1>Second Curtain</h1>
102
+ <ul>
103
+ <!-- <li><a href="file:///Users/orta/dev/ruby/second_curtain/lib/second_curtain/template.mustache.html">artsy/eigen#1112</a></li>
104
+ <li><a href="file:///Users/orta/dev/ruby/second_curtain/lib/second_curtain/template.mustache.html">travis#5240812</a></li> -->
105
+ </ul>
106
+ </div>
107
+ </nav>
108
+
109
+ <!-- <article class="content">
110
+ <h1>ARAmbiguousSplitStackViewSpec</h1>
111
+ <h3>Single Stack With Two Views</h3>
112
+ <section >
113
+ <div class="onion">
114
+ <img class="before" src="https://github.com/artsy/energy/raw/2c1b4d2eb35bba900c697a11e7e65f22024e7d0a/ArtsyFolio%20Tests/ReferenceImages/ARAmbiguousSplitStackViewSpec/single_stack_with_two_views%402x.png?raw=true">
115
+ <img class="after" src="https://github.com/orta/energy/raw/5978c5bfa0dfdd0317f2b68e855efad7d7dc7df2/ArtsyFolio%20Tests/ReferenceImages/ARAmbiguousSplitStackViewSpec/single_stack_with_two_views%402x.png?raw=true">
116
+ <p>320 x 280</p>
117
+ </div>
118
+ </section>
119
+ </article> -->
120
+
121
+ {{#uploads}}
122
+ <article class="content">
123
+ <section>
124
+ <div class="onion">
125
+ <img class="before" src="{{ uploaded_expected_url }}">
126
+ <img class="after" src="{{ uploaded_actual_url }}">
127
+ </div>
128
+ </section>
129
+ </article>
130
+ {{/uploads}}
131
+
132
+
133
+ <script>
134
+
135
+ /*!
136
+ * imagesLoaded PACKAGED v3.1.8
137
+ * JavaScript is all like "You images are done yet or what?"
138
+ * MIT License
139
+ */
140
+
141
+ (function(){function e(){}function t(e,t){for(var n=e.length;n--;)if(e[n].listener===t)return n;return-1}function n(e){return function(){return this[e].apply(this,arguments)}}var i=e.prototype,r=this,o=r.EventEmitter;i.getListeners=function(e){var t,n,i=this._getEvents();if("object"==typeof e){t={};for(n in i)i.hasOwnProperty(n)&&e.test(n)&&(t[n]=i[n])}else t=i[e]||(i[e]=[]);return t},i.flattenListeners=function(e){var t,n=[];for(t=0;e.length>t;t+=1)n.push(e[t].listener);return n},i.getListenersAsObject=function(e){var t,n=this.getListeners(e);return n instanceof Array&&(t={},t[e]=n),t||n},i.addListener=function(e,n){var i,r=this.getListenersAsObject(e),o="object"==typeof n;for(i in r)r.hasOwnProperty(i)&&-1===t(r[i],n)&&r[i].push(o?n:{listener:n,once:!1});return this},i.on=n("addListener"),i.addOnceListener=function(e,t){return this.addListener(e,{listener:t,once:!0})},i.once=n("addOnceListener"),i.defineEvent=function(e){return this.getListeners(e),this},i.defineEvents=function(e){for(var t=0;e.length>t;t+=1)this.defineEvent(e[t]);return this},i.removeListener=function(e,n){var i,r,o=this.getListenersAsObject(e);for(r in o)o.hasOwnProperty(r)&&(i=t(o[r],n),-1!==i&&o[r].splice(i,1));return this},i.off=n("removeListener"),i.addListeners=function(e,t){return this.manipulateListeners(!1,e,t)},i.removeListeners=function(e,t){return this.manipulateListeners(!0,e,t)},i.manipulateListeners=function(e,t,n){var i,r,o=e?this.removeListener:this.addListener,s=e?this.removeListeners:this.addListeners;if("object"!=typeof t||t instanceof RegExp)for(i=n.length;i--;)o.call(this,t,n[i]);else for(i in t)t.hasOwnProperty(i)&&(r=t[i])&&("function"==typeof r?o.call(this,i,r):s.call(this,i,r));return this},i.removeEvent=function(e){var t,n=typeof e,i=this._getEvents();if("string"===n)delete i[e];else if("object"===n)for(t in i)i.hasOwnProperty(t)&&e.test(t)&&delete i[t];else delete this._events;return this},i.removeAllListeners=n("removeEvent"),i.emitEvent=function(e,t){var n,i,r,o,s=this.getListenersAsObject(e);for(r in s)if(s.hasOwnProperty(r))for(i=s[r].length;i--;)n=s[r][i],n.once===!0&&this.removeListener(e,n.listener),o=n.listener.apply(this,t||[]),o===this._getOnceReturnValue()&&this.removeListener(e,n.listener);return this},i.trigger=n("emitEvent"),i.emit=function(e){var t=Array.prototype.slice.call(arguments,1);return this.emitEvent(e,t)},i.setOnceReturnValue=function(e){return this._onceReturnValue=e,this},i._getOnceReturnValue=function(){return this.hasOwnProperty("_onceReturnValue")?this._onceReturnValue:!0},i._getEvents=function(){return this._events||(this._events={})},e.noConflict=function(){return r.EventEmitter=o,e},"function"==typeof define&&define.amd?define("eventEmitter/EventEmitter",[],function(){return e}):"object"==typeof module&&module.exports?module.exports=e:this.EventEmitter=e}).call(this),function(e){function t(t){var n=e.event;return n.target=n.target||n.srcElement||t,n}var n=document.documentElement,i=function(){};n.addEventListener?i=function(e,t,n){e.addEventListener(t,n,!1)}:n.attachEvent&&(i=function(e,n,i){e[n+i]=i.handleEvent?function(){var n=t(e);i.handleEvent.call(i,n)}:function(){var n=t(e);i.call(e,n)},e.attachEvent("on"+n,e[n+i])});var r=function(){};n.removeEventListener?r=function(e,t,n){e.removeEventListener(t,n,!1)}:n.detachEvent&&(r=function(e,t,n){e.detachEvent("on"+t,e[t+n]);try{delete e[t+n]}catch(i){e[t+n]=void 0}});var o={bind:i,unbind:r};"function"==typeof define&&define.amd?define("eventie/eventie",o):e.eventie=o}(this),function(e,t){"function"==typeof define&&define.amd?define(["eventEmitter/EventEmitter","eventie/eventie"],function(n,i){return t(e,n,i)}):"object"==typeof exports?module.exports=t(e,require("wolfy87-eventemitter"),require("eventie")):e.imagesLoaded=t(e,e.EventEmitter,e.eventie)}(window,function(e,t,n){function i(e,t){for(var n in t)e[n]=t[n];return e}function r(e){return"[object Array]"===d.call(e)}function o(e){var t=[];if(r(e))t=e;else if("number"==typeof e.length)for(var n=0,i=e.length;i>n;n++)t.push(e[n]);else t.push(e);return t}function s(e,t,n){if(!(this instanceof s))return new s(e,t);"string"==typeof e&&(e=document.querySelectorAll(e)),this.elements=o(e),this.options=i({},this.options),"function"==typeof t?n=t:i(this.options,t),n&&this.on("always",n),this.getImages(),a&&(this.jqDeferred=new a.Deferred);var r=this;setTimeout(function(){r.check()})}function f(e){this.img=e}function c(e){this.src=e,v[e]=this}var a=e.jQuery,u=e.console,h=u!==void 0,d=Object.prototype.toString;s.prototype=new t,s.prototype.options={},s.prototype.getImages=function(){this.images=[];for(var e=0,t=this.elements.length;t>e;e++){var n=this.elements[e];"IMG"===n.nodeName&&this.addImage(n);var i=n.nodeType;if(i&&(1===i||9===i||11===i))for(var r=n.querySelectorAll("img"),o=0,s=r.length;s>o;o++){var f=r[o];this.addImage(f)}}},s.prototype.addImage=function(e){var t=new f(e);this.images.push(t)},s.prototype.check=function(){function e(e,r){return t.options.debug&&h&&u.log("confirm",e,r),t.progress(e),n++,n===i&&t.complete(),!0}var t=this,n=0,i=this.images.length;if(this.hasAnyBroken=!1,!i)return this.complete(),void 0;for(var r=0;i>r;r++){var o=this.images[r];o.on("confirm",e),o.check()}},s.prototype.progress=function(e){this.hasAnyBroken=this.hasAnyBroken||!e.isLoaded;var t=this;setTimeout(function(){t.emit("progress",t,e),t.jqDeferred&&t.jqDeferred.notify&&t.jqDeferred.notify(t,e)})},s.prototype.complete=function(){var e=this.hasAnyBroken?"fail":"done";this.isComplete=!0;var t=this;setTimeout(function(){if(t.emit(e,t),t.emit("always",t),t.jqDeferred){var n=t.hasAnyBroken?"reject":"resolve";t.jqDeferred[n](t)}})},a&&(a.fn.imagesLoaded=function(e,t){var n=new s(this,e,t);return n.jqDeferred.promise(a(this))}),f.prototype=new t,f.prototype.check=function(){var e=v[this.img.src]||new c(this.img.src);if(e.isConfirmed)return this.confirm(e.isLoaded,"cached was confirmed"),void 0;if(this.img.complete&&void 0!==this.img.naturalWidth)return this.confirm(0!==this.img.naturalWidth,"naturalWidth"),void 0;var t=this;e.on("confirm",function(e,n){return t.confirm(e.isLoaded,n),!0}),e.check()},f.prototype.confirm=function(e,t){this.isLoaded=e,this.emit("confirm",this,t)};var v={};return c.prototype=new t,c.prototype.check=function(){if(!this.isChecked){var e=new Image;n.bind(e,"load",this),n.bind(e,"error",this),e.src=this.src,this.isChecked=!0}},c.prototype.handleEvent=function(e){var t="on"+e.type;this[t]&&this[t](e)},c.prototype.onload=function(e){this.confirm(!0,"onload"),this.unbindProxyEvents(e)},c.prototype.onerror=function(e){this.confirm(!1,"onerror"),this.unbindProxyEvents(e)},c.prototype.confirm=function(e,t){this.isConfirmed=!0,this.isLoaded=e,this.emit("confirm",this,t)},c.prototype.unbindProxyEvents=function(e){n.unbind(e.target,"load",this),n.unbind(e.target,"error",this)},s});
142
+
143
+ /* Second Curtain JS */
144
+
145
+ $(".onion").each(function(index, element) {
146
+
147
+ var $before = $($(element).find(".before"))[0]
148
+ var $after = $($(element).find(".after"))[0]
149
+
150
+ // position once we have the images
151
+
152
+ imagesLoaded( element, function( instance ) {
153
+
154
+ var left = ((1200 - $($before).width()) / 2) + "px"
155
+ var top = ((660 - $($before).height()) / 2) + "px"
156
+
157
+ $($before).css("top", top)
158
+ $($before).css("left", left)
159
+
160
+ $($after).css("top", top)
161
+ $($after).css("left", left)
162
+ });
163
+
164
+ // allow mouse drag to change the clip on the after
165
+
166
+ $( $before ).mousemove(function( event ) {
167
+ var x = event.pageX - element.offsetLeft - ((1200 - $(this).width() ) / 2)
168
+ var css = "rect( 0px, " + x + "px, " + $(this).height() + "px, 0px)"
169
+ $after.style.clip = css
170
+ });
171
+
172
+ });
173
+ </script>
174
+
175
+ </body>
176
+ </html>
@@ -0,0 +1,22 @@
1
+ class TestSuite
2
+ attr_accessor :test_cases
3
+ attr_accessor :name
4
+
5
+ def self.suite_from_line(line)
6
+ components = line.split("Test Suite '")
7
+ end_components = line.split("' started at")
8
+
9
+ if components.count == 2 && end_components.count == 2
10
+ TestSuite.new(components.last.split("'").first)
11
+ end
12
+ end
13
+
14
+ def initialize (name)
15
+ @name = name
16
+ @test_cases = []
17
+ end
18
+
19
+ def latest_test_case
20
+ @test_cases.last
21
+ end
22
+ end
@@ -28,8 +28,4 @@ class Upload
28
28
  actual_object.write(:file => @actual_path)
29
29
  @uploaded_actual_url = actual_object.public_url
30
30
  end
31
-
32
- def to_html
33
- "<li><a href='#{ @uploaded_expected_url.to_s }'>Expected</a>, <a href='#{ @uploaded_actual_url.to_s }'>Actual</li>"
34
- end
35
31
  end
@@ -1,5 +1,6 @@
1
1
  require 'aws-sdk'
2
2
  require 'second_curtain/upload'
3
+ require 'second_curtain/web_preview'
3
4
 
4
5
  class UploadManager
5
6
  def initialize (bucket, path_prefix)
@@ -22,12 +23,9 @@ class UploadManager
22
23
  upload.upload(@bucket, @path_prefix)
23
24
  end
24
25
 
26
+ preview = WebPreview.new(@uploads)
25
27
  index_object = @bucket.objects[@path_prefix + folder_name + "/index.html"]
26
- index_object.write(to_html)
28
+ index_object.write(preview.generate_html)
27
29
  index_object.public_url.to_s
28
30
  end
29
-
30
- def to_html
31
- "<html><body>#{@uploads.map(&:to_html).join}</body></html>"
32
- end
33
31
  end
@@ -0,0 +1,16 @@
1
+ require 'mustache'
2
+
3
+ class WebPreview
4
+ attr_reader :uploads
5
+
6
+ def initialize(uploads)
7
+ @uploads = uploads
8
+ end
9
+
10
+ def generate_html
11
+ lib_path = File.expand_path(File.dirname(__FILE__))
12
+ template = File.read(lib_path + "/template.mustache.html")
13
+
14
+ Mustache.render(template, :uploads => @uploads, :travis_id => ENV['TRAVIS_JOB_ID'])
15
+ end
16
+ end
@@ -0,0 +1,46 @@
1
+ class XcodeTestCase
2
+ attr_accessor :commands
3
+ attr_accessor :name
4
+
5
+ def self.test_case_from_line(line)
6
+ components = line.split("Test Case '-[")
7
+
8
+ if components.count == 2 && line.include?("]' started.")
9
+ # Let's make it readable
10
+ name = components.last.split("'").first
11
+ name = name.split(" ").last
12
+ name = name.split("]").first
13
+ name = name.gsub("_", " ")
14
+
15
+ # We avoid hitting ends of words by addng the space, but that potentially misses the first one
16
+ name += " "
17
+
18
+ name.gsub!(" hasnt ", " hasn't")
19
+ name.gsub!(" isn t", " isn't")
20
+ name.gsub!(" won t", " won't")
21
+ name.gsub!(" don t", " don't")
22
+ name.gsub!(" doesn t", " doesn't")
23
+ name.gsub!(" shouldn t", " shouldn't")
24
+ name.gsub!(" can t", " can't")
25
+
26
+ first_char_upper = name[0].upcase
27
+ name[0] = first_char_upper
28
+ name.strip!
29
+ XcodeTestCase.new(name)
30
+ end
31
+ end
32
+
33
+ def initialize (name)
34
+ @commands = []
35
+ @name = name
36
+ end
37
+
38
+ def add_command(command)
39
+ @commands.push(command)
40
+ end
41
+
42
+ def latest_command
43
+ @commands.last
44
+ end
45
+ end
46
+
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: second_curtain
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ash Furrow
8
+ - Orta Therox
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2014-08-02 00:00:00.000000000 Z
12
+ date: 2014-08-05 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: aws-sdk
@@ -24,6 +25,20 @@ dependencies:
24
25
  - - ~>
25
26
  - !ruby/object:Gem::Version
26
27
  version: '1.48'
28
+ - !ruby/object:Gem::Dependency
29
+ name: mustache
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: '0.99'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ version: '0.99'
27
42
  description: ! "\n If you're using the cool FBSnapshotTestCase to test your iOS view
28
43
  logic, awesome! Even better if you have continuous integration, like on Travis,
29
44
  to automate running those tests!\n\n Wouldn't it be awesome if we could upload
@@ -37,8 +52,14 @@ extra_rdoc_files: []
37
52
  files:
38
53
  - bin/second_curtain
39
54
  - lib/second_curtain.rb
55
+ - lib/second_curtain/kaleidoscope_command.rb
56
+ - lib/second_curtain/parser.rb
57
+ - lib/second_curtain/template.mustache.html
58
+ - lib/second_curtain/test_suite.rb
40
59
  - lib/second_curtain/upload.rb
41
60
  - lib/second_curtain/upload_manager.rb
61
+ - lib/second_curtain/web_preview.rb
62
+ - lib/second_curtain/xcode_test_case.rb
42
63
  homepage: https://github.com/AshFurrow/second_curtain
43
64
  licenses:
44
65
  - MIT