magicspec 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.project +18 -0
  4. data/Gemfile +16 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +95 -0
  7. data/README.rdoc +38 -0
  8. data/Rakefile +44 -0
  9. data/bin/magicspec +6 -0
  10. data/lib/magicspec/cli.rb +73 -0
  11. data/lib/magicspec/errors.rb +6 -0
  12. data/lib/magicspec/ext/string.rb +11 -0
  13. data/lib/magicspec/generators/magicspec/.rspec +1 -0
  14. data/lib/magicspec/generators/magicspec/app/matchers/.empty_directory +5 -0
  15. data/lib/magicspec/generators/magicspec/app/pages/yale/yale_page.rb.tt +15 -0
  16. data/lib/magicspec/generators/magicspec/app/pages/yale/yale_search_result_page.rb.tt +9 -0
  17. data/lib/magicspec/generators/magicspec/app/reports/.empty_directory +5 -0
  18. data/lib/magicspec/generators/magicspec/app/reports/screenshots/.empty_directory +0 -0
  19. data/lib/magicspec/generators/magicspec/app/spec/shared/login.rb +11 -0
  20. data/lib/magicspec/generators/magicspec/app/spec/spec_helper.rb.tt +114 -0
  21. data/lib/magicspec/generators/magicspec/app/spec/support/formatters/dry_run_formatter.rb +13 -0
  22. data/lib/magicspec/generators/magicspec/app/spec/support/formatters/html_override.rb +360 -0
  23. data/lib/magicspec/generators/magicspec/app/spec/support/formatters/magicspec_formatter.rb +46 -0
  24. data/lib/magicspec/generators/magicspec/app/spec/support/matchers/custom_matcher.rb +7 -0
  25. data/lib/magicspec/generators/magicspec/app/spec/support/matchers/email_matcher.rb +1 -0
  26. data/lib/magicspec/generators/magicspec/app/spec/support/matchers/file_matcher.rb +12 -0
  27. data/lib/magicspec/generators/magicspec/app/spec/yale/yale_example_spec.rb +34 -0
  28. data/lib/magicspec/generators/magicspec/app/test_data/baidu.yml +4 -0
  29. data/lib/magicspec/generators/magicspec/app/test_data/login_user.yml +4 -0
  30. data/lib/magicspec/generators/magicspec/bin/console +7 -0
  31. data/lib/magicspec/generators/magicspec/bin/console.bat +6 -0
  32. data/lib/magicspec/generators/magicspec/bin/setup.rb.tt +12 -0
  33. data/lib/magicspec/generators/magicspec/config/config.yml +6 -0
  34. data/lib/magicspec/generators/magicspec/config/magicspec_formatter.rb +47 -0
  35. data/lib/magicspec/generators/magicspec/config/override.rb +351 -0
  36. data/lib/magicspec/magicspec_config.rb +21 -0
  37. data/lib/magicspec/magicspec_initializer.rb +33 -0
  38. data/lib/magicspec/page_override.rb +5 -0
  39. data/lib/magicspec/templates/browser_spec_template.rb.tt +22 -0
  40. data/lib/magicspec/templates/mobile_template.rb.tt +15 -0
  41. data/lib/magicspec/templates/plain_template.rb.tt +22 -0
  42. data/lib/magicspec/templates/template_page.rb.tt +11 -0
  43. data/lib/magicspec/templates/web_service_template.rb.tt +18 -0
  44. data/lib/magicspec/watir_browser.rb +7 -0
  45. data/lib/magicspec.rb +8 -0
  46. data/magicspec.gemspec +120 -0
  47. data/spec/app/pages/components/footer.rb +3 -0
  48. data/spec/app/pages/components/sub/sub_footer.rb +3 -0
  49. data/spec/app/pages/module1/module1_page.rb +6 -0
  50. data/spec/app/pages/module1/sub_test_page.rb +4 -0
  51. data/spec/app/pages/test_navigator.rb +4 -0
  52. data/spec/app/pages/test_page.rb +4 -0
  53. data/spec/config/config.yml +3 -0
  54. data/spec/config/wrong_config.yml +5 -0
  55. data/spec/lazy_initializer_spec.rb +28 -0
  56. data/spec/lazy_navigator_spec.rb +36 -0
  57. data/spec/lazy_page_spec.rb +44 -0
  58. data/spec/magicspec_config_spec.rb +28 -0
  59. data/spec/pages/components/footer.rb +2 -0
  60. data/spec/pages/test_page.rb +5 -0
  61. data/spec/spec_helper.rb +20 -0
  62. data/spec/string_spec.rb +10 -0
  63. metadata +206 -0
