puppet7 0.2.0.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.
@@ -0,0 +1,292 @@
1
+ # coding: utf-8
2
+ require "erb"
3
+ require "puppet7/common"
4
+
5
+ module Puppet7
6
+ def self.report
7
+ @report ||= Puppet7::PuppetReport.new
8
+ end
9
+
10
+ class PuppetReport
11
+ include ERB::Util
12
+
13
+ def initialize
14
+ @top_level = []
15
+ @current_example_group = nil
16
+ @cur_depth = 0
17
+ @max_depth = 0
18
+
19
+ @image_errors = {}
20
+ @js_errors = {}
21
+ @undefined_object = {}
22
+
23
+ # summary
24
+ @example_summary = {total: 0, passed: 0, failed: 0, pending: 0}
25
+ @test_summary = {total: 0, passed: 0, failed: 0, not_tested: 0, partial_passed: 0, automation_rate: 0, pass_rate: 0}
26
+
27
+ # for print
28
+ @example_group_stack = []
29
+ end
30
+
31
+
32
+ def write_report output
33
+ make_summary
34
+ output.write apply_template :puppet_report, binding
35
+ end
36
+
37
+ def start_example_group example_group
38
+ @cur_depth += 1
39
+
40
+ siblings = []
41
+ if @current_example_group
42
+ siblings.concat @current_example_group.example_groups.select{|exg| exg.description == example_group.description}
43
+ else
44
+ siblings.concat @top_level.select{|exg| exg.description == example_group.description}
45
+ end
46
+
47
+ if siblings.empty?
48
+ ex_group = ExampleGroup.new(example_group, @current_example_group, @cur_depth)
49
+ @top_level << ex_group unless @current_example_group
50
+ else
51
+ ex_group = siblings.first
52
+ end
53
+ @current_example_group = ex_group
54
+ @max_depth = [@max_depth, @cur_depth].max
55
+ end
56
+
57
+ def end_example_group example_group
58
+ unless example_group.description == @current_example_group.description
59
+ raise "Nested Example Groups are something wrong!"
60
+ end
61
+ @current_example_group = @current_example_group.parent_group
62
+ @cur_depth -= 1
63
+ end
64
+
65
+ def add_example example
66
+ Example.new(example, @current_example_group)
67
+ end
68
+
69
+ def add_image_errors page_url, image_urls
70
+ @image_errors[page_url.to_sym] ||= []
71
+ @image_errors[page_url.to_sym].concat(image_urls)
72
+ @image_errors[page_url.to_sym].uniq!
73
+ end
74
+
75
+ def add_js_errors page_url, js_errors
76
+ js_errors.select! {|err| err[:url] and err[:line]}
77
+ return if js_errors.empty?
78
+ @js_errors[page_url.to_sym] ||= []
79
+ @js_errors[page_url.to_sym].concat(js_errors)
80
+ @js_errors[page_url.to_sym].uniq!
81
+ end
82
+
83
+ def add_undefined_object type, name
84
+ @undefined_object[type.to_sym] ||= []
85
+ @undefined_object[type.to_sym] << name
86
+ @undefined_object[type.to_sym].uniq!
87
+ end
88
+
89
+ private
90
+ def make_summary
91
+ leaf_ex_groups = @top_level.collect{|exg| exg.get_leaf_example_groups}.flatten
92
+ leaf_ex_groups.each do |exg|
93
+ @test_summary[:total] += 1
94
+ @test_summary[exg.status] +=1
95
+ end
96
+
97
+ @test_summary[:automation_rate] =
98
+ (@test_summary[:total]-@test_summary[:not_tested]) * 100 / @test_summary[:total] if @test_summary[:total] > 0
99
+ @test_summary[:pass_rate] =
100
+ (@test_summary[:passed]) * 100 / (@test_summary[:total]-@test_summary[:not_tested]) if (@test_summary[:total]-@test_summary[:not_tested]) > 0
101
+
102
+ @top_level.collect{|exg| exg.all_examples}.flatten.each do |ex|
103
+ @example_summary[:total] += 1
104
+ @example_summary[ex.status] += 1
105
+ end
106
+ end
107
+
108
+ def example_group_result example_group
109
+ begin
110
+ @example_group_stack << example_group
111
+ apply_template :_example_group, binding
112
+ ensure
113
+ @example_group_stack.pop
114
+ end
115
+ end
116
+
117
+ def example_results
118
+ apply_template :_examples, binding
119
+ end
120
+
121
+ def apply_template template_name, _binding
122
+ template = ERB.new(read_template template_name)
123
+ template.result(_binding)
124
+ end
125
+
126
+ def read_template name
127
+ template_file = File.join(File.dirname(__FILE__), "report", "#{name}.erb")
128
+ if File.exist?(template_file)
129
+ File.read(template_file)
130
+ else
131
+ raise "Can't find the report template file : #{template_file}"
132
+ end
133
+ end
134
+ end
135
+
136
+ class ExampleGroup
137
+ attr_reader :description, :example_groups, :examples, :parent_group, :depth, :status, :no
138
+ @@no = 0
139
+ def self.no
140
+ @@no
141
+ end
142
+ def initialize example_group, parent_group, depth
143
+ @description = example_group.description
144
+ @example_groups = []
145
+ @examples = []
146
+ @parent_group = parent_group
147
+ @parent_group.example_groups << self if @parent_group
148
+ @depth = depth
149
+ @no = @@no += 1
150
+ end
151
+
152
+ def has_examples?
153
+ not @examples.empty?
154
+ end
155
+
156
+ def has_example_groups?
157
+ not @example_groups.empty?
158
+ end
159
+
160
+ def all_examples
161
+ examples = []
162
+ if has_example_groups?
163
+ @example_groups.each do |exg|
164
+ examples.concat exg.all_examples
165
+ end
166
+ else
167
+ examples.concat @examples
168
+ end
169
+ examples
170
+ end
171
+
172
+ def first?
173
+ if @parent_group
174
+ @parent_group.example_groups.first == self
175
+ else
176
+ true
177
+ end
178
+ end
179
+
180
+ def row_count
181
+ cnt = 0
182
+ @example_groups.each do |exg|
183
+ cnt += exg.row_count
184
+ end
185
+ [cnt, 1].max
186
+ end
187
+
188
+ def get_leaf_example_groups
189
+ if has_example_groups?
190
+ rv = []
191
+ @example_groups.each {|exg| rv.concat(exg.get_leaf_example_groups)}
192
+ rv
193
+ else
194
+ [self]
195
+ end
196
+ end
197
+
198
+ def status
199
+ return @status if @status
200
+ if has_examples?
201
+ summary = {passed: 0, failed: 0, pending:0}
202
+ @examples.inject(summary) {|r, ex| summary[ex.status] += 1}
203
+ if summary[:passed] == @examples.length
204
+ @status = :passed
205
+ elsif summary[:failed]> 0
206
+ @status = :failed
207
+ elsif summary[:passed] > 0
208
+ @status = :partial_passed
209
+ else
210
+ @status = :not_tested
211
+ end
212
+ elsif has_example_groups?
213
+ summary = {passed: 0, failed: 0, not_tested:0, partial_passed:0}
214
+ @example_groups.inject(summary) {|r,exg| summary[exg.status] +=1 }
215
+ if summary[:passed] == @example_groups.length
216
+ @status = :passed
217
+ elsif summary[:failed] > 0
218
+ @status = :failed
219
+ elsif summary[:passed] + summary[:partial_passed] > 0
220
+ @status = :partial_passed
221
+ else
222
+ @status = :not_tested
223
+ end
224
+ else
225
+ @status = :not_tested
226
+ end
227
+ @status
228
+ end
229
+
230
+ end
231
+
232
+ class Example
233
+ attr_reader :description, :status, :pending_message, :parent_group, :no
234
+ @@no = 0
235
+ def self.no
236
+ @@no
237
+ end
238
+
239
+ def initialize example, parent_group
240
+ @example = example
241
+ @description = example.description
242
+ @parent_group = parent_group
243
+ @parent_group.examples << self
244
+ @no = @@no += 1
245
+ end
246
+
247
+ def code_where
248
+ "in #{@example.metadata[:file_path]}:#{@example.metadata[:line_number]}"
249
+ end
250
+
251
+ def source_code
252
+ src_file = @example.metadata[:file_path]
253
+ line = @example.metadata[:line_number]
254
+ if File.file?(src_file)
255
+ lines = File.open(src_file).read.split("\n")
256
+ min = [0, line-1].max
257
+ unless lines[min].chomp.end_with?("do")
258
+ return "#{min+1}:#{lines[min]}"
259
+ end
260
+ indents = indent_cnt lines[min]
261
+ ln = min + 1
262
+ while indents != indent_cnt(lines[ln]) and ln < lines.length do
263
+ ln += 1
264
+ end
265
+ lines[min..ln].collect {|l| "#{min+=1}:" + l}.join("\n")
266
+ else
267
+ "# Couldn't get source code : #{src_file}"
268
+ end
269
+ end
270
+
271
+ def status
272
+ @example.metadata[:execution_result][:status].to_sym
273
+ end
274
+
275
+ def pending_message
276
+ @example.metadata[:execution_result][:pending_message]
277
+ end
278
+
279
+ def exception_message
280
+ @example.metadata[:execution_result][:exception]
281
+ end
282
+
283
+ private
284
+ def indent_cnt line
285
+ if line =~ /^(\s*)[^\s]/
286
+ $1.length
287
+ else
288
+ 0
289
+ end
290
+ end
291
+ end
292
+ end
@@ -0,0 +1,24 @@
1
+ <%# coding: utf-8%>
2
+ <% exgroup = @example_group_stack.last %>
3
+ <%unless exgroup.first? and exgroup.depth != 1%>
4
+ <tr>
5
+ <%end%>
6
+ <% (@max_depth - exgroup.depth).times do %>
7
+ <td class="<%=exgroup.status%>_result"> &nbsp; </td>
8
+ <%end unless exgroup.has_example_groups?%>
9
+ <td rowspan="<%=exgroup.row_count%>" class="<%=exgroup.status%>_result">
10
+ <%=h(exgroup.description)%>
11
+ <% if exgroup.has_example_groups? %>
12
+ </td>
13
+ <%# print sub example group %>
14
+ <% exgroup.example_groups.each do |ex_group|%>
15
+ <%=example_group_result(ex_group)%>
16
+ <%end%>
17
+ <%else%>
18
+ <%# print examples%>
19
+ <%=example_results%>
20
+ </td>
21
+ <%end%>
22
+ <%unless exgroup.has_example_groups? and exgroup.depth != 1%>
23
+ </tr>
24
+ <%end%>
@@ -0,0 +1,22 @@
1
+ <%# coding: utf-8%>
2
+ <% exgroup = @example_group_stack.last %>
3
+ <table class="examples_table">
4
+ <% exgroup.examples.each do |ex| %>
5
+ <tr>
6
+ <td class="<%=ex.status%>">
7
+ # <%=h(ex.description)%>
8
+ <%if ex.status == :pending %>
9
+ (PENDING: <%=h ex.pending_message%>)
10
+ <%end%>
11
+ <span class="view_script_btn" id="viewbutton<%=ex.no%>"></span>
12
+ <div class="test_script" id="testscript<%=ex.no%>" style="display:<%= ex.status == :failed ? "":"none"%>">
13
+ <code class="code_where">
14
+ <%=h ex.code_where%>
15
+ <pre><%=h ex.exception_message%></pre>
16
+ </code>
17
+ <pre class="source_code"><%=h ex.source_code%></pre>
18
+ </div>
19
+ </td>
20
+ </tr>
21
+ <% end %>
22
+ </table>
@@ -0,0 +1,187 @@
1
+ <%# codnig: utf-8%>
2
+ <?xml version="1.0" encoding="UTF-8"?>
3
+ <!DOCTYPE html
4
+ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
5
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
6
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
7
+ <head>
8
+ <title>Checklist & Test Result</title>
9
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
10
+ <meta http-equiv="Expires" content="-1" />
11
+ <meta http-equiv="Pragma" content="no-cache" />
12
+ <style type="text/css">
13
+ * {margin:0;padding:0;font-size:9pt;}
14
+ h1 {font-size: 2em; font-weight:bold; font-family:serif}
15
+ h2 {font-size: 1.5em; font-weight:bold; font-family:serif; color: red}
16
+ #header {margin: 1em;}
17
+ #content {margin: 1em;}
18
+ #control {}
19
+ #test_result {}
20
+ #footer {margin: 1em;text-align: right}
21
+ #summary {margin: 0.5em 1em;}
22
+
23
+ .cont {color:#0033FF}
24
+
25
+ .question {color: #FF3300; font-style:italic;font-weight: bold;}
26
+ .confirm {color: #0033FF; font-style:italic;font-weight: bold;}
27
+ .show_tc {color: #888; font-style:italic;}
28
+
29
+ .pending {background-color: #FFFF99; color:black;font-size: 0.9em;}
30
+ .passed {background-color: #ddFFaa; color:black;font-size: 0.9em;}
31
+ .failed {background-color: #FFaa99; color:black;font-size: 0.9em;}
32
+
33
+ .summary {font-weight: bold; color:black; padding: 2px;line-height: 1.5em;}
34
+
35
+ .passed_result {background-color: #ddFFaa; }
36
+ .failed_result {background-color: #FFaa99; }
37
+ .partial_passed_result {background-color: #FFFFDD; }
38
+ .not_tested_result {background-color: #EDEDED; }
39
+
40
+ .passed_text {color: #33aa33; }
41
+ .failed_text {color: #FF3300; }
42
+ .pending_text {color: #444444;}
43
+
44
+ .view_script_btn {color: #337; font-style: italic; cursor: pointer}
45
+ .code_where {display: block;background-color:#ace;color:#337; padding: 3px;margin-top:3px;}
46
+ .source_code {background-color:black;color:#aaa;padding: 3px;margin-bottom:-4px;}
47
+
48
+ table {width:100%; border-collapse:collapse;cellspacing:0; cellpadding:0;padding:0;margin:0;}
49
+ th {border:1px solid gray; padding: 3px 1em; font-weight:bold; background-color:#AAA}
50
+ td {border:1px solid gray; padding: 3px 1em;}
51
+
52
+ td.exgrp_title {padding: 3px 1.5em; border-bottom:0;}
53
+ td.exgrp_detail {border-top:0;width: 10px;text-align:center; font-size:0.9em;}
54
+ td.exgrp_child {width: 10px; border:0;}
55
+ td.ex_result {padding:3px; }
56
+ td.ex_desc {padding: 3px 10px;background-color: #FDFDFD}
57
+
58
+ table.examples_table {
59
+ margin: 3px 0 -4px 0;
60
+ }
61
+ </style>
62
+ </head>
63
+ <body>
64
+ <div id="header">
65
+ <h1>Checklist &amp; Test Result</h1>
66
+ </div>
67
+ <div id="content">
68
+ <div id="control"></div>
69
+ <div id="test_result">
70
+ <div id="summary">
71
+ <span class="summary">Automation rate: <%=@test_summary[:automation_rate]%> %</span>
72
+ <span class="summary">Pass rate: <%=@test_summary[:pass_rate]%> %</span>
73
+ <br/>
74
+ <span class="summary">Checklist Total: <%=@test_summary[:total]%> </span> (
75
+ <span class="summary passed_result"> Passed:<%=@test_summary[:passed]%> </span>
76
+ <span class="summary failed_result"> Failed:<%=@test_summary[:failed]%> </span>
77
+ <span class="summary partial_passed_result"> Partial passed:<%=@test_summary[:partial_passed]%> </span>
78
+ <span class="summary not_tested_result"> Not Tested:<%=@test_summary[:not_tested]%> </span> )
79
+ <br/>
80
+ <span class="summary">Example Total: <%=@example_summary[:total]%> </span> (
81
+ <span class="summary passed"> Passed:<%=@example_summary[:passed]%> </span>
82
+ <span class="summary failed"> Failed:<%=@example_summary[:failed]%> </span>
83
+ <span class="summary pending"> Pending:<%=@example_summary[:pending]%> </span>)
84
+ </div>
85
+ <table>
86
+ <tr><!--# Table Header -->
87
+ <%@max_depth.times do |i| %><th>LEVEL<%=i%></th><%end%>
88
+ </tr>
89
+ <%@top_level.each do |ex_group|%>
90
+ <%=example_group_result(ex_group)%>
91
+ <%end%>
92
+ </table>
93
+ </div>
94
+ <div class="etc_errors">
95
+ <%unless @undefined_object.empty? %>
96
+ <h2> Undefined Page Objects </h2>
97
+ <table>
98
+ <tr>
99
+ <th>Type</th><th>Undefined object and property</th>
100
+ </tr>
101
+ <%@undefined_object.each do |type, names|%>
102
+ <tr>
103
+ <td><%=h type%></td>
104
+ <td><%=h names.join("<br/>")%></td>
105
+ </tr>
106
+ <%end%>
107
+ </table>
108
+ <%end%>
109
+ </div>
110
+ <div class="etc_errors">
111
+ <%unless @image_errors.empty? %>
112
+ <h2> Loading Image Errors </h2>
113
+ <table>
114
+ <tr>
115
+ <th>Page URL</th><th>Image URLs</th>
116
+ </tr>
117
+ <%@image_errors.each do |page, images|%>
118
+ <tr>
119
+ <td><%=h page%></td>
120
+ <td><%=h images.join("<br/>")%></td>
121
+ </tr>
122
+ <%end%>
123
+ </table>
124
+ <%end%>
125
+ </div>
126
+ <div class="etc_errors">
127
+ <%unless @js_errors.empty? %>
128
+ <h2> Javascript Errors </h2>
129
+ <table>
130
+ <tr>
131
+ <th>Page URL</th><th>Error message</th>
132
+ </tr>
133
+ <%@js_errors.each do |page, errors|%>
134
+ <tr>
135
+ <td><%=h page%></td>
136
+ <td><%=errors.collect{|e| h "#{e['msg']} : file:#{e['url']}(#{e['line']})"}.join("<br/>")%></td>
137
+ </tr>
138
+ <%end%>
139
+ </table>
140
+ <%end%>
141
+ </div>
142
+ </div>
143
+
144
+ <div id="footer">Powered by <strong>puppet7</strong>. made by yunsang.choi@nhn.com</div>
145
+
146
+ <script type="text/javascript">
147
+ var exg_cnt = <%=ExampleGroup.no%>;
148
+ var ex_cnt = <%=Example.no%>;
149
+
150
+ for(var i=1; i <= ex_cnt; i++) {
151
+ var content = document.getElementById('testscript'+i);
152
+ if(content == null) continue ;
153
+ var btn = document.getElementById('viewbutton'+i);
154
+ if(content.style.display == "none") {
155
+ btn.innerHTML = "[show script]";
156
+ btn.onclick = get_show_script_func(i, true);
157
+ } else {
158
+ btn.innerHTML = "[hide script]";
159
+ btn.onclick = get_show_script_func(i, false);
160
+ }
161
+ }
162
+
163
+ function get_show_script_func(no, view) {
164
+ return function(){show_script(no, view);}
165
+ }
166
+
167
+ function show_script(no, view) {
168
+ if(no > ex_cnt) {alert(no);}
169
+ if(view == null) view = true;
170
+
171
+ var content = document.getElementById('testscript'+no);
172
+ var btn = document.getElementById('viewbutton'+no);
173
+
174
+ if (view) {
175
+ content.style.display = "";
176
+ btn.innerHTML = "[hide script]";
177
+ btn.onclick = get_show_script_func(no, false);
178
+ } else {
179
+ content.style.display = "none";
180
+ btn.innerHTML = "[show script]";
181
+ btn.onclick = get_show_script_func(no, true);
182
+ }
183
+ }
184
+
185
+ </script>
186
+ </body>
187
+ </html>
@@ -0,0 +1,20 @@
1
+ # coding: utf-8
2
+
3
+ require "selenium/client"
4
+ require "json"
5
+
6
+ module Puppet7
7
+ module SeleniumActions
8
+ def get_stored_var name
9
+ JSON.parse get_eval("storedVars.#{name}.toJSONString();")
10
+ end
11
+
12
+ def set_stored_var name, value
13
+ get_eval("storedVars.#{name} = #{JSON.generate([value])}[0];")
14
+ end
15
+ end
16
+ end
17
+
18
+ class Selenium::Client::Driver
19
+ include Puppet7::SeleniumActions
20
+ end