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.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +28 -0
  3. data/README.md +673 -0
  4. data/lib/prism_checker/absence_expectation.rb +9 -0
  5. data/lib/prism_checker/check_dispatcher.rb +168 -0
  6. data/lib/prism_checker/checker.rb +83 -0
  7. data/lib/prism_checker/colorizer.rb +9 -0
  8. data/lib/prism_checker/config.rb +14 -0
  9. data/lib/prism_checker/element_wrapper.rb +59 -0
  10. data/lib/prism_checker/expectation_classifier.rb +71 -0
  11. data/lib/prism_checker/item_checker/any.rb +25 -0
  12. data/lib/prism_checker/item_checker/array.rb +27 -0
  13. data/lib/prism_checker/item_checker/checkbox.rb +29 -0
  14. data/lib/prism_checker/item_checker/element.rb +52 -0
  15. data/lib/prism_checker/item_checker/elements.rb +53 -0
  16. data/lib/prism_checker/item_checker/image.rb +22 -0
  17. data/lib/prism_checker/item_checker/input.rb +27 -0
  18. data/lib/prism_checker/item_checker/item_check/empty.rb +17 -0
  19. data/lib/prism_checker/item_checker/item_check/empty_array.rb +17 -0
  20. data/lib/prism_checker/item_checker/item_check/number.rb +17 -0
  21. data/lib/prism_checker/item_checker/item_check/regexp.rb +17 -0
  22. data/lib/prism_checker/item_checker/item_check/string.rb +25 -0
  23. data/lib/prism_checker/item_checker/item_value/array.rb +13 -0
  24. data/lib/prism_checker/item_checker/item_value/element.rb +13 -0
  25. data/lib/prism_checker/item_checker/item_value/elements.rb +13 -0
  26. data/lib/prism_checker/item_checker/item_value/image.rb +13 -0
  27. data/lib/prism_checker/item_checker/item_value/input.rb +13 -0
  28. data/lib/prism_checker/item_checker/item_value/page.rb +13 -0
  29. data/lib/prism_checker/item_checker/item_value/string.rb +13 -0
  30. data/lib/prism_checker/item_checker/item_value/textarea.rb +13 -0
  31. data/lib/prism_checker/item_checker/nil.rb +35 -0
  32. data/lib/prism_checker/item_checker/page.rb +38 -0
  33. data/lib/prism_checker/item_checker/string.rb +26 -0
  34. data/lib/prism_checker/item_checker/textarea.rb +26 -0
  35. data/lib/prism_checker/item_classifier.rb +126 -0
  36. data/lib/prism_checker/node/array.rb +26 -0
  37. data/lib/prism_checker/node/bad_expectation.rb +7 -0
  38. data/lib/prism_checker/node/base.rb +140 -0
  39. data/lib/prism_checker/node/check_fail.rb +7 -0
  40. data/lib/prism_checker/node/expectation.rb +15 -0
  41. data/lib/prism_checker/node/hash.rb +27 -0
  42. data/lib/prism_checker/report_builder.rb +78 -0
  43. data/lib/prism_checker.rb +19 -0
  44. metadata +261 -0
