teuton 2.1.8 → 2.1.9

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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -8
  3. data/bin/check_teuton +43 -0
  4. data/docs/changelog/contributions.md +32 -0
  5. data/docs/changelog/v2.1.md +22 -0
  6. data/docs/changelog/v2.2.md +29 -0
  7. data/docs/commands/README.md +105 -7
  8. data/docs/commands/example_check.md +54 -0
  9. data/docs/commands/example_run.md +112 -0
  10. data/docs/dsl/README.md +11 -9
  11. data/docs/dsl/definition/expect.md +25 -21
  12. data/docs/dsl/definition/group.md +5 -1
  13. data/docs/dsl/definition/result.md +45 -34
  14. data/docs/dsl/definition/run_local.md +34 -0
  15. data/docs/dsl/definition/run_remote.md +119 -0
  16. data/docs/dsl/definition/target.md +6 -0
  17. data/docs/dsl/execution/export.md +27 -19
  18. data/docs/dsl/execution/play.md +4 -0
  19. data/docs/dsl/execution/send.md +21 -2
  20. data/docs/dsl/execution/show.md +13 -8
  21. data/docs/dsl/setting/get.md +24 -8
  22. data/docs/dsl/setting/set.md +8 -3
  23. data/docs/install/README.md +19 -26
  24. data/docs/install/modes_of_use.md +27 -26
  25. data/docs/install/scripts.md +53 -36
  26. data/docs/install/vagrant_docker.md +56 -0
  27. data/docs/learn/README.md +13 -6
  28. data/docs/learn/example-01-target.md +78 -61
  29. data/docs/learn/example-02-config.md +152 -0
  30. data/docs/learn/example-03-remote-hosts.md +31 -25
  31. data/docs/learn/example-04-use.md +23 -17
  32. data/docs/learn/example-05-debug.md +24 -17
  33. data/docs/learn/example-06-log.md +70 -0
  34. data/lib/teuton/application.rb +7 -4
  35. data/lib/teuton/case_manager/case/case.rb +4 -1
  36. data/lib/teuton/case_manager/case/dsl/expect.rb +3 -1
  37. data/lib/teuton/case_manager/case/dsl/goto.rb +12 -7
  38. data/lib/teuton/case_manager/case/dsl/macro.rb +38 -0
  39. data/lib/teuton/case_manager/case/dsl/main.rb +1 -2
  40. data/lib/teuton/case_manager/case/dsl/target.rb +1 -1
  41. data/lib/teuton/case_manager/case/runner.rb +7 -7
  42. data/lib/teuton/case_manager/case_manager.rb +1 -20
  43. data/lib/teuton/case_manager/check_cases.rb +12 -2
  44. data/lib/teuton/case_manager/dsl.rb +4 -6
  45. data/lib/teuton/case_manager/export_manager.rb +29 -3
  46. data/lib/teuton/case_manager/report.rb +29 -8
  47. data/lib/teuton/case_manager/show.rb +8 -4
  48. data/lib/teuton/cli.rb +1 -0
  49. data/lib/teuton/cli/play.rb +1 -0
  50. data/lib/teuton/cli/version.rb +1 -4
  51. data/lib/teuton/files/config.yaml +0 -1
  52. data/lib/teuton/files/start.rb +1 -1
  53. data/lib/teuton/files/template/case.html +135 -0
  54. data/lib/teuton/files/template/resume.html +115 -0
  55. data/lib/teuton/project/laboratory/builtin.rb +2 -1
  56. data/lib/teuton/project/laboratory/dsl.rb +13 -15
  57. data/lib/teuton/project/laboratory/laboratory.rb +5 -1
  58. data/lib/teuton/project/laboratory/show.rb +21 -13
  59. data/lib/teuton/project/name_file_finder.rb +6 -1
  60. data/lib/teuton/project/project.rb +7 -3
  61. data/lib/teuton/project/readme/dsl.rb +3 -1
  62. data/lib/teuton/project/readme/readme.rb +37 -26
  63. data/lib/teuton/project/skeleton.rb +20 -4
  64. data/lib/teuton/report/close.rb +15 -11
  65. data/lib/teuton/report/formatter/formatter_factory.rb +10 -6
  66. data/lib/teuton/report/formatter/html_formatter.rb +16 -79
  67. data/lib/teuton/report/formatter/resume_html_formatter.rb +39 -0
  68. data/lib/teuton/report/formatter/resume_yaml_formatter.rb +7 -1
  69. data/lib/teuton/report/report.rb +5 -4
  70. data/lib/teuton/report/show.rb +55 -26
  71. metadata +26 -39
  72. data/docs/changelog/todo.md +0 -46
  73. data/docs/commands/create_skeleton.md +0 -31
  74. data/docs/commands/help.md +0 -13
  75. data/docs/commands/revise_test.md +0 -46
  76. data/docs/commands/run_test_unit.md +0 -78
  77. data/docs/commands/show_version.md +0 -9
  78. data/docs/developers/01-telnet.md +0 -121
  79. data/docs/developers/02-ssh.md +0 -93
  80. data/docs/developers/03-encoding.md +0 -153
  81. data/docs/developers/comparative.md +0 -17
  82. data/docs/dsl/_Sidebar.md +0 -30
  83. data/docs/dsl/definition/goto.md +0 -112
  84. data/docs/dsl/definition/run.md +0 -23
  85. data/docs/install/tested_os.md +0 -25
  86. data/docs/install/vagrant.md +0 -9
  87. data/docs/learn/example-02-configfile.md +0 -174
  88. data/docs/learn/quick-demo.md +0 -170
  89. data/lib/teuton/case_manager/case/dsl/check.rb +0 -24
  90. data/lib/teuton/case_manager/case/dsl/missing.rb +0 -12
  91. data/lib/teuton/files/gitignore +0 -2
