prism_checker 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|