@@ -0,0 +1,168 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'item_classifier'
4
+ require_relative 'expectation_classifier'
5
+ require_relative 'item_checker/array'
6
+ require_relative 'item_checker/element'
7
+ require_relative 'item_checker/elements'
8
+ require_relative 'item_checker/image'
9
+ require_relative 'item_checker/input'
10
+ require_relative 'item_checker/checkbox'
11
+ require_relative 'item_checker/any'
12
+ require_relative 'item_checker/page'
13
+ require_relative 'item_checker/string'
14
+ require_relative 'item_checker/textarea'
15
+ require_relative 'item_checker/nil'
16
+ require_relative 'node/bad_expectation'
17
+
18
+ module PrismChecker
19
+ class CheckDispatcher
20
+ @check_map = {
21
+ page: {
22
+ string: [ItemChecker::Page::Loaded, ItemChecker::Page::String],
23
+ regexp: [ItemChecker::Page::Loaded, ItemChecker::Page::Regexp],
24
+ hash: [ItemChecker::Page::Loaded]
25
+ },
26
+
27
+ section: {
28
+ string: [ItemChecker::Element::Visible, ItemChecker::Element::String],
29
+ empty: [ItemChecker::Element::Visible, ItemChecker::Element::Empty],
30
+ regexp: [ItemChecker::Element::Visible, ItemChecker::Element::Regexp],
31
+ hash: [ItemChecker::Element::Visible],
32
+ visible: [ItemChecker::Element::Visible],
33
+ invisible: [ItemChecker::Element::Invisible]
34
+ },
35
+
36
+ sections: {
37
+ string: [ItemChecker::Elements::String],
38
+ regexp: [ItemChecker::Elements::Regexp],
39
+ array: [ItemChecker::Elements::Array],
40
+ number: [ItemChecker::Elements::Number]
41
+ },
42
+
43
+ element: {
44
+ string: [ItemChecker::Element::Visible, ItemChecker::Element::String],
45
+ empty: [ItemChecker::Element::Visible, ItemChecker::Element::Empty],
46
+ regexp: [ItemChecker::Element::Visible, ItemChecker::Element::Regexp],
47
+ hash: [ItemChecker::Element::Visible],
48
+ visible: [ItemChecker::Element::Visible],
49
+ invisible: [ItemChecker::Element::Invisible]
50
+ },
51
+
52
+ elements: {
53
+ string: [ItemChecker::Elements::String],
54
+ empty: [ItemChecker::Elements::Empty],
55
+ regexp: [ItemChecker::Elements::Regexp],
56
+ array: [ItemChecker::Elements::Array],
57
+ number: [ItemChecker::Elements::Number]
58
+ },
59
+
60
+ image: {
61
+ string: [ItemChecker::Element::Visible, ItemChecker::Image::String],
62
+ regexp: [ItemChecker::Element::Visible, ItemChecker::Image::Regexp],
63
+ hash: [ItemChecker::Element::Visible],
64
+ visible: [ItemChecker::Element::Visible],
65
+ invisible: [ItemChecker::Element::Invisible]
66
+ },
67
+
68
+ input: {
69
+ string: [ItemChecker::Element::Visible, ItemChecker::Input::String],
70
+ empty: [ItemChecker::Element::Visible, ItemChecker::Input::Empty],
71
+ regexp: [ItemChecker::Element::Visible, ItemChecker::Input::Regexp],
72
+ hash: [ItemChecker::Element::Visible],
73
+ visible: [ItemChecker::Element::Visible],
74
+ invisible: [ItemChecker::Element::Invisible]
75
+ },
76
+
77
+ textarea: {
78
+ string: [ItemChecker::Element::Visible, ItemChecker::Textarea::String],
79
+ empty: [ItemChecker::Element::Visible, ItemChecker::Textarea::Empty],
80
+ regexp: [ItemChecker::Element::Visible, ItemChecker::Textarea::Regexp],
81
+ hash: [ItemChecker::Element::Visible],
82
+ visible: [ItemChecker::Element::Visible],
83
+ invisible: [ItemChecker::Element::Invisible]
84
+ },
85
+
86
+ select: {
87
+ string: [ItemChecker::Element::Visible, ItemChecker::Input::String],
88
+ empty: [ItemChecker::Element::Visible, ItemChecker::Input::Empty],
89
+ regexp: [ItemChecker::Element::Visible, ItemChecker::Input::Regexp],
90
+ hash: [ItemChecker::Element::Visible],
91
+ visible: [ItemChecker::Element::Visible],
92
+ invisible: [ItemChecker::Element::Invisible]
93
+ },
94
+
95
+ checkbox: {
96
+ hash: [ItemChecker::Element::Visible],
97
+ visible: [ItemChecker::Element::Visible],
98
+ invisible: [ItemChecker::Element::Invisible],
99
+ boolean: [ItemChecker::Element::Visible, ItemChecker::Checkbox::Boolean]
100
+ },
101
+
102
+ radio: {
103
+ string: [ItemChecker::Element::Visible, ItemChecker::Input::String],
104
+ regexp: [ItemChecker::Element::Visible, ItemChecker::Input::Regexp],
105
+ hash: [ItemChecker::Element::Visible],
106
+ visible: [ItemChecker::Element::Visible],
107
+ invisible: [ItemChecker::Element::Invisible],
108
+ boolean: [ItemChecker::Element::Visible, ItemChecker::Checkbox::Boolean]
109
+ },
110
+
111
+ array: {
112
+ string: [ItemChecker::Array::String],
113
+ empty: [ItemChecker::Array::String],
114
+ regexp: [ItemChecker::Array::Regexp],
115
+ number: [ItemChecker::Elements::Number]
116
+ },
117
+
118
+ boolean: {
119
+ boolean: [ItemChecker::Any::Any]
120
+ },
121
+
122
+ number: {
123
+ number: [ItemChecker::Any::Any]
124
+ },
125
+
126
+ string: {
127
+ string: [ItemChecker::String::String],
128
+ empty: [ItemChecker::String::Empty],
129
+ regexp: [ItemChecker::String::Regexp]
130
+ },
131
+
132
+ nil: {
133
+ string: [ItemChecker::Nil::String],
134
+ regexp: [ItemChecker::Nil::Regexp]
135
+ }
136
+ }
137
+
138
+ def self.checkers(_node, element, expectation, item_type)
139
+ expectation_type = ExpectationClassifier.classify(expectation)
140
+
141
+ element_expectations = @check_map[item_type]
142
+
143
+ raise_bad_element(element) unless element_expectations
144
+
145
+ checkers = element_expectations[expectation_type]
146
+
147
+ raise_bad_expectation(element, expectation) unless checkers
148
+
149
+ checkers
150
+ end
151
+
152
+ def self.raise_bad_element(element)
153
+ error = "Don't know how to check #{element.class.name}"
154
+ raise Node::BadExpectation, error
155
+ end
156
+
157
+ def self.raise_bad_expectation(element, expectation)
158
+ element_class = element.class.name || element.class.ancestors.map(&:name).compact.first || '<Unknown>'
159
+ error = "Don't know how to compare #{element_class} with #{expectation.class.name}"
160
+ raise Node::BadExpectation, error
161
+ end
162
+
163
+ def self.add(element_type, check_type, checks)
164
+ @check_map[element_type] ||= {}
165
+ @check_map[element_type][check_type] = checks
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'node/hash'
4
+ require_relative 'node/array'
5
+ require_relative 'node/expectation'
6
+ require_relative 'report_builder'
7
+
8
+ module PrismChecker
9
+ class Checker
10
+ attr_reader :item, :root, :result
11
+
12
+ def initialize
13
+ @item = nil
14
+ @expectation = nil
15
+ @root = nil
16
+ @result = nil
17
+ end
18
+
19
+ def check(item, expectation)
20
+ prepare(item, expectation)
21
+
22
+ walk_through do |node|
23
+ node.check
24
+ end
25
+
26
+ @result = true
27
+ rescue Node::CheckFail
28
+ # puts report
29
+ @result = false
30
+ # rescue Node::BadExpectation => e
31
+ # # raise
32
+ # raise e.class, report + "\n" + e.message
33
+ rescue StandardError => e
34
+ # puts '---------------------'
35
+ # puts e.class
36
+ # puts e.message
37
+ # pp e.backtrace
38
+ # puts '---------------------'
39
+ raise e.class, report + "\n" + e.message
40
+ end
41
+
42
+ def report
43
+ ReportBuilder.new(@root).build
44
+ end
45
+
46
+ private
47
+
48
+ def walk_through(&block)
49
+ @root.walk_through(&block)
50
+ end
51
+
52
+ def build_node(expectation, parent, key)
53
+ klass = case expectation
54
+ when Hash then Node::Hash
55
+ when Array then Node::Array
56
+ else Node::Expectation
57
+ end
58
+
59
+ klass.new(self, parent, key, expectation)
60
+ end
61
+
62
+ def prepare(item, expectation)
63
+ @item = item
64
+ @expectation = expectation
65
+ @root = build_node(expectation, self, :root)
66
+
67
+ build_tree(expectation, @root)
68
+ end
69
+
70
+ def build_tree(expectation, parent)
71
+ enumerator = case expectation
72
+ when Hash then expectation.each_key
73
+ when Array then expectation.each_index
74
+ else return
75
+ end
76
+
77
+ enumerator.each do |key|
78
+ child = parent.add_child(key, build_node(expectation[key], parent, key))
79
+ build_tree(expectation[key], child)
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PrismChecker
4
+ class Colorizer
5
+ def self.colorize(text, _code)
6
+ text
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'colorizer'
4
+
5
+ module PrismChecker
6
+ class Config
7
+ attr_accessor :string_comparison, :colorizer
8
+
9
+ def initialize
10
+ @string_comparison = :inclusion
11
+ @colorizer = PrismChecker::Colorizer
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'prism_checker/item_classifier'
4
+
5
+ module PrismChecker
6
+ class ElementWrapper
7
+ def initialize(element)
8
+ @element = element
9
+ end
10
+
11
+ def class
12
+ @element[:class]
13
+ end
14
+
15
+ def checked
16
+ @element.checked?
17
+ end
18
+
19
+ def disabled
20
+ @element.disabled?
21
+ end
22
+
23
+ def multiple
24
+ @element.multiple?
25
+ end
26
+
27
+ def readonly
28
+ @element.readonly?
29
+ end
30
+
31
+ def selected
32
+ @element.selected?
33
+ end
34
+
35
+ def method_missing(method, *args)
36
+ if @element.respond_to?(method)
37
+ return @element.send(method, *args)
38
+ end
39
+
40
+ # if (ItemClassifier.element_checkbox?(@element) || ItemClassifier.element_radio?(@element)) && method == :checked
41
+ # return @element.checked?
42
+ # end
43
+
44
+ ret = @element[method]
45
+
46
+ if ret.nil? && !method.start_with?('data-')
47
+ # return '' if method.start_with?('data-')
48
+
49
+ raise NoMethodError, "unknown attribute '#{method}'"
50
+ end
51
+
52
+ ret
53
+ end
54
+
55
+ def respond_to_missing?(*_args)
56
+ true
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PrismChecker
4
+ class ExpectationClassifier
5
+ @expectations_map = [
6
+ %i[invisible invisible?],
7
+ %i[visible visible?],
8
+ %i[empty empty?],
9
+ %i[string string?],
10
+ %i[regexp regexp?],
11
+ %i[array array?],
12
+ %i[hash hash?],
13
+ %i[boolean boolean?],
14
+ %i[number number?]
15
+ ]
16
+
17
+ def self.classify(expectation)
18
+ @expectations_map.each do |data|
19
+ type = data[0]
20
+ probe = data[1]
21
+ if probe.is_a? Symbol
22
+ return type if send(probe, expectation)
23
+ elsif probe.call(expectation)
24
+ return type
25
+ end
26
+ end
27
+
28
+ :other
29
+ end
30
+
31
+ def self.invisible?(expectation)
32
+ expectation == :invisible
33
+ end
34
+
35
+ def self.visible?(expectation)
36
+ expectation == :visible
37
+ end
38
+
39
+ def self.empty?(expectation)
40
+ expectation == :empty
41
+ end
42
+
43
+ def self.string?(expectation)
44
+ expectation.is_a?(String)
45
+ end
46
+
47
+ def self.regexp?(expectation)
48
+ expectation.is_a?(Regexp)
49
+ end
50
+
51
+ def self.array?(expectation)
52
+ expectation.is_a?(Array)
53
+ end
54
+
55
+ def self.hash?(expectation)
56
+ expectation.is_a?(Hash)
57
+ end
58
+
59
+ def self.boolean?(expectation)
60
+ expectation.is_a?(TrueClass) || expectation.is_a?(FalseClass)
61
+ end
62
+
63
+ def self.number?(expectation)
64
+ expectation.is_a?(Integer)
65
+ end
66
+
67
+ def self.add(type, probe, position = 0)
68
+ @expectations_map.insert(position, [type, probe])
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'item_check/string'
4
+ require_relative 'item_check/regexp'
5
+ require_relative 'item_value/elements'
6
+
7
+ module PrismChecker
8
+ module ItemChecker
9
+ module Any
10
+ class Any
11
+ def self.value(value)
12
+ value
13
+ end
14
+
15
+ def self.check(_checkbox, value, expectation)
16
+ value == expectation
17
+ end
18
+
19
+ def self.error_message(_checkbox, value, expectation)
20
+ "Expected: #{expectation}\nGot: #{value}"
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'item_check/string'
4
+ require_relative 'item_check/regexp'
5
+ require_relative 'item_check/empty_array'
6
+ require_relative 'item_value/array'
7
+
8
+ module PrismChecker
9
+ module ItemChecker
10
+ module Array
11
+ class String
12
+ extend ItemValue::Array
13
+ extend ItemCheck::String
14
+ end
15
+
16
+ class Empty
17
+ extend ItemValue::Array
18
+ extend ItemCheck::EmptyArray
19
+ end
20
+
21
+ class Regexp
22
+ extend ItemValue::Array
23
+ extend ItemCheck::Regexp
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'item_check/string'
4
+ require_relative 'item_check/regexp'
5
+ require_relative 'item_value/elements'
6
+
7
+ module PrismChecker
8
+ module ItemChecker
9
+ module Checkbox
10
+ class Boolean
11
+ def self.value(checkbox)
12
+ checkbox.checked?
13
+ end
14
+
15
+ def self.check(_checkbox, value, expectation)
16
+ value == expectation
17
+ end
18
+
19
+ def self.error_message(_checkbox, value, expectation)
20
+ if expectation
21
+ 'Expected to be checked'
22
+ else
23
+ 'Expected to be unchecked'
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'item_value/element'
4
+ require_relative 'item_check/regexp'
5
+ require_relative 'item_check/string'
6
+ require_relative 'item_check/empty'
7
+
8
+ module PrismChecker
9
+ module ItemChecker
10
+ module Element
11
+
12
+ class String
13
+ extend ItemValue::Element
14
+ extend ItemCheck::String
15
+ end
16
+
17
+ class Empty
18
+ extend ItemValue::Element
19
+ extend ItemCheck::Empty
20
+ end
21
+
22
+ class Regexp
23
+ extend ItemValue::Element
24
+ extend ItemCheck::Regexp
25
+ end
26
+
27
+ class Visible
28
+ def self.value(_element); end
29
+
30
+ def self.check(element, _value, _expectation)
31
+ element.visible?
32
+ end
33
+
34
+ def self.error_message(_element, _value, _expectation)
35
+ 'Element is not visible'
36
+ end
37
+ end
38
+
39
+ class Invisible
40
+ def self.value(_element); end
41
+
42
+ def self.check(element, _value, _expectation)
43
+ !element.visible?
44
+ end
45
+
46
+ def self.error_message(_element, _value, _expectation)
47
+ 'Element is visible'
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'item_check/string'
4
+ require_relative 'item_check/regexp'
5
+ require_relative 'item_check/number'
6
+ require_relative 'item_check/empty_array'
7
+ require_relative 'item_value/elements'
8
+
9
+ module PrismChecker
10
+ module ItemChecker
11
+ module Elements
12
+ class String
13
+ extend ItemValue::Elements
14
+ extend ItemCheck::String
15
+ end
16
+
17
+ class Regexp
18
+ extend ItemValue::Elements
19
+ extend ItemCheck::Regexp
20
+ end
21
+
22
+ class Array
23
+ def self.value(elements)
24
+ elements
25
+ end
26
+
27
+ def self.check(elements, _value, expectation)
28
+ elements.size == expectation.size
29
+ end
30
+
31
+ def self.error_message(elements, _value, expectation)
32
+ "Wrong elements count\nActual: #{elements.size}\nExpected: #{expectation.size}"
33
+ end
34
+ end
35
+
36
+ class Number
37
+ def self.value(elements)
38
+ elements.size
39
+ end
40
+
41
+ extend ItemCheck::Number
42
+ end
43
+
44
+ class Empty
45
+ def self.value(elements)
46
+ elements
47
+ end
48
+
49
+ extend ItemCheck::EmptyArray
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'item_value/element'
4
+ require_relative 'item_value/image'
5
+ require_relative 'item_check/regexp'
6
+ require_relative 'item_check/string'
7
+
8
+ module PrismChecker
9
+ module ItemChecker
10
+ module Image
11
+ class String
12
+ extend ItemValue::Image
13
+ extend ItemCheck::String
14
+ end
15
+
16
+ class Regexp
17
+ extend ItemValue::Image
18
+ extend ItemCheck::Regexp
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'item_value/input'
4
+ require_relative 'item_check/string'
5
+ require_relative 'item_check/empty'
6
+ require_relative 'item_check/regexp'
7
+
8
+ module PrismChecker
9
+ module ItemChecker
10
+ module Input
11
+ class String
12
+ extend ItemValue::Input
13
+ extend ItemCheck::String
14
+ end
15
+
16
+ class Empty
17
+ extend ItemValue::Input
18
+ extend ItemCheck::Empty
19
+ end
20
+
21
+ class Regexp
22
+ extend ItemValue::Input
23
+ extend ItemCheck::Regexp
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PrismChecker
4
+ module ItemChecker
5
+ module ItemCheck
6
+ module Empty
7
+ def check(_element, value, _expectation)
8
+ value.empty?
9
+ end
10
+
11
+ def error_message(_element, value, _expectation)
12
+ "Expected '#{value}' to be empty"
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PrismChecker
4
+ module ItemChecker
5
+ module ItemCheck
6
+ module EmptyArray
7
+ def check(_element, value, _expectation)
8
+ value.empty?
9
+ end
10
+
11
+ def error_message(_element, _value, _expectation)
12
+ 'Expected to be empty'
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PrismChecker
4
+ module ItemChecker
5
+ module ItemCheck
6
+ module Number
7
+ def check(_elements, value, expectation)
8
+ value == expectation
9
+ end
10
+
11
+ def error_message(_elements, value, expectation)
12
+ "Wrong elements count\nActual: #{value}\nExpected: #{expectation}"
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end