dekiru 0.1.10 → 0.2.2
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/.github/workflows/rspec.yml +28 -0
- data/.gitignore +1 -0
- data/README.md +14 -10
- data/dekiru.gemspec +1 -0
- data/lib/dekiru/capybara/helpers/wait_for_position_stable.rb +53 -0
- data/lib/dekiru/capybara/helpers.rb +3 -34
- data/lib/dekiru/capybara/legacy_helpers.rb +40 -0
- data/lib/dekiru/data_migration_operator.rb +18 -7
- data/lib/dekiru/validators/existence.rb +1 -1
- data/lib/dekiru/version.rb +1 -1
- data/lib/generators/maintenance_script/USAGE +8 -0
- data/lib/generators/maintenance_script/maintenance_script_generator.rb +15 -0
- data/lib/generators/maintenance_script/templates/maintenance_script.rb.erb +3 -0
- data/spec/dekiru/data_migration_operator_spec.rb +50 -1
- data/spec/spec_helper.rb +1 -0
- metadata +22 -3
- data/.travis.yml +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0293842d02fc6417c18e53f353a842aec6bb0b41425a00afecae9fb6a11c7848'
|
4
|
+
data.tar.gz: 28f30a08869901b5f0621fba78a8d259bafe8e0c4630925baa5606b604a9840c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fdb142b9f203cb3e47a4b2305a2b67f1b0c649f36710bef29c9cbdf34be4d55cf2c8475f59bc370281e8d7e90a1603d2b2a47bb8ea3adb80c190328f115945ed
|
7
|
+
data.tar.gz: f92cf2b65aacb0da17014580b537cbf9eac9fa190b3f3c5032590cccfc46b01f8bdea6fac453f3015a4899beef9c4bd25a27c72a907006c297bf258353435fcb
|
@@ -0,0 +1,28 @@
|
|
1
|
+
name: Ruby
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [master]
|
6
|
+
pull_request:
|
7
|
+
|
8
|
+
jobs:
|
9
|
+
rspec:
|
10
|
+
runs-on: ubuntu-latest
|
11
|
+
env:
|
12
|
+
BUNDLE_JOBS: 4
|
13
|
+
BUNDLE_RETRY: 3
|
14
|
+
strategy:
|
15
|
+
fail-fast: false
|
16
|
+
matrix:
|
17
|
+
ruby: ["2.6", "2.7", "3.0"]
|
18
|
+
steps:
|
19
|
+
- uses: actions/checkout@v2
|
20
|
+
|
21
|
+
- name: Set up Ruby
|
22
|
+
uses: ruby/setup-ruby@v1
|
23
|
+
with:
|
24
|
+
ruby-version: ${{ matrix.ruby }}
|
25
|
+
bundler-cache: true
|
26
|
+
|
27
|
+
- name: Run rspec
|
28
|
+
run: bundle exec rspec
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -36,16 +36,20 @@ end
|
|
36
36
|
### examples
|
37
37
|
|
38
38
|
```ruby
|
39
|
-
#
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
39
|
+
# アニメーション終了待ちヘルパー(アニメーション中のクリックは失敗することがある)
|
40
|
+
|
41
|
+
# CSSセレクタで指定した要素の位置が動かなくなるまで待つ
|
42
|
+
wait_for_position_stable(:css, '[data-test-id="confirmation-modal"]')
|
43
|
+
click_button 'OK'
|
44
|
+
|
45
|
+
# チェックボックスの位置が0.5秒間停止し続けるまで待つ
|
46
|
+
# タイムアウトは5秒
|
47
|
+
wait_for_position_stable(:checkbox, 'Red', wait: 5, stable_wait: 0.5)
|
48
|
+
check 'Red'
|
49
|
+
|
50
|
+
# findした要素を指定してアニメーション終了待ち
|
51
|
+
element = find('[data-test-id="confirmation-modal"]')
|
52
|
+
wait_for_element_position_stable(element)
|
49
53
|
```
|
50
54
|
|
51
55
|
## Capybara Matchers
|
data/dekiru.gemspec
CHANGED
@@ -0,0 +1,53 @@
|
|
1
|
+
module Dekiru
|
2
|
+
module Capybara
|
3
|
+
module Helpers
|
4
|
+
module WaitForPositionStable
|
5
|
+
class StableTimer
|
6
|
+
def initialize(wait)
|
7
|
+
@wait = wait
|
8
|
+
@stable = false
|
9
|
+
@start_time = nil
|
10
|
+
@prev_obj = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def stable?(obj)
|
14
|
+
if @prev_obj && @prev_obj == obj
|
15
|
+
if @start_time.nil?
|
16
|
+
@start_time = current
|
17
|
+
elsif current - @start_time > @wait
|
18
|
+
return true
|
19
|
+
end
|
20
|
+
else
|
21
|
+
@start_time = nil
|
22
|
+
end
|
23
|
+
@prev_obj = obj
|
24
|
+
false
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def current
|
30
|
+
::Capybara::Helpers.monotonic_time
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def wait_for_element_position_stable(element, wait: ::Capybara.default_max_wait_time, stable_wait: 0.5)
|
35
|
+
stable_timer = StableTimer.new(stable_wait)
|
36
|
+
timer = ::Capybara::Helpers.timer(expire_in: wait)
|
37
|
+
loop do
|
38
|
+
rect = element.rect
|
39
|
+
break if stable_timer.stable?(rect)
|
40
|
+
raise 'Timeout to wait animation finished' if timer.expired?
|
41
|
+
|
42
|
+
sleep 0.1
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def wait_for_position_stable(selector, locator, **options)
|
47
|
+
element = find(selector, locator, **options.except(:stable_wait))
|
48
|
+
wait_for_element_position_stable(element, **options.slice(:wait, :stable_wait))
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -1,40 +1,9 @@
|
|
1
|
+
require 'dekiru/capybara/helpers/wait_for_position_stable'
|
2
|
+
|
1
3
|
module Dekiru
|
2
4
|
module Capybara
|
3
5
|
module Helpers
|
4
|
-
|
5
|
-
|
6
|
-
def wait_for_event(event)
|
7
|
-
page.execute_script(<<~"EOS")
|
8
|
-
(function(){
|
9
|
-
var eventName = '#{event}';
|
10
|
-
window._dekiruCapybaraWaitEvents = window._dekiruCapybaraWaitEvents || {};
|
11
|
-
window._dekiruCapybaraWaitEvents[eventName] = 1;
|
12
|
-
jQuery(document).one(eventName, function(){window._dekiruCapybaraWaitEvents[eventName] = 0;});
|
13
|
-
})();
|
14
|
-
EOS
|
15
|
-
yield
|
16
|
-
|
17
|
-
script = <<~"EOS"
|
18
|
-
(function(){
|
19
|
-
var eventName = '#{event}';
|
20
|
-
return window._dekiruCapybaraWaitEvents && window._dekiruCapybaraWaitEvents[eventName];
|
21
|
-
})();
|
22
|
-
EOS
|
23
|
-
wait_until do
|
24
|
-
result = page.evaluate_script(script)
|
25
|
-
raise Error, 'wait_for_event: Missing context. probably moved to another page.' if result.nil?
|
26
|
-
result == 0
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# https://robots.thoughtbot.com/automatically-wait-for-ajax-with-capybara
|
31
|
-
def wait_for_ajax
|
32
|
-
wait_until { finished_all_ajax_requests? }
|
33
|
-
end
|
34
|
-
|
35
|
-
def finished_all_ajax_requests?
|
36
|
-
page.evaluate_script('jQuery.active').zero?
|
37
|
-
end
|
6
|
+
include WaitForPositionStable
|
38
7
|
|
39
8
|
def wait_until(timeout: ::Capybara.default_max_wait_time, interval: 0.2, **opts, &block)
|
40
9
|
if defined?(Selenium::WebDriver::Wait)
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Dekiru
|
2
|
+
module Capybara
|
3
|
+
module LegacyHelpers
|
4
|
+
class Error < StandardError; end
|
5
|
+
|
6
|
+
def wait_for_event(event)
|
7
|
+
page.execute_script(<<~"EOS")
|
8
|
+
(function(){
|
9
|
+
var eventName = '#{event}';
|
10
|
+
window._dekiruCapybaraWaitEvents = window._dekiruCapybaraWaitEvents || {};
|
11
|
+
window._dekiruCapybaraWaitEvents[eventName] = 1;
|
12
|
+
jQuery(document).one(eventName, function(){window._dekiruCapybaraWaitEvents[eventName] = 0;});
|
13
|
+
})();
|
14
|
+
EOS
|
15
|
+
yield
|
16
|
+
|
17
|
+
script = <<~"EOS"
|
18
|
+
(function(){
|
19
|
+
var eventName = '#{event}';
|
20
|
+
return window._dekiruCapybaraWaitEvents && window._dekiruCapybaraWaitEvents[eventName];
|
21
|
+
})();
|
22
|
+
EOS
|
23
|
+
wait_until do
|
24
|
+
result = page.evaluate_script(script)
|
25
|
+
raise Error, 'wait_for_event: Missing context. probably moved to another page.' if result.nil?
|
26
|
+
result == 0
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# https://robots.thoughtbot.com/automatically-wait-for-ajax-with-capybara
|
31
|
+
def wait_for_ajax
|
32
|
+
wait_until { finished_all_ajax_requests? }
|
33
|
+
end
|
34
|
+
|
35
|
+
def finished_all_ajax_requests?
|
36
|
+
page.evaluate_script('jQuery.active').zero?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -12,6 +12,7 @@ module Dekiru
|
|
12
12
|
@title = title
|
13
13
|
@options = options
|
14
14
|
@stream = @options[:output] || $stdout
|
15
|
+
@without_transaction = @options[:without_transaction] || false
|
15
16
|
@side_effects = Hash.new do |hash, key|
|
16
17
|
hash[key] = Hash.new(0)
|
17
18
|
end
|
@@ -20,13 +21,14 @@ module Dekiru
|
|
20
21
|
def execute(&block)
|
21
22
|
@started_at = Time.current
|
22
23
|
log "Start: #{title} at #{started_at}\n\n"
|
23
|
-
@
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
if @without_transaction
|
25
|
+
run(&block)
|
26
|
+
@result = true
|
27
|
+
else
|
28
|
+
@result = ActiveRecord::Base.transaction(requires_new: true, joinable: false) do
|
29
|
+
run(&block)
|
30
|
+
confirm?("\nAre you sure to commit?")
|
28
31
|
end
|
29
|
-
confirm?("\nAre you sure to commit?")
|
30
32
|
end
|
31
33
|
log "Finished successfully: #{title}" if @result == true
|
32
34
|
rescue => e
|
@@ -46,10 +48,11 @@ module Dekiru
|
|
46
48
|
end
|
47
49
|
|
48
50
|
def find_each_with_progress(target_scope, options = {})
|
51
|
+
total = options.delete(:total)
|
49
52
|
opt = {
|
50
53
|
format: '%a |%b>>%i| %p%% %t',
|
51
54
|
}.merge(options).merge(
|
52
|
-
total: target_scope.count,
|
55
|
+
total: total || target_scope.count,
|
53
56
|
output: stream
|
54
57
|
)
|
55
58
|
pb = ::ProgressBar.create(opt)
|
@@ -117,5 +120,13 @@ module Dekiru
|
|
117
120
|
end
|
118
121
|
end
|
119
122
|
end
|
123
|
+
|
124
|
+
def run(&block)
|
125
|
+
if @options[:warning_side_effects]
|
126
|
+
warning_side_effects(&block)
|
127
|
+
else
|
128
|
+
instance_eval(&block)
|
129
|
+
end
|
130
|
+
end
|
120
131
|
end
|
121
132
|
end
|
@@ -9,7 +9,7 @@ module ActiveModel
|
|
9
9
|
class ExistenceValidator < EachValidator
|
10
10
|
def validate_each(record, attribute, value)
|
11
11
|
unless exists?(record, value)
|
12
|
-
record.errors.add(attribute, :existence, options.except(:in).merge!(value: value))
|
12
|
+
record.errors.add(attribute, :existence, **options.except(:in).merge!(value: value))
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
data/lib/dekiru/version.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
class MaintenanceScriptGenerator < Rails::Generators::NamedBase
|
4
|
+
source_root File.expand_path('templates', __dir__)
|
5
|
+
|
6
|
+
def copy_maintenance_script_file
|
7
|
+
template 'maintenance_script.rb.erb', "scripts/#{filename_date}_#{file_name}.rb"
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def filename_date
|
13
|
+
Time.current.strftime('%Y%m%d')
|
14
|
+
end
|
15
|
+
end
|
@@ -26,7 +26,8 @@ describe Dekiru::DataMigrationOperator do
|
|
26
26
|
end
|
27
27
|
Dekiru::DummyStream.new
|
28
28
|
end
|
29
|
-
let(:
|
29
|
+
let(:without_transaction) { false }
|
30
|
+
let(:operator) { Dekiru::DataMigrationOperator.new('dummy', output: dummy_stream, without_transaction: without_transaction) }
|
30
31
|
|
31
32
|
describe '#execute' do
|
32
33
|
it 'confirm で yes' do
|
@@ -74,6 +75,23 @@ describe Dekiru::DataMigrationOperator do
|
|
74
75
|
expect(operator.stream.out).not_to include('Canceled:')
|
75
76
|
expect(operator.stream.out).to include('Total time:')
|
76
77
|
end
|
78
|
+
|
79
|
+
context 'without_transaction: true のとき' do
|
80
|
+
let(:without_transaction) { true }
|
81
|
+
|
82
|
+
it 'トランザクションがかからないこと' do
|
83
|
+
expect do
|
84
|
+
operator.execute { log 'processing'; sleep 1.0 }
|
85
|
+
end.not_to raise_error
|
86
|
+
|
87
|
+
expect(operator.result).to eq(true)
|
88
|
+
expect(operator.duration).to be_within(0.1).of(1.0)
|
89
|
+
expect(operator.error).to eq(nil)
|
90
|
+
expect(operator.stream.out).not_to include('Are you sure to commit?')
|
91
|
+
expect(operator.stream.out).to include('Finished successfully:')
|
92
|
+
expect(operator.stream.out).to include('Total time:')
|
93
|
+
end
|
94
|
+
end
|
77
95
|
end
|
78
96
|
|
79
97
|
describe '#find_each_with_progress' do
|
@@ -109,5 +127,36 @@ describe Dekiru::DataMigrationOperator do
|
|
109
127
|
expect(operator.stream.out).to include('Finished successfully:')
|
110
128
|
expect(operator.stream.out).to include('Total time:')
|
111
129
|
end
|
130
|
+
|
131
|
+
it 'total をオプションで渡すことができる' do
|
132
|
+
class Dekiru::DummyRecord
|
133
|
+
def self.count
|
134
|
+
raise "won't call"
|
135
|
+
end
|
136
|
+
|
137
|
+
def self.find_each
|
138
|
+
yield 99
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
allow(STDIN).to receive(:gets) do
|
143
|
+
"yes\n"
|
144
|
+
end
|
145
|
+
|
146
|
+
sum = 0
|
147
|
+
operator.execute do
|
148
|
+
find_each_with_progress(Dekiru::DummyRecord, title: 'pass total as option', total: 1) do |num|
|
149
|
+
sum += num
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
expect(sum).to eq(99)
|
154
|
+
expect(operator.result).to eq(true)
|
155
|
+
expect(operator.error).to eq(nil)
|
156
|
+
expect(operator.stream.out).to include('Are you sure to commit?')
|
157
|
+
expect(operator.stream.out).to include('pass total as option:')
|
158
|
+
expect(operator.stream.out).to include('Finished successfully:')
|
159
|
+
expect(operator.stream.out).to include('Total time:')
|
160
|
+
end
|
112
161
|
end
|
113
162
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dekiru
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Akihiro Matsumura
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: http_accept_language
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: 1.19.0
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: byebug
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
111
125
|
description: Usefull helper methods for Ruby on Rails
|
112
126
|
email:
|
113
127
|
- matsumura.aki@gmail.com
|
@@ -115,9 +129,9 @@ executables: []
|
|
115
129
|
extensions: []
|
116
130
|
extra_rdoc_files: []
|
117
131
|
files:
|
132
|
+
- ".github/workflows/rspec.yml"
|
118
133
|
- ".gitignore"
|
119
134
|
- ".ruby-version"
|
120
|
-
- ".travis.yml"
|
121
135
|
- Gemfile
|
122
136
|
- LICENSE
|
123
137
|
- README.md
|
@@ -126,6 +140,8 @@ files:
|
|
126
140
|
- lib/dekiru.rb
|
127
141
|
- lib/dekiru/camelize_hash.rb
|
128
142
|
- lib/dekiru/capybara/helpers.rb
|
143
|
+
- lib/dekiru/capybara/helpers/wait_for_position_stable.rb
|
144
|
+
- lib/dekiru/capybara/legacy_helpers.rb
|
129
145
|
- lib/dekiru/capybara/matchers.rb
|
130
146
|
- lib/dekiru/controller_additions.rb
|
131
147
|
- lib/dekiru/data_migration_operator.rb
|
@@ -138,6 +154,9 @@ files:
|
|
138
154
|
- lib/dekiru/tasks/smtp_check.rake
|
139
155
|
- lib/dekiru/validators/existence.rb
|
140
156
|
- lib/dekiru/version.rb
|
157
|
+
- lib/generators/maintenance_script/USAGE
|
158
|
+
- lib/generators/maintenance_script/maintenance_script_generator.rb
|
159
|
+
- lib/generators/maintenance_script/templates/maintenance_script.rb.erb
|
141
160
|
- spec/dekiru/camelize_hash_spec.rb
|
142
161
|
- spec/dekiru/data_migration_operator_spec.rb
|
143
162
|
- spec/dekiru/helper_spec.rb
|