@@ -55,10 +55,8 @@ class CaseManager
55
55
  puts ' Usage: export :format => :colored_text'
56
56
  raise '[ERROR] CaseManager#export: Argument error!'
57
57
  end
58
- # First: export files
58
+ # Export report files
59
59
  ExportManager.run(@report, @cases, args)
60
- # Second: preserve files if required
61
- preserve_files if args[:preserve] == true
62
60
  end
63
61
 
64
62
  ##
@@ -71,21 +69,4 @@ class CaseManager
71
69
  @cases.each { |c| threads << Thread.new { c.send(args) } }
72
70
  threads.each(&:join)
73
71
  end
74
-
75
- private
76
-
77
- ##
78
- # Preserve output files for current project
79
- def preserve_files
80
- app = Application.instance
81
- t = Time.now
82
- subdir = "#{t.year}#{format('%02d',t.month)}#{format('%02d',t.day)}-" \
83
- "#{format('%02d',t.hour)}#{format('%02d',t.min)}" \
84
- "#{format('%02d',t.sec)}"
85
- logdir = File.join(app.output_basedir, app.global[:tt_testname], subdir)
86
- srcdir = File.join(app.output_basedir, app.global[:tt_testname])
87
- puts "[INFO] Preserving files => #{logdir}"
88
- FileUtils.mkdir(logdir)
89
- Dir.glob(File.join(srcdir, '**.*')).each { |file| FileUtils.cp(file, logdir) }
90
- end
91
72
  end
@@ -5,6 +5,8 @@
5
5
  class CaseManager
6
6
  private
7
7
 
8
+ ##
9
+ # Start checking every single case
8
10
  def check_cases!
9
11
  app = Application.instance
10
12
 
@@ -33,14 +35,16 @@ class CaseManager
33
35
  close_main_report(start_time)
34
36
  end
35
37
 
38
+ ##
39
+ # Run all cases
36
40
  def run_all_cases
37
41
  start_time = Time.now
38
42
  if Application.instance.global[:tt_sequence]
39
- verboseln "[INFO] Running in sequence (#{start_time})"
43
+ verboseln Rainbow("[INFO] Running in sequence (#{start_time})").yellow.bright
40
44
  # Run every case in sequence
41
45
  @cases.each(&:play)
42
46
  else
43
- verboseln "[INFO] Running in parallel (#{start_time})"
47
+ verboseln Rainbow("[INFO] Running in parallel (#{start_time})").yellow.bright
44
48
  threads = []
45
49
  # Run all cases in parallel
46
50
  @cases.each { |c| threads << Thread.new { c.play } }
@@ -49,6 +53,8 @@ class CaseManager
49
53
  start_time
50
54
  end
51
55
 
56
+ ##
57
+ # Collect uniques values for all cases
52
58
  def collect_uniques_for_all_cases
53
59
  uniques = {} # Collect "unique" values from all cases
54
60
  @cases.each do |c|
@@ -63,6 +69,10 @@ class CaseManager
63
69
  uniques
64
70
  end
65
71
 
72
+ ##
73
+ # 1) Reevaluate every case with collected unique values
74
+ # 2) Close all case reports
75
+ # 3) And order to build hall of fame
66
76
  def close_reports_for_all_cases(uniques)
67
77
  threads = []
68
78
  @cases.each { |c| threads << Thread.new { c.close uniques } }
@@ -12,13 +12,11 @@ def use(filename)
12
12
  app.uses << File.basename(findfiles.first)
13
13
  end
14
14
 
15
- def define_check(name, *args, &block)
16
- Application.instance.checks[name] = { args: args, block: block }
15
+ def define_macro(name, *args, &block)
16
+ Application.instance.macros[name] = { args: args, block: block }
17
17
  end
18
- alias definecheck define_check
19
- alias def_check define_check
20
- alias defcheck define_check
21
- alias dcheck define_check
18
+ alias def_macro define_macro
19
+ alias defmacro define_macro
22
20
 
23
21
  def group(name, &block)
24
22
  Application.instance.groups << { name: name, block: block }
@@ -3,24 +3,50 @@
3
3
  require_relative '../application'
4
4
 
5
5
  ##
6
- # ExportManager is used by CaseManager to export output reports)
6
+ # ExportManager is used by CaseManager to export output reports
7
7
  module ExportManager
8
8
  ##
9
9
  # Run export function
10
10
  # @param main_report (Report)
11
11
  # @param cases (Array)
12
12
  # @param args (Hash) Selected export options
13
+ # rubocop: disable Metrics/AbcSize
13
14
  def self.run(main_report, cases, args)
14
15
  # default :mode=>:all, :format=>:txt
15
16
  format = args[:format] || Application.instance.default[:format]
16
17
  mode = args[:mode] || :all
17
- # Export case reports
18
+ # Step 1: Export case reports
18
19
  if %i[details all].include? mode
19
20
  threads = []
20
21
  cases.each { |c| threads << Thread.new { c.export format } }
21
22
  threads.each(&:join)
22
23
  end
23
- # Export resume report
24
+ # Step 2: Export resume report
24
25
  main_report.export_resume format if %i[resume all].include? mode
26
+ # Step 3: Preserve files if required
27
+ preserve_files if args[:preserve] == true
25
28
  end
