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.
- data/LICENSE +1 -0
- data/README +80 -0
- data/lib/puppet7/common.rb +59 -0
- data/lib/puppet7/configuration.rb +38 -0
- data/lib/puppet7/domain.rb +136 -0
- data/lib/puppet7/element.rb +62 -0
- data/lib/puppet7/exceptions.rb +17 -0
- data/lib/puppet7/extend.rb +173 -0
- data/lib/puppet7/javascript/json.js +527 -0
- data/lib/puppet7/javascript/on_page_loading.js +78 -0
- data/lib/puppet7/javascript/selenium_extension.js +5 -0
- data/lib/puppet7/page.rb +138 -0
- data/lib/puppet7/page_part.rb +140 -0
- data/lib/puppet7/puppet.rb +79 -0
- data/lib/puppet7/puppet_formatter.rb +121 -0
- data/lib/puppet7/puppet_report.rb +292 -0
- data/lib/puppet7/report/_example_group.erb +24 -0
- data/lib/puppet7/report/_examples.erb +22 -0
- data/lib/puppet7/report/puppet_report.erb +187 -0
- data/lib/puppet7/selenium_actions.rb +20 -0
- data/lib/puppet7/selenium_locator_actions.rb +302 -0
- data/lib/puppet7/selenium_support.rb +56 -0
- data/lib/puppet7/sql_agent.rb +98 -0
- data/lib/puppet7/sql_exec.rb +148 -0
- data/lib/puppet7/utils.rb +72 -0
- data/lib/puppet7.rb +28 -0
- metadata +136 -0
data/lib/puppet7/page.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require "erb"
|
4
|
+
require "puppet7/page_part"
|
5
|
+
require "puppet7/utils"
|
6
|
+
require "puppet7/exceptions"
|
7
|
+
require "puppet7/puppet_report"
|
8
|
+
|
9
|
+
module Puppet7
|
10
|
+
|
11
|
+
class Page < PagePart
|
12
|
+
include ERB::Util
|
13
|
+
include Puppet7::Utils
|
14
|
+
|
15
|
+
attr_accessor :url, :encoding
|
16
|
+
class << self
|
17
|
+
def url url
|
18
|
+
self.class_eval do
|
19
|
+
@__url = url
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def encoding encoding
|
24
|
+
self.class_eval do
|
25
|
+
@__encoding = encoding
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def new *args
|
30
|
+
instance = super
|
31
|
+
instance.instance_eval do
|
32
|
+
@encoding = nil
|
33
|
+
end
|
34
|
+
self.class_eval do
|
35
|
+
@__url ||= nil
|
36
|
+
@__encoding ||= nil
|
37
|
+
instance.url = @__url
|
38
|
+
instance.encoding = @__encoding
|
39
|
+
end
|
40
|
+
if instance.url == nil
|
41
|
+
do_pending "Should define 'url' of Page[#{instance.fullname}]!"
|
42
|
+
end
|
43
|
+
instance
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def page
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
def encoding
|
52
|
+
if @encoding
|
53
|
+
@encoding
|
54
|
+
elsif @parent
|
55
|
+
@parent.encoding
|
56
|
+
else
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def open params={}, &block
|
62
|
+
_url = make_url params
|
63
|
+
if @parent
|
64
|
+
@parent.selenium.open _url
|
65
|
+
else
|
66
|
+
do_pending "Page[#{fullname}] does not belong to any Domain!"
|
67
|
+
end
|
68
|
+
if block_given?
|
69
|
+
@block_binding = block.binding
|
70
|
+
self.instance_eval &block
|
71
|
+
@block_binding = nil
|
72
|
+
end
|
73
|
+
return self
|
74
|
+
end
|
75
|
+
|
76
|
+
def method_missing sym, *args, &b
|
77
|
+
if @block_binding
|
78
|
+
catch :pending_declared_in_example do
|
79
|
+
return @block_binding.eval("#{sym}(#{args.collect{|a| a.inspect}.join(',')})")
|
80
|
+
end
|
81
|
+
super
|
82
|
+
else
|
83
|
+
super
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def selenium
|
88
|
+
if @parent
|
89
|
+
if same_page?@parent.selenium.location
|
90
|
+
@parent.selenium
|
91
|
+
else
|
92
|
+
raise "'#{fullname}' page is NOT match to #{@parent.selenium.location}"
|
93
|
+
end
|
94
|
+
else
|
95
|
+
do_pending "Page[#{fullname}] does not belong to any Domain!"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def same_page? url
|
100
|
+
url_arg = parse_url url
|
101
|
+
if String === @url
|
102
|
+
url_self = parse_url @url
|
103
|
+
if url_self.baseurl == nil
|
104
|
+
url_arg.path == url_self.path and
|
105
|
+
(url_arg.baseurl == nil or @parent.baseurl == url_arg.baseurl)
|
106
|
+
else
|
107
|
+
url_arg.path == url_self.path and url_arg.baseurl == url_self.baseurl
|
108
|
+
end
|
109
|
+
elsif Regexp === @url
|
110
|
+
url_arg.baseurl == @parent.baseurl and "#{url_arg.path}#{url_arg.query_str}" =~ @url
|
111
|
+
else
|
112
|
+
do_pending "@url is Unexpected value! : #{fullname}.url => #{@url.inspect}"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def current?
|
117
|
+
same_page?@parent.selenium.location
|
118
|
+
end
|
119
|
+
|
120
|
+
def make_url params={}
|
121
|
+
if String === @url
|
122
|
+
param_str = make_param_str params
|
123
|
+
if param_str.empty?
|
124
|
+
return @url
|
125
|
+
else
|
126
|
+
return @url + ( @url.include?("?") ? "&" : "?") + param_str
|
127
|
+
end
|
128
|
+
else
|
129
|
+
do_pending "#{fullname}.url is defined regular expression. Do define 'make_url' method for this page."
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def make_param_str params={}
|
134
|
+
params.collect{|k,v| "#{k}=#{u(v)}"}.join("&")
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require "puppet7/puppet"
|
4
|
+
require "puppet7/element"
|
5
|
+
require "puppet7/utils"
|
6
|
+
require "puppet7/exceptions"
|
7
|
+
require "puppet7/puppet_report"
|
8
|
+
|
9
|
+
module Puppet7
|
10
|
+
# PagePart class
|
11
|
+
#
|
12
|
+
# A page part could contain UIElements and other page part.
|
13
|
+
# This class is super class of Page class.
|
14
|
+
class PagePart < Puppet
|
15
|
+
attr_accessor :elements, :parts, :parent
|
16
|
+
|
17
|
+
class << self
|
18
|
+
include Puppet7::Utils
|
19
|
+
def element name, *args
|
20
|
+
self.class_eval do
|
21
|
+
@__elements ||= {}
|
22
|
+
unless @__elements.key?name.to_sym
|
23
|
+
@__elements[name.to_sym] = args
|
24
|
+
else
|
25
|
+
do_pending "'#{name}' is already defined!", DuplicatedUIElementException
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def part name
|
31
|
+
self.class_eval do
|
32
|
+
@__parts ||= []
|
33
|
+
unless @__parts.include?name.to_sym
|
34
|
+
@__parts << name.to_sym
|
35
|
+
else
|
36
|
+
do_pending "'#{name}' is already defined!", DuplicatedPagePartException
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def new *args
|
42
|
+
instance = super
|
43
|
+
instance.instance_eval do
|
44
|
+
@elements = {}
|
45
|
+
@parts = {}
|
46
|
+
end
|
47
|
+
self.class_eval do
|
48
|
+
@__elements ||= {}
|
49
|
+
@__elements.each do |name, arg|
|
50
|
+
elm = Element.new instance, name, *arg
|
51
|
+
instance.elements[name] = elm
|
52
|
+
make_element_accessor name
|
53
|
+
end
|
54
|
+
@__parts ||= []
|
55
|
+
@__parts.each do |part_name|
|
56
|
+
a_part = PagePart.get_instance(part_name, instance)
|
57
|
+
instance.parts[part_name] = a_part
|
58
|
+
make_part_accessor part_name
|
59
|
+
end
|
60
|
+
end
|
61
|
+
instance
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
def make_element_accessor elm_name
|
66
|
+
self.class_eval <<-END
|
67
|
+
def #{elm_name}
|
68
|
+
@elements[:'#{elm_name}']
|
69
|
+
end
|
70
|
+
END
|
71
|
+
end
|
72
|
+
def make_part_accessor part_name
|
73
|
+
self.class_eval <<-END
|
74
|
+
def #{part_name} &block
|
75
|
+
part = parts[:'#{part_name}']
|
76
|
+
if block_given?
|
77
|
+
part.instance_exec &block
|
78
|
+
else
|
79
|
+
part
|
80
|
+
end
|
81
|
+
end
|
82
|
+
END
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def initialize parent=nil
|
87
|
+
@parent = parent
|
88
|
+
end
|
89
|
+
|
90
|
+
def page
|
91
|
+
@parent ? @parent.page : nil
|
92
|
+
end
|
93
|
+
|
94
|
+
def fullname
|
95
|
+
name_stack = [] << self.class.name
|
96
|
+
_page = page
|
97
|
+
cur = self
|
98
|
+
while cur != _page
|
99
|
+
cur = cur.parent
|
100
|
+
name_stack << cur.class.name if cur
|
101
|
+
end
|
102
|
+
name_stack.reverse.join(">")
|
103
|
+
end
|
104
|
+
|
105
|
+
def selenium
|
106
|
+
if @parent
|
107
|
+
@parent.selenium
|
108
|
+
else
|
109
|
+
do_pending "PagePart[#{fullname}] does not belong to any Page!", NotDefinedException
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def method_missing sym, *args, &b
|
114
|
+
begin
|
115
|
+
super
|
116
|
+
rescue
|
117
|
+
first_arg = args.shift
|
118
|
+
if first_arg && Element === first_arg
|
119
|
+
first_arg.send(sym, *args)
|
120
|
+
elsif first_arg && Symbol === first_arg
|
121
|
+
elm_obj = elements[first_arg]
|
122
|
+
if elm_obj
|
123
|
+
elm_obj.send(sym, *args)
|
124
|
+
else
|
125
|
+
Puppet7.report.add_undefined_object :element, "#{fullname}.#{sym}"
|
126
|
+
do_pending "[#{fullname}] has no element or action named '#{sym}'", NotDefinedException
|
127
|
+
end
|
128
|
+
else
|
129
|
+
Puppet7.report.add_undefined_object :element, "#{fullname}.#{sym}"
|
130
|
+
do_pending "[#{fullname}] has no element or action named '#{sym}'", NotDefinedException
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def image_ok? img_url
|
136
|
+
@parent.image_ok? img_url
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require "puppet7/exceptions"
|
4
|
+
|
5
|
+
module Puppet7
|
6
|
+
# Base class for all page object class (e.g. Page, PagePart, Domain)
|
7
|
+
class Puppet
|
8
|
+
@subclasses = {}
|
9
|
+
@name = self.to_s.to_sym
|
10
|
+
# class name.
|
11
|
+
# if this class was create by #subclass method, then it has the name used by #subclass method.
|
12
|
+
def self.name
|
13
|
+
@name
|
14
|
+
end
|
15
|
+
|
16
|
+
# initialize class vars when a subclass is created.
|
17
|
+
def self.inherited subclass
|
18
|
+
subclass.class_eval do
|
19
|
+
@subclasses = {}
|
20
|
+
@name = self.to_s.to_sym
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
@@puppet_testing = false
|
25
|
+
def self.puppet_testing
|
26
|
+
@@puppet_testing
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.begin_testing
|
30
|
+
@@puppet_testing = true
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.end_testing
|
34
|
+
@@puppet_testing = false
|
35
|
+
end
|
36
|
+
|
37
|
+
# create a anonymouse subclass and return it.
|
38
|
+
# If the class given name was create already, then just return it without error.
|
39
|
+
def self.subclass name
|
40
|
+
unless @subclasses[name.to_sym]
|
41
|
+
klass = Class.new(self)
|
42
|
+
klass.class_eval do
|
43
|
+
@name = name
|
44
|
+
end
|
45
|
+
@subclasses[name.to_sym] = klass
|
46
|
+
end
|
47
|
+
@subclasses[name.to_sym]
|
48
|
+
end
|
49
|
+
|
50
|
+
# return if it has the subclass given name
|
51
|
+
def self.subclass? name
|
52
|
+
@subclasses.key?(name.to_sym)
|
53
|
+
end
|
54
|
+
|
55
|
+
# clear all subclasses create by #subclass method
|
56
|
+
def self.clear_subclasses
|
57
|
+
@subclasses.clear
|
58
|
+
end
|
59
|
+
|
60
|
+
# delete subclass create by #subclass method.
|
61
|
+
def self.delete_subclass name
|
62
|
+
@subclasses.delete name.to_sym
|
63
|
+
end
|
64
|
+
|
65
|
+
# create a instance of the class given name
|
66
|
+
# It'll raise NotDefinedException if the class given name is not exists.
|
67
|
+
def self.get_instance name, *args, &b
|
68
|
+
if subclass? name
|
69
|
+
subclass(name).new *args, &b
|
70
|
+
else
|
71
|
+
raise NotDefinedException.new "#{self.name} class has no subclass named '#{name}'."
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def puppet_name
|
76
|
+
self.class.name
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'rspec/core/formatters/base_text_formatter'
|
3
|
+
|
4
|
+
module Puppet7
|
5
|
+
class PuppetFormatter < RSpec::Core::Formatters::BaseTextFormatter
|
6
|
+
# real formatter
|
7
|
+
@formatter_class = nil
|
8
|
+
def self.formatter_class= formatter
|
9
|
+
@formatter_class = formatter
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.formatter_class
|
13
|
+
@formatter_class
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(output)
|
17
|
+
@formatter = self.class.formatter_class.new(output)
|
18
|
+
@report = Puppet7.report
|
19
|
+
end
|
20
|
+
|
21
|
+
# This method is invoked before any examples are run, right after
|
22
|
+
# they have all been collected. This can be useful for special
|
23
|
+
# formatters that need to provide progress on feedback (graphical ones)
|
24
|
+
#
|
25
|
+
# This will only be invoked once, and the next one to be invoked
|
26
|
+
# is #example_group_started
|
27
|
+
def start(example_count)
|
28
|
+
@formatter.start example_count
|
29
|
+
end
|
30
|
+
|
31
|
+
# This method is invoked at the beginning of the execution of each example group.
|
32
|
+
# +example_group+ is the example_group.
|
33
|
+
#
|
34
|
+
# The next method to be invoked after this is +example_passed+,
|
35
|
+
# +example_pending+, or +example_finished+
|
36
|
+
def example_group_started(example_group)
|
37
|
+
@report.start_example_group(example_group)
|
38
|
+
@formatter.example_group_started example_group
|
39
|
+
end
|
40
|
+
|
41
|
+
# This method is invoked at the end of the execution of each example group.
|
42
|
+
# +example_group+ is the example_group.
|
43
|
+
def example_group_finished(example_group)
|
44
|
+
@report.end_example_group(example_group)
|
45
|
+
@formatter.example_group_finished(example_group)
|
46
|
+
end
|
47
|
+
|
48
|
+
def add_example_group(example_group)
|
49
|
+
@formatter.add_example_group(example_group)
|
50
|
+
end
|
51
|
+
|
52
|
+
def example_started(example)
|
53
|
+
@report.add_example(example)
|
54
|
+
@formatter.example_started(example)
|
55
|
+
end
|
56
|
+
|
57
|
+
def example_passed(example)
|
58
|
+
@formatter.example_passed(example)
|
59
|
+
end
|
60
|
+
|
61
|
+
def example_pending(example)
|
62
|
+
@formatter.example_pending(example)
|
63
|
+
end
|
64
|
+
|
65
|
+
def example_failed(example)
|
66
|
+
@formatter.example_failed(example)
|
67
|
+
end
|
68
|
+
|
69
|
+
def message(message)
|
70
|
+
puts "message>>#{message}"
|
71
|
+
@formatter.message(message)
|
72
|
+
end
|
73
|
+
|
74
|
+
def stop
|
75
|
+
@formatter.stop
|
76
|
+
end
|
77
|
+
|
78
|
+
# This method is invoked after all of the examples have executed. The next method
|
79
|
+
# to be invoked after this one is #dump_failure (once for each failed example),
|
80
|
+
def start_dump
|
81
|
+
@formatter.start_dump
|
82
|
+
end
|
83
|
+
|
84
|
+
# Dumps detailed information about each example failure.
|
85
|
+
def dump_failures
|
86
|
+
@formatter.dump_failures
|
87
|
+
end
|
88
|
+
|
89
|
+
# This method is invoked after the dumping of examples and failures.
|
90
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
91
|
+
@formatter.dump_summary(duration, example_count, failure_count, pending_count)
|
92
|
+
end
|
93
|
+
|
94
|
+
# This gets invoked after the summary if option is set to do so.
|
95
|
+
def dump_pending
|
96
|
+
@formatter.dump_pending
|
97
|
+
end
|
98
|
+
|
99
|
+
# This method is invoked at the very end. Allows the formatter to clean up, like closing open streams.
|
100
|
+
def close
|
101
|
+
@formatter.close
|
102
|
+
File.open(Puppet7.configuration.report_file, "w") do |f|
|
103
|
+
@report.write_report(f)
|
104
|
+
end if Puppet7.configuration.use_report
|
105
|
+
end
|
106
|
+
|
107
|
+
def format_backtrace(backtrace, example)
|
108
|
+
@formatter.format_backtrace(backtrace, example)
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
require 'puppet7/common'
|
115
|
+
require 'puppet7/configuration'
|
116
|
+
|
117
|
+
# hook rspec formatter
|
118
|
+
if class_by_name("RSpec")
|
119
|
+
Puppet7::PuppetFormatter.formatter_class = RSpec.configuration.formatter_class
|
120
|
+
RSpec.configuration.formatter = Puppet7::PuppetFormatter
|
121
|
+
end
|