prism_checker 0.0.1

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