@testomatio/reporter 0.5.10 → 0.6.0-beta.1

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.
@@ -0,0 +1,146 @@
1
+ require 'test_helper'
2
+
3
+ class SearchServiceTest < ActiveSupport::TestCase
4
+ let(:project) { Project.create title: 'Project 1' }
5
+ let(:seeder) { Seeder.new project }
6
+ let(:search_service) { SearchService.new project }
7
+
8
+ before(:each) do
9
+ s = seeder.create_suite title: 'User Management'
10
+ seeder.create_test suite: s, title: 'Login @auth', state: :automated
11
+ seeder.create_test suite: s, title: 'Login without password @auth'
12
+ seeder.create_test suite: s, title: 'Logout @auth'
13
+ seeder.create_test suite: s, title: 'Disable authorization', state: :automated
14
+ seeder.create_test suite: s, title: 'Delete account'
15
+
16
+ s2 = seeder.create_suite title: 'Product'
17
+ seeder.create_test suite: s2, title: 'Create product'
18
+
19
+ Suite.reindex!
20
+ Test.reindex!
21
+ end
22
+
23
+ test 'should search tests by title' do
24
+ Retryable.retryable(tries: 5) do
25
+ serialized = search_service.find_tests_and_suites 'Login'
26
+ _(serialized[:included].length).must_equal 2
27
+ _(found_tests(serialized)).must_include 'Login @auth'
28
+ end
29
+ end
30
+
31
+ test 'should search tests by tag' do
32
+ Retryable.retryable(tries: 5) do
33
+ serialized = search_service.find_tests_and_suites '@auth'
34
+ assert serialized[:included]
35
+ _(serialized[:included].length).must_equal 3
36
+ _(found_tests(serialized)).wont_include 'Disable authorization'
37
+ end
38
+ end
39
+
40
+ test 'should search tests by title and state' do
41
+ Retryable.retryable(tries: 5) do
42
+ serialized = search_service.find_tests_and_suites 'Login', { state: 'automated' }
43
+ _(serialized[:included].length).must_equal 1
44
+ _(found_tests(serialized)).must_include 'Login @auth'
45
+ end
46
+ end
47
+
48
+ test 'should filter tests by state' do
49
+ serialized = search_service.filter_tests state: 'automated'
50
+ _(serialized[:included].length).must_equal 2
51
+ end
52
+
53
+ test 'should filter tests by empty state' do
54
+ sleep 0.3
55
+ Retryable.retryable(tries: 5) do
56
+ serialized = search_service.filter_tests state: ''
57
+ _(serialized[:included].length).must_equal 6
58
+ end
59
+ end
60
+
61
+ test 'should take description into account' do
62
+ test = project.tests.find_by title: 'Logout @auth'
63
+ test.description = 'User account must exist'
64
+ test.save
65
+ Retryable.retryable(tries: 5) do
66
+ test.index!
67
+ sleep 0.25
68
+ serialized = search_service.find_tests_and_suites 'Account'
69
+ echo Test.pluck(:title, :description)
70
+ _(serialized[:included].length).must_equal 2
71
+ _(found_tests(serialized)).must_include 'Logout @auth'
72
+ end
73
+ end
74
+
75
+ test 'should ignore tags in description' do
76
+ test = project.tests.find_by title: 'Delete account'
77
+ test.description = 'This is also @auth'
78
+ test.save
79
+ Retryable.retryable(tries: 5) do
80
+ serialized = search_service.find_tests_and_suites '@auth'
81
+ _(serialized[:included].length).must_equal 3
82
+ _(found_tests(serialized)).wont_include 'Delete account'
83
+ end
84
+ end
85
+
86
+ test 'find tests in suites by tag' do
87
+ s2 = project.suites.last
88
+ s3 = seeder.create_suite title: 'Cart @slow @important'
89
+ seeder.create_test suite: s3, title: 'Add to cart'
90
+ seeder.create_test suite: s3, title: 'Remove from cart @slow'
91
+ seeder.create_test suite: s3, title: 'Add more to cart'
92
+
93
+ seeder.create_test suite: s2, title: 'Add exclusve product @important'
94
+ TagsService.new(project).rebuild_project_tags
95
+ tests = search_service.find_tests '@important'
96
+ echo tests.pluck(:title)
97
+ _(tests.length).must_equal 4
98
+ _(tests.pluck(:title)).must_include 'Add exclusve product @important'
99
+ _(tests.pluck(:title)).must_include 'Add to cart'
100
+ end
101
+
102
+ test 'should find tests on a branch' do
103
+ test = project.tests.find_by title: 'Delete account'
104
+ branch = project.branches.create title: 'dev'
105
+ switch_to_branch branch
106
+ test.title = 'Remove account'
107
+ test.save
108
+
109
+ sleep 0.25
110
+ Retryable.retryable(tries: 10) do
111
+ serialized = search_service.find_tests_and_suites 'Delete'
112
+ echo serialized[:included]
113
+ # well, maybe we should not show it but ok :(
114
+ _(serialized[:included].length).must_equal 1
115
+
116
+ serialized = search_service.find_tests_and_suites 'Remove'
117
+ _(serialized[:included].length).must_equal 1
118
+ end
119
+ end
120
+
121
+ test 'should search globally by title' do
122
+ sleep 0.25
123
+ Retryable.retryable(tries: 10) do
124
+ suites = SearchService.global_find_tests_and_suites('Login', [project])
125
+ _(suites.size).must_equal 1
126
+ _(suites.first[:filtered_tests].size).must_equal 2
127
+
128
+ suites = SearchService.global_find_tests_and_suites('@auth', [project])
129
+ _(suites.size).must_equal 1
130
+ echo suites.first[:filtered_tests]
131
+
132
+ # actually should be 3, because result also includes 'authorization' word
133
+ _(suites.first[:filtered_tests].size).must_equal 4
134
+
135
+ suites = SearchService.global_find_tests_and_suites('Hello', [project])
136
+ _(suites.size).must_equal 0
137
+ end
138
+ end
139
+
140
+ private
141
+
142
+ def found_tests(serialized)
143
+ assert serialized[:included]
144
+ serialized[:included].map { |t| t[:attributes][:title] }
145
+ end
146
+ end
@@ -0,0 +1,51 @@
1
+ const { expect } = require('chai');
2
+ const {
3
+ fetchFilesFromStackTrace,
4
+ fetchSourceCodeFromStackTrace,
5
+ } = require('../lib/util');
6
+
7
+ describe('Utils', () => {
8
+ it('#fetchFilesFromStackTrace | should match images from stack trace', () => {
9
+ const file1 = `${process.cwd()}/tests/data/artifacts/failed_test.png`
10
+ const file2 = `${process.cwd()}/tests/data/artifacts/screenshot1.png`
11
+ const stack = `
12
+ PayrollPBTest:everyPayrollIsPositive =
13
+ |-------------------jqwik-------------------
14
+ tries = 1000 | # of calls to property
15
+ checks = 1000 | # of not rejected calls
16
+ file:/${file1}
17
+ generation = RANDOMIZED | parameters are randomly generated
18
+ after-failure = PREVIOUS_SEED | use the previous seed
19
+ edge-cases# file:/${file2}
20
+ edge-cases#total = 12 | # of all combined edge cases
21
+ edge-cases#tried = 12 | # of edge cases tried in current run
22
+ seed = 7004898156813507962 | random seed to reproduce generated values
23
+ `
24
+ const files = fetchFilesFromStackTrace(stack);
25
+ expect(files).to.include(file1);
26
+ expect(files).to.include(file2);
27
+ });
28
+
29
+ it('#fetchSourceCodeFromStackTrace | prefixed with at ', () => {
30
+ const stack = `
31
+ Expected: <4.0>
32
+ but: was <6.0>
33
+ at ${process.cwd()}/tests/data/cli/RunCest.php:24
34
+ `
35
+ const source = fetchSourceCodeFromStackTrace(stack);
36
+ expect(source).to.include(`$I->executeCommand('run --colors tests/dummy/FileExistsCept.php');`);
37
+ expect(source).to.include(`24 >`);
38
+ })
39
+
40
+ it('#fetchSourceCodeFromStackTrace | without prefix', () => {
41
+ const stack = `
42
+ Expected: <4.0>
43
+ but: was <6.0>
44
+ ${process.cwd()}/tests/data/cli/RunCest.php:24
45
+ `
46
+ const source = fetchSourceCodeFromStackTrace(stack);
47
+ expect(source).to.include(`$I->executeCommand('run --colors tests/dummy/FileExistsCept.php');`);
48
+ expect(source).to.include(`24 >`);
49
+ })
50
+
51
+ });
@@ -0,0 +1,232 @@
1
+ const path = require('path');
2
+ const { expect, assert } = require('chai');
3
+ const ServerMock = require('mock-http-server');
4
+ const { host, port, TESTOMATIO_URL, TESTOMATIO, RUN_ID } = require('./adapter/config');
5
+ const { registerHandlers } = require('./adapter/utils');
6
+ const XmlReader = require('../lib/xmlReader')
7
+
8
+ describe('XML Reader', () => {
9
+ const server = new ServerMock({ host, port });
10
+
11
+ before(done => {
12
+ server.start(() => {
13
+ console.log(`[mock-http-server]: Server started at ${TESTOMATIO_URL}`);
14
+
15
+ done();
16
+ });
17
+ });
18
+
19
+ after(done => {
20
+ server.stop(() => {
21
+ console.log('[mock-http-server]: Server stopped');
22
+
23
+ done();
24
+ });
25
+ });
26
+
27
+
28
+ it('should parse Jest XML', () => {
29
+ const reader = new XmlReader();
30
+ const jsonData = reader.parse(path.join(__dirname, 'data/junit1.xml'))
31
+ expect(jsonData.status).to.eql('failed')
32
+ expect(jsonData.tests_count).to.eql(13)
33
+ expect(jsonData.tests.length).to.eql(jsonData.tests_count)
34
+
35
+ jsonData.tests.forEach(t => {
36
+ expect(t).to.contain.keys([
37
+ 'stack',
38
+ 'create',
39
+ 'status',
40
+ 'title',
41
+ 'run_time',
42
+ 'suite_title',
43
+ ])
44
+ })
45
+ })
46
+
47
+
48
+ it('should parse minitest XML', () => {
49
+ const reader = new XmlReader();
50
+ const jsonData = reader.parse(path.join(__dirname, 'data/minitest.xml'))
51
+ expect(jsonData.status).to.eql('passed')
52
+
53
+ const stats = reader.calculateStats();
54
+ expect(stats.status).to.eql('passed')
55
+ expect(stats.tests_count).to.eql(10)
56
+ expect(jsonData.tests.length).to.eql(stats.tests_count)
57
+
58
+ reader.fetchSourceCode();
59
+
60
+ jsonData.tests.forEach(t => {
61
+ expect(t).to.contain.keys([
62
+ 'stack',
63
+ 'create',
64
+ 'status',
65
+ 'file',
66
+ 'title',
67
+ 'run_time',
68
+ 'suite_title',
69
+ ])
70
+ })
71
+
72
+ expect(jsonData.tests[0].code).to.be.ok;
73
+ expect(jsonData.tests[0].code).to.include("test 'should ")
74
+ })
75
+
76
+ it('should parse Pytest XML', () => {
77
+ const reader = new XmlReader();
78
+ const jsonData = reader.parse(path.join(__dirname, 'data/pytest.xml'))
79
+
80
+ expect(jsonData.status).to.eql('failed')
81
+ const stats = reader.calculateStats();
82
+ expect(stats.status).to.eql('failed')
83
+ expect(stats.tests_count).to.eql(7)
84
+ expect(jsonData.tests.length).to.eql(stats.tests_count)
85
+
86
+
87
+ reader.fetchSourceCode();
88
+ reader.formatErrors();
89
+ reader.formatTests();
90
+
91
+ jsonData.tests.forEach(t => {
92
+ expect(t).to.contain.keys([
93
+ 'stack',
94
+ 'create',
95
+ 'status',
96
+ 'file',
97
+ 'title',
98
+ 'run_time',
99
+ 'suite_title',
100
+ ])
101
+ })
102
+
103
+ expect(jsonData.tests[0].title).to.eql("login with valid credentials")
104
+
105
+ const failedTests = jsonData.tests.filter(t => t.status === 'failed')
106
+ })
107
+
108
+ it('should parse Codeception XML', () => {
109
+ const reader = new XmlReader();
110
+ const jsonData = reader.parse(path.join(__dirname, 'data/codecept.xml'))
111
+
112
+ expect(jsonData.status).to.eql('failed')
113
+ const stats = reader.calculateStats();
114
+ expect(stats.status).to.eql('failed')
115
+ expect(stats.tests_count).to.eql(89)
116
+ expect(jsonData.tests.length).to.eql(stats.tests_count)
117
+
118
+
119
+ reader.fetchSourceCode();
120
+ reader.formatErrors();
121
+ reader.formatTests();
122
+
123
+ jsonData.tests.forEach(t => {
124
+ expect(t).to.contain.keys([
125
+ 'stack',
126
+ 'create',
127
+ 'status',
128
+ 'file',
129
+ 'title',
130
+ 'run_time',
131
+ 'suite_title',
132
+ ])
133
+ })
134
+
135
+ expect(jsonData.tests[0].code).to.be.ok;
136
+ expect(jsonData.tests[0].code).to.include("public function runCestWithTwoFailedTest(")
137
+ expect(jsonData.tests[0].title).to.eql("run cest with two failed test")
138
+
139
+ const failedTests = jsonData.tests.filter(t => t.status === 'failed')
140
+ const failedTest = failedTests[0];
141
+ expect(failedTest.stack).to.include('public function')
142
+ })
143
+
144
+ it('should parse JUnit XML', () => {
145
+ const reader = new XmlReader();
146
+ const jsonData = reader.parse(path.join(__dirname, 'data/java.xml'))
147
+
148
+ expect(jsonData.status).to.eql('failed')
149
+ const stats = reader.calculateStats();
150
+ expect(stats.status).to.eql('failed')
151
+ expect(stats.tests_count).to.eql(6)
152
+ expect(jsonData.tests.length).to.eql(stats.tests_count)
153
+
154
+
155
+ reader.fetchSourceCode();
156
+ reader.formatErrors();
157
+ reader.formatTests();
158
+
159
+ jsonData.tests.forEach(t => {
160
+ expect(t).to.contain.keys([
161
+ 'stack',
162
+ 'create',
163
+ 'status',
164
+ 'file',
165
+ 'title',
166
+ 'run_time',
167
+ 'suite_title',
168
+ ])
169
+ })
170
+
171
+ // expect(jsonData.tests[0].code).to.be.ok;
172
+ // expect(jsonData.tests[0].code).to.include("public function runCestWithTwoFailedTest(")
173
+ // expect(jsonData.tests[0].title).to.eql("Run cest with two failed test")
174
+
175
+ const failedTests = jsonData.tests.filter(t => t.status === 'failed')
176
+ const failedTest = failedTests[0];
177
+ expect(failedTest.stack).to.include('(CalculatorTest.java:43')
178
+ })
179
+
180
+ describe('#request', () => {
181
+
182
+ before(function () {
183
+ this.timeout(5000);
184
+ });
185
+
186
+ beforeEach(() => {
187
+ registerHandlers(server, RUN_ID);
188
+ })
189
+
190
+ it('should create a new run Id', async () => {
191
+ const reader = new XmlReader({
192
+ url: TESTOMATIO_URL,
193
+ apiKey: TESTOMATIO,
194
+ });
195
+ reader.parse(path.join(__dirname, 'data/junit1.xml'))
196
+ await reader.createRun()
197
+ expect(reader.runId).to.eql(RUN_ID)
198
+
199
+ const [req] = server.requests({ method: 'POST', path: '/api/reporter' });
200
+ const expectedResult = { api_key: TESTOMATIO };
201
+ assert.isObject(req.body);
202
+ assert.deepEqual(req.body, expectedResult);
203
+ });
204
+
205
+ it('should publish updates', async () => {
206
+ const reader = new XmlReader({
207
+ url: TESTOMATIO_URL,
208
+ apiKey: TESTOMATIO,
209
+ runId: RUN_ID,
210
+ });
211
+ reader.parse(path.join(__dirname, 'data/junit1.xml'))
212
+ expect(reader.runId).to.eql(RUN_ID)
213
+
214
+ const resp = await reader.uploadData();
215
+ expect(resp.status).to.eql(200)
216
+
217
+ const [req] = server.requests({ method: 'PUT', path: '/api/reporter/' + RUN_ID });
218
+ assert.isObject(req.body);
219
+ expect(req.body).to.include({ status: 'failed' })
220
+ });
221
+
222
+
223
+
224
+
225
+ afterEach(() => {
226
+ server.reset();
227
+ });
228
+
229
+
230
+ })
231
+
232
+ });