page_magic 2.0.0.alpha1 → 2.0.0
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 +4 -4
- data/.rubocop.yml +5 -2
- data/.zsh_config +5 -5
- data/Dockerfile +2 -1
- data/Gemfile +2 -1
- data/Gemfile.lock +9 -5
- data/Makefile +7 -3
- data/README.md +16 -4
- data/VERSION +1 -1
- data/lib/active_support/core_ext/object/to_query.rb +6 -6
- data/lib/page_magic.rb +15 -16
- data/lib/page_magic/class_methods.rb +1 -1
- data/lib/page_magic/comparator.rb +37 -0
- data/lib/page_magic/comparator/fuzzy.rb +23 -0
- data/lib/page_magic/comparator/literal.rb +22 -0
- data/lib/page_magic/comparator/null.rb +26 -0
- data/lib/page_magic/comparator/parameter_map.rb +52 -0
- data/lib/page_magic/drivers.rb +2 -2
- data/lib/page_magic/element.rb +19 -8
- data/lib/page_magic/element/locators.rb +4 -4
- data/lib/page_magic/element/not_found.rb +38 -0
- data/lib/page_magic/element/query.rb +19 -27
- data/lib/page_magic/element/query/multiple_results.rb +21 -0
- data/lib/page_magic/element/query/prefetched_result.rb +26 -0
- data/lib/page_magic/element/query/single_result.rb +20 -0
- data/lib/page_magic/element/selector.rb +38 -16
- data/lib/page_magic/element/selector/methods.rb +18 -0
- data/lib/page_magic/element/selector/model.rb +21 -0
- data/lib/page_magic/element_context.rb +5 -21
- data/lib/page_magic/element_definition_builder.rb +17 -24
- data/lib/page_magic/elements.rb +62 -102
- data/lib/page_magic/elements/config.rb +103 -0
- data/lib/page_magic/elements/inheritance_hooks.rb +15 -0
- data/lib/page_magic/elements/types.rb +25 -0
- data/lib/page_magic/exceptions.rb +3 -0
- data/lib/page_magic/instance_methods.rb +2 -2
- data/lib/page_magic/mapping.rb +79 -0
- data/lib/page_magic/session.rb +10 -32
- data/lib/page_magic/session_methods.rb +1 -1
- data/lib/page_magic/transitions.rb +49 -0
- data/lib/page_magic/utils/string.rb +4 -0
- data/lib/page_magic/utils/url.rb +20 -0
- data/lib/page_magic/watcher.rb +10 -17
- data/lib/page_magic/watchers.rb +28 -15
- data/spec/page_magic/class_methods_spec.rb +64 -37
- data/spec/page_magic/comparator/fuzzy_spec.rb +44 -0
- data/spec/page_magic/comparator/literal_spec.rb +41 -0
- data/spec/page_magic/comparator/null_spec.rb +35 -0
- data/spec/page_magic/comparator/parameter_map_spec.rb +75 -0
- data/spec/page_magic/driver_spec.rb +25 -29
- data/spec/page_magic/drivers/poltergeist_spec.rb +4 -7
- data/spec/page_magic/drivers/rack_test_spec.rb +4 -9
- data/spec/page_magic/drivers/selenium_spec.rb +9 -12
- data/spec/page_magic/drivers_spec.rb +36 -29
- data/spec/page_magic/element/locators_spec.rb +26 -25
- data/spec/page_magic/element/not_found_spec.rb +24 -0
- data/spec/page_magic/element/query/multiple_results_spec.rb +14 -0
- data/spec/page_magic/element/query/single_result_spec.rb +21 -0
- data/spec/page_magic/element/query_spec.rb +26 -47
- data/spec/page_magic/element/selector_spec.rb +118 -110
- data/spec/page_magic/element_context_spec.rb +46 -88
- data/spec/page_magic/element_definition_builder_spec.rb +12 -71
- data/spec/page_magic/element_spec.rb +256 -0
- data/spec/page_magic/elements/config_spec.rb +200 -0
- data/spec/page_magic/elements_spec.rb +87 -138
- data/spec/page_magic/instance_methods_spec.rb +63 -63
- data/spec/page_magic/mapping_spec.rb +181 -0
- data/spec/page_magic/session_methods_spec.rb +27 -25
- data/spec/page_magic/session_spec.rb +109 -198
- data/spec/page_magic/transitions_spec.rb +43 -0
- data/spec/page_magic/utils/string_spec.rb +20 -27
- data/spec/page_magic/utils/url_spec.rb +9 -0
- data/spec/page_magic/wait_methods_spec.rb +14 -22
- data/spec/page_magic/watcher_spec.rb +22 -0
- data/spec/page_magic/watchers_spec.rb +56 -62
- data/spec/page_magic_spec.rb +27 -24
- data/spec/spec_helper.rb +7 -3
- data/spec/support/shared_examples.rb +15 -17
- metadata +48 -15
- data/lib/page_magic/element/query_builder.rb +0 -61
- data/lib/page_magic/element/selector_methods.rb +0 -16
- data/lib/page_magic/matcher.rb +0 -130
- data/spec/element_spec.rb +0 -251
- data/spec/page_magic/element/query_builder_spec.rb +0 -110
- data/spec/page_magic/matcher_spec.rb +0 -338
- data/spec/support/shared_contexts/files_context.rb +0 -9
- data/spec/support/shared_contexts/nested_elements_html_context.rb +0 -18
- data/spec/support/shared_contexts/rack_application_context.rb +0 -11
- data/spec/support/shared_contexts/webapp_fixture_context.rb +0 -41
- data/spec/watcher_spec.rb +0 -64
@@ -1,35 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
expect(described_class.classify(:Symbol)).to eq('Symbol')
|
11
|
-
end
|
12
|
-
end
|
3
|
+
RSpec.describe PageMagic::Utils::String do
|
4
|
+
describe '.classify' do
|
5
|
+
context 'when parameter is symbol' do
|
6
|
+
it 'returns a string' do
|
7
|
+
expect(described_class.classify(:Symbol)).to eq('Symbol')
|
8
|
+
end
|
9
|
+
end
|
13
10
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
11
|
+
context 'when parameter is string' do
|
12
|
+
it 'returns a string' do
|
13
|
+
expect(described_class.classify(:String)).to eq('String')
|
14
|
+
end
|
15
|
+
end
|
19
16
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
26
|
-
end
|
17
|
+
context 'when the first letter is lower case' do
|
18
|
+
it 'converts the first letter to uppercase' do
|
19
|
+
expect(described_class.classify(:symbol)).to eq('Symbol')
|
20
|
+
end
|
21
|
+
end
|
27
22
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
32
|
-
end
|
23
|
+
context 'when parameter is in snakecase' do
|
24
|
+
it 'removes underscores and capitalises each word' do
|
25
|
+
expect(described_class.classify(:snake_case)).to eq('SnakeCase')
|
33
26
|
end
|
34
27
|
end
|
35
28
|
end
|
@@ -1,42 +1,34 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
subject do
|
6
|
-
Object.new.tap do |o|
|
7
|
-
o.extend(described_class)
|
8
|
-
end
|
9
|
-
end
|
3
|
+
RSpec.describe PageMagic::WaitMethods do
|
4
|
+
include described_class
|
10
5
|
|
6
|
+
describe '#wait_until' do
|
11
7
|
let(:default_options) { { timeout_after: 0.1, retry_every: 0.05 } }
|
8
|
+
let!(:start_time) { Time.now }
|
12
9
|
|
13
10
|
it 'waits until the prescribed thing has happened' do
|
14
|
-
expect {
|
11
|
+
expect { wait_until(**default_options) { true } }.not_to raise_exception
|
15
12
|
end
|
16
13
|
|
17
|
-
it '
|
18
|
-
|
19
|
-
|
20
|
-
expect { subject.wait_until(**default_options) { false } }.to raise_exception TimeoutException
|
21
|
-
|
14
|
+
it 'keeps trying for a specified period' do
|
15
|
+
wait_until(**default_options) { false }
|
16
|
+
rescue PageMagic::TimeoutException
|
22
17
|
expect(Time.now - default_options[:timeout_after]).to be > start_time
|
23
18
|
end
|
24
19
|
|
25
|
-
context 'timeout_after specified' do
|
20
|
+
context 'when `timeout_after` specified' do
|
26
21
|
it 'throws an exception if when the prescribed action does not happen in time' do
|
27
|
-
expect {
|
22
|
+
expect { wait_until(**default_options) { false } }.to raise_error PageMagic::TimeoutException
|
28
23
|
end
|
29
24
|
end
|
30
25
|
|
31
|
-
context 'retry time specified' do
|
26
|
+
context 'when retry time specified' do
|
32
27
|
it 'retries at the given interval' do
|
33
28
|
count = 0
|
34
|
-
expect
|
35
|
-
|
36
|
-
|
37
|
-
end
|
38
|
-
end.to raise_exception TimeoutException
|
39
|
-
expect(count).to eq(2)
|
29
|
+
expect { wait_until(timeout_after: 0.2, retry_every: 0.1) { count += 1 } }
|
30
|
+
.to raise_exception(PageMagic::TimeoutException)
|
31
|
+
.and change { count }.by(2)
|
40
32
|
end
|
41
33
|
end
|
42
34
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe PageMagic::Watcher do
|
4
|
+
describe '#initialize' do
|
5
|
+
context 'when `check` has not been called yet' do
|
6
|
+
it 'sets `observed_value` to nil' do
|
7
|
+
instance = described_class.new(:custom_watcher, context: self)
|
8
|
+
expect(instance.observed_value).to be_nil
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#check' do
|
14
|
+
it 'assigns last to be the result of calling the block passed to the constructor' do
|
15
|
+
instance = described_class.new(:object_id, context: self) do
|
16
|
+
object_id
|
17
|
+
end
|
18
|
+
instance.check
|
19
|
+
expect(instance.observed_value).to eq(object_id)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,86 +1,80 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
require 'ostruct'
|
4
|
+
RSpec.describe PageMagic::Watchers do
|
5
|
+
include described_class
|
6
|
+
let(:element) { OpenStruct.new(text: :current_value) }
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
describe '#changed?' do
|
9
|
+
context 'when the watched element has changed' do
|
10
|
+
it 'returns true' do
|
11
|
+
watch(:element_watcher, context: element, method: :text)
|
12
|
+
element.text = :new_value
|
13
|
+
expect(changed?(:element_watcher)).to eq(true)
|
11
14
|
end
|
12
15
|
end
|
13
16
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
context 'watched element has changed' do
|
20
|
-
it 'returns true' do
|
21
|
-
element.text = :new_value
|
22
|
-
expect(subject.changed?(:my_watcher)).to eq(true)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
context 'watched element has not changed' do
|
27
|
-
it 'returns false' do
|
28
|
-
expect(subject.changed?(:my_watcher)).to eq(false)
|
29
|
-
end
|
17
|
+
context 'when the watched element has not changed' do
|
18
|
+
it 'returns false' do
|
19
|
+
watch(:element_watcher, context: element, method: :text)
|
20
|
+
expect(changed?(:element_watcher)).to eq(false)
|
30
21
|
end
|
31
22
|
end
|
23
|
+
end
|
32
24
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
25
|
+
describe '#watch' do
|
26
|
+
it 'stores the initial value of the watched element' do
|
27
|
+
watch(:element_watcher, context: element, method: :text)
|
28
|
+
expect(watcher(:element_watcher).observed_value).to eq(:current_value)
|
29
|
+
end
|
38
30
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
31
|
+
context 'when a method name is supplied' do
|
32
|
+
it 'stores the watch instruction' do
|
33
|
+
watch(:object_id)
|
34
|
+
watcher = watcher(:object_id)
|
35
|
+
expect(watcher.check.observed_value).to eq(object_id)
|
44
36
|
end
|
37
|
+
end
|
45
38
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
39
|
+
context 'when a watcher name and a method are supplied' do
|
40
|
+
it 'stores the watch instruction' do
|
41
|
+
watch(:my_watcher, method: :object_id)
|
42
|
+
watcher = watcher(:my_watcher)
|
43
|
+
expect(watcher.check.observed_value).to eq(object_id)
|
51
44
|
end
|
45
|
+
end
|
52
46
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
47
|
+
context 'when a block is supplied' do
|
48
|
+
it 'stores the watch instruction' do
|
49
|
+
block = proc { :value }
|
50
|
+
watch(:my_watcher, &block)
|
51
|
+
watcher = watcher(:my_watcher)
|
52
|
+
expect(watcher.check.observed_value).to eq(:value)
|
59
53
|
end
|
54
|
+
end
|
60
55
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
subject.watch(:object_id)
|
66
|
-
expect(subject.watchers.size).to eq(1)
|
67
|
-
expect(subject.watchers.first).to_not be(original_watcher)
|
68
|
-
end
|
56
|
+
context 'when a watcher with the same name is added' do
|
57
|
+
it 'replaces the watcher' do
|
58
|
+
original_watcher = watch(:object_id)
|
59
|
+
expect(watcher(:object_id)).not_to be(original_watcher)
|
69
60
|
end
|
61
|
+
end
|
70
62
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
63
|
+
context 'when a watcher defined on a method that does not exist' do
|
64
|
+
it 'raises an error' do
|
65
|
+
expected_message = described_class::ELEMENT_MISSING_MSG % :text
|
66
|
+
expect do
|
67
|
+
watch(:missing, method: :text)
|
68
|
+
end.to raise_exception(PageMagic::ElementMissingException, expected_message)
|
76
69
|
end
|
77
70
|
end
|
71
|
+
end
|
78
72
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
73
|
+
describe '#watcher' do
|
74
|
+
it 'returns the watcher with the given name' do
|
75
|
+
watch(:my_watcher, method: :object_id)
|
76
|
+
watcher = watcher(:my_watcher)
|
77
|
+
expect(watcher.check.observed_value).to eq(object_id)
|
84
78
|
end
|
85
79
|
end
|
86
80
|
end
|
data/spec/page_magic_spec.rb
CHANGED
@@ -2,9 +2,11 @@
|
|
2
2
|
|
3
3
|
require 'page_magic'
|
4
4
|
|
5
|
-
describe PageMagic do
|
6
|
-
subject do
|
7
|
-
Class.new
|
5
|
+
RSpec.describe PageMagic do
|
6
|
+
subject(:page_class) do
|
7
|
+
Class.new.tap do |klass|
|
8
|
+
klass.include(described_class)
|
9
|
+
end
|
8
10
|
end
|
9
11
|
|
10
12
|
describe '.drivers' do
|
@@ -17,12 +19,12 @@ describe PageMagic do
|
|
17
19
|
|
18
20
|
describe '.included' do
|
19
21
|
it 'gives a method for defining the url' do
|
20
|
-
|
21
|
-
expect(
|
22
|
+
page_class.url :url
|
23
|
+
expect(page_class.url).to eq(:url)
|
22
24
|
end
|
23
25
|
|
24
26
|
it 'lets you define elements' do
|
25
|
-
expect(
|
27
|
+
expect(page_class).to be_a(PageMagic::Elements)
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
@@ -38,12 +40,12 @@ describe PageMagic do
|
|
38
40
|
Class.new(parent_page)
|
39
41
|
end
|
40
42
|
|
41
|
-
|
42
|
-
it '
|
43
|
+
describe 'children' do
|
44
|
+
it 'inherits elements defined on the parent class' do
|
43
45
|
expect(child_page.element_definitions).to include(:next)
|
44
46
|
end
|
45
47
|
|
46
|
-
it '
|
48
|
+
it 'passes on element definitions to their children' do
|
47
49
|
grand_child_class = Class.new(child_page)
|
48
50
|
expect(grand_child_class.element_definitions).to include(:next)
|
49
51
|
end
|
@@ -53,40 +55,41 @@ describe PageMagic do
|
|
53
55
|
describe '#mapping' do
|
54
56
|
it 'returns a matcher' do
|
55
57
|
mapping = described_class.mapping('/', parameters: {}, fragment: '')
|
56
|
-
expect(mapping).to eq(PageMagic::
|
58
|
+
expect(mapping).to eq(PageMagic::Mapping.new('/', parameters: {}, fragment: ''))
|
57
59
|
end
|
58
60
|
end
|
59
61
|
|
60
62
|
describe '.session' do
|
61
|
-
|
63
|
+
let(:rack_application) do
|
64
|
+
Class.new do
|
65
|
+
def self.call(_env)
|
66
|
+
[200, {}, ['hello world!!']]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
62
70
|
|
63
71
|
let(:url) { 'http://url.com/' }
|
64
|
-
let(:application) { rack_application.new }
|
65
|
-
|
66
|
-
before do
|
67
|
-
allow_any_instance_of(Capybara::Selenium::Driver).to receive(:visit)
|
68
|
-
end
|
69
72
|
|
70
73
|
it "defaults to capybara's default session " do
|
71
74
|
Capybara.default_driver = :rack_test
|
72
|
-
expect(
|
75
|
+
expect(page_class.new.browser.mode).to eq(:rack_test)
|
73
76
|
end
|
74
77
|
|
75
|
-
context '
|
78
|
+
context 'when `:browser` is specified' do
|
76
79
|
it 'loads the correct driver' do
|
77
|
-
session = described_class.session(application: rack_application
|
80
|
+
session = described_class.session(application: rack_application, browser: :firefox, url: :url)
|
78
81
|
expect(session.raw_session.driver).to be_a(Capybara::Selenium::Driver)
|
79
82
|
end
|
80
83
|
end
|
81
84
|
|
82
|
-
context '
|
85
|
+
context 'when `:rack_application` is specified' do
|
83
86
|
it 'configures capybara to run against the app' do
|
84
|
-
session = described_class.session(application:
|
85
|
-
expect(session.raw_session.app).to be(
|
87
|
+
session = described_class.session(application: rack_application, url: url)
|
88
|
+
expect(session.raw_session.app).to be(rack_application)
|
86
89
|
end
|
87
90
|
end
|
88
91
|
|
89
|
-
context '
|
92
|
+
context 'when `:options` is specified' do
|
90
93
|
it 'passes the options to the browser driver' do
|
91
94
|
options = { option: :config }
|
92
95
|
session = described_class.session(options: options, browser: :chrome, url: url)
|
@@ -95,7 +98,7 @@ describe PageMagic do
|
|
95
98
|
end
|
96
99
|
end
|
97
100
|
|
98
|
-
context 'driver
|
101
|
+
context 'when the driver assigned to `:browser` is not found' do
|
99
102
|
it 'raises an error' do
|
100
103
|
expected_exception = described_class::UnsupportedBrowserException
|
101
104
|
expect { described_class.session(browser: :invalid, url: url) }.to raise_exception expected_exception
|
data/spec/spec_helper.rb
CHANGED
@@ -1,11 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
|
4
|
-
$LOAD_PATH.unshift("#{
|
2
|
+
|
3
|
+
this_dir = File.dirname(__FILE__)
|
4
|
+
$LOAD_PATH.unshift("#{this_dir}/lib")
|
5
5
|
require 'support/shared_contexts'
|
6
6
|
require 'support/shared_examples'
|
7
7
|
|
8
8
|
require 'simplecov' if ENV['coverage']
|
9
9
|
|
10
10
|
require 'page_magic'
|
11
|
+
|
12
|
+
Dir["#{this_dir}/../lib/page_magic/drivers/*.rb"].sort.each do |driver|
|
13
|
+
require driver
|
14
|
+
end
|
11
15
|
Capybara.server = :webrick
|
@@ -1,27 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
expect(described_class.included_modules).to include(SessionMethods)
|
7
|
-
end
|
3
|
+
RSpec.shared_examples 'session accessor' do
|
4
|
+
it 'includes session methods' do
|
5
|
+
expect(described_class.included_modules).to include(PageMagic::SessionMethods)
|
8
6
|
end
|
7
|
+
end
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
9
|
+
RSpec.shared_examples 'element watcher' do
|
10
|
+
it 'includes watchers' do
|
11
|
+
expect(described_class.included_modules).to include(PageMagic::Watchers)
|
14
12
|
end
|
13
|
+
end
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
15
|
+
RSpec.shared_examples 'waiter' do
|
16
|
+
it 'includes waiters' do
|
17
|
+
expect(described_class.included_modules).to include(PageMagic::WaitMethods)
|
20
18
|
end
|
19
|
+
end
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
21
|
+
RSpec.shared_examples 'element locator' do
|
22
|
+
it 'includes Locators' do
|
23
|
+
expect(described_class.included_modules).to include(PageMagic::Element::Locators)
|
26
24
|
end
|
27
25
|
end
|