@parcel/core
Version:
255 lines (232 loc) • 7.31 kB
JavaScript
// @flow strict-local
import WorkerFarm from '@parcel/workers';
import path from 'path';
import assert from 'assert';
import sinon from 'sinon';
import {MemoryFS} from '@parcel/fs';
import {hashString} from '@parcel/rust';
import type {
ConfigRequest,
ConfigRequestResult,
} from '../../src/requests/ConfigRequest';
import type {RunAPI} from '../../src/RequestTracker';
import {runConfigRequest} from '../../src/requests/ConfigRequest';
import {toProjectPath} from '../../src/projectPath';
// $FlowFixMe unclear-type forgive me
const mockCast = (f: any): any => f;
describe('ConfigRequest tests', () => {
const projectRoot = 'project_root';
const farm = new WorkerFarm({
workerPath: require.resolve('../../src/worker.js'),
maxConcurrentWorkers: 1,
});
let fs = new MemoryFS(farm);
beforeEach(() => {
fs = new MemoryFS(farm);
});
const getMockRunApi = (
options: mixed = {projectRoot, inputFS: fs},
): RunAPI<ConfigRequestResult> => {
const mockRunApi = {
storeResult: sinon.spy(),
canSkipSubrequest: sinon.spy(),
invalidateOnFileCreate: sinon.spy(),
getInvalidSubRequests: sinon.spy(),
getInvalidations: sinon.spy(),
getPreviousResult: sinon.spy(),
getRequestResult: sinon.spy(),
getSubRequests: sinon.spy(),
invalidateOnBuild: sinon.spy(),
invalidateOnConfigKeyChange: sinon.spy(),
invalidateOnEnvChange: sinon.spy(),
invalidateOnFileDelete: sinon.spy(),
invalidateOnFileUpdate: sinon.spy(),
invalidateOnOptionChange: sinon.spy(),
invalidateOnStartup: sinon.spy(),
runRequest: sinon.spy(request => {
return request.run({
api: mockRunApi,
options,
});
}),
};
return mockRunApi;
};
const baseRequest: ConfigRequest = {
id: 'config_request_test',
invalidateOnBuild: false,
invalidateOnConfigKeyChange: [],
invalidateOnFileCreate: [],
invalidateOnEnvChange: new Set(),
invalidateOnOptionChange: new Set(),
invalidateOnStartup: false,
invalidateOnFileChange: new Set(),
};
it('can execute a config request', async () => {
const mockRunApi = getMockRunApi();
await runConfigRequest(mockRunApi, {
...baseRequest,
});
});
it('forwards "invalidateOnFileChange" calls to runAPI', async () => {
const mockRunApi = getMockRunApi();
await runConfigRequest(mockRunApi, {
...baseRequest,
invalidateOnFileChange: new Set([
toProjectPath(projectRoot, 'path1'),
toProjectPath(projectRoot, 'path2'),
]),
});
assert(
mockCast(mockRunApi.invalidateOnFileUpdate).called,
'Invalidate was called',
);
assert(
mockCast(mockRunApi.invalidateOnFileUpdate).calledWith('path1'),
'Invalidate was called with path1',
);
assert(
mockCast(mockRunApi.invalidateOnFileUpdate).calledWith('path2'),
'Invalidate was called with path2',
);
assert(
mockCast(mockRunApi.invalidateOnFileDelete).calledWith('path1'),
'Invalidate was called with path1',
);
assert(
mockCast(mockRunApi.invalidateOnFileDelete).calledWith('path2'),
'Invalidate was called with path2',
);
});
it('forwards "invalidateOnFileCreate" calls to runAPI', async () => {
const mockRunApi = getMockRunApi();
await runConfigRequest(mockRunApi, {
...baseRequest,
invalidateOnFileCreate: [
{filePath: toProjectPath(projectRoot, 'filePath')},
{glob: toProjectPath(projectRoot, 'glob')},
{
fileName: 'package.json',
aboveFilePath: toProjectPath(projectRoot, 'fileAbove'),
},
],
});
assert(
mockCast(mockRunApi.invalidateOnFileCreate).called,
'Invalidate was called',
);
assert(
mockCast(mockRunApi.invalidateOnFileCreate).calledWithMatch({
filePath: 'filePath',
}),
'Invalidate was called for path',
);
assert(
mockCast(mockRunApi.invalidateOnFileCreate).calledWithMatch({
glob: 'glob',
}),
'Invalidate was called for glob',
);
assert(
mockCast(mockRunApi.invalidateOnFileCreate).calledWithMatch({
fileName: 'package.json',
aboveFilePath: 'fileAbove',
}),
'Invalidate was called for fileAbove',
);
});
it('forwards "invalidateOnEnvChange" calls to runAPI', async () => {
const mockRunApi = getMockRunApi();
await runConfigRequest(mockRunApi, {
...baseRequest,
invalidateOnEnvChange: new Set(['env1', 'env2']),
});
assert(
mockCast(mockRunApi.invalidateOnEnvChange).called,
'Invalidate was called',
);
assert(
mockCast(mockRunApi.invalidateOnEnvChange).calledWithMatch('env1'),
'Invalidate was called for env1',
);
assert(
mockCast(mockRunApi.invalidateOnEnvChange).calledWithMatch('env2'),
'Invalidate was called for env1',
);
});
it('forwards "invalidateOnOptionChange" calls to runAPI', async () => {
const mockRunApi = getMockRunApi();
await runConfigRequest(mockRunApi, {
...baseRequest,
invalidateOnOptionChange: new Set(['option1', 'option2']),
});
assert(
mockCast(mockRunApi.invalidateOnOptionChange).called,
'Invalidate was called',
);
assert(
mockCast(mockRunApi.invalidateOnOptionChange).calledWithMatch('option1'),
'Invalidate was called for option1',
);
assert(
mockCast(mockRunApi.invalidateOnOptionChange).calledWithMatch('option2'),
'Invalidate was called for option2',
);
});
it('forwards "invalidateOnStartup" calls to runAPI', async () => {
const mockRunApi = getMockRunApi();
await runConfigRequest(mockRunApi, {
...baseRequest,
invalidateOnStartup: true,
});
assert(
mockCast(mockRunApi.invalidateOnStartup).called,
'Invalidate was called',
);
});
it('forwards "invalidateOnBuild" calls to runAPI', async () => {
const mockRunApi = getMockRunApi();
await runConfigRequest(mockRunApi, {
...baseRequest,
invalidateOnBuild: true,
});
assert(
mockCast(mockRunApi.invalidateOnBuild).called,
'Invalidate was called',
);
});
it('forwards "invalidateOnConfigKeyChange" calls to runAPI', async () => {
await fs.mkdirp('/project_root');
await fs.writeFile(
'/project_root/config.json',
JSON.stringify({key1: 'value1'}),
);
sinon.spy(fs, 'readFile');
sinon.spy(fs, 'readFileSync');
const mockRunApi = getMockRunApi();
await runConfigRequest(mockRunApi, {
...baseRequest,
invalidateOnConfigKeyChange: [
{
configKey: 'key1',
filePath: toProjectPath(
projectRoot,
path.join('project_root', 'config.json'),
),
},
],
});
const fsCall = mockCast(fs).readFile.getCall(0);
assert.deepEqual(
fsCall?.args,
[path.join('project_root', 'config.json'), 'utf8'],
'readFile was called',
);
const call = mockCast(mockRunApi.invalidateOnConfigKeyChange).getCall(0);
assert.deepEqual(
call.args,
['config.json', 'key1', hashString('"value1"')],
'Invalidate was called for key1',
);
});
});