test-recorder 0.2.0 → 0.3.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/.github/workflows/ci.yml +25 -12
- data/.github/workflows/push_gem.yml +33 -0
- data/.gitignore +1 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile +1 -1
- data/README.md +17 -0
- data/Rakefile +1 -1
- data/lib/test_recorder/cdp_recorder.rb +80 -30
- data/lib/test_recorder/rails/setup_and_teardown.rb +4 -4
- data/lib/test_recorder/rails.rb +1 -0
- data/lib/test_recorder/rspec.rb +2 -3
- data/lib/test_recorder/version.rb +1 -1
- data/lib/test_recorder.rb +24 -0
- data/test-recorder.gemspec +1 -1
- metadata +5 -9
- data/Gemfile.lock +0 -55
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f76a3cec00d302949375e3ad8d9c4c566f8c52cac703db8384b36505d2be47bb
|
|
4
|
+
data.tar.gz: 109b533201bcde42f210224cf1a01f5b0b795cb1dc5c737d83a80a0b232d67b3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5b4ca4f5087cc0d32cb335f79fdface896ae918493958ff753f36207f93e44b80a0d1af11f9486c8a6cdcad9d2dd2974599cabfac1afaf158e85d51842d5f71c
|
|
7
|
+
data.tar.gz: 52a41a7cc4a35ee019892cea4c67f467bb0e7a9e7f391bba7bfca52a596bda057b2fb92f72c9dc20ef85e700b52985dd049a2bfed6baac874cb3bad8479eb19d
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -3,32 +3,45 @@ name: CI
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
5
5
|
branches:
|
|
6
|
-
-
|
|
6
|
+
- main
|
|
7
7
|
|
|
8
8
|
pull_request:
|
|
9
9
|
|
|
10
|
+
env:
|
|
11
|
+
FFMPEG_BUILD: ffmpeg-n8.1-latest-linux64-gpl-8.1
|
|
12
|
+
|
|
10
13
|
jobs:
|
|
11
14
|
build:
|
|
12
15
|
runs-on: ubuntu-latest
|
|
16
|
+
timeout-minutes: 10
|
|
13
17
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
strategy:
|
|
19
|
+
matrix:
|
|
20
|
+
ruby: [ '4.0', '3.4', '3.3' ]
|
|
17
21
|
|
|
18
22
|
steps:
|
|
19
|
-
- uses: actions/checkout@
|
|
23
|
+
- uses: actions/checkout@v4
|
|
20
24
|
- uses: ruby/setup-ruby@v1
|
|
21
25
|
with:
|
|
22
|
-
ruby-version:
|
|
23
|
-
|
|
26
|
+
ruby-version: ${{ matrix.ruby }}
|
|
27
|
+
bundler-cache: true
|
|
28
|
+
- name: Cache ffmpeg
|
|
29
|
+
id: cache-ffmpeg
|
|
30
|
+
uses: actions/cache@v4
|
|
24
31
|
with:
|
|
25
|
-
|
|
32
|
+
path: ~/.local/bin/ffmpeg
|
|
33
|
+
key: ffmpeg-${{ runner.os }}-${{ env.FFMPEG_BUILD }}
|
|
26
34
|
- name: Install ffmpeg
|
|
35
|
+
if: steps.cache-ffmpeg.outputs.cache-hit != 'true'
|
|
27
36
|
run: |
|
|
28
|
-
|
|
29
|
-
|
|
37
|
+
mkdir -p "$HOME/.local/bin"
|
|
38
|
+
curl -fsSL -o "$RUNNER_TEMP/ffmpeg.tar.xz" \
|
|
39
|
+
"https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/${FFMPEG_BUILD}.tar.xz"
|
|
40
|
+
tar -xJf "$RUNNER_TEMP/ffmpeg.tar.xz" -C "$RUNNER_TEMP" "${FFMPEG_BUILD}/bin/ffmpeg"
|
|
41
|
+
mv "$RUNNER_TEMP/${FFMPEG_BUILD}/bin/ffmpeg" "$HOME/.local/bin/ffmpeg"
|
|
42
|
+
- name: Set up ffmpeg
|
|
30
43
|
run: |
|
|
31
|
-
|
|
32
|
-
|
|
44
|
+
chmod +x "$HOME/.local/bin/ffmpeg"
|
|
45
|
+
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
|
33
46
|
- name: Run test
|
|
34
47
|
run: bundle exec rake
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: Push Gem
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- v*
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
push:
|
|
13
|
+
if: github.repository == 'y-yagi/test-recorder'
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: write
|
|
18
|
+
id-token: write
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- name: Harden Runner
|
|
22
|
+
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
|
|
23
|
+
with:
|
|
24
|
+
egress-policy: audit
|
|
25
|
+
|
|
26
|
+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
27
|
+
- name: Set up Ruby
|
|
28
|
+
uses: ruby/setup-ruby@2e007403fc1ec238429ecaa57af6f22f019cc135 # v1.234.0
|
|
29
|
+
with:
|
|
30
|
+
bundler-cache: true
|
|
31
|
+
ruby-version: ruby
|
|
32
|
+
|
|
33
|
+
- uses: rubygems/release-gem@9e85cb11501bebc2ae661c1500176316d3987059 # v1.1.0
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## Unreleased
|
|
2
|
+
|
|
3
|
+
## 0.3.0 - 2026-08-23
|
|
4
|
+
|
|
5
|
+
* Reduce recording overhead
|
|
6
|
+
* Make recording JPEG quality, max dimension and screencast frame interval configurable
|
|
7
|
+
* Explicitly encode videos with VP8 to avoid relying on ffmpeg's default codec
|
|
8
|
+
* Sanitize characters that can't use for video file names
|
|
9
|
+
* Stop recording a video for a skipped Rails system test
|
|
10
|
+
|
|
1
11
|
## 0.2.0 - 2023-08-23
|
|
2
12
|
|
|
3
13
|
* Add support for aggregate_failures #21 (@willnet)
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -94,4 +94,21 @@ TestRecorder.disable!
|
|
|
94
94
|
it "test to something", test_recorder: true do
|
|
95
95
|
# ...
|
|
96
96
|
end
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Configuration
|
|
100
|
+
|
|
101
|
+
You can change the recording quality and the max width/height (in pixels).
|
|
102
|
+
|
|
103
|
+
```ruby
|
|
104
|
+
TestRecorder.jpeg_quality = 80 # default: 60
|
|
105
|
+
TestRecorder.max_dimension = 1280 # default: 1000
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
You can also record only every Nth frame. This lowers the recording overhead
|
|
109
|
+
at the cost of a choppier video. The playback duration stays the same.
|
|
110
|
+
|
|
111
|
+
```ruby
|
|
112
|
+
TestRecorder.every_nth_frame = 3 # default: 1
|
|
113
|
+
```
|
|
97
114
|
|
data/Rakefile
CHANGED
|
@@ -1,19 +1,49 @@
|
|
|
1
|
-
require "
|
|
1
|
+
require "base64"
|
|
2
2
|
require "fileutils"
|
|
3
3
|
require "tempfile"
|
|
4
4
|
|
|
5
5
|
module TestRecorder
|
|
6
6
|
class CdpRecorder
|
|
7
|
+
FFMPEG_ENCODE_OPTIONS = %w[-y -an -r 25 -c:v vp8 -qmin 0 -qmax 50 -crf 8 -deadline realtime -speed 8 -b:v 1M -threads 1].freeze
|
|
8
|
+
|
|
9
|
+
Record = Struct.new(:page, :io, :frame_count)
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
def record(devtools)
|
|
13
|
+
records[devtools] ||= begin
|
|
14
|
+
page = devtools.page
|
|
15
|
+
page.enable
|
|
16
|
+
|
|
17
|
+
record = Record.new(page, nil, 0)
|
|
18
|
+
page.on(:screencast_frame) do |event|
|
|
19
|
+
write_frame(record, event["data"])
|
|
20
|
+
record.page.screencast_frame_ack(session_id: event["sessionId"])
|
|
21
|
+
end
|
|
22
|
+
record
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def write_frame(record, data)
|
|
29
|
+
return if record.io.nil?
|
|
30
|
+
|
|
31
|
+
record.io.write(Base64.decode64(data))
|
|
32
|
+
record.frame_count += 1
|
|
33
|
+
rescue IOError
|
|
34
|
+
# A frame can still arrive after the recording was stopped and the file was closed.
|
|
35
|
+
rescue => e
|
|
36
|
+
warn "[TestRecorder] Failed to write a screencast frame: #{e.class}: #{e.message}"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def records
|
|
40
|
+
@records ||= {}.compare_by_identity
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
7
44
|
def initialize(enabled:)
|
|
8
45
|
@enabled = enabled
|
|
9
46
|
@started = nil
|
|
10
|
-
@page = nil
|
|
11
|
-
setup
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def setup
|
|
15
|
-
@video_dir = ::Rails.root.join("tmp", "videos")
|
|
16
|
-
FileUtils.mkdir_p(@video_dir)
|
|
17
47
|
end
|
|
18
48
|
|
|
19
49
|
def start(page:, enabled: nil)
|
|
@@ -21,40 +51,60 @@ module TestRecorder
|
|
|
21
51
|
@started = enabled
|
|
22
52
|
return unless @started
|
|
23
53
|
|
|
24
|
-
@tmp_video = Tempfile.
|
|
25
|
-
|
|
26
|
-
@stdin, @wait_thrs = *Open3.pipeline_w(cmd)
|
|
27
|
-
@stdin.set_encoding("ASCII-8BIT")
|
|
54
|
+
@tmp_video = Tempfile.new(["testrecorder", ".mjpeg"])
|
|
55
|
+
@tmp_video.binmode
|
|
28
56
|
|
|
29
|
-
@
|
|
30
|
-
@
|
|
57
|
+
@record = self.class.record(page.driver.browser.devtools)
|
|
58
|
+
@record.io = @tmp_video
|
|
59
|
+
@record.frame_count = 0
|
|
31
60
|
|
|
32
|
-
@
|
|
33
|
-
decoded_data = Base64.decode64(event["data"])
|
|
34
|
-
@stdin.print(decoded_data) rescue nil
|
|
35
|
-
@page.driver.browser.devtools.page.screencast_frame_ack(session_id: event["sessionId"])
|
|
36
|
-
end
|
|
61
|
+
@every_nth_frame = TestRecorder.every_nth_frame
|
|
37
62
|
|
|
38
|
-
@
|
|
63
|
+
@record.page.start_screencast(format: "jpeg", quality: TestRecorder.jpeg_quality, max_width: TestRecorder.max_dimension, max_height: TestRecorder.max_dimension, every_nth_frame: @every_nth_frame)
|
|
39
64
|
end
|
|
40
65
|
|
|
41
66
|
def stop_and_discard
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
67
|
+
return unless @started
|
|
68
|
+
|
|
69
|
+
@record.io = nil
|
|
70
|
+
@record.page.stop_screencast
|
|
71
|
+
@tmp_video.close!
|
|
46
72
|
end
|
|
47
73
|
|
|
48
74
|
def stop_and_save(filename)
|
|
49
75
|
return "" unless @started
|
|
50
76
|
|
|
51
|
-
@
|
|
52
|
-
@
|
|
53
|
-
@
|
|
77
|
+
@record.io = nil
|
|
78
|
+
@record.page.stop_screencast
|
|
79
|
+
@tmp_video.flush
|
|
54
80
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
81
|
+
# Chrome sends a frame as soon as the screencast starts, so a test that fails
|
|
82
|
+
# before it draws anything still leaves behind the one frame of the blank page
|
|
83
|
+
# it started on.
|
|
84
|
+
if @record.frame_count < 2
|
|
85
|
+
@tmp_video.close!
|
|
86
|
+
return ""
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
video_dir = ::Rails.root.join("tmp", "videos")
|
|
90
|
+
FileUtils.mkdir_p(video_dir)
|
|
91
|
+
video_path = video_dir.join(filename).to_s
|
|
92
|
+
|
|
93
|
+
# Chrome captures at about 25 fps, but `every_nth_frame` makes it deliver only
|
|
94
|
+
# one out of every N frames. So the captured file holds 25 / N frames per second.
|
|
95
|
+
# Tell ffmpeg that input rate, otherwise it assumes 25 fps and the video plays
|
|
96
|
+
# N times faster than the actual test.
|
|
97
|
+
result = system("ffmpeg", "-loglevel", "error", "-f", "image2pipe", "-c:v", "mjpeg", "-framerate", "25/#{@every_nth_frame}", "-i", @tmp_video.path, *FFMPEG_ENCODE_OPTIONS, video_path)
|
|
98
|
+
|
|
99
|
+
@tmp_video.close!
|
|
100
|
+
|
|
101
|
+
if result.nil?
|
|
102
|
+
warn "[TestRecorder] Failed to execute ffmpeg. Please make sure that FFmpeg is installed."
|
|
103
|
+
return ""
|
|
104
|
+
elsif !result
|
|
105
|
+
warn "[TestRecorder] ffmpeg failed to encode #{video_path}."
|
|
106
|
+
return ""
|
|
107
|
+
end
|
|
58
108
|
|
|
59
109
|
video_path
|
|
60
110
|
end
|
|
@@ -10,11 +10,11 @@ module TestRecorder
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def before_teardown
|
|
13
|
-
if failures.
|
|
14
|
-
@cdp_recorder.
|
|
15
|
-
else
|
|
16
|
-
video_path = @cdp_recorder.stop_and_save("failures_#{self.name}.webm")
|
|
13
|
+
if failures.any? { |failure| !failure.is_a?(Minitest::Skip) }
|
|
14
|
+
video_path = @cdp_recorder.stop_and_save("failures_#{TestRecorder.sanitize_filename(self.name)}.webm")
|
|
17
15
|
puts "[Video]: #{video_path}" if File.exist?(video_path)
|
|
16
|
+
else
|
|
17
|
+
@cdp_recorder.stop_and_discard
|
|
18
18
|
end
|
|
19
19
|
ensure
|
|
20
20
|
super
|
data/lib/test_recorder/rails.rb
CHANGED
data/lib/test_recorder/rspec.rb
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
+
require "test_recorder"
|
|
1
2
|
require "test_recorder/cdp_recorder"
|
|
2
3
|
require "test_recorder/rspec/example_wrapper"
|
|
3
4
|
|
|
4
5
|
module TestRecorder
|
|
5
6
|
module RSpec
|
|
6
|
-
CHARS_TO_TRANSLATE = ['/', '.', ':', ',', "'", '"', " "].freeze
|
|
7
|
-
|
|
8
7
|
class << self
|
|
9
8
|
attr_accessor :cdp_recorder
|
|
10
9
|
|
|
@@ -20,7 +19,7 @@ module TestRecorder
|
|
|
20
19
|
end
|
|
21
20
|
|
|
22
21
|
def method_name(example)
|
|
23
|
-
example.description.underscore
|
|
22
|
+
TestRecorder.sanitize_filename(example.description.underscore)[0...200] + "_#{rand(1000)}"
|
|
24
23
|
end
|
|
25
24
|
|
|
26
25
|
def passed?(example)
|
data/lib/test_recorder.rb
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
require "test_recorder/version"
|
|
2
2
|
|
|
3
3
|
module TestRecorder
|
|
4
|
+
DEFAULT_JPEG_QUALITY = 60
|
|
5
|
+
DEFAULT_MAX_DIMENSION = 1000
|
|
6
|
+
DEFAULT_EVERY_NTH_FRAME = 1
|
|
7
|
+
|
|
8
|
+
CHARS_TO_TRANSLATE = ['/', '.', ':', ',', "'", '"', " "].freeze
|
|
9
|
+
|
|
4
10
|
class << self
|
|
11
|
+
attr_writer :jpeg_quality, :max_dimension, :every_nth_frame
|
|
12
|
+
|
|
5
13
|
def enable!
|
|
6
14
|
@enable = true
|
|
7
15
|
end
|
|
@@ -13,5 +21,21 @@ module TestRecorder
|
|
|
13
21
|
def enabled?
|
|
14
22
|
defined?(@enable) ? @enable : true
|
|
15
23
|
end
|
|
24
|
+
|
|
25
|
+
def jpeg_quality
|
|
26
|
+
defined?(@jpeg_quality) ? @jpeg_quality : DEFAULT_JPEG_QUALITY
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def max_dimension
|
|
30
|
+
defined?(@max_dimension) ? @max_dimension : DEFAULT_MAX_DIMENSION
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def every_nth_frame
|
|
34
|
+
defined?(@every_nth_frame) ? @every_nth_frame : DEFAULT_EVERY_NTH_FRAME
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def sanitize_filename(name)
|
|
38
|
+
name.tr(CHARS_TO_TRANSLATE.join, "_")
|
|
39
|
+
end
|
|
16
40
|
end
|
|
17
41
|
end
|
data/test-recorder.gemspec
CHANGED
|
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
|
9
9
|
spec.summary = %q{Automatically record videos when tests failed.}
|
|
10
10
|
spec.homepage = "http://github.com/y-yagi/test-recorder"
|
|
11
11
|
spec.license = "MIT"
|
|
12
|
-
spec.required_ruby_version = Gem::Requirement.new(">= 2.
|
|
12
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
|
|
13
13
|
|
|
14
14
|
spec.metadata["homepage_uri"] = spec.homepage
|
|
15
15
|
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: test-recorder
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yuji Yaginuma
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: activesupport
|
|
@@ -66,7 +65,6 @@ dependencies:
|
|
|
66
65
|
- - ">="
|
|
67
66
|
- !ruby/object:Gem::Version
|
|
68
67
|
version: '0'
|
|
69
|
-
description:
|
|
70
68
|
email:
|
|
71
69
|
- yuuji.yaginuma@gmail.com
|
|
72
70
|
executables: []
|
|
@@ -74,10 +72,10 @@ extensions: []
|
|
|
74
72
|
extra_rdoc_files: []
|
|
75
73
|
files:
|
|
76
74
|
- ".github/workflows/ci.yml"
|
|
75
|
+
- ".github/workflows/push_gem.yml"
|
|
77
76
|
- ".gitignore"
|
|
78
77
|
- CHANGELOG.md
|
|
79
78
|
- Gemfile
|
|
80
|
-
- Gemfile.lock
|
|
81
79
|
- LICENSE.txt
|
|
82
80
|
- README.md
|
|
83
81
|
- Rakefile
|
|
@@ -97,7 +95,6 @@ licenses:
|
|
|
97
95
|
- MIT
|
|
98
96
|
metadata:
|
|
99
97
|
homepage_uri: http://github.com/y-yagi/test-recorder
|
|
100
|
-
post_install_message:
|
|
101
98
|
rdoc_options: []
|
|
102
99
|
require_paths:
|
|
103
100
|
- lib
|
|
@@ -105,15 +102,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
105
102
|
requirements:
|
|
106
103
|
- - ">="
|
|
107
104
|
- !ruby/object:Gem::Version
|
|
108
|
-
version: 2.
|
|
105
|
+
version: 2.7.0
|
|
109
106
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
107
|
requirements:
|
|
111
108
|
- - ">="
|
|
112
109
|
- !ruby/object:Gem::Version
|
|
113
110
|
version: '0'
|
|
114
111
|
requirements: []
|
|
115
|
-
rubygems_version: 3.
|
|
116
|
-
signing_key:
|
|
112
|
+
rubygems_version: 3.6.7
|
|
117
113
|
specification_version: 4
|
|
118
114
|
summary: Automatically record videos when tests failed.
|
|
119
115
|
test_files: []
|
data/Gemfile.lock
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
PATH
|
|
2
|
-
remote: .
|
|
3
|
-
specs:
|
|
4
|
-
test-recorder (0.2.0)
|
|
5
|
-
activesupport
|
|
6
|
-
selenium-devtools
|
|
7
|
-
selenium-webdriver (>= 4.0)
|
|
8
|
-
|
|
9
|
-
GEM
|
|
10
|
-
remote: https://rubygems.org/
|
|
11
|
-
specs:
|
|
12
|
-
activesupport (7.0.7)
|
|
13
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
14
|
-
i18n (>= 1.6, < 2)
|
|
15
|
-
minitest (>= 5.1)
|
|
16
|
-
tzinfo (~> 2.0)
|
|
17
|
-
activesupport-testing-metadata (0.1.0)
|
|
18
|
-
activesupport (>= 4.0)
|
|
19
|
-
concurrent-ruby (1.2.2)
|
|
20
|
-
debug (1.8.0)
|
|
21
|
-
irb (>= 1.5.0)
|
|
22
|
-
reline (>= 0.3.1)
|
|
23
|
-
i18n (1.14.1)
|
|
24
|
-
concurrent-ruby (~> 1.0)
|
|
25
|
-
io-console (0.6.0)
|
|
26
|
-
irb (1.7.4)
|
|
27
|
-
reline (>= 0.3.6)
|
|
28
|
-
minitest (5.19.0)
|
|
29
|
-
rake (12.3.3)
|
|
30
|
-
reline (0.3.8)
|
|
31
|
-
io-console (~> 0.5)
|
|
32
|
-
rexml (3.2.6)
|
|
33
|
-
rubyzip (2.3.2)
|
|
34
|
-
selenium-devtools (0.115.0)
|
|
35
|
-
selenium-webdriver (~> 4.2)
|
|
36
|
-
selenium-webdriver (4.11.0)
|
|
37
|
-
rexml (~> 3.2, >= 3.2.5)
|
|
38
|
-
rubyzip (>= 1.2.2, < 3.0)
|
|
39
|
-
websocket (~> 1.0)
|
|
40
|
-
tzinfo (2.0.6)
|
|
41
|
-
concurrent-ruby (~> 1.0)
|
|
42
|
-
websocket (1.2.9)
|
|
43
|
-
|
|
44
|
-
PLATFORMS
|
|
45
|
-
ruby
|
|
46
|
-
|
|
47
|
-
DEPENDENCIES
|
|
48
|
-
activesupport-testing-metadata
|
|
49
|
-
debug
|
|
50
|
-
minitest (~> 5.0)
|
|
51
|
-
rake (~> 12.0)
|
|
52
|
-
test-recorder!
|
|
53
|
-
|
|
54
|
-
BUNDLED WITH
|
|
55
|
-
2.4.3
|