Skip to content

Commit

Permalink
Extend mockNodeFetch
Browse files Browse the repository at this point in the history
* mock all "normal" requests
* allow mocking additional URLs (for importing a store)
* allow mocking "normal" requests once (e.g. fail only for the first time)
  • Loading branch information
BuZZ-T committed Nov 5, 2021
1 parent 77ca14c commit 2d1f5f0
Show file tree
Hide file tree
Showing 25 changed files with 833 additions and 273 deletions.
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
}
}
],
"import/no-cycle": "error",
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/explicit-module-boundary-types": "error",
"no-console": "error",
Expand Down
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ script:
- npm run lint
- npm run build:silent
- npm run test
- npm run test:int
- npm run test:coverage:coveralls
2 changes: 1 addition & 1 deletion config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function readConfig(args: string[], platform: NodeJS.Platform): ConfigWra
.version(packageJson.version)
.option('-m, --min <version>', 'The minimum version', DEFAULT_OPTIONS.min)
.option('-M, --max <version>', 'The maximum version. Newest version if not specificied', DEFAULT_OPTIONS.max)
.option('-r, --max-results <results>', 'The maximum amount of results to choose from')
.option('-r, --max-results <results>', 'The maximum amount of results to choose from', null)
.option('-o, --os <os>', 'The operating system for what the binary should be downloaded')
.option('-a, --arch <arch>', 'The architecture for what the binary should be downloaded. Valid values are "x86" and "x64". Only works when --os is also set')
.option('-d, --decrease-on-fail', 'If a binary does not exist, go to the next lower version number and try again (regarding --min, --max and --max-results)', false)
Expand Down
279 changes: 279 additions & 0 deletions download.int.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
/**
* Integration tests for downloading chromium
*
* @group int/use-case/downloadChromium
*/

import { existsSync, readFile as fsReadFile, writeFile as fsWriteFile, unlink as fsUnlink } from 'fs'
import * as mockFs from 'mock-fs'
import * as fetch from 'node-fetch'
import * as path from 'path'
import { MaybeMocked } from 'ts-jest/dist/utils/testing'
import { mocked } from 'ts-jest/utils'
import { promisify } from 'util'

import { MappedVersion } from './commons/MappedVersion'
import { IListStore } from './interfaces/store.interfaces'
import { rusted } from './rusted'
import { mockNodeFetch, chromeZipStream, branchPositionResponse } from './test/int.utils'
import { createStore } from './test/test.utils'
import { popArray } from './utils'

/* eslint-disable-next-line @typescript-eslint/no-var-requires */
const prompts = require('prompts')

jest.mock('node-fetch', () => jest.fn())
jest.mock('prompts')