29
+ # rubocop:enable Metrics/AbcSize
30
+
31
+ ##
32
+ # Preserve output files for current project
33
+ # rubocop:disable Metrics/AbcSize
34
+ # rubocop:disable Metrics/MethodLength
35
+ # rubocop:disable Layout/LineLength
36
+ private_class_method def self.preserve_files
37
+ app = Application.instance
38
+ t = Time.now
39
+ data = { year: t.year, month: t.month, day: t.day,
40
+ hour: t.hour, min: t.min, sec: t.sec }
41
+ subdir = format('%<year>s%<month>02d%<day>02d-' \
42
+ '%<hour>02d%<min>02d%<sec>02d', data)
43
+ logdir = File.join(app.output_basedir, app.global[:tt_testname], subdir)
44
+ srcdir = File.join(app.output_basedir, app.global[:tt_testname])
45
+ puts "[INFO] Preserving files => #{logdir}"
46
+ FileUtils.mkdir(logdir)
47
+ Dir.glob(File.join(srcdir, '**.*')).each { |file| FileUtils.cp(file, logdir) }
48
+ end
49
+ # rubocop:enable Metrics/AbcSize
50
+ # rubocop:enable Metrics/MethodLength
51
+ # rubocop:enable Layout/LineLength
26
52
  end
@@ -1,21 +1,28 @@
1
-
1
+ require 'rainbow'
2
+ ##
3
+ # Class CaseManager
4
+ # Methods related with report
2
5
  class CaseManager
3
6
 
4
7
  private
5
8
 
6
- def open_main_report(p_config_filename)
9
+ ##
10
+ # Open main report (resume report)
11
+ # @param config_filepath (String)
12
+ def open_main_report(config_filepath)
7
13
  app = Application.instance
8
14
 
9
15
  @report.head[:tt_title] = "Executing [#{app.name}] (version #{Application::VERSION})"
10
- @report.head[:tt_scriptname] = app.script_path
11
- @report.head[:tt_configfile] = p_config_filename
16
+ @report.head[:tt_scriptname] = trim(app.script_path)
17
+ @report.head[:tt_configfile] = trim(config_filepath)
18
+ @report.head[:tt_pwd] = app.running_basedir
12
19
  @report.head[:tt_debug] = true if @debug
13
- # @report.head[:tt_uses] = app.uses.join(', ')
20
+ # @report.head[:tt_uses] = app.uses.join(', ') # TO-REVISE
14
21
  @report.head.merge!(app.global)
15
22
 
16
23
  verboseln ' '
17
24
  verboseln '=' * @report.head[:tt_title].length
18
- verboseln @report.head[:tt_title]
25
+ verboseln Rainbow(@report.head[:tt_title]).yellow.bright
19
26
  end
20
27
 
21
28
  def close_main_report(start_time)
@@ -24,8 +31,8 @@ class CaseManager
24
31
  @report.tail[:finish_time] = finish_time
25
32
  @report.tail[:duration] = finish_time - start_time
26
33
 
27
- verbose "\n[INFO] Duration = #{format('%3.3f',(finish_time - start_time))}"
28
- verboseln " (#{finish_time})"
34
+ verbose Rainbow("\n[INFO] Duration = #{format('%3.3f',(finish_time - start_time))}").yellow.bright
35
+ verboseln Rainbow(" (#{finish_time})").yellow.bright
29
36
  verboseln '=' * @report.head[:tt_title].length
30
37
  verboseln ' '
31
38
 
@@ -49,4 +56,18 @@ class CaseManager
49
56
  @report.lines << line
50
57
  end
51
58
  end
59
+
60
+ ##
61
+ # Trim string text when is too long
62
+ # @param input (String)
63
+ # @return String
64
+ def trim(input)
65
+ return input unless input.to_s.start_with? Dir.pwd.to_s
66
+ return input if input == Dir.pwd.to_s
67
+
68
+ output = input.to_s
69
+ offset = (Dir.pwd).length + 1
70
+ output = "#{input[offset, input.size]}"
71
+ output.to_s
72
+ end
52
73
  end
@@ -2,19 +2,23 @@
2
2
 
3
3
  require_relative '../application'
4
4
 
5
- # CaseManager#show
5
+ # CaseManager show method
6
6
  class CaseManager
7
+ ##
8
+ # Show cases and resume report data on screep
9
+ # @param mode (Symbol) Values => :resume, :cases or :all
7
10
  def show(mode = :resume)
8
11
  return if Application.instance.quiet?
9
12
 
13
+ # Show resume report data on screen
10
14
  @report.show if %i[resume all].include? mode
11
15
 
12
- return unless %i[details all].include? mode
16
+ # Show cases report data on screen
17
+ return if mode == :resume
13
18
 
14
19
  @cases.each do |c|
15
- puts '____'
20
+ puts '=' * 40
16
21
  c.show
17
22
  end
18
- puts '.'
19
23
  end
20
24
  end
data/lib/teuton/cli.rb CHANGED
@@ -27,6 +27,7 @@ class CLI < Thor
27
27
  ##
28
28
  # These inputs are equivalents:
29
29
  # * teuton dir/foo
30
+ # * teuton run dir/foo
30
31
  # * teuton play dir/foo
31
32
  def method_missing(method, *_args, &_block)
32
33
  play(method.to_s)
@@ -7,6 +7,7 @@ class CLI < Thor
7
7
  option :cname, type: :string
8
8
  option :cpath, type: :string
9
9
  option :case, type: :string
10
+ option :color, type: :boolean
10
11
  option :quiet, type: :boolean
11
12
  desc '[run] [OPTIONS] DIRECTORY',
12
13
  'Run challenge from directory'
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rainbow'
4
-
5
3
  # Class method Teuton#version
6
4
  class CLI < Thor
7
5
  map ['v', '-v', '--version'] => 'version'
@@ -9,7 +7,6 @@ class CLI < Thor
9
7
  ##
10
8
  # Display version
11
9
  def version
