liveqa 1.4.6

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.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.rspec +1 -0
  4. data/.rubocop.yml +40 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +10 -0
  7. data/CHANGELOG.md +5 -0
  8. data/Gemfile +12 -0
  9. data/README.md +40 -0
  10. data/Rakefile +4 -0
  11. data/lib/liveqa/api_operation/save.rb +57 -0
  12. data/lib/liveqa/api_resource.rb +123 -0
  13. data/lib/liveqa/async_handlers/base.rb +17 -0
  14. data/lib/liveqa/async_handlers/sidekiq.rb +33 -0
  15. data/lib/liveqa/config.rb +116 -0
  16. data/lib/liveqa/errors.rb +41 -0
  17. data/lib/liveqa/event.rb +22 -0
  18. data/lib/liveqa/library_name.rb +3 -0
  19. data/lib/liveqa/liveqa_object.rb +139 -0
  20. data/lib/liveqa/message.rb +50 -0
  21. data/lib/liveqa/plugins/rack/middleware.rb +121 -0
  22. data/lib/liveqa/plugins/rails/middleware_data.rb +44 -0
  23. data/lib/liveqa/plugins/rails/railtie.rb +23 -0
  24. data/lib/liveqa/plugins/sidekiq/client_middleware.rb +19 -0
  25. data/lib/liveqa/plugins/sidekiq/load.rb +14 -0
  26. data/lib/liveqa/plugins/sidekiq/server_middleware.rb +47 -0
  27. data/lib/liveqa/plugins.rb +16 -0
  28. data/lib/liveqa/request.rb +132 -0
  29. data/lib/liveqa/store.rb +49 -0
  30. data/lib/liveqa/util.rb +148 -0
  31. data/lib/liveqa/version.rb +3 -0
  32. data/lib/liveqa.rb +105 -0
  33. data/liveqa.gemspec +26 -0
  34. data/spec/lib/liveqa/async_handlers/base_spec.rb +19 -0
  35. data/spec/lib/liveqa/async_handlers/sidekiq_spec.rb +40 -0
  36. data/spec/lib/liveqa/config_spec.rb +40 -0
  37. data/spec/lib/liveqa/event_spec.rb +36 -0
  38. data/spec/lib/liveqa/liveqa_object_spec.rb +72 -0
  39. data/spec/lib/liveqa/message_spec.rb +101 -0
  40. data/spec/lib/liveqa/plugins/rack/middleware_spec.rb +25 -0
  41. data/spec/lib/liveqa/plugins/rails/middleware_data_spec.rb +67 -0
  42. data/spec/lib/liveqa/plugins/sidekiq/client_middleware_spec.rb +15 -0
  43. data/spec/lib/liveqa/plugins/sidekiq/server_middleware_spec.rb +63 -0
  44. data/spec/lib/liveqa/store_spec.rb +82 -0
  45. data/spec/lib/liveqa/util_spec.rb +123 -0
  46. data/spec/lib/liveqa_spec.rb +78 -0
  47. data/spec/spec_helper.rb +31 -0
  48. data/spec/support/rack_app.rb +12 -0
  49. metadata +176 -0
data/lib/liveqa.rb ADDED
@@ -0,0 +1,105 @@
1
+ # Lib
2
+ require 'securerandom'
3
+ require 'net/http'
4
+ require 'ostruct'
5
+ require 'json'
6
+
7
+ # Async
8
+ require 'liveqa/async_handlers/base'
9
+
10
+ # Base
11
+ require 'liveqa/version'
12
+ require 'liveqa/library_name'
13
+ require 'liveqa/util'
14
+ require 'liveqa/config'
15
+ require 'liveqa/errors'
16
+ require 'liveqa/liveqa_object'
17
+ require 'liveqa/request'
18
+ require 'liveqa/api_resource'
19
+ require 'liveqa/store'
20
+ require 'liveqa/message'
21
+
22
+ # Operations
23
+ require 'liveqa/api_operation/save'
24
+
25
+ # Resources
26
+ require 'liveqa/event'
27
+
28
+ # Plugins
29
+ require 'liveqa/plugins'
30
+
31
+ ##
32
+ # Implementation of the LiveQA
33
+ module LiveQA
34
+ class << self
35
+
36
+ ##
37
+ # @return [LiveQA::Config] configurations
38
+ attr_reader :configurations
39
+
40
+ ##
41
+ # Configures the LiveQA API
42
+ #
43
+ # @example Default configuration
44
+ # LiveQA.configure do |config|
45
+ # config.api_key = 'your-api-key'
46
+ # end
47
+ def configure
48
+ yield @configurations = LiveQA::Config.new
49
+
50
+ LiveQA.configurations.valid!
51
+ end
52
+
53
+ ##
54
+ # Send a track event to the server
55
+ #
56
+ # @param [String] event name
57
+ # @param [String] user id from your database
58
+ # @param [Hash] payload to be send
59
+ # @param [Hash] options for the request
60
+ #
61
+ # @return [LiveQA::Object] response from the server
62
+ def track(name, payload = {}, request_options = {})
63
+ return true unless configurations.enabled
64
+
65
+ payload[:type] = 'track'
66
+ payload[:name] = name
67
+
68
+ payload = Event.build_payload(payload)
69
+
70
+ if configurations.async_handler
71
+ return configurations.async_handler.enqueue('LiveQA::Event', 'create', payload, request_options)
72
+ end
73
+
74
+ event = Event.create(payload, request_options)
75
+
76
+ event.successful?
77
+ end
78
+
79
+ ##
80
+ # Send an identify event to the server
81
+ #
82
+ # @param [String] user id from your database
83
+ # @param [Hash] payload to be send
84
+ # @param [Hash] options for the request
85
+ #
86
+ # @return [LiveQA::Object] response from the server
87
+ def identify(user_id, payload = {}, request_options = {})
88
+ return true unless configurations.enabled
89
+
90
+ payload[:type] = 'identify'
91
+ payload[:user_id] = user_id
92
+
93
+ payload = Event.build_payload(payload)
94
+
95
+ if configurations.async_handler
96
+ return configurations.async_handler.enqueue('LiveQA::Event', 'create', payload, request_options)
97
+ end
98
+
99
+ event = Event.create(payload, request_options)
100
+
101
+ event.successful?
102
+ end
103
+
104
+ end
105
+ end
data/liveqa.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'liveqa/version'
4
+ require 'liveqa/library_name'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = LiveQA::LIBRARY_NAME
8
+ s.version = LiveQA::VERSION
9
+ s.platform = Gem::Platform::RUBY
10
+ s.authors = ['LiveQA']
11
+ s.email = ['support@liveqa.io']
12
+ s.homepage = 'https://github.com/arkes/liveqa-ruby'
13
+ s.summary = 'LiveQA ruby integration'
14
+ s.description = 'LiveQA ruby integration'
15
+
16
+ s.license = 'MIT'
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- spec/*`.split("\n")
20
+
21
+ s.add_development_dependency 'faker', '~> 1.8.4'
22
+ s.add_development_dependency 'rake', '>= 0.9.0'
23
+ s.add_development_dependency 'pry'
24
+ s.add_development_dependency 'rspec', '~> 3.5'
25
+ s.add_development_dependency 'rubocop', '= 0.49.1'
26
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe LiveQA::AsyncHandlers::Base do
4
+ subject(:base) { LiveQA::AsyncHandlers::Base.new }
5
+
6
+ describe '#enqueue' do
7
+ subject(:enqueue) { base.enqueue('Event', 'create', test: true) }
8
+
9
+ it { expect { enqueue }.to raise_error(LiveQA::MissingImplementation) }
10
+ end
11
+
12
+ describe 'execute' do
13
+ let(:params) { ['LiveQA::Event', 'create', { test: true }] }
14
+
15
+ after { base.execute(params) }
16
+
17
+ it { expect(LiveQA::Event).to receive(:create).with({ test: true }, nil) }
18
+ end
19
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+ require 'liveqa/async_handlers/sidekiq'
3
+
4
+ describe LiveQA::AsyncHandlers::Sidekiq do
5
+ let(:params) {{}}
6
+ subject(:sidekiq) { LiveQA::AsyncHandlers::Sidekiq.new(params) }
7
+
8
+ describe '#initialize' do
9
+ it { expect(sidekiq.options['queue']).to eq('liveqa') }
10
+ it { expect(sidekiq.options['class']).to eq(LiveQA::AsyncHandlers::Sidekiq) }
11
+
12
+ context 'with options' do
13
+ let(:params) {{
14
+ queue: 'default'
15
+ }}
16
+
17
+ it { expect(sidekiq.options['queue']).to eq('default') }
18
+ end
19
+ end
20
+
21
+ describe '#enqueue' do
22
+ after { sidekiq.enqueue('Event', 'create', test: true) }
23
+
24
+ let(:expected_params) {{
25
+ 'queue' => 'liveqa',
26
+ 'class' => LiveQA::AsyncHandlers::Sidekiq,
27
+ 'args' => ['Event', 'create', { test: true }]
28
+ }}
29
+
30
+ it { expect(::Sidekiq::Client).to receive(:push).with(expected_params) }
31
+ end
32
+
33
+ describe 'perform' do
34
+ let(:expected_params) { ['LiveQA::Event', 'create', { test: true }] }
35
+
36
+ after { sidekiq.perform(*expected_params) }
37
+
38
+ it { expect(sidekiq).to receive(:execute).with(expected_params) }
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe LiveQA::Config do
4
+ subject(:config) { LiveQA::Config.new(params) }
5
+
6
+ describe '#initialize' do
7
+ let(:params) {{ api_key: SecureRandom.hex }}
8
+
9
+ it { expect(config.valid!).to be_truthy }
10
+
11
+ %i[api_key api_host api_version].each do |field|
12
+ context "validate #{field}" do
13
+ let(:params) {{ api_key: 'api-key', api_host: 'host', api_version: 'v1' }.merge(field => '')}
14
+
15
+ it { expect { config.valid! }.to raise_error(LiveQA::ConfigurationError, "#{field} can't be blank") }
16
+ end
17
+ end
18
+
19
+ context 'format obfuscated_fields' do
20
+ let(:params) {{ api_key: SecureRandom.hex, obfuscated_fields: %i[another_password password_confirmation] }}
21
+
22
+ before { config.valid! }
23
+
24
+ it { expect(config.obfuscated_fields).to match_array(%w[another_password password_confirmation password access_token api_key ccv credit_card_number cvv secret secret_token token]) }
25
+ end
26
+
27
+ context 'async_handler' do
28
+ context 'sidekiq' do
29
+ let(:params) {{
30
+ api_key: SecureRandom.hex,
31
+ async_handler: :sidekiq
32
+ }}
33
+ before { config.valid! }
34
+
35
+ it { expect(config.async_handler).to be_a(LiveQA::AsyncHandlers::Sidekiq) }
36
+ end
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe LiveQA::Event do
4
+
5
+ describe '.build_payload' do
6
+ before { LiveQA::Store.set(:tracker_id, '41') }
7
+
8
+ let(:expected) {{
9
+ library: {
10
+ name: "liveqa",
11
+ language: "ruby",
12
+ version: kind_of(String)
13
+ },
14
+ server: {
15
+ host: kind_of(String),
16
+ pid: kind_of(Numeric)
17
+ },
18
+ message_id: kind_of(String),
19
+ timestamp: kind_of(String),
20
+ tracker_id: '42',
21
+ session_tracker_id: kind_of(String)
22
+ }}
23
+
24
+ it { expect(LiveQA::Event.build_payload(tracker_id: '42')).to match(expected) }
25
+ end
26
+
27
+ describe '.create' do
28
+ let(:response) { double('LiveQA::Request', body: '') }
29
+ before { expect(LiveQA::Request).to receive(:execute).and_return(response) }
30
+
31
+ subject(:create) { LiveQA::Event.create(user_id: 42) }
32
+
33
+ it { is_expected.to be_successful }
34
+ end
35
+
36
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ describe LiveQA::LiveQAObject do
4
+
5
+ let(:klass) { Class.new(LiveQA::LiveQAObject) }
6
+ subject(:instance) { klass.new(id: 42, name: 'test', test: true) }
7
+
8
+ let(:api_response) { '' }
9
+
10
+ describe 'add attribute accessors' do
11
+ it { expect(instance.id).to eq(42) }
12
+ it { expect(instance.name).to eq('test') }
13
+ it { expect(instance.test).to be_truthy }
14
+ it { expect(instance.test?).to be_truthy }
15
+ end
16
+
17
+ describe 'add array attribute' do
18
+ it { expect(instance[:id]).to eq(42) }
19
+ it { expect(instance[:name]).to eq('test') }
20
+ it { expect(instance[:test]).to be_truthy }
21
+ end
22
+
23
+ describe 'set array attribute' do
24
+ before { instance[:id] = 84 }
25
+
26
+ it { expect(instance.id).to eq(84) }
27
+ it { expect(instance[:id]).to eq(84) }
28
+ end
29
+
30
+ describe 'method missing' do
31
+ before { instance.card = '42' }
32
+
33
+ it { expect(instance.card).to eq('42') }
34
+ it { expect { instance.other }.to raise_error(NameError) }
35
+ end
36
+
37
+ describe '#keys' do
38
+ it { expect(instance.keys).to match_array([:id, :name, :test]) }
39
+ end
40
+
41
+ describe '#to_hash' do
42
+ it { expect(instance.to_hash).to eq(id: 42, name: 'test', test: true) }
43
+ end
44
+
45
+ describe '#to_json' do
46
+ it { expect(instance.to_json).to eq(JSON.generate(id: 42, name: 'test', test: true)) }
47
+ end
48
+
49
+ describe '#add_data' do
50
+ before { instance.add_data(:test) }
51
+
52
+ it { expect(instance.data).to match_array([:test]) }
53
+ end
54
+
55
+ describe '#update_attributes' do
56
+ before { instance.update_attributes(id: 84, other: 'other test') }
57
+
58
+ it { expect(instance.id).to eq(84) }
59
+ it { expect(instance.other).to eq('other test') }
60
+ it { expect(instance.name).to eq('test') }
61
+ end
62
+
63
+ describe '.initialize_from' do
64
+ context 'with single object' do
65
+ subject(:instance) { klass.initialize_from(api_response) }
66
+
67
+ it { is_expected.to be_successful }
68
+ end
69
+ end
70
+
71
+
72
+ end
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+
3
+ describe LiveQA::Message do
4
+ subject(:base) { LiveQA::Message }
5
+
6
+ describe '#to_h' do
7
+ let(:expected_hash) {{
8
+ tracker_id: kind_of(String),
9
+ message_id: kind_of(String),
10
+ timestamp: kind_of(String),
11
+ session_tracker_id: kind_of(String),
12
+ library: {
13
+ name: "liveqa",
14
+ language: "ruby",
15
+ version: kind_of(String)
16
+ },
17
+ server: {
18
+ host: kind_of(String),
19
+ pid: kind_of(Numeric)
20
+ }
21
+ }}
22
+
23
+ it { expect(base.to_h).to match(expected_hash) }
24
+
25
+ context 'with store' do
26
+ before do
27
+ LiveQA::Store.set(:tracker_id, 'hello')
28
+ LiveQA::Store.set(:request,
29
+ url: 'http://www.test.com/',
30
+ ssl: true,
31
+ host: 'www.test.com',
32
+ port: 4242,
33
+ path: '/',
34
+ referrer: 'http://www.google.com/',
35
+ method: 'GET',
36
+ xhr: false,
37
+ user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36',
38
+ ip: '127.0.0.1',
39
+ )
40
+ LiveQA::Store.set(:worker,
41
+ name: 'sidekiq',
42
+ version: '5.0.4',
43
+ queue: 'chameleon',
44
+ class: 'LiveQA::AsyncHandlers::Sidekiq',
45
+ id: '106a61579bc0e7e3d18e3b1c',
46
+ created_at: '2017-12-15T03:45:10Z',
47
+ process_at: '2017-12-15T03:45:10Z',
48
+ args: ['LiveQA::Event']
49
+ )
50
+
51
+ LiveQA::Store.bulk_set(
52
+ environement: 'production',
53
+ server_software: 'WEBrick/1.3.1 (Ruby/2.2.7/2017-03-28)'
54
+ )
55
+ end
56
+
57
+ let(:expected_hash) {{
58
+ tracker_id: 'hello',
59
+ message_id: kind_of(String),
60
+ timestamp: kind_of(String),
61
+ session_tracker_id: 'hello',
62
+ library: {
63
+ name: 'liveqa',
64
+ language: 'ruby',
65
+ version: kind_of(String)
66
+ },
67
+ server: {
68
+ host: kind_of(String),
69
+ pid: kind_of(Numeric),
70
+ software: 'WEBrick/1.3.1 (Ruby/2.2.7/2017-03-28)'
71
+ },
72
+ request: {
73
+ url: 'http://www.test.com/',
74
+ ssl: true,
75
+ host: 'www.test.com',
76
+ port: 4242,
77
+ path: '/',
78
+ referrer: 'http://www.google.com/',
79
+ method: 'GET',
80
+ xhr: false,
81
+ user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36',
82
+ ip: '127.0.0.1',
83
+ },
84
+ worker: {
85
+ name: 'sidekiq',
86
+ version: '5.0.4',
87
+ queue: 'chameleon',
88
+ class: 'LiveQA::AsyncHandlers::Sidekiq',
89
+ id: '106a61579bc0e7e3d18e3b1c',
90
+ created_at: '2017-12-15T03:45:10Z',
91
+ process_at: '2017-12-15T03:45:10Z',
92
+ args: ['LiveQA::Event']
93
+ },
94
+ environement: 'production'
95
+ }}
96
+
97
+ it { expect(base.to_h).to match(expected_hash) }
98
+ end
99
+ end
100
+
101
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+ require 'rack'
3
+ require 'liveqa/plugins/rack/middleware'
4
+
5
+ describe LiveQA::Plugins::Rack::Middleware do
6
+
7
+ let(:app) { RackApp.new }
8
+ let(:middleware) { LiveQA::Plugins::Rack::Middleware.new(app) }
9
+
10
+ context 'reset the store' do
11
+ before do
12
+ 2.times { middleware.call({}) }
13
+ end
14
+
15
+ it { expect(app.last_value).to eq(1) }
16
+ it { expect(LiveQA::Store.store).to eq({}) }
17
+ end
18
+
19
+ it 'reset the store with error' do
20
+ expect { middleware.call(error: true) }.to raise_error(RuntimeError)
21
+
22
+ expect(LiveQA::Store.store).to eq({})
23
+ end
24
+
25
+ end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+ require 'rails'
3
+ require 'liveqa/plugins/rails/middleware_data'
4
+
5
+ describe LiveQA::Plugins::Rails::MiddlewareData do
6
+
7
+ let(:middleware) { LiveQA::Plugins::Rails::MiddlewareData }
8
+
9
+ describe '#store_data' do
10
+ let(:request) do
11
+ double('request',
12
+ env: {
13
+ 'action_dispatch.request_id' => '42a'
14
+ }
15
+ )
16
+ end
17
+
18
+ context 'blank store' do
19
+ before { middleware.store_data(request) }
20
+
21
+ let(:expected) {{
22
+ environement: kind_of(String),
23
+ request: {
24
+ id: '42a'
25
+ },
26
+ stack: [
27
+ {
28
+ name: 'rails',
29
+ version: kind_of(String)
30
+ }
31
+ ]
32
+ }}
33
+
34
+ it { expect(LiveQA::Store.store).to match(expected) }
35
+ end
36
+
37
+ context 'update the store' do
38
+ before do
39
+ LiveQA::Store.set(:request, { xhr: false })
40
+ LiveQA::Store.set(:stack, [{ name: 'rack' }])
41
+ end
42
+ before { middleware.store_data(request) }
43
+
44
+ let(:expected) {{
45
+ environement: kind_of(String),
46
+ request: {
47
+ id: '42a',
48
+ xhr: false
49
+ },
50
+ stack: [
51
+ {
52
+ name: 'rack'
53
+ },
54
+ {
55
+ name: 'rails',
56
+ version: kind_of(String)
57
+ }
58
+ ]
59
+ }}
60
+
61
+ it { expect(LiveQA::Store.store).to match(expected) }
62
+ end
63
+
64
+
65
+ end
66
+
67
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+ require 'sidekiq'
3
+ require 'liveqa/plugins/sidekiq/client_middleware'
4
+
5
+ describe LiveQA::Plugins::Sidekiq::ClientMiddleware do
6
+
7
+ let(:middleware) { LiveQA::Plugins::Sidekiq::ClientMiddleware.new }
8
+
9
+ describe '#call' do
10
+ before { LiveQA::Store.set(:tracker_id, 1) }
11
+
12
+ it { expect { middleware.call('MyWorker', {}, 'default', {}) {} }.to_not raise_error }
13
+ end
14
+
15
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+ require 'sidekiq'
3
+ require 'liveqa/plugins/sidekiq/server_middleware'
4
+
5
+ describe LiveQA::Plugins::Sidekiq::ServerMiddleware do
6
+
7
+ let(:middleware) { LiveQA::Plugins::Sidekiq::ServerMiddleware.new }
8
+
9
+ describe '#call' do
10
+ let(:job_attr) {{
11
+ 'class' => 'MyWorker',
12
+ 'args' => ['42'],
13
+ 'retry' => 3,
14
+ 'queue' => 'default',
15
+ 'jid' => '24cc849f71325b62ef470901',
16
+ 'created_at' => 1513299839.2563882,
17
+ 'liveqa_store' => {
18
+ 'tracker_id' => '06a09f70-6219-4860-babc-18aa47a62f7f',
19
+ 'user_agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36',
20
+ 'ip' => '127.0.0.1'
21
+ },
22
+ 'enqueued_at' => 1513300328.8271549,
23
+ 'error_message' => 'exit',
24
+ 'error_class' => 'SystemExit',
25
+ 'failed_at' => 1513300166.646098,
26
+ 'retry_count' => 1,
27
+ 'retried_at' => 1513300238.6037261
28
+ }}
29
+
30
+ context 'expected to be clean at the end' do
31
+ before { middleware.call('MyWorker', job_attr, 'default') {} }
32
+
33
+ it { expect(LiveQA::Store.store).to be_empty }
34
+ end
35
+
36
+ context 'expected to be clean at the end' do
37
+ before { allow(LiveQA::Store).to receive(:clear!).and_return(true) }
38
+ before { middleware.call('MyWorker', job_attr, 'default') {} }
39
+
40
+ let(:expected) {{
41
+ tracker_id: '06a09f70-6219-4860-babc-18aa47a62f7f',
42
+ user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36',
43
+ ip: '127.0.0.1',
44
+ worker: {
45
+ name: 'sidekiq',
46
+ version: kind_of(String),
47
+ queue: 'default',
48
+ class: 'MyWorker',
49
+ id: '24cc849f71325b62ef470901',
50
+ created_at: '2017-12-15T01:03:59Z',
51
+ process_at: '2017-12-15T01:12:08Z',
52
+ args: ['42'],
53
+ retried: true,
54
+ retry_number: 1,
55
+ failed_at: '2017-12-15T01:09:26Z'
56
+ }
57
+ }}
58
+
59
+ it { expect(LiveQA::Store.store).to match(expected) }
60
+ end
61
+ end
62
+
63
+ end