describe('[int] download chromium', () => {

const chromeZip10 = path.join(__dirname, 'chrome-linux-x64-10.0.0.0.zip')
const chromeZip20 = path.join(__dirname, 'chrome-linux-x64-20.0.0.0.zip')
const localStoreFile = path.join(__dirname, 'localstore.json')

let promptsMock: MaybeMocked<typeof prompts>
let nodeFetchMock: MaybeMocked<typeof fetch>

let readFile: typeof fsReadFile.__promisify__
let writeFile: typeof fsWriteFile.__promisify__
let unlink: typeof fsUnlink.__promisify__

beforeAll(() => {

promptsMock = mocked(prompts)

mockFs({
'localstore.json': JSON.stringify(createStore()),

// pass some folders to the mock for jest to be able to run
'node_modules': mockFs.load(path.resolve(__dirname, './node_modules')),
'/tmp/jest_rs': mockFs.load(path.resolve(__dirname, '/tmp/jest_rs')),
})

readFile = promisify(fsReadFile)
writeFile = promisify(fsWriteFile)
unlink = promisify(fsUnlink)
})

beforeEach(async () => {
// clear mock-fs
await writeFile(localStoreFile, JSON.stringify(createStore()))
if (existsSync(chromeZip10)) {
await unlink(chromeZip10)
}
if (existsSync(chromeZip20)) {
await unlink(chromeZip20)
}

nodeFetchMock = mocked(fetch)
mockNodeFetch(nodeFetchMock, {
config: {
chromeZip: {
contentLength: 20,
}
}
})

promptsMock.mockClear()
})

afterAll(() => {
mockFs.restore()
})

it('should download a chrome file with --results=1', async () => {
await rusted(['/some/path/to/node', '/some/path/to/rusted-chromium', '--max-results=1'], 'linux')

chromeZipStream.emit('data', 'asdf')
chromeZipStream.end()

expect(existsSync(chromeZip10)).toBe(true)
expect(promptsMock).toHaveBeenCalledTimes(0)
})

it('should write the received data in the zip file and complete', async () => {
const data = 'some-data-foor-zip'

mockNodeFetch(nodeFetchMock, {
config: {
chromeZip: {
contentLength: data.length,
}
}
})

promptsMock.mockReturnValue({ version: '10.0.0.0' })

await rusted(['/some/path/to/node', '/some/path/to/rusted-chromium', '--max-results=1'], 'linux')

chromeZipStream.emit('data', data)
chromeZipStream.end()

expect(existsSync(chromeZip10)).toBe(true)

await expect(readFile(chromeZip10, { encoding: 'utf-8' })).resolves.toEqual(data)
})

it('should select and download a version', async () => {
mockNodeFetch(nodeFetchMock, {
params: {
tags: ['10.0.0.0', '20.0.0.0']
}
})
promptsMock.mockReturnValue({ version: '20.0.0.0' })

await rusted(['/some/path/to/node', '/some/path/to/rusted-chromium'], 'linux')

expect(existsSync(chromeZip20)).toBe(true)

expect(promptsMock).toHaveBeenCalledTimes(1)
expect(promptsMock).toHaveBeenCalledWith({
choices: [
new MappedVersion({
major: 20,
minor: 0,
branch: 0,
patch: 0,
disabled: false,
}),
new MappedVersion({
major: 10,
minor: 0,
branch: 0,
patch: 0,
disabled: false,
}),
],
hint: 'for linux x64',
message: 'Select a version',
name: 'version',
type: 'select',
warn: 'This version seems to not have a binary',
})
})

it('should mark a chrome version as disabled, on no binary found', async () => {
mockNodeFetch(nodeFetchMock, {
params: {
branchPosition: '4444',
}
})
promptsMock.mockReturnValue({ version: '10.0.0.0' })

await rusted(['/some/path/to/node', '/some/path/to/rusted-chromium'], 'linux')

expect(existsSync(chromeZip10)).toBe(false)

const storedStore = await readFile(localStoreFile, { encoding: 'utf-8' })
const store: IListStore = JSON.parse(storedStore)

expect(store.linux.x64).toEqual(['10.0.0.0'])
expect(store.linux.x86).toEqual([])
expect(store.win.x64).toEqual([])
expect(store.win.x86).toEqual([])
expect(store.mac.x64).toEqual([])
expect(store.mac.arm).toEqual([])
})

it('should mark a chrome version as disabled, on no binary found and init with an empty store on no store file found', async () => {
await unlink(localStoreFile)
mockNodeFetch(nodeFetchMock, {
params: {
branchPosition: '4444',
}
})
promptsMock.mockReturnValue({ version: '10.0.0.0' })

expect(existsSync(localStoreFile)).toBe(false)

await rusted(['/some/path/to/node', '/some/path/to/rusted-chromium'], 'linux')

expect(existsSync(chromeZip10)).toBe(false)
expect(existsSync(localStoreFile)).toBe(true)

const storedStore = await readFile(localStoreFile, { encoding: 'utf-8' })
const store: IListStore = JSON.parse(storedStore)

expect(store.linux.x64).toEqual(['10.0.0.0'])
expect(store.linux.x86).toEqual([])
expect(store.win.x64).toEqual([])
expect(store.win.x86).toEqual([])
expect(store.mac.x64).toEqual([])
expect(store.mac.arm).toEqual([])
})

it('should mark a chrome version as disabled, on no binary found and init with an empty store on currupt JSON', async () => {
await writeFile(localStoreFile, '{ asdf')
mockNodeFetch(nodeFetchMock, {
params: {
branchPosition: '4444',
}
})
promptsMock.mockReturnValue({ version: '10.0.0.0' })

await rusted(['/some/path/to/node', '/some/path/to/rusted-chromium'], 'linux')

expect(existsSync(chromeZip10)).toBe(false)
expect(existsSync(localStoreFile)).toBe(true)

const storedStore = await readFile(localStoreFile, { encoding: 'utf-8' })
const store: IListStore = JSON.parse(storedStore)

expect(store.linux.x64).toEqual(['10.0.0.0'])
expect(store.linux.x86).toEqual([])
expect(store.win.x64).toEqual([])
expect(store.win.x86).toEqual([])
expect(store.mac.x64).toEqual([])
expect(store.mac.arm).toEqual([])
})

it('should decrease on fail', async () => {
const gen = popArray(['4444'])

mockNodeFetch(nodeFetchMock, {
params: {
tags: ['20.0.0.0', '10.0.0.0']
},
urls: [
{
once: true,
name: 'branchPosition',
gen: () => gen.next(),
mock: (position: string) => branchPositionResponse(position),
}
]
})
promptsMock.mockReturnValueOnce({ version: '20.0.0.0' })
promptsMock.mockReturnValue({ version: '10.0.0.0' })

await rusted(['/some/path/to/node', '/some/path/to/rusted-chromium', '--decrease-on-fail'], 'linux')

expect(existsSync(chromeZip20)).toBe(false)
expect(existsSync(chromeZip10)).toBe(true)
})

it('should increase on fail', async () => {
const gen = popArray(['4444'])

mockNodeFetch(nodeFetchMock, {
params: {
tags: ['20.0.0.0', '10.0.0.0']
},
urls: [
{
once: true,
name: 'branchPosition',
gen: () => gen.next(),
mock: (position: string) => branchPositionResponse(position),
}
]
})
promptsMock.mockReturnValueOnce({ version: '10.0.0.0' })
promptsMock.mockReturnValue({ version: '20.0.0.0' })

await rusted(['/some/path/to/node', '/some/path/to/rusted-chromium', '--increase-on-fail'], 'linux')

expect(existsSync(chromeZip20)).toBe(true)
expect(existsSync(chromeZip10)).toBe(false)
})
})
1 change: 0 additions & 1 deletion download.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { progress } from './log/progress'
import { logger } from './log/spinner'
import { loadStore } from './store/loadStore'
import { Store } from './store/Store'
import { createChromeConfig, createStore, createDownloadSettings, MkdirWithOptions, StatsWithoutOptions } from './test.utils'
import { createChromeConfig, createStore, createDownloadSettings, MkdirWithOptions, StatsWithoutOptions } from './test/test.utils'
import { getChromeDownloadUrl, loadVersions, mapVersions } from './versions'

Expand Down
Loading

0 comments on commit 2d1f5f0

Please sign in to comment.