@@ -0,0 +1,360 @@
1
+ require 'rspec'
2
+ require 'rspec/core/formatters/base_text_formatter'
3
+ require 'rspec/core/formatters/html_printer'
4
+ require 'gmail'
5
+ require 'sys/uname'
6
+
7
+ include Sys
8
+
9
+ #https://github.com/GICodeWarrior/threaded-rspec
10
+
11
+ module RSpec
12
+ module Core
13
+ module Formatters
14
+ class HtmlPrinter
15
+ def print_html_start
16
+ @output.puts YALE_HTML_HEADER
17
+ @output.puts YALE_REPORT_HEADER
18
+ end
19
+
20
+ def print_example_group_start( group_id, description, number_of_parents )
21
+ @output.puts "<div id=\"div_group_#{group_id}\" class=\"example_group passed\">"
22
+ @output.puts " <dl #{indentation_style(number_of_parents)}>"
23
+ @output.puts " <dt id=\"example_group_#{group_id}\" class=\"passed\">#{h(description)}</dt>"
24
+ end
25
+
26
+ def print_summary( was_dry_run, duration, example_count, failure_count, pending_count )
27
+ # TODO - kill dry_run?
28
+ if was_dry_run
29
+ totals = "This was a dry-run"
30
+ else
31
+ totals = "#{example_count} example#{'s' unless example_count == 1}, "
32
+ totals << "#{failure_count} failure#{'s' unless failure_count == 1}"
33
+ totals << ", #{pending_count} pending" if pending_count > 0
34
+ end
35
+
36
+ formatted_duration = sprintf("%.5f", duration)
37
+
38
+ @output.puts "<script type=\"text/javascript\">document.getElementById('duration').innerHTML = \"Finished in <strong>#{formatted_duration} seconds</strong>\";</script>"
39
+ @output.puts "<script type=\"text/javascript\">document.getElementById('totals').innerHTML = \"#{totals}\";</script>"
40
+ @output.puts "<script type=\"text/javascript\">document.getElementById('browser').innerHTML = \"#{Uname.sysname}\";</script>"
41
+ @output.puts "</div>"
42
+ @output.puts "</div>"
43
+ @output.puts "</body>"
44
+ @output.puts "</html>"
45
+
46
+ # Send a note to all the emails!
47
+ gmail = Gmail.new("yaleqa@gmail.com","")
48
+ gmail.deliver do
49
+ to $emails
50
+ subject "Test is complete!"
51
+ html_part do
52
+ content_type 'text/html; charset=UTF-8'
53
+ body "<p>Done!</p><p>#{totals}</p>"
54
+ end
55
+ #add_file "/path/to/some_image.jpg"
56
+ end
57
+ end
58
+
59
+ YALE_REPORT_HEADER = <<-EOF
60
+ <div class="rspec-report container">
61
+ <div id="rspec-header">
62
+ <div id="label">
63
+ <h1>Yale Automation Report</h1>
64
+ </div>
65
+
66
+ <div id="display-filters">
67
+ <input id="passed_checkbox" name="passed_checkbox" type="checkbox" checked="checked" onchange="apply_filters()" value="1" /> <label for="passed_checkbox">Passed</label>
68
+ <input id="failed_checkbox" name="failed_checkbox" type="checkbox" checked="checked" onchange="apply_filters()" value="2" /> <label for="failed_checkbox">Failed</label>
69
+ <input id="pending_checkbox" name="pending_checkbox" type="checkbox" checked="checked" onchange="apply_filters()" value="3" /> <label for="pending_checkbox">Pending</label>
70
+ </div>
71
+
72
+ <div id="summary">
73
+ <p id="totals">&#160;</p>
74
+ <p id="duration">&#160;</p>
75
+ </div>
76
+ <div id="chart">
77
+ <div id="container" style="min-width: 200px; height: 200px; margin: 0 auto"></div>
78
+ <script>
79
+ $(function () {
80
+ var chart;
81
+
82
+ $(document).ready(function () {
83
+
84
+ // Build the chart
85
+ $('#container').highcharts({
86
+ chart: {
87
+ plotBackgroundColor: null,
88
+ plotBorderWidth: null,
89
+ plotShadow: false
90
+ },
91
+ title: {
92
+ text: 'Test Results'
93
+ },
94
+ tooltip: {
95
+ pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
96
+ },
97
+ plotOptions: {
98
+ pie: {
99
+ allowPointSelect: true,
100
+ cursor: 'pointer',
101
+ dataLabels: {
102
+ enabled: false
103
+ },
104
+ showInLegend: true
105
+ }
106
+ },
107
+ series: [{
108
+ type: 'pie',
109
+ name: 'Browser share',
110
+ data: [
111
+ ['Pass', 10],
112
+ ['Fail', 15],
113
+ {
114
+ name: 'Not Implemented',
115
+ y: 5,
116
+ sliced: true,
117
+ selected: true
118
+ }
119
+ ]
120
+ }]
121
+ });
122
+ });
123
+
124
+ });
125
+ </script>
126
+ </div>
127
+ <div id="deets">
128
+ <table class="table table-bordered table-condensed table-responsive">
129
+ <tr>
130
+ <td>Browser</td>
131
+ <td id="browser"></td>
132
+ </tr>
133
+ <tr>
134
+ <td>OS</td>
135
+ <td id="OS">Mac</td>
136
+ </tr>
137
+ <tr>
138
+ <td>Date</td>
139
+ <td id="Date">#{Time.now.to_s}</td>
140
+ </tr>
141
+ <tr>
142
+ <td>Time</td>
143
+ <td id="Time">12 PM</td>
144
+ </tr>
145
+ </table>
146
+ </div>
147
+ </div>
148
+ <div class="results">
149
+ EOF
150
+
151
+ YALE_GLOBAL_STYLES = <<-EOF
152
+ #rspec-header {
153
+ background: #65C400; color: #fff; height: 250px;
154
+ margin: 10px 10px 10px 10px;
155
+ }
156
+
157
+ .rspec-report h1 {
158
+ margin: 0px 10px 0px 10px;
159
+ padding: 10px;
160
+ font-family: "Lucida Grande", Helvetica, sans-serif;
161
+ font-size: 1.8em;
162
+ position: absolute;
163
+ }
164
+
165
+ #deets {
166
+ float:left;
167
+ margin: 60px 10px 0px 20px;
168
+ position: absolute;
169
+ }
170
+
171
+ #chart {
172
+ float:right;
173
+ margin: 10px 10px 0px 60px;
174
+ }
175
+
176
+ #label {
177
+ float:left;
178
+ }
179
+
180
+ #display-filters {
181
+ float:left;
182
+ padding: 28px 0 0 40%;
183
+ font-family: "Lucida Grande", Helvetica, sans-serif;
184
+ }
185
+
186
+ #summary {
187
+ float:right;
188
+ padding: 5px 10px;
189
+ font-family: "Lucida Grande", Helvetica, sans-serif;
190
+ text-align: right;
191
+ }
192
+
193
+ #summary p {
194
+ margin: 0 0 0 2px;
195
+ }
196
+
197
+ #summary #totals {
198
+ font-size: 1.2em;
199
+ }
200
+
201
+ .example_group {
202
+ margin: 0 10px 5px;
203
+ background: #fff;
204
+ }
205
+
206
+ dl {
207
+ margin: 0; padding: 0 0 5px;
208
+ font: normal 11px "Lucida Grande", Helvetica, sans-serif;
209
+ }
210
+
211
+ dt {
212
+ padding: 3px;
213
+ background: #65C400;
214
+ color: #fff;
215
+ font-weight: bold;
216
+ }
217
+
218
+ dd {
219
+ margin: 5px 0 5px 5px;
220
+ padding: 3px 3px 3px 18px;
221
+ }
222
+
223
+ dd .duration {
224
+ padding-left: 5px;
225
+ text-align: right;
226
+ right: 0px;
227
+ float:right;
228
+ }
229
+
230
+ dd.example.passed {
231
+ border-left: 5px solid #65C400;
232
+ border-bottom: 1px solid #65C400;
233
+ background: #DBFFB4; color: #3D7700;
234
+ }
235
+
236
+ dd.example.not_implemented {
237
+ border-left: 5px solid #FAF834;
238
+ border-bottom: 1px solid #FAF834;
239
+ background: #FCFB98; color: #131313;
240
+ }
241
+
242
+ dd.example.pending_fixed {
243
+ border-left: 5px solid #0000C2;
244
+ border-bottom: 1px solid #0000C2;
245
+ color: #0000C2; background: #D3FBFF;
246
+ }
247
+
248
+ dd.example.failed {
249
+ border-left: 5px solid #C20000;
250
+ border-bottom: 1px solid #C20000;
251
+ color: #C20000; background: #FFFBD3;
252
+ }
253
+
254
+ dt.not_implemented {
255
+ color: #000000; background: #FAF834;
256
+ }
257
+
258
+ dt.pending_fixed {
259
+ color: #FFFFFF; background: #C40D0D;
260
+ }
261
+
262
+ dt.failed {
263
+ color: #FFFFFF; background: #C40D0D;
264
+ }
265
+
266
+ #rspec-header.not_implemented {
267
+ color: #000000; background: #FAF834;
268
+ }
269
+
270
+ #rspec-header.pending_fixed {
271
+ color: #FFFFFF; background: #C40D0D;
272
+ }
273
+
274
+ #rspec-header.failed {
275
+ color: #FFFFFF; background: #C40D0D;
276
+ }
277
+
278
+ .backtrace {
279
+ color: #000;
280
+ font-size: 12px;
281
+ }
282
+
283
+ a {
284
+ color: #BE5C00;
285
+ }
286
+
287
+ /* Ruby code, style similar to vibrant ink */
288
+ .ruby {
289
+ font-size: 12px;
290
+ font-family: monospace;
291
+ color: white;
292
+ background-color: black;
293
+ padding: 0.1em 0 0.2em 0;
294
+ }
295
+
296
+ .ruby .keyword { color: #FF6600; }
297
+ .ruby .constant { color: #339999; }
298
+ .ruby .attribute { color: white; }
299
+ .ruby .global { color: white; }
300
+ .ruby .module { color: white; }
301
+ .ruby .class { color: white; }
302
+ .ruby .string { color: #66FF00; }
303
+ .ruby .ident { color: white; }
304
+ .ruby .method { color: #FFCC00; }
305
+ .ruby .number { color: white; }
306
+ .ruby .char { color: white; }
307
+ .ruby .comment { color: #9933CC; }
308
+ .ruby .symbol { color: white; }
309
+ .ruby .regex { color: #44B4CC; }
310
+ .ruby .punct { color: white; }
311
+ .ruby .escape { color: white; }
312
+ .ruby .interp { color: white; }
313
+ .ruby .expr { color: white; }
314
+
315
+ .ruby .offending { background-color: gray; }
316
+ .ruby .linenum {
317
+ width: 75px;
318
+ padding: 0.1em 1em 0.2em 0;
319
+ color: #000000;
320
+ background-color: #FFFBD3;
321
+ }
322
+ EOF
323
+
324
+ YALE_HTML_HEADER = <<-EOF
325
+ <!DOCTYPE html>
326
+ <html lang='en'>
327
+ <head>
328
+ <title>RSpec results</title>
329
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
330
+ <meta http-equiv="Expires" content="-1" />
331
+ <meta http-equiv="Pragma" content="no-cache" />
332
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
333
+ <script src='http://code.jquery.com/jquery-1.10.1.min.js'></script>"
334
+ <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
335
+ <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
336
+ <script src='http://code.highcharts.com/highcharts.js'></script>
337
+ <style type="text/css">
338
+ body {
339
+ margin: 0;
340
+ padding: 0;
341
+ background: #fff;
342
+ font-size: 80%;
343
+ }
344
+ </style>
345
+ <script type="text/javascript">
346
+ // <![CDATA[
347
+ #{GLOBAL_SCRIPTS}
348
+ // ]]>
349
+ </script>
350
+ <style type="text/css">
351
+ #{YALE_GLOBAL_STYLES}
352
+ </style>
353
+ </head>
354
+ <body>
355
+ EOF
356
+
357
+ end
358
+ end
359
+ end
360
+ end
@@ -0,0 +1,46 @@
1
+ require 'erb'
2
+ require 'rspec/core/formatters/html_formatter'
3
+ #require './override.rb'
4
+
5
+ module Lazyman
6
+ class LazymanFormatter < ::RSpec::Core::Formatters::HtmlFormatter
7
+ def initialize(output)
8
+ output = File.new(File.expand_path(File.join('.', 'app', 'reports', "#{Time.now.strftime("%Y%m%d_%H%M%S")}.html")), 'w')
9
+ super(output)
10
+ @printer.class.send(:define_method, 'puts') do |what|
11
+ @output.puts what
12
+ end #define_method
13
+ end
14
+
15
+ def example_failed(example)
16
+ super(example)
17
+ if $navi
18
+ failed_url = $navi.url rescue $navi.current_url
19
+ @printer.puts "<a target=\"_blank\" href=\"#{failed_url}\">failed url is [#{failed_url}]</a>"
20
+ @printer.puts '<br />'
21
+ @printer.puts '<p>Extra problem text</p>'
22
+ @printer.flush
23
+ end #if
24
+ end
25
+
26
+ def example_passed(example)
27
+ super(example)
28
+ @printer.flush
29
+ end
30
+
31
+ def extra_failure_content(failure)
32
+ browser = example_group.before_all_ivars[:@browser] || @browser
33
+ # If we'ere dealing with a browser get a screenshot on failure
34
+ if browser
35
+ browser.screenshot.save File.expand_path(File.join('.', 'app', 'reports','screenshots', "#{Time.now.strftime("%Y%m%d_%H%M%S")}.png"))
36
+
37
+ # Need to figure out how to remotely upload
38
+ content = []
39
+ content << "<span>"
40
+ content << "<a target='_blank' href='http://127.0.0.1:8020/o365/app/reports/screenshots/20131031_103612.png'>screenshot</a>"
41
+ content << "</span>"
42
+ super + content.join($/)
43
+ end
44
+ end
45
+ end #LazymanFormatter
46
+ end #Lazyman
@@ -0,0 +1,7 @@
1
+ require 'rspec/expectations'
2
+
3
+ RSpec::Matchers.define :be_a_multiple_of do |expected|
4
+ match do |actual|
5
+ actual % expected == 0
6
+ end
7
+ end
@@ -0,0 +1 @@
1
+ # Make a custom email matcher
@@ -0,0 +1,12 @@
1
+ require 'rspec/expectations'
2
+
3
+ # Not quite sure what the usage is for this yet?
4
+ RSpec::Matchers.define(:be_same_file_as) do |exected_file_path|
5
+ match do |actual_file_path|
6
+ md5_hash(actual_file_path).should == md5_hash(exected_file_path)
7
+ end
8
+
9
+ def md5_hash(file_path)
10
+ Digest::MD5.hexdigest(File.read(file_path))
11
+ end
12
+ end
@@ -0,0 +1,34 @@
1
+ #encoding: utf-8
2
+ require File.expand_path 'app/spec/spec_helper'
3
+
4
+ $config["browsers"].each do |b|
5
+ describe 'The Yale home page', :yale do
6
+
7
+ before(:all) do
8
+ @browser = Watir::Browser.new b
9
+ @yale_page = YalePage.new(@browser)
10
+ @yale_page.goto
11
+ end
12
+
13
+ it 'has the correct title' do
14
+ expect(@yale_page.title).to eq 'Yale University'
15
+ end
16
+
17
+ it 'has the correct text' do
18
+ expect(@yale_page.text).to include 'Harvard'
19
+ end
20
+
21
+ it 'has the correct links'
22
+
23
+ describe 'The Yale search', :yale do
24
+ term = "stuff"
25
+ it "has the correct results for '#{term}'" do
26
+ result_page = @yale_page.search_for term
27
+ expect(result_page.term_found?(term)).to eq true
28
+ end
29
+ end
30
+ after(:all) do
31
+ @browser.close rescue nil
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,4 @@
1
+ ---
2
+ one:
3
+ keyword=: '<%= 1.day.ago %>'
4
+ search_element: 'click'
@@ -0,0 +1,4 @@
1
+ ---
2
+ demo:
3
+ name: demo
4
+ password: demo
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ spec_helper = File.expand_path(File.join('.', 'app', 'cases', 'spec_helper.rb'))
4
+
5
+ setup = File.join(File.dirname(__FILE__), 'setup.rb')
6
+
7
+ exec "irb -r rspec -r #{spec_helper} -r #{setup} -r irb/completion --simple-prompt --readline"
@@ -0,0 +1,6 @@
1
+ @ECHO OFF
2
+ IF NOT "%~f0" == "~f0" GOTO :WinNT
3
+ @"ruby.exe" "" %1 %2 %3 %4 %5 %6 %7 %8 %9
4
+ GOTO :EOF
5
+ :WinNT
6
+ @"ruby.exe" "%~dpn0" %*
@@ -0,0 +1,12 @@
1
+ def test_data file
2
+ content = ''
3
+ file_path = File.expand_path(File.join('.', 'app', 'test_data', "#{file}.yml"))
4
+ raise "Can not find #{file}.yml" unless File.exists?(file_path)
5
+ File.open(file_path, 'r') do |handle|
6
+ content = handle.read
7
+ end
8
+ Psych.load ERB.new(content).result(binding)
9
+ end
10
+ <% require 'active_support/all' %>
11
+ $navi = <%= @name.camelize %>Navigator.new $config
12
+
@@ -0,0 +1,6 @@
1
+ ---
2
+ browsers:
3
+ - firefox
4
+ - chrome
5
+ host: www.yale.edu
6
+ tags: yale
@@ -0,0 +1,47 @@
1
+ require 'erb'
2
+ require 'rspec/core/formatters/html_formatter'
3
+ require './config/override'
4
+
5
+ module Lazyman
6
+ class LazymanFormatter < ::RSpec::Core::Formatters::HtmlFormatter
7
+ def initialize(output)
8
+ output = File.new(File.expand_path(File.join('.', 'app', 'reports', "#{Time.now.strftime("%Y%m%d_%H%M%S")}.html")), 'w')
9
+ super(output)
10
+ @printer.class.send(:define_method, 'puts') do |what|
11
+ @output.puts what
12
+ end #define_method
13
+ end
14
+
15
+ def example_failed(example)
16
+ super(example)
17
+ if $navi
18
+ failed_url = $navi.url rescue $navi.current_url
19
+ @printer.puts "<a target=\"_blank\" href=\"#{failed_url}\">failed url is [#{failed_url}]</a>"
20
+ @printer.puts '<br />'
21
+ @printer.puts '<p>Extra problem text</p>'
22
+ @printer.flush
23
+ end #if
24
+ end
25
+
26
+ def example_passed(example)
27
+ super(example)
28
+ @printer.puts "<p>I'm here.</p>"
29
+ @printer.flush
30
+ end
31
+
32
+ def extra_failure_content(failure)
33
+ browser = example_group.before_all_ivars[:@browser] || @browser
34
+ # If we'ere dealing with a browser get a screenshot on failure
35
+ if browser
36
+ browser.screenshot.save File.expand_path(File.join('.', 'app', 'reports','screenshots', "#{Time.now.strftime("%Y%m%d_%H%M%S")}.png"))
37
+
38
+ # Need to figure out how to remotely upload
39
+ content = []
40
+ content << "<span>"
41
+ content << "<a target='_blank' href='http://127.0.0.1:8020/o365/app/reports/screenshots/20131031_103612.png'>screenshot</a>"
42
+ content << "</span>"
43
+ super + content.join($/)
44
+ end
45
+ end
46
+ end #LazymanFormatter
47
+ end #Lazyman