prism_checker 0.0.1
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.
- checksums.yaml +7 -0
- data/LICENSE.md +28 -0
- data/README.md +673 -0
- data/lib/prism_checker/absence_expectation.rb +9 -0
- data/lib/prism_checker/check_dispatcher.rb +168 -0
- data/lib/prism_checker/checker.rb +83 -0
- data/lib/prism_checker/colorizer.rb +9 -0
- data/lib/prism_checker/config.rb +14 -0
- data/lib/prism_checker/element_wrapper.rb +59 -0
- data/lib/prism_checker/expectation_classifier.rb +71 -0
- data/lib/prism_checker/item_checker/any.rb +25 -0
- data/lib/prism_checker/item_checker/array.rb +27 -0
- data/lib/prism_checker/item_checker/checkbox.rb +29 -0
- data/lib/prism_checker/item_checker/element.rb +52 -0
- data/lib/prism_checker/item_checker/elements.rb +53 -0
- data/lib/prism_checker/item_checker/image.rb +22 -0
- data/lib/prism_checker/item_checker/input.rb +27 -0
- data/lib/prism_checker/item_checker/item_check/empty.rb +17 -0
- data/lib/prism_checker/item_checker/item_check/empty_array.rb +17 -0
- data/lib/prism_checker/item_checker/item_check/number.rb +17 -0
- data/lib/prism_checker/item_checker/item_check/regexp.rb +17 -0
- data/lib/prism_checker/item_checker/item_check/string.rb +25 -0
- data/lib/prism_checker/item_checker/item_value/array.rb +13 -0
- data/lib/prism_checker/item_checker/item_value/element.rb +13 -0
- data/lib/prism_checker/item_checker/item_value/elements.rb +13 -0
- data/lib/prism_checker/item_checker/item_value/image.rb +13 -0
- data/lib/prism_checker/item_checker/item_value/input.rb +13 -0
- data/lib/prism_checker/item_checker/item_value/page.rb +13 -0
- data/lib/prism_checker/item_checker/item_value/string.rb +13 -0
- data/lib/prism_checker/item_checker/item_value/textarea.rb +13 -0
- data/lib/prism_checker/item_checker/nil.rb +35 -0
- data/lib/prism_checker/item_checker/page.rb +38 -0
- data/lib/prism_checker/item_checker/string.rb +26 -0
- data/lib/prism_checker/item_checker/textarea.rb +26 -0
- data/lib/prism_checker/item_classifier.rb +126 -0
- data/lib/prism_checker/node/array.rb +26 -0
- data/lib/prism_checker/node/bad_expectation.rb +7 -0
- data/lib/prism_checker/node/base.rb +140 -0
- data/lib/prism_checker/node/check_fail.rb +7 -0
- data/lib/prism_checker/node/expectation.rb +15 -0
- data/lib/prism_checker/node/hash.rb +27 -0
- data/lib/prism_checker/report_builder.rb +78 -0
- data/lib/prism_checker.rb +19 -0
- metadata +261 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PrismChecker
|
4
|
+
module ItemChecker
|
5
|
+
module ItemCheck
|
6
|
+
module Regexp
|
7
|
+
def check(_element, value, expectation)
|
8
|
+
value =~ expectation
|
9
|
+
end
|
10
|
+
|
11
|
+
def error_message(_element, value, expectation)
|
12
|
+
"Expected '#{value}' to match /#{expectation.source}/"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PrismChecker
|
4
|
+
module ItemChecker
|
5
|
+
module ItemCheck
|
6
|
+
module String
|
7
|
+
def check(_element, value, expectation)
|
8
|
+
if PrismChecker.string_comparison == :inclusion
|
9
|
+
value.to_s.include?(expectation)
|
10
|
+
else
|
11
|
+
value == expectation
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def error_message(_element, value, expectation)
|
16
|
+
if PrismChecker.string_comparison == :inclusion
|
17
|
+
"Expected '#{value}' to include '#{expectation}'"
|
18
|
+
else
|
19
|
+
"Expected '#{value}' to be equal '#{expectation}'"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'item_check/string'
|
4
|
+
require_relative 'item_check/regexp'
|
5
|
+
require_relative 'item_value/string'
|
6
|
+
|
7
|
+
module PrismChecker
|
8
|
+
module ItemChecker
|
9
|
+
module Nil
|
10
|
+
class String
|
11
|
+
def self.value(_element); end
|
12
|
+
|
13
|
+
def self.check(_element, _value, _expectation)
|
14
|
+
false
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.error_message(_element, _value, expectation)
|
18
|
+
"Expected '#{expectation}', got nil"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Regexp
|
23
|
+
def self.value(_element); end
|
24
|
+
|
25
|
+
def self.check(_element, _value, _expectation)
|
26
|
+
false
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.error_message(_element, _value, expectation)
|
30
|
+
"Expected '/#{expectation.source}/', got nil"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'item_value/page'
|
4
|
+
require_relative 'item_check/string'
|
5
|
+
require_relative 'item_check/regexp'
|
6
|
+
|
7
|
+
module PrismChecker
|
8
|
+
module ItemChecker
|
9
|
+
module Page
|
10
|
+
class String
|
11
|
+
extend ItemValue::Page
|
12
|
+
extend ItemCheck::String
|
13
|
+
end
|
14
|
+
|
15
|
+
class Empty
|
16
|
+
extend ItemValue::Page
|
17
|
+
extend ItemCheck::Empty
|
18
|
+
end
|
19
|
+
|
20
|
+
class Regexp
|
21
|
+
extend ItemValue::Page
|
22
|
+
extend ItemCheck::Regexp
|
23
|
+
end
|
24
|
+
|
25
|
+
class Loaded
|
26
|
+
def self.value(_element); end
|
27
|
+
|
28
|
+
def self.check(page, _value, _expectation)
|
29
|
+
page.loaded?
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.error_message(_element, _value, _expectation)
|
33
|
+
'Page is not loaded'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'item_check/string'
|
4
|
+
require_relative 'item_check/regexp'
|
5
|
+
require_relative 'item_value/string'
|
6
|
+
|
7
|
+
module PrismChecker
|
8
|
+
module ItemChecker
|
9
|
+
module String
|
10
|
+
class String
|
11
|
+
extend ItemValue::String
|
12
|
+
extend ItemCheck::String
|
13
|
+
end
|
14
|
+
|
15
|
+
class Empty
|
16
|
+
extend ItemValue::String
|
17
|
+
extend ItemCheck::Empty
|
18
|
+
end
|
19
|
+
|
20
|
+
class Regexp
|
21
|
+
extend ItemValue::String
|
22
|
+
extend ItemCheck::Regexp
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'item_value/textarea'
|
4
|
+
require_relative 'item_check/string'
|
5
|
+
require_relative 'item_check/regexp'
|
6
|
+
|
7
|
+
module PrismChecker
|
8
|
+
module ItemChecker
|
9
|
+
module Textarea
|
10
|
+
class String
|
11
|
+
extend ItemValue::Textarea
|
12
|
+
extend ItemCheck::String
|
13
|
+
end
|
14
|
+
|
15
|
+
class Empty
|
16
|
+
extend ItemValue::Textarea
|
17
|
+
extend ItemCheck::Empty
|
18
|
+
end
|
19
|
+
|
20
|
+
class Regexp
|
21
|
+
extend ItemValue::Textarea
|
22
|
+
extend ItemCheck::Regexp
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PrismChecker
|
4
|
+
class ItemClassifier
|
5
|
+
@elements_map = [
|
6
|
+
%i[checkbox element_checkbox?],
|
7
|
+
%i[radio element_radio?],
|
8
|
+
%i[input element_input?],
|
9
|
+
%i[textarea element_textarea?],
|
10
|
+
%i[select element_select?],
|
11
|
+
%i[image element_image?],
|
12
|
+
%i[element element?],
|
13
|
+
%i[elements elements?],
|
14
|
+
%i[section section?],
|
15
|
+
%i[sections sections?],
|
16
|
+
%i[page page?],
|
17
|
+
%i[array array?],
|
18
|
+
%i[string string?],
|
19
|
+
%i[boolean boolean?],
|
20
|
+
%i[nil element_nil?]
|
21
|
+
]
|
22
|
+
|
23
|
+
def self.classify(element)
|
24
|
+
@elements_map.each do |data|
|
25
|
+
type = data[0]
|
26
|
+
probe = data[1]
|
27
|
+
if probe.is_a? Symbol
|
28
|
+
return type if send(probe, element)
|
29
|
+
elsif probe.call(element)
|
30
|
+
return type
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
:other
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.page?(element)
|
38
|
+
element.is_a?(SitePrism::Page)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.section?(element)
|
42
|
+
element.is_a?(SitePrism::Section)
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.sections?(element)
|
46
|
+
element.all?(SitePrism::Section)
|
47
|
+
rescue StandardError
|
48
|
+
false
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.element?(element)
|
52
|
+
element.is_a?(Capybara::Node::Element)
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.elements?(element)
|
56
|
+
element.all?(Capybara::Node::Element)
|
57
|
+
rescue StandardError
|
58
|
+
false
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.array?(element)
|
62
|
+
element.is_a?(::Array)
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.string?(element)
|
66
|
+
element.is_a?(::String)
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.element_image?(element)
|
70
|
+
return false unless element?(element)
|
71
|
+
return false unless element.tag_name == 'img'
|
72
|
+
|
73
|
+
true
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.element_input?(element)
|
77
|
+
return false unless element?(element)
|
78
|
+
return false unless element.tag_name == 'input'
|
79
|
+
|
80
|
+
true
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.element_textarea?(element)
|
84
|
+
return false unless element?(element)
|
85
|
+
return false unless element.tag_name == 'textarea'
|
86
|
+
|
87
|
+
true
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.element_select?(element)
|
91
|
+
return false unless element?(element)
|
92
|
+
return false unless element.tag_name == 'select'
|
93
|
+
|
94
|
+
true
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.element_checkbox?(element)
|
98
|
+
return false unless element?(element)
|
99
|
+
return false unless element['type'] == 'checkbox'
|
100
|
+
|
101
|
+
true
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.element_radio?(element)
|
105
|
+
return false unless element?(element)
|
106
|
+
return false unless element['type'] == 'radio'
|
107
|
+
|
108
|
+
true
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.boolean?(element)
|
112
|
+
return true if element.is_a?(TrueClass)
|
113
|
+
return true if element.is_a?(FalseClass)
|
114
|
+
|
115
|
+
false
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.element_nil?(element)
|
119
|
+
element.nil?
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.add(type, probe, position = 0)
|
123
|
+
@elements_map.insert(position, [type, probe])
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base'
|
4
|
+
module PrismChecker
|
5
|
+
module Node
|
6
|
+
class Array < PrismChecker::Node::Base
|
7
|
+
attr_reader :children
|
8
|
+
|
9
|
+
def initialize(checker, parent, name, expectation)
|
10
|
+
super
|
11
|
+
@children = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_child(idx, child)
|
15
|
+
@children[idx] = child
|
16
|
+
end
|
17
|
+
|
18
|
+
def walk_through(level = 0, &block)
|
19
|
+
yield self, level
|
20
|
+
@children.each do |c|
|
21
|
+
c.walk_through(level + 1, &block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'check_fail'
|
4
|
+
require_relative 'bad_expectation'
|
5
|
+
require_relative '../element_wrapper'
|
6
|
+
require_relative '../absence_expectation'
|
7
|
+
require_relative '../item_classifier'
|
8
|
+
|
9
|
+
module PrismChecker
|
10
|
+
module Node
|
11
|
+
class Base
|
12
|
+
attr_reader :name, :status, :error, :parent, :checker, :expectation
|
13
|
+
|
14
|
+
def initialize(checker, parent, name, expectation)
|
15
|
+
@parent = parent
|
16
|
+
@checker = checker
|
17
|
+
@name = name
|
18
|
+
@expectation = build_expectation(expectation)
|
19
|
+
@element = nil
|
20
|
+
@status = 'Not checked'
|
21
|
+
@error = nil
|
22
|
+
@timeout = Capybara.default_max_wait_time
|
23
|
+
@type = nil
|
24
|
+
@checked_element = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def build_expectation(expectation)
|
28
|
+
if expectation.is_a?(Symbol) && expectation.start_with?('absent')
|
29
|
+
delay = expectation == :absent ? 0 : Integer(expectation.to_s.split('absent').last)
|
30
|
+
|
31
|
+
return AbsenceExpectation.new(delay)
|
32
|
+
end
|
33
|
+
|
34
|
+
expectation
|
35
|
+
rescue ArgumentError
|
36
|
+
expectation
|
37
|
+
end
|
38
|
+
|
39
|
+
def root?
|
40
|
+
parent.is_a?(Checker)
|
41
|
+
end
|
42
|
+
|
43
|
+
def failure?
|
44
|
+
@status == 'Fail' || @status == 'Error'
|
45
|
+
end
|
46
|
+
|
47
|
+
def success?
|
48
|
+
@status == 'Ok'
|
49
|
+
end
|
50
|
+
|
51
|
+
def element
|
52
|
+
return @checked_element if @checked_element
|
53
|
+
|
54
|
+
if root?
|
55
|
+
@checker.item
|
56
|
+
elsif parent.is_a?(Node::Hash)
|
57
|
+
if parent.element.is_a?(Capybara::Node::Element)
|
58
|
+
ElementWrapper.new(parent.element).send(@name)
|
59
|
+
else
|
60
|
+
parent.element.send(@name)
|
61
|
+
end
|
62
|
+
elsif parent.is_a?(Node::Array)
|
63
|
+
parent.element[@name]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def wait_until_true(timeout = @timeout, &block)
|
68
|
+
SitePrism::Waiter.wait_until_true(timeout, &block)
|
69
|
+
rescue SitePrism::TimeoutError
|
70
|
+
false
|
71
|
+
end
|
72
|
+
|
73
|
+
def check_wrapper
|
74
|
+
yield
|
75
|
+
@status = 'Ok'
|
76
|
+
rescue Node::CheckFail => e
|
77
|
+
@error = e
|
78
|
+
@status = 'Fail'
|
79
|
+
raise
|
80
|
+
rescue StandardError => e
|
81
|
+
@error = e
|
82
|
+
@status = 'Error'
|
83
|
+
raise
|
84
|
+
end
|
85
|
+
|
86
|
+
def check_absence
|
87
|
+
sleep expectation.delay
|
88
|
+
|
89
|
+
check_wrapper do
|
90
|
+
result = wait_until_true(0.1) do
|
91
|
+
parent.element.public_send("has_no_#{name}?")
|
92
|
+
end
|
93
|
+
|
94
|
+
raise Node::CheckFail, 'Element is present' unless result
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def path
|
99
|
+
result = []
|
100
|
+
p = self
|
101
|
+
|
102
|
+
while p.is_a? Base
|
103
|
+
result << p.name
|
104
|
+
p = p.parent
|
105
|
+
end
|
106
|
+
|
107
|
+
result.reverse
|
108
|
+
end
|
109
|
+
|
110
|
+
def type(element)
|
111
|
+
@type ||= ItemClassifier.classify(element)
|
112
|
+
end
|
113
|
+
|
114
|
+
def check
|
115
|
+
return check_absence if expectation.is_a?(AbsenceExpectation)
|
116
|
+
|
117
|
+
check_wrapper do
|
118
|
+
element = self.element
|
119
|
+
element_type = type(element)
|
120
|
+
checkers = CheckDispatcher.checkers(self, element, expectation, element_type)
|
121
|
+
value = nil
|
122
|
+
checkers.each do |checker|
|
123
|
+
result = wait_until_true do
|
124
|
+
element = self.element if element.is_a? ::Array
|
125
|
+
|
126
|
+
value = checker.value(element)
|
127
|
+
checker.check(element, value, expectation)
|
128
|
+
end
|
129
|
+
|
130
|
+
unless result
|
131
|
+
raise Node::CheckFail, checker.error_message(element, value, expectation)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
@checked_element = element
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base'
|
4
|
+
require_relative '../item_classifier'
|
5
|
+
require_relative '../check_dispatcher'
|
6
|
+
|
7
|
+
module PrismChecker
|
8
|
+
module Node
|
9
|
+
class Expectation < PrismChecker::Node::Base
|
10
|
+
def walk_through(level = 0)
|
11
|
+
yield self, level
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base'
|
4
|
+
|
5
|
+
module PrismChecker
|
6
|
+
module Node
|
7
|
+
class Hash < PrismChecker::Node::Base
|
8
|
+
attr_reader :children
|
9
|
+
|
10
|
+
def initialize(checker, parent, name, expectation)
|
11
|
+
super
|
12
|
+
@children = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_child(name, child)
|
16
|
+
@children[name] = child
|
17
|
+
end
|
18
|
+
|
19
|
+
def walk_through(level = 0, &block)
|
20
|
+
yield self, level
|
21
|
+
@children.each_value do |child|
|
22
|
+
child.walk_through(level + 1, &block)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|