12
- print Rainbow(Application::NAME).bright.blue
13
- puts ' (version ' + Rainbow(Application::VERSION).green + ')'
10
+ puts "#{Application::NAME} (version #{Application::VERSION})"
14
11
  end
15
12
  end
@@ -1,5 +1,4 @@
1
1
  ---
2
- :alias:
3
2
  :global:
4
3
  :cases:
5
4
  - :tt_members: MEMBERS
@@ -2,7 +2,7 @@
2
2
  group "GROUP NAME" do
3
3
 
4
4
  target "TARGET-1 DESCRIPTION"
5
- goto :localhost, :exec => "COMMAND-1"
5
+ run "COMMAND-1"
6
6
  expect "TEXT-1"
7
7
 
8
8
  end
@@ -0,0 +1,135 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6
+ <meta http-equiv="x-ua-compatible" content="IE=edge" />
7
+ <title>Teuton report</title>
8
+ <style>
9
+ body{margin:0;padding:0;font-family:sans-serif;font-size:12pt}a,a:visited,body{color:#303030}#content{padding-left:50px;padding-right:50px;padding-top:30px;padding-bottom:30px}#content h1{font-size:160%;margin-bottom:10px}#footer{margin-top:100px;font-size:80%;white-space:nowrap}#footer,#footer a{color:#a0a0a0}#line-wrapping-toggle{vertical-align:middle}#label-for-line-wrapping-toggle{vertical-align:middle}ul{margin-left:0}h1,h2,h3{white-space:nowrap}h2{font-size:120%}ul.tabLinks{padding-left:0;padding-top:10px;padding-bottom:10px;overflow:auto;min-width:800px;width:auto!important;width:800px}ul.tabLinks li{float:left;height:100%;list-style:none;padding-left:10px;padding-right:10px;padding-top:5px;padding-bottom:5px;margin-bottom:0;-moz-border-radius:7px;border-radius:7px;margin-right:25px;border:solid 1px #d4d4d4;background-color:#f0f0f0}ul.tabLinks li:hover{background-color:#fafafa}ul.tabLinks li.selected{background-color:#00c21b;border-color:#00c21b}ul.tabLinks a{font-size:120%;display:block;outline:0;text-decoration:none;margin:0;padding:0}ul.tabLinks li h2{margin:0;padding:0}div.selected{display:block}div.deselected{display:none}div.tab table{min-width:350px;width:auto!important;width:350px;border-collapse:collapse}div.tab table,div.tab th{border-bottom:solid #d0d0d0 1px}div.tab th{text-align:left;white-space:nowrap;padding-left:6em}div.tab th:first-child{padding-left:0}div.tab td{white-space:nowrap;padding-left:6em;padding-top:5px;padding-bottom:5px}div.tab td:first-child{padding-left:0}div.tab td.numeric,div.tab th.numeric{text-align:right}span.code{display:inline-block;margin-top:0;margin-bottom:1em}span.code pre{font-size:11pt;padding-top:10px;padding-bottom:10px;padding-left:10px;padding-right:10px;margin:0;background-color:#f7f7f7;border:solid 1px #d0d0d0;min-width:700px;width:auto!important;width:700px}span.wrapped pre{word-wrap:break-word;white-space:pre-wrap;word-break:break-all}label.hidden{display:none}div.tab td.indentPath{padding-left:3em}
10
+ </style>
11
+ <script type="text/javascript">
12
+ !function(e,t){"use strict";var n={};function i(e,t){e.getAttribute("className")?e.setAttribute("className",t):e.setAttribute("class",t)}function s(e){return e.getAttribute("className")?e.getAttribute("className"):e.getAttribute("class")}function r(e,t){i(e,s(e)+" "+t)}function a(e,t){i(e,s(e).replace(t,""))}function l(){var e=t.getElementById("tabs");return n.tabs=function(e){return p(e,"DIV","tab")}(e),n.titles=function(e){for(var t=[],n=0;n<e.length;n++){var i=e[n],s=p(i,"H2",null)[0];s.parentNode.removeChild(s),s.innerText?t.push(s.innerText):t.push(s.textContent)}return t}(n.tabs),n.headers=function(e){var t=p(e,"UL","tabLinks");return p(t[0],"LI",null)}(e),n.select=b,n.deselectAll=g,n.select(0),!0}function d(){return t.getElementById("line-wrapping-toggle")}function h(){for(var e=t.getElementById("tabs").getElementsByTagName("span"),n=[],i=0;i<e.length;++i)e[i].className.indexOf("code")>=0&&n.push(e[i]);return n}function c(e){for(var t=h(),n=0;n<t.length;++n)e(t[n],"wrapped")}function o(){d().checked?c(r):c(a)}function u(){if(h().length>0){var e=d(),n=t.getElementById("label-for-line-wrapping-toggle");e.onclick=o,e.checked=!1,a(n,"hidden")}}function f(){for(var e=this.id.substr(1),t=0;t<n.tabs.length;t++)if(n.tabs[t].id===e){n.select(t);break}return!1}function b(e){for(this.deselectAll(),i(this.tabs[e],"tab selected"),i(this.headers[e],"selected");this.headers[e].firstChild;)this.headers[e].removeChild(this.headers[e].firstChild);var n=t.createElement("H2");n.appendChild(t.createTextNode(this.titles[e])),this.headers[e].appendChild(n)}function g(){for(var e=0;e<this.tabs.length;e++){for(i(this.tabs[e],"tab deselected"),i(this.headers[e],"deselected");this.headers[e].firstChild;)this.headers[e].removeChild(this.headers[e].firstChild);var n=t.createElement("A");n.setAttribute("id","ltab"+e),n.setAttribute("href","#tab"+e),n.onclick=f,n.appendChild(t.createTextNode(this.titles[e])),this.headers[e].appendChild(n)}}function p(e,t,n){for(var i=[],s=e.childNodes,r=0;r<s.length;r++){var a=s.item(r);if(1===a.nodeType&&a.nodeName===t){if(n&&a.className.indexOf(n)<0)continue;i.push(a)}}return i}e.onload=function(){l(),u()}}(window,window.document);
13
+ </script>
14
+ </head>
15
+
16
+ <body>
17
+ <div id="content">
18
+ <h1><img title="teuton logo" alt="logo" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAFg0lEQVQ4T23UW0yTdxgG8Pf/9UQPtIUWKJSWciiDcj4VhRoZh9iZoAJDIZuJ2wUyxS3CdMvkZmOaLFtczDJ1ajaGTBxVNEQdYRoYKBRqWTkUKAiVcmoLBaQt/aCl36LJEi94r9/8rp7nQbDDBQQEsNL2pmVa55aPURm0fNzlCiQAnIggnjIYzKZTp052t9xqmVWpVHD23Nm0J0+fKCxTlta5ubkptBOYmp162IfO+DohPUkqCheTjIZpYLAYr1+9hpHxNbNp4eH95ntnFPkKWlhUeB0JYQVeL3HJtrF0eUcwPi2pRpYi+y5DISdZzUvQ19kDVCoVZClxAICg75+ezqyU3R8+G3gmDwwJviEUC/0n9AbdJnv7ox3BDIWikC/g3GRxfDkDPVowzy4AQRAgEAVDTEIsLC1ab40Pjn0WnRT7rihcVB8RHcmYmZ4x6XWjZTuCymJlht2+cRe8XtFgvw5wFw4UKgVCJaEgkUZ4V6zLF7W92jp5bla6v79fszRWyjMZTepdcRkf7AiWV5XHmI3WO7tzFXE26xK0NNwBUZgIio+VwtTYFD6i1dVqnmou5ynz4jEfyl1xRJjI9GLmd3XHs5odwTO1ZyKfa7XNBYeUqRgJg19/vA5BIUFw6Oj7MNj/7/r44FhNf7e6IasgR8ag+9zlC3iihZfzF7raO3/YEbxy5Yqk6d7tpvyD+3ax2CxoutYIfnx/2Fe0HzRdatvMlPHT3o7eZqVSKXOTPS1MNou/Zl2p7nrc1fg2iEpLSykAQDp9+jS9uramNjo+tjI+NYE+rBkEOpMBXJ4fdLd3Gv1E4hOP6pvaD5QfiHfYN1p8GD4U74bnk7YHbW2vQVTwcUGwTW8r2qJsp3ncHnoQO9C4OD/PQyTsSEJ6EidIKIDFuQUwz5hh3bZmo3IY3w50913LKzkQRSE8LTQ6baO8+EhFWUmZGlVWVgpbB9ouLmc5i9yxiAIYADblAVovQKRLDFwaF+bNs8BmciA2Kg5IGAmM81M2p9deJwwVGtftjp+pNNrsiHqw2mKxaNDB0oMJHTZ1szefEuNH5wJGIHARm7BqWwWejgm7SOkwt2CCQH4QhAQK3+TR6XLCqHHU5rS/WmWyWGGAoVWC2G6++tPVOlRRVRWjGlCpwmXh8WWpJcD3C4Ch8WFoGLoNpG0M0tyJYDYvAofNBR6XBw6nw0uhURAiA3ppNAKTyQJeIM8zazK1X/jmfAWqqKqIURlaVYx3fOOLA/aDLFQGTVoVaNeHIIwSCmXRRWAxWwBDCCxW69bw6LA2TCJh7ZZnysbHx0nmRTNIY6ItC8vztXwavxEdLToa30p7rLLnemL2TKeAjJDCL8I/gWCRIKojADLJKYC7NgHHXRAiDNmanjE2Oh32e75+nNyc7L0VBsM4k83lGNbWVo/fvH6zCyVHJGcYsueb8UJMkjESA1KbGP5IbwOMRobCyT2QjGKhr0fzehNgf6ES1h32kRcTkyeoGFWtf6E/TkLk86ny1PaHdx58MTk5OY3kcnnSWPDLBmcplshZYgB7ggom+SpBnQB3njUTZYSlUHRDg7CFb4JCoQDP9varv/5+9Lm6U92Qsy8nd8Y4Vy2Rii51POxoA4BtlPleJtu1uVkxHW05tZFNiAjci1jPMbO/nqFFFm8sh8WJCBIEmRFCZBzH+TabbYXB8f2qv6u3PjMnM0CeIo+sv1Gvt9vty68H802wExMTA3yEzMOTjJmTHo+bI14RfM8ms5yjutFzjnWHOEQc0u92u1nL5mUZiUzCA0MCuwCRfosUSe53dnbib4/0/9VD2dnZLDqXnoU7cKp+SN+VnJacNzEx8aXLhXMFwuA+18aGYH1lXerxeHy2vR5fKp1mE4tFJTqNTvM2+B9Df2VX8nqE4QAAAABJRU5ErkJggg==" />
19
+ Teuton report</h1>
20
+ <div id="header">
21
+ <p><b>Test name:</b> <%= config[:tt_testname] %></p>
22
+ <p><b>Members:</b> <%= config[:tt_members] %></p>
23
+ <p><b>Grade:</b> <%= results[:grade] %></p>
24
+ </div>
25
+ <div id="tabs">
26
+ <ul class="tabLinks">
27
+ <li><a href="#tab0">Config</a></li>
28
+ <li><a href="#tab1">Logs</a></li>
29
+ <li><a href="#tab2">Groups</a></li>
30
+ <li><a href="#tab3">Results</a></li>
31
+ <li><a href="#tab4">Hall of fame</a></li>
32
+ </ul>
33
+ <div class="tab" id="tab0">
34
+ <h2>Config</h2>
35
+ <table>
36
+ <thead>
37
+ <tr>
38
+ <th>Property</th>
39
+ <th class="numeric">Value</th>
40
+ </tr>
41
+ </thead>
42
+ <% config.each_pair do |key, value| %>
43
+ <tr>
44
+ <td><%= key.to_s %></td>
45
+ <td class="numeric"><%= value.to_s %></td>
46
+ </tr>
47
+ <% end %>
48
+ </table>
49
+ </div>
50
+ <div class="tab" id="tab1">
51
+ <h2>Logs</h2>
52
+ <% logs.each do |line| %>
53
+ <p><%= line %></p>
54
+ <% end %>
55
+ </div>
56
+ <div class="tab" id="tab2">
57
+ <h2>Groups</h2>
58
+ <% groups.each do |group| %>
59
+ <h2><%= group[:title] %></h2>
60
+ <table>
61
+ <thead>
62
+ <tr>
63
+ <th>Target</th>
64
+ <th>Property</th>
65
+ <th class="numeric">Value</th>
66
+ </tr>
67
+ </thead>
68
+ <% group[:targets].each do |target| %>
69
+ <tr>
70
+ <td><b><%= target[:description] %></b></td>
71
+ <td></td>
72
+ <td class="numeric"></td>
73
+ </tr>
74
+ <% target.each_pair do |key, value| %>
75
+ <% next if key == :description %>
76
+ <tr>
77
+ <td></td>
78
+ <td><%= key.to_s %></td>
79
+ <td class="numeric"><%= value.to_s %></td>
80
+ </tr>
81
+ <% end %>
82
+ <% end %>
83
+ <% end %>
84
+ </table>
85
+ <br/>
86
+ </div>
87
+ <div class="tab" id="tab3">
88
+ <h2>Results</h2>
89
+ <table>
90
+ <thead>
91
+ <tr>
92
+ <th>Property</th>
93
+ <th class="numeric">Value</th>
94
+ </tr>
95
+ </thead>
96
+ <% results.each_pair do |key, value| %>
97
+ <tr>
98
+ <td><%= key.to_s %></td>
99
+ <td class="numeric"><%= value.to_s %></td>
100
+ </tr>
101
+ <% end %>
102
+ </table>
103
+ </div>
104
+ <div class="tab" id="tab4">
105
+ <h2>Hall of fame</h2>
106
+ <table>
107
+ <thead>
108
+ <tr>
109
+ <th>Grade</th>
110
+ <th class="numeric">Cases</th>
111
+ </tr>
112
+ </thead>
113
+ <% hall_of_fame.each_pair do |key, value| %>
114
+ <tr>
115
+ <td><%= key.to_s %></td>
116
+ <td class="numeric"><%= value.to_s %></td>
117
+ </tr>
118
+ <% end %>
119
+ </table>
120
+ </div>
121
+ </div>
122
+ <div id="footer">
123
+ <p>
124
+ <div>
125
+ <label class="hidden" id="label-for-line-wrapping-toggle" for="line-wrapping-toggle">Wrap lines
126
+ <input id="line-wrapping-toggle" type="checkbox" autocomplete="off" />
127
+ </label>
128
+ </div>
129
+ Generated by <a href="http://github.com/teuton-software/teuton">Teuton <%= version %></a>
130
+ at <%= results[:finish_time] %>
131
+ </p>
132
+ </div>
133
+ </div>
134
+ </body>
135
+ </html>
@@ -0,0 +1,115 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6
+ <meta http-equiv="x-ua-compatible" content="IE=edge" />
7
+ <title>Teuton report</title>
8
+ <style>
9
+ body{margin:0;padding:0;font-family:sans-serif;font-size:12pt}a,a:visited,body{color:#303030}#content{padding-left:50px;padding-right:50px;padding-top:30px;padding-bottom:30px}#content h1{font-size:160%;margin-bottom:10px}#footer{margin-top:100px;font-size:80%;white-space:nowrap}#footer,#footer a{color:#a0a0a0}#line-wrapping-toggle{vertical-align:middle}#label-for-line-wrapping-toggle{vertical-align:middle}ul{margin-left:0}h1,h2,h3{white-space:nowrap}h2{font-size:120%}ul.tabLinks{padding-left:0;padding-top:10px;padding-bottom:10px;overflow:auto;min-width:800px;width:auto!important;width:800px}ul.tabLinks li{float:left;height:100%;list-style:none;padding-left:10px;padding-right:10px;padding-top:5px;padding-bottom:5px;margin-bottom:0;-moz-border-radius:7px;border-radius:7px;margin-right:25px;border:solid 1px #d4d4d4;background-color:#f0f0f0}ul.tabLinks li:hover{background-color:#fafafa}ul.tabLinks li.selected{background-color:#00c21b;border-color:#00c21b}ul.tabLinks a{font-size:120%;display:block;outline:0;text-decoration:none;margin:0;padding:0}ul.tabLinks li h2{margin:0;padding:0}div.selected{display:block}div.deselected{display:none}div.tab table{min-width:350px;width:auto!important;width:350px;border-collapse:collapse}div.tab table,div.tab th{border-bottom:solid #d0d0d0 1px}div.tab th{text-align:left;white-space:nowrap;padding-left:6em}div.tab th:first-child{padding-left:0}div.tab td{white-space:nowrap;padding-left:6em;padding-top:5px;padding-bottom:5px}div.tab td:first-child{padding-left:0}div.tab td.numeric,div.tab th.numeric{text-align:right}span.code{display:inline-block;margin-top:0;margin-bottom:1em}span.code pre{font-size:11pt;padding-top:10px;padding-bottom:10px;padding-left:10px;padding-right:10px;margin:0;background-color:#f7f7f7;border:solid 1px #d0d0d0;min-width:700px;width:auto!important;width:700px}span.wrapped pre{word-wrap:break-word;white-space:pre-wrap;word-break:break-all}label.hidden{display:none}div.tab td.indentPath{padding-left:3em}
10
+ </style>
11
+ <script type="text/javascript">
12
+ !function(e,t){"use strict";var n={};function i(e,t){e.getAttribute("className")?e.setAttribute("className",t):e.setAttribute("class",t)}function s(e){return e.getAttribute("className")?e.getAttribute("className"):e.getAttribute("class")}function r(e,t){i(e,s(e)+" "+t)}function a(e,t){i(e,s(e).replace(t,""))}function l(){var e=t.getElementById("tabs");return n.tabs=function(e){return p(e,"DIV","tab")}(e),n.titles=function(e){for(var t=[],n=0;n<e.length;n++){var i=e[n],s=p(i,"H2",null)[0];s.parentNode.removeChild(s),s.innerText?t.push(s.innerText):t.push(s.textContent)}return t}(n.tabs),n.headers=function(e){var t=p(e,"UL","tabLinks");return p(t[0],"LI",null)}(e),n.select=b,n.deselectAll=g,n.select(0),!0}function d(){return t.getElementById("line-wrapping-toggle")}function h(){for(var e=t.getElementById("tabs").getElementsByTagName("span"),n=[],i=0;i<e.length;++i)e[i].className.indexOf("code")>=0&&n.push(e[i]);return n}function c(e){for(var t=h(),n=0;n<t.length;++n)e(t[n],"wrapped")}function o(){d().checked?c(r):c(a)}function u(){if(h().length>0){var e=d(),n=t.getElementById("label-for-line-wrapping-toggle");e.onclick=o,e.checked=!1,a(n,"hidden")}}function f(){for(var e=this.id.substr(1),t=0;t<n.tabs.length;t++)if(n.tabs[t].id===e){n.select(t);break}return!1}function b(e){for(this.deselectAll(),i(this.tabs[e],"tab selected"),i(this.headers[e],"selected");this.headers[e].firstChild;)this.headers[e].removeChild(this.headers[e].firstChild);var n=t.createElement("H2");n.appendChild(t.createTextNode(this.titles[e])),this.headers[e].appendChild(n)}function g(){for(var e=0;e<this.tabs.length;e++){for(i(this.tabs[e],"tab deselected"),i(this.headers[e],"deselected");this.headers[e].firstChild;)this.headers[e].removeChild(this.headers[e].firstChild);var n=t.createElement("A");n.setAttribute("id","ltab"+e),n.setAttribute("href","#tab"+e),n.onclick=f,n.appendChild(t.createTextNode(this.titles[e])),this.headers[e].appendChild(n)}}function p(e,t,n){for(var i=[],s=e.childNodes,r=0;r<s.length;r++){var a=s.item(r);if(1===a.nodeType&&a.nodeName===t){if(n&&a.className.indexOf(n)<0)continue;i.push(a)}}return i}e.onload=function(){l(),u()}}(window,window.document);
13
+ </script>
14
+ </head>
15
+
16
+ <body>
17
+ <div id="content">
18
+ <h1><img title="teuton logo" alt="logo" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAFg0lEQVQ4T23UW0yTdxgG8Pf/9UQPtIUWKJSWciiDcj4VhRoZh9iZoAJDIZuJ2wUyxS3CdMvkZmOaLFtczDJ1ajaGTBxVNEQdYRoYKBRqWTkUKAiVcmoLBaQt/aCl36LJEi94r9/8rp7nQbDDBQQEsNL2pmVa55aPURm0fNzlCiQAnIggnjIYzKZTp052t9xqmVWpVHD23Nm0J0+fKCxTlta5ubkptBOYmp162IfO+DohPUkqCheTjIZpYLAYr1+9hpHxNbNp4eH95ntnFPkKWlhUeB0JYQVeL3HJtrF0eUcwPi2pRpYi+y5DISdZzUvQ19kDVCoVZClxAICg75+ezqyU3R8+G3gmDwwJviEUC/0n9AbdJnv7ox3BDIWikC/g3GRxfDkDPVowzy4AQRAgEAVDTEIsLC1ab40Pjn0WnRT7rihcVB8RHcmYmZ4x6XWjZTuCymJlht2+cRe8XtFgvw5wFw4UKgVCJaEgkUZ4V6zLF7W92jp5bla6v79fszRWyjMZTepdcRkf7AiWV5XHmI3WO7tzFXE26xK0NNwBUZgIio+VwtTYFD6i1dVqnmou5ynz4jEfyl1xRJjI9GLmd3XHs5odwTO1ZyKfa7XNBYeUqRgJg19/vA5BIUFw6Oj7MNj/7/r44FhNf7e6IasgR8ag+9zlC3iihZfzF7raO3/YEbxy5Yqk6d7tpvyD+3ax2CxoutYIfnx/2Fe0HzRdatvMlPHT3o7eZqVSKXOTPS1MNou/Zl2p7nrc1fg2iEpLSykAQDp9+jS9uramNjo+tjI+NYE+rBkEOpMBXJ4fdLd3Gv1E4hOP6pvaD5QfiHfYN1p8GD4U74bnk7YHbW2vQVTwcUGwTW8r2qJsp3ncHnoQO9C4OD/PQyTsSEJ6EidIKIDFuQUwz5hh3bZmo3IY3w50913LKzkQRSE8LTQ6baO8+EhFWUmZGlVWVgpbB9ouLmc5i9yxiAIYADblAVovQKRLDFwaF+bNs8BmciA2Kg5IGAmM81M2p9deJwwVGtftjp+pNNrsiHqw2mKxaNDB0oMJHTZ1szefEuNH5wJGIHARm7BqWwWejgm7SOkwt2CCQH4QhAQK3+TR6XLCqHHU5rS/WmWyWGGAoVWC2G6++tPVOlRRVRWjGlCpwmXh8WWpJcD3C4Ch8WFoGLoNpG0M0tyJYDYvAofNBR6XBw6nw0uhURAiA3ppNAKTyQJeIM8zazK1X/jmfAWqqKqIURlaVYx3fOOLA/aDLFQGTVoVaNeHIIwSCmXRRWAxWwBDCCxW69bw6LA2TCJh7ZZnysbHx0nmRTNIY6ItC8vztXwavxEdLToa30p7rLLnemL2TKeAjJDCL8I/gWCRIKojADLJKYC7NgHHXRAiDNmanjE2Oh32e75+nNyc7L0VBsM4k83lGNbWVo/fvH6zCyVHJGcYsueb8UJMkjESA1KbGP5IbwOMRobCyT2QjGKhr0fzehNgf6ES1h32kRcTkyeoGFWtf6E/TkLk86ny1PaHdx58MTk5OY3kcnnSWPDLBmcplshZYgB7ggom+SpBnQB3njUTZYSlUHRDg7CFb4JCoQDP9varv/5+9Lm6U92Qsy8nd8Y4Vy2Rii51POxoA4BtlPleJtu1uVkxHW05tZFNiAjci1jPMbO/nqFFFm8sh8WJCBIEmRFCZBzH+TabbYXB8f2qv6u3PjMnM0CeIo+sv1Gvt9vty68H802wExMTA3yEzMOTjJmTHo+bI14RfM8ms5yjutFzjnWHOEQc0u92u1nL5mUZiUzCA0MCuwCRfosUSe53dnbib4/0/9VD2dnZLDqXnoU7cKp+SN+VnJacNzEx8aXLhXMFwuA+18aGYH1lXerxeHy2vR5fKp1mE4tFJTqNTvM2+B9Df2VX8nqE4QAAAABJRU5ErkJggg==" />
19
+ Teuton report</h1>
20
+ <div id="header">
21
+ <p><b>Test name:</b> <%= config[:tt_testname] %></p>
22
+ <p><b>Case number:</b> <%= cases.size %></p>
23
+ </div>
24
+ <div id="tabs">
25
+ <ul class="tabLinks">
26
+ <li><a href="#tab0">Config</a></li>
27
+ <li><a href="#tab1">Cases</a></li>
28
+ <li><a href="#tab2">Results</a></li>
29
+ <li><a href="#tab3">Hall of fame</a></li>
30
+ </ul>
31
+ <div class="tab" id="tab0">
32
+ <h2>Config</h2>
33
+ <table>
34
+ <thead>
35
+ <tr>
36
+ <th>Property</th>
37
+ <th class="numeric">Value</th>
38
+ </tr>
39
+ </thead>
40
+ <% config.each_pair do |key, value| %>
41
+ <tr>
42
+ <td><%= key.to_s %></td>
43
+ <td class="numeric"><%= value.to_s %></td>
44
+ </tr>
45
+ <% end %>
46
+ </table>
47
+ </div>
48
+ <div class="tab" id="tab1">
49
+ <h2>Cases</h2>
50
+ <table>
51
+ <thead>
52
+ <tr>
53
+ <th>Target</th>
54
+ <th>Property</th>
55
+ <th class="numeric">Value</th>
56
+ </tr>
57
+ </thead>
58
+ <% cases.each do |item| %>
59
+ <tr>
60
+ <td><b><%= item[:id] %></b></td>
61
+ <td><b><%= item[:members] %></b></td>
62
+ <td class="numeric"><%= item[:grade] %></td>
63
+ </tr>
64
+ <% end %>
65
+ </table>
66
+ <br/>
67
+ </div>
68
+ <div class="tab" id="tab2">
69
+ <h2>Results</h2>
70
+ <table>
71
+ <thead>
72
+ <tr>
73
+ <th>Property</th>
74
+ <th class="numeric">Value</th>
75
+ </tr>
76
+ </thead>
77
+ <% results.each_pair do |key, value| %>
78
+ <tr>
79
+ <td><%= key.to_s %></td>
80
+ <td class="numeric"><%= value.to_s %></td>
81
+ </tr>
82
+ <% end %>
83
+ </table>
84
+ </div>
85
+ <div class="tab" id="tab3">
86
+ <h2>Hall of fame</h2>
87
+ <table>
88
+ <thead>
89
+ <tr>
90
+ <th>Grade</th>
91
+ <th class="numeric">Cases</th>
92
+ </tr>
93
+ </thead>
94
+ <% hall_of_fame.each_pair do |key, value| %>
95
+ <tr>
96
+ <td><%= key.to_s %></td>
97
+ <td class="numeric"><%= value.to_s %></td>
98
+ </tr>
99
+ <% end %>
100
+ </table>
101
+ </div>
102
+ </div>
103
+ <div id="footer">
104
+ <p>
105
+ <div>
106
+ <label class="hidden" id="label-for-line-wrapping-toggle" for="line-wrapping-toggle">Wrap lines
107
+ <input id="line-wrapping-toggle" type="checkbox" autocomplete="off" />
108
+ </label>
109
+ </div>
110
+ Generated by <a href="http://github.com/teuton-software/teuton">Teuton <%= version %></a> at <%= results[:finish_time] %>
111
+ </p>
112
+ </div>
113
+ </div>
114
+ </body>
115
+ </html>