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