blinka-reporter 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/blinka_client.rb DELETED
@@ -1,195 +0,0 @@
1
- require 'httparty'
2
-
3
- class BlinkaClient
4
- DEFAULT_HOST = 'https://www.blinka.app'.freeze
5
- SUPPORTED_MIME_TYPES = {
6
- jpg: 'image/jpeg',
7
- jpeg: 'image/jpeg',
8
- png: 'image/png'
9
- }
10
-
11
- include HTTParty
12
-
13
- class BlinkaConfig
14
- attr_reader(:host, :repository, :team_id, :team_secret, :jwt_token)
15
-
16
- def initialize
17
- @host = ENV.fetch('BLINKA_HOST', DEFAULT_HOST)
18
- @team_id = ENV.fetch('BLINKA_TEAM_ID', nil)
19
- @team_secret = ENV.fetch('BLINKA_TEAM_SECRET', nil)
20
- @repository = ENV.fetch('BLINKA_REPOSITORY', nil)
21
-
22
- if @team_id.nil? || @team_secret.nil? || @repository.nil?
23
- raise(BlinkaError, <<~EOS)
24
- Missing configuration, make sure to set required environment variables:
25
- - BLINKA_TEAM_ID
26
- - BLINKA_TEAM_SECRET
27
- - BLINKA_REPOSITORY
28
- EOS
29
- end
30
- end
31
- end
32
-
33
- class BlinkaError < StandardError; end
34
-
35
- def initialize
36
- @config = BlinkaConfig.new
37
- self.class.base_uri("#{@config.host}/api/v1")
38
- end
39
-
40
- def report(filepath: './blinka_results.json')
41
- unless File.exist?(filepath)
42
- raise(
43
- BlinkaError,
44
- 'Could not find blinka_results.json, did tests run with environment variable BLINKA_JSON=true set?'
45
- )
46
- end
47
-
48
- if ENV.fetch('BLINKA_ALLOW_WEBMOCK_DISABLE', 'true') == 'true' &&
49
- defined?(WebMock) && WebMock.respond_to?(:disable!)
50
- WebMock.disable!
51
- end
52
-
53
- self.authenticate
54
- data = JSON.parse(File.open(filepath).read)
55
-
56
- results =
57
- data
58
- .fetch('results', [])
59
- .map do |result|
60
- if result.key?('image')
61
- result['image'] =
62
- BlinkaClient.upload_image(filepath: result['image'])
63
- result
64
- else
65
- result
66
- end
67
- end
68
-
69
- body = {
70
- report: {
71
- repository: @config.repository,
72
- tag: data['tag'],
73
- commit: data['commit'],
74
- metadata: {
75
- total_time: data['total_time'],
76
- nbr_tests: data['nbr_tests'],
77
- nbr_assertions: data['nbr_assertions'],
78
- seed: data['seed']
79
- }.compact,
80
- results: results
81
- }
82
- }
83
-
84
- response =
85
- self.class.post(
86
- '/report',
87
- body: body.to_json,
88
- headers: {
89
- 'Content-Type' => 'application/json',
90
- 'Authorization' => "Bearer #{@jwt_token}"
91
- }
92
- )
93
- case response.code
94
- when 200
95
- puts "Reported #{data['nbr_tests']} tests of commit #{data['commit']}!"
96
- else
97
- raise(BlinkaError, "Could not report, got response code #{response.code}")
98
- end
99
- rescue => error
100
- raise(BlinkaError, <<-EOS)
101
- BLINKA:
102
- Failed to create report because of #{error.class} with message:
103
- #{error.message}
104
- EOS
105
- ensure
106
- WebMock.enable! if defined?(WebMock) && WebMock.respond_to?(:enable!)
107
- end
108
-
109
- def self.report(filepath: './blinka_results.json')
110
- client = BlinkaClient.new
111
- client.report(filepath: filepath)
112
- end
113
-
114
- def self.upload_image(filepath:)
115
- return unless File.exist?(filepath)
116
-
117
- file = File.open(filepath)
118
- filename = File.basename(filepath)
119
- extension = File.extname(filepath).delete('.').to_sym
120
- content_type = SUPPORTED_MIME_TYPES[extension]
121
- return if content_type.nil?
122
-
123
- presigned_post =
124
- BlinkaClient.presign_image(filename: filename, content_type: content_type)
125
- BlinkaClient.upload_to_storage(presigned_post: presigned_post, file: file)
126
-
127
- puts "Uploaded: #{filename}"
128
- BlinkaClient.to_shrine_object(
129
- presigned_post: presigned_post,
130
- file: file,
131
- filename: filename
132
- )
133
- end
134
-
135
- def authenticate
136
- response =
137
- self.class.post(
138
- '/authentication',
139
- body: {
140
- token_id: @config.team_id,
141
- token_secret: @config.team_secret
142
- }.to_json,
143
- headers: { 'Content-Type' => 'application/json' }
144
- )
145
- case response.code
146
- when 200
147
- @jwt_token = JSON.parse(response.body).dig('auth_token')
148
- else
149
- raise(BlinkaError, 'Could not authenticate to API')
150
- end
151
- end
152
-
153
- def self.presign_image(filename:, content_type:)
154
- response =
155
- self.get(
156
- '/presign',
157
- body: { filename: filename, content_type: content_type }
158
- )
159
-
160
- case response.code
161
- when 200
162
- JSON.parse(response.body)
163
- else
164
- raise(BlinkaError, 'Could not presign file')
165
- end
166
- end
167
-
168
- def self.upload_to_storage(presigned_post:, file:)
169
- url = URI.parse(presigned_post.fetch('url'))
170
- fields = presigned_post.fetch('fields')
171
-
172
- body = presigned_post['fields'].merge({ 'file' => file.read })
173
- response = HTTParty.post(url, multipart: true, body: body)
174
-
175
- case response.code
176
- when 204
177
- true
178
- else
179
- raise(BlinkaError, 'Could not upload file to storage')
180
- end
181
- end
182
-
183
- def self.to_shrine_object(presigned_post:, file:, filename:)
184
- storage, idx = presigned_post.dig('fields', 'key').split('/')
185
- {
186
- "id": idx,
187
- "storage": storage,
188
- "metadata": {
189
- "size": file.size,
190
- "filename": filename,
191
- "mime_type": presigned_post.dig('fields', 'Content-Type')
192
- }
193
- }
194
- end
195
- end
@@ -1,90 +0,0 @@
1
- class BlinkaMinitest
2
- def initialize(test_result)
3
- @test_result = test_result
4
- end
5
-
6
- def path
7
- @path ||= source_location.first.gsub(Dir.getwd, '').delete_prefix('/')
8
- end
9
-
10
- def line
11
- @line ||= source_location.last
12
- end
13
-
14
- # Handle broken API in Minitest between 5.10 and 5.11
15
- # https://github.com/minitest-reporters/minitest-reporters/blob/e9092460b5a5cf5ca9eb375428217cbb2a7f6dbb/lib/minitest/reporters/default_reporter.rb#L159
16
- def source_location
17
- @source_location ||=
18
- if @test_result.respond_to?(:klass)
19
- @test_result.source_location
20
- else
21
- @test_result.method(@test_result.name).source_location
22
- end
23
- end
24
-
25
- def kind
26
- parts = self.path.gsub('test/', '').split('/')
27
- parts.length > 1 ? parts.first : 'general'
28
- end
29
-
30
- def message
31
- failure = @test_result.failure
32
- return unless failure
33
- "#{failure.error.class}: #{failure.error.message}"
34
- end
35
-
36
- def backtrace
37
- return unless @test_result.failure
38
- Minitest.filter_backtrace(@test_result.failure.backtrace)
39
- end
40
-
41
- def result
42
- if @test_result.error?
43
- :error
44
- elsif @test_result.skipped?
45
- :skip
46
- elsif @test_result.failure
47
- :fail
48
- else
49
- :pass
50
- end
51
- end
52
-
53
- def time
54
- @test_result.time
55
- end
56
-
57
- def name
58
- @test_result.name
59
- end
60
-
61
- def image
62
- return unless kind == 'system'
63
-
64
- image_path =
65
- if defined?(Capybara) && Capybara.respond_to?(:save_path) &&
66
- Capybara.save_path.present?
67
- "#{Capybara.save_path}/failures_#{name}.png"
68
- else
69
- "./tmp/screenshots/failures_#{name}.png"
70
- end
71
-
72
- return unless File.exist?(image_path)
73
-
74
- image_path
75
- end
76
-
77
- def report
78
- {
79
- backtrace: backtrace,
80
- message: message,
81
- line: line,
82
- image: image,
83
- kind: kind,
84
- name: name,
85
- path: path,
86
- result: result,
87
- time: time
88
- }.compact
89
- end
90
- end