test-recorder 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 745f47568a578d0d76e8558dc16fd6277045cd86dca6a09f38b4914b90e09775
4
- data.tar.gz: 9ec908cb4e136d8137d5304c77594fd0d88e81070ff5b086198035e5cdef1d39
3
+ metadata.gz: e868dca992d2695188debf897102cd76ed6374a25abcb0bbd8875414f9714f9e
4
+ data.tar.gz: ecad80fbed7bc759ef3d30043b1fcdeb15202f3caa3a6e095b29e9d5ccf77e9c
5
5
  SHA512:
6
- metadata.gz: f3962a434f3c98a2dfdd9840cf60205795cc175a18b34d2eb3dd66f6c1ec43603f9b6bd53cc0970811e1cfd6cb54149bdef3db2858173db72769f75a191b750e
7
- data.tar.gz: 97b93c654e9125cf0732c803e49808d4fb6a72402827307708cd52853d21def581843c9d8da877b027206d322cebae31a9efab655f28617212adfc4e299152f2
6
+ metadata.gz: d13e0d7f4fe1056b99f367c08ea89424cfc86780a0d04754425098c7d9c9964f8abb675360a6fafd8c3e8db4fdb0e5f4b9d55890e2376dbf70391a2c3ddfac52
7
+ data.tar.gz: dccb98cfda3cf96ffd888f3cea87cc8cfd9d27631da0ce66408c410fbf1b74fc74c7ea45461c48ffe1c29cca1895d96c7716884189fe4e689ea7175c4dd6e480
@@ -0,0 +1,29 @@
1
+ name: CI
2
+
3
+ on: [push]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+
9
+ concurrency:
10
+ group: ${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+ - uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: '3.0.3'
18
+ - uses: actions/setup-node@v1
19
+ with:
20
+ node-version: '14'
21
+ - name: Install ffmpeg
22
+ run: |
23
+ sudo apt install ffmpeg
24
+ - name: Install dependencies
25
+ run: |
26
+ gem install bundler --no-document
27
+ bundle install
28
+ - name: Run test
29
+ run: bundle exec rake
data/Gemfile.lock CHANGED
@@ -1,67 +1,36 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- test-recorder (0.1.0)
5
- headless
6
- railties
4
+ test-recorder (0.1.1)
5
+ activesupport
6
+ selenium-devtools
7
+ selenium-webdriver (>= 4.0)
7
8
 
8
9
  GEM
9
10
  remote: https://rubygems.org/
10
11
  specs:
11
- actionpack (6.0.3.4)
12
- actionview (= 6.0.3.4)
13
- activesupport (= 6.0.3.4)
14
- rack (~> 2.0, >= 2.0.8)
15
- rack-test (>= 0.6.3)
16
- rails-dom-testing (~> 2.0)
17
- rails-html-sanitizer (~> 1.0, >= 1.2.0)
18
- actionview (6.0.3.4)
19
- activesupport (= 6.0.3.4)
20
- builder (~> 3.1)
21
- erubi (~> 1.4)
22
- rails-dom-testing (~> 2.0)
23
- rails-html-sanitizer (~> 1.1, >= 1.2.0)
24
- activesupport (6.0.3.4)
12
+ activesupport (7.0.0)
25
13
  concurrent-ruby (~> 1.0, >= 1.0.2)
26
- i18n (>= 0.7, < 2)
27
- minitest (~> 5.1)
28
- tzinfo (~> 1.1)
29
- zeitwerk (~> 2.2, >= 2.2.2)
30
- builder (3.2.4)
31
- concurrent-ruby (1.1.7)
32
- crass (1.0.6)
33
- erubi (1.9.0)
34
- headless (2.3.1)
35
- i18n (1.8.5)
14
+ i18n (>= 1.6, < 2)
15
+ minitest (>= 5.1)
16
+ tzinfo (~> 2.0)
17
+ childprocess (4.1.0)
18
+ concurrent-ruby (1.1.9)
19
+ i18n (1.8.11)
36
20
  concurrent-ruby (~> 1.0)
37
- loofah (2.7.0)
38
- crass (~> 1.0.2)
39
- nokogiri (>= 1.5.9)
40
- method_source (1.0.0)
41
- mini_portile2 (2.4.0)
42
21
  minitest (5.14.2)
43
- nokogiri (1.10.10)
44
- mini_portile2 (~> 2.4.0)
45
- rack (2.2.3)
46
- rack-test (1.1.0)
47
- rack (>= 1.0, < 3)
48
- rails-dom-testing (2.0.3)
49
- activesupport (>= 4.2.0)
50
- nokogiri (>= 1.6)
51
- rails-html-sanitizer (1.3.0)
52
- loofah (~> 2.3)
53
- railties (6.0.3.4)
54
- actionpack (= 6.0.3.4)
55
- activesupport (= 6.0.3.4)
56
- method_source
57
- rake (>= 0.8.7)
58
- thor (>= 0.20.3, < 2.0)
59
22
  rake (12.3.3)
60
- thor (1.0.1)
61
- thread_safe (0.3.6)
62
- tzinfo (1.2.7)
63
- thread_safe (~> 0.1)
64
- zeitwerk (2.4.0)
23
+ rexml (3.2.5)
24
+ rubyzip (2.3.2)
25
+ selenium-devtools (0.96.0)
26
+ websocket (~> 1.0)
27
+ selenium-webdriver (4.1.0)
28
+ childprocess (>= 0.5, < 5.0)
29
+ rexml (~> 3.2, >= 3.2.5)
30
+ rubyzip (>= 1.2.2)
31
+ tzinfo (2.0.4)
32
+ concurrent-ruby (~> 1.0)
33
+ websocket (1.2.9)
65
34
 
66
35
  PLATFORMS
67
36
  ruby
@@ -72,4 +41,4 @@ DEPENDENCIES
72
41
  test-recorder!
73
42
 
74
43
  BUNDLED WITH
75
- 2.1.4
44
+ 2.2.32
data/README.md CHANGED
@@ -1,3 +1,49 @@
1
- # Videotest::Recorder
1
+ # TestRecorder
2
2
 
3
- :hammer_and_pick: WIP :hammer_and_pick:
3
+ Record a video automatically when tests failed. The videos are generated in `tmp/videos` directory.
4
+
5
+ ![CI](https://github.com/y-yagi/test-recorder/workflows/CI/badge.svg)
6
+ [![Gem Version](https://badge.fury.io/rb/test-recorder.svg)](http://badge.fury.io/rb/test-recorder)
7
+
8
+
9
+ ## Requirements
10
+
11
+ This gem depends on FFmpeg. Please install that package.
12
+
13
+ On Debian/Ubuntu:
14
+
15
+ ```bash
16
+ sudo apt-get install ffmpeg
17
+ ```
18
+
19
+ ## Supported libraries
20
+
21
+ Rails system tests and RSpec(System Spec and Feature Spec).
22
+
23
+ ## Limitations
24
+
25
+ Currently, this gem only supports a Chrome headless.
26
+
27
+ ## Usage
28
+
29
+ ### 1: Install the gem
30
+
31
+ Using Bundler, add the following to your Gemfile:
32
+
33
+ ```ruby
34
+ gem 'test-recorder', group: :test
35
+ ```
36
+
37
+ ### 2: Load library into your tests
38
+
39
+ #### Rails
40
+
41
+ ```ruby
42
+ require 'test_recorder/rails'
43
+ ```
44
+
45
+ #### RSpec
46
+
47
+ ```ruby
48
+ require 'test_recorder/rspec'
49
+ ```
data/Rakefile CHANGED
@@ -6,7 +6,7 @@ Rake::TestTask.new(:test) do |t|
6
6
  t.libs << "lib"
7
7
  t.verbose = true
8
8
  t.warning = true
9
- t.test_files = FileList["test/**/*_test.rb"]
9
+ t.test_files = ["test/integration_test.rb"]
10
10
  end
11
11
 
12
12
  task :default => :test
@@ -0,0 +1,59 @@
1
+ require "fileutils"
2
+
3
+ module TestRecorder
4
+ class CdpRecorder
5
+ def initialize(enabled:)
6
+ @enabled = enabled
7
+ setup if @enabled
8
+ end
9
+
10
+ def setup
11
+ @video_dir = ::Rails.root.join("tmp", "videos")
12
+ FileUtils.mkdir_p(@video_dir)
13
+ end
14
+
15
+ def start(page:)
16
+ return unless @enabled
17
+
18
+ @tmpdir = Dir.mktmpdir("testrecorder")
19
+ @counter = 1
20
+
21
+ @page = page
22
+ @page.driver.browser.devtools.page.enable
23
+
24
+ @page.driver.browser.devtools.page.on(:screencast_frame) do |event|
25
+ decoded_data = Base64.decode64(event["data"])
26
+ filename = "%010d.jpeg" % @counter
27
+ if Dir.exist?(@tmpdir)
28
+ IO.binwrite("#{File.join(@tmpdir, filename)}", decoded_data)
29
+ @counter += 1
30
+ end
31
+ @page.driver.browser.devtools.page.screencast_frame_ack(session_id: event["sessionId"])
32
+ end
33
+
34
+ @page.driver.browser.devtools.page.start_screencast(format: "jpeg", quality: 90)
35
+ end
36
+
37
+ def stop_and_discard
38
+ FileUtils.rm_rf(@tmpdir)
39
+ end
40
+
41
+ def stop_and_save(filename)
42
+ return if !@enabled || @page.nil?
43
+
44
+ @page.driver.browser.devtools.page.stop_screencast
45
+ video_path = File.join(@video_dir, filename)
46
+
47
+ args = %W(-loglevel error -f image2 -avioflags direct -fpsprobesize 0
48
+ -probesize 32 -analyzeduration 0 -c:v mjpeg -i #{File.join(@tmpdir, "%010d.jpeg")}
49
+ -y -an -r 25 -qmin 0 -qmax 50 -crf 8 -deadline realtime -speed 8 -b:v 1M
50
+ -threads 1 #{video_path})
51
+ system("ffmpeg", *args, exception: true)
52
+ video_path
53
+ rescue => e
54
+ $stderr.puts("[TestRecorder] ffmpeg failed: #{e.message}")
55
+ ensure
56
+ FileUtils.rm_rf(@tmpdir)
57
+ end
58
+ end
59
+ end
@@ -1,30 +1,21 @@
1
- require "headless"
2
1
  require "fileutils"
3
2
 
4
3
  module TestRecorder
5
4
  module Rails
6
5
  module SetupAndTeardown
7
- attr_reader :video_dir, :headless
8
-
9
6
  def before_setup
10
- @video_dir = ::Rails.root.join("tmp", "videos")
11
- FileUtils.mkdir_p(video_dir)
12
-
13
- # TODO: Allow configuring parameters.
14
- @headless = Headless.new(video: { provider: :ffmpeg, codec: :libx264, extra: %w(-preset ultrafast) })
15
- headless.start
16
- headless.video.start_capture
7
+ @cdp_recorder = TestRecorder::CdpRecorder.new(enabled: true)
8
+ @cdp_recorder.start(page: page)
17
9
 
18
10
  super
19
11
  end
20
12
 
21
13
  def before_teardown
22
14
  if failures.empty?
23
- headless.video.stop_and_discard
15
+ @cdp_recorder.stop_and_discard
24
16
  else
25
- video = video_dir.join("failures_#{self.name}.mp4")
26
- headless.video.stop_and_save(video)
27
- puts "[Video]: #{video}"
17
+ video_path = @cdp_recorder.stop_and_save("failures_#{self.name}.mp4")
18
+ puts "[Video]: #{video_path}" if File.exist?(video_path)
28
19
  end
29
20
  ensure
30
21
  super
@@ -1,3 +1,4 @@
1
+ require "test_recorder/cdp_recorder"
1
2
  require "test_recorder/rails/setup_and_teardown"
2
3
 
3
4
  ActiveSupport.on_load(:action_dispatch_system_test_case) do
@@ -0,0 +1,10 @@
1
+ module TestRecorder
2
+ module RSpec
3
+ module ExampleWrapper
4
+ def run_before_example
5
+ super
6
+ TestRecorder::RSpec.cdp_recorder.start(page: @example_group_instance.page)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -1,20 +1,21 @@
1
- require "headless"
2
- require "fileutils"
1
+ require "test_recorder/cdp_recorder"
2
+ require "test_recorder/rspec/example_wrapper"
3
3
 
4
4
  module TestRecorder
5
- module Rspec
5
+ module RSpec
6
6
  CHARS_TO_TRANSLATE = ['/', '.', ':', ',', "'", '"', " "].freeze
7
7
 
8
8
  class << self
9
- attr_accessor :headless, :video_dir
9
+ attr_accessor :cdp_recorder
10
10
 
11
11
  def after_failed_example(example)
12
12
  if example.exception
13
- video = video_dir.join("failures_#{method_name(example)}.mp4")
14
- headless.video.stop_and_save(video)
15
- example.metadata[:extra_failure_lines] = [example.metadata[:extra_failure_lines], "[Video]: #{video}"]
13
+ video_path = cdp_recorder.stop_and_save("failures_#{method_name(example)}.mp4").to_s
14
+ if File.exist?(video_path)
15
+ example.metadata[:extra_failure_lines] = [example.metadata[:extra_failure_lines], "[Video]: #{video_path}"].flatten
16
+ end
16
17
  else
17
- headless.video.stop_and_discard
18
+ cdp_recorder.stop_and_discard
18
19
  end
19
20
  end
20
21
 
@@ -25,21 +26,16 @@ module TestRecorder
25
26
  end
26
27
  end
27
28
 
28
- RSpec.configure do |config|
29
- config.before do
30
- TestRecorder::Rspec.video_dir = ::Rails.root.join("tmp", "videos")
31
- FileUtils.mkdir_p(TestRecorder::Rspec.video_dir)
29
+ RSpec::Core::Example.prepend(TestRecorder::RSpec::ExampleWrapper)
32
30
 
33
- TestRecorder::Rspec.headless = Headless.new(video: { provider: :ffmpeg, codec: :libx264, extra: %w(-preset ultrafast) })
34
- TestRecorder::Rspec.headless.start
35
- TestRecorder::Rspec.headless.video.start_capture
36
- end
31
+ RSpec.configure do |config|
32
+ TestRecorder::RSpec.cdp_recorder = TestRecorder::CdpRecorder.new(enabled: true)
37
33
 
38
34
  config.after(type: :system) do |example|
39
- TestRecorder::Rspec.after_failed_example(example)
35
+ TestRecorder::RSpec.after_failed_example(example)
40
36
  end
41
37
 
42
38
  config.after(type: :feature) do |example|
43
- TestRecorder::Rspec.after_failed_example(example)
39
+ TestRecorder::RSpec.after_failed_example(example)
44
40
  end
45
41
  end
@@ -1,3 +1,3 @@
1
1
  module TestRecorder
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.bindir = "exe"
20
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
21
  spec.require_paths = ["lib"]
22
- spec.add_dependency "headless"
23
- spec.add_dependency "railties"
22
+ spec.add_dependency "activesupport"
23
+ spec.add_dependency "selenium-webdriver", ">= 4.0"
24
+ spec.add_dependency "selenium-devtools"
24
25
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: test-recorder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuji Yaginuma
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-10-23 00:00:00.000000000 Z
11
+ date: 2022-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: headless
14
+ name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
@@ -25,7 +25,21 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: railties
28
+ name: selenium-webdriver
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '4.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '4.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: selenium-devtools
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - ">="
@@ -45,6 +59,7 @@ executables: []
45
59
  extensions: []
46
60
  extra_rdoc_files: []
47
61
  files:
62
+ - ".github/workflows/ci.yml"
48
63
  - ".gitignore"
49
64
  - Gemfile
50
65
  - Gemfile.lock
@@ -55,9 +70,11 @@ files:
55
70
  - bin/setup
56
71
  - lib/test-recorder.rb
57
72
  - lib/test_recorder.rb
73
+ - lib/test_recorder/cdp_recorder.rb
58
74
  - lib/test_recorder/rails.rb
59
75
  - lib/test_recorder/rails/setup_and_teardown.rb
60
76
  - lib/test_recorder/rspec.rb
77
+ - lib/test_recorder/rspec/example_wrapper.rb
61
78
  - lib/test_recorder/version.rb
62
79
  - test-recorder.gemspec
63
80
  homepage: http://github.com/y-yagi/test-recorder
@@ -80,7 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
97
  - !ruby/object:Gem::Version
81
98
  version: '0'
82
99
  requirements: []
83
- rubygems_version: 3.1.2
100
+ rubygems_version: 3.2.32
84
101
  signing_key:
85
102
  specification_version: 4
86
103
  summary: Automatically record videos when tests failed.