Skip to content

Commit 60cd317

Browse files
committed
chore: convert linux spec to vitest
1 parent 0aa252e commit 60cd317

File tree

2 files changed

+320
-230
lines changed

2 files changed

+320
-230
lines changed
Lines changed: 320 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
import { describe, it, expect, beforeEach, vi } from 'vitest'
2+
import _ from 'lodash'
3+
import cp from 'child_process'
4+
import { EventEmitter } from 'events'
5+
import * as linuxHelper from '../../lib/linux'
6+
import { log } from '../log'
7+
import { detect } from '../../lib/detect'
8+
import { goalBrowsers } from '../fixtures'
9+
import os from 'os'
10+
import mockFs from 'mock-fs'
11+
12+
vi.mock('os', async (importActual) => {
13+
const actual = await importActual()
14+
15+
return {
16+
default: {
17+
// @ts-expect-error
18+
...actual.default,
19+
platform: vi.fn(),
20+
release: vi.fn(),
21+
homedir: vi.fn(),
22+
},
23+
}
24+
})
25+
26+
vi.mock('child_process', async (importActual) => {
27+
const actual = await importActual()
28+
29+
return {
30+
default: {
31+
// @ts-expect-error
32+
...actual.default,
33+
spawn: vi.fn(),
34+
},
35+
}
36+
})
37+
38+
describe('linux browser detection', () => {
39+
let cpSpawnCallback: (cmd: string, args: readonly string[], opts, cp: cp.ChildProcess) => void
40+
41+
beforeEach(() => {
42+
vi.unstubAllEnvs()
43+
vi.resetAllMocks()
44+
45+
vi.mocked(os.platform).mockReturnValue('linux')
46+
vi.mocked(os.release).mockReturnValue('1.0.0')
47+
48+
vi.mocked(cp.spawn).mockImplementation((cmd, args, opts) => {
49+
const cpSpawnMock = {
50+
on: vi.fn(),
51+
stdout: new EventEmitter(),
52+
stderr: new EventEmitter(),
53+
kill: vi.fn(),
54+
}
55+
56+
cpSpawnMock.on.mockImplementation((event: string, callback: (...args: any[]) => void) => {
57+
if (event === 'exit') {
58+
setTimeout(() => callback(), 0)
59+
}
60+
61+
if (event === 'close') {
62+
setTimeout(() => callback(), 0)
63+
}
64+
})
65+
66+
cpSpawnCallback(cmd, args, opts, cpSpawnMock as unknown as cp.ChildProcess)
67+
68+
return cpSpawnMock as unknown as cp.ChildProcess
69+
})
70+
})
71+
72+
afterEach(() => {
73+
mockFs.restore()
74+
})
75+
76+
it('detects browser by running --version', async () => {
77+
const goal = goalBrowsers[0]
78+
79+
cpSpawnCallback = (cmd, args, opts, cpSpawnMock) => {
80+
if (cmd === 'test-browser') {
81+
setTimeout(() => {
82+
cpSpawnMock.stdout.emit('data', 'test-browser v100.1.2.3')
83+
}, 0)
84+
}
85+
}
86+
87+
// @ts-expect-error
88+
const browser = await linuxHelper.detect(goal)
89+
90+
expect(browser).toEqual({
91+
name: 'test-browser-name',
92+
path: 'test-browser',
93+
version: '100.1.2.3',
94+
})
95+
})
96+
97+
// https://github.com/cypress-io/cypress/pull/7039
98+
it('sets profilePath on snapcraft chromium', async () => {
99+
vi.mocked(os.homedir).mockReturnValue('/home/foo')
100+
101+
cpSpawnCallback = (cmd, args, opts, cpSpawnMock) => {
102+
if (cmd === 'chromium') {
103+
setTimeout(() => {
104+
cpSpawnMock.stdout.emit('data', 'Chromium 64.2.3 snap')
105+
}, 0)
106+
}
107+
}
108+
109+
const [browser] = await detect()
110+
111+
expect(browser).toEqual({
112+
channel: 'stable',
113+
name: 'chromium',
114+
family: 'chromium',
115+
displayName: 'Chromium',
116+
majorVersion: '64',
117+
path: 'chromium',
118+
profilePath: '/home/foo/snap/chromium/current',
119+
version: '64.2.3',
120+
})
121+
})
122+
123+
// https://github.com/cypress-io/cypress/issues/19793
124+
describe('sets profilePath on snapcraft firefox', () => {
125+
const expectedSnapFirefox = {
126+
channel: 'stable',
127+
name: 'firefox',
128+
family: 'firefox',
129+
displayName: 'Firefox',
130+
majorVersion: '135',
131+
path: 'firefox',
132+
profilePath: '/home/foo/snap/firefox/current',
133+
version: '135.0.1',
134+
}
135+
136+
beforeEach(() => {
137+
cpSpawnCallback = (cmd, args, opts, cpSpawnMock) => {
138+
if (cmd === 'firefox') {
139+
setTimeout(() => {
140+
cpSpawnMock.stdout.emit('data', 'Mozilla Firefox 135.0.1')
141+
}, 0)
142+
}
143+
}
144+
145+
vi.mocked(os.homedir).mockReturnValue('/home/foo')
146+
})
147+
148+
it('with shim script', async () => {
149+
vi.stubEnv('PATH', '/bin')
150+
mockFs({
151+
'/bin/firefox': mockFs.symlink({ path: '/usr/bin/firefox' }),
152+
'/usr/bin/firefox': mockFs.file({ mode: 0o777, content: 'foo bar foo bar foo bar\nexec /snap/bin/firefox\n' }),
153+
})
154+
155+
const [browser] = await detect()
156+
157+
expect(browser).toEqual(expectedSnapFirefox)
158+
})
159+
160+
it('with /snap/bin in path', async () => {
161+
vi.stubEnv('PATH', '/bin:/snap/bin')
162+
mockFs({
163+
'/snap/bin/firefox': mockFs.file({ mode: 0o777, content: 'binary' }),
164+
})
165+
166+
const [browser] = await detect()
167+
168+
expect(browser).toEqual(expectedSnapFirefox)
169+
})
170+
171+
it('with symlink to /snap/bin in path', async () => {
172+
vi.stubEnv('PATH', '/bin')
173+
mockFs({
174+
'/bin/firefox': mockFs.symlink({ path: '/snap/bin/firefox' }),
175+
'/snap/bin/firefox': mockFs.file({ mode: 0o777, content: 'binary' }),
176+
})
177+
178+
const [browser] = await detect()
179+
180+
expect(browser).toEqual(expectedSnapFirefox)
181+
})
182+
})
183+
184+
// https://github.com/cypress-io/cypress/issues/6669
185+
it('detects browser if the --version stdout is multiline', async () => {
186+
cpSpawnCallback = (cmd, args, opts, cpSpawnMock) => {
187+
if (cmd === 'multiline-foo') {
188+
setTimeout(() => {
189+
cpSpawnMock.stdout.emit('data', `
190+
Running without a11y support!
191+
foo-browser v9001.1.2.3
192+
`)
193+
}, 0)
194+
}
195+
}
196+
197+
const goal = _.defaults({ binary: 'multiline-foo' }, _.find(goalBrowsers, { name: 'foo-browser' }))
198+
199+
// @ts-expect-error
200+
const [browser] = await detect([goal])
201+
202+
expect(browser).toEqual({
203+
displayName: 'Foo Browser',
204+
majorVersion: '9001',
205+
name: 'foo-browser',
206+
path: 'multiline-foo',
207+
version: '9001.1.2.3',
208+
})
209+
})
210+
211+
// despite using detect(), this test is in linux/spec instead of detect_spec because it is
212+
// testing side effects that occur within the Linux-specific detect function
213+
// https://github.com/cypress-io/cypress/issues/1400
214+
it('properly eliminates duplicates', async () => {
215+
const expected = [
216+
{
217+
displayName: 'Test Browser',
218+
name: 'test-browser-name',
219+
version: '100.1.2.3',
220+
path: 'test-browser',
221+
majorVersion: '100',
222+
},
223+
{
224+
displayName: 'Foo Browser',
225+
name: 'foo-browser',
226+
version: '100.1.2.3',
227+
path: 'foo-browser',
228+
majorVersion: '100',
229+
},
230+
]
231+
232+
cpSpawnCallback = (cmd, args, opts, cpSpawnMock) => {
233+
if (cmd === 'test-browser') {
234+
setTimeout(() => {
235+
cpSpawnMock.stdout.emit('data', 'test-browser v100.1.2.3')
236+
}, 0)
237+
}
238+
239+
if (cmd === 'foo-browser') {
240+
setTimeout(() => {
241+
cpSpawnMock.stdout.emit('data', 'foo-browser v100.1.2.3')
242+
}, 0)
243+
}
244+
}
245+
246+
// @ts-expect-error
247+
const browsers = await detect(goalBrowsers)
248+
249+
log('Browsers: %o', browsers)
250+
log('Expected browsers: %o', expected)
251+
expect(browsers).toEqual(expected)
252+
})
253+
254+
it('considers multiple binary names', async () => {
255+
const goalBrowsers = [
256+
{
257+
name: 'foo-browser',
258+
versionRegex: /v(\S+)$/,
259+
binary: ['foo-browser', 'foo-bar-browser'],
260+
},
261+
]
262+
263+
const expected = [
264+
{
265+
name: 'foo-browser',
266+
version: '100.1.2.3',
267+
path: 'foo-browser',
268+
majorVersion: '100',
269+
},
270+
]
271+
272+
cpSpawnCallback = (cmd, args, opts, cpSpawnMock) => {
273+
if (cmd === 'foo-browser' || cmd === 'foo-bar-browser') {
274+
setTimeout(() => {
275+
cpSpawnMock.stdout.emit('data', 'foo-browser v100.1.2.3')
276+
}, 0)
277+
}
278+
}
279+
280+
//@ts-expect-error
281+
const browsers = await detect(goalBrowsers)
282+
283+
log('Browsers: %o', browsers)
284+
log('Expected browsers: %o', expected)
285+
expect(browsers).toEqual(expected)
286+
})
287+
288+
describe('#getVersionString', () => {
289+
it('runs the command with `--version` and returns trimmed output', async () => {
290+
cpSpawnCallback = (cmd, args, opts, cpSpawnMock) => {
291+
if (cmd === 'foo') {
292+
setTimeout(() => {
293+
cpSpawnMock.stdout.emit('data', ' bar ')
294+
}, 0)
295+
}
296+
}
297+
298+
const versionString = await linuxHelper.getVersionString('foo')
299+
300+
expect(versionString).toEqual('bar')
301+
})
302+
303+
it('rejects with errors', async () => {
304+
const err = new Error()
305+
306+
cpSpawnCallback = (cmd, args, opts, cpSpawnMock) => {
307+
if (cmd === 'foo') {
308+
// @ts-expect-error - overriding the mock on this method
309+
cpSpawnMock.on.mockImplementation((event: string, callback: (...args: any[]) => void) => {
310+
if (event === 'error') {
311+
setTimeout(() => callback(err), 0)
312+
}
313+
})
314+
}
315+
}
316+
317+
await expect(linuxHelper.getVersionString('foo')).rejects.toThrow(err)
318+
})
319+
})
320+
})

0 commit comments

Comments
 (0)