fix tests

Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
Fredrik Adelöw
2024-02-13 13:49:04 +01:00
parent 6bb6f3e64d
commit 361bef35a4
4 changed files with 142 additions and 222 deletions
+62 -152
View File
@@ -14,29 +14,21 @@
* limitations under the License.
*/
import fs from 'fs-extra';
import { resolve as resolvePath } from 'path';
import { getVoidLogger } from '@backstage/backend-common';
import { createMockDirectory } from '@backstage/backend-test-utils';
import { injectConfig } from './config';
jest.mock('fs-extra');
const fsMock = fs as jest.Mocked<typeof fs>;
const readFileMock = fsMock.readFile as unknown as jest.MockedFunction<
(name: string) => Promise<string>
>;
const MOCK_DIR = 'mock-dir';
const baseOptions = {
appConfigs: [],
staticDir: MOCK_DIR,
logger: getVoidLogger(),
};
describe('injectConfig', () => {
const mockDir = createMockDirectory();
const baseOptions = {
appConfigs: [],
staticDir: mockDir.path,
logger: getVoidLogger(),
};
beforeEach(() => {
fsMock.readdir.mockResolvedValue(['main.js'] as any);
mockDir.clear();
});
afterEach(() => {
@@ -44,185 +36,103 @@ describe('injectConfig', () => {
});
it('should inject without config', async () => {
fsMock.readdir.mockResolvedValue(['main.js'] as any);
readFileMock.mockImplementation(
async () => '"__APP_INJECTED_RUNTIME_CONFIG__"',
);
await injectConfig(baseOptions);
expect(fsMock.readdir).toHaveBeenCalledTimes(1);
expect(fsMock.readFile).toHaveBeenCalledTimes(1);
expect(fsMock.writeFile).toHaveBeenCalledTimes(1);
expect(fsMock.writeFile).toHaveBeenCalledWith(
resolvePath(MOCK_DIR, 'main.js'),
'/*__APP_INJECTED_CONFIG_MARKER__*/"[]"/*__INJECTED_END__*/',
'utf8',
);
mockDir.setContent({
'main.js': '"__APP_INJECTED_RUNTIME_CONFIG__"',
});
// eslint-disable-next-line no-eval
expect(JSON.parse(eval(fsMock.writeFile.mock.calls[0][1]))).toEqual([]);
await injectConfig(baseOptions);
expect(mockDir.content()).toEqual({
'main.js': '/*__APP_INJECTED_CONFIG_MARKER__*/"[]"/*__INJECTED_END__*/',
});
});
it('should inject config repeatedly if marker appears multiple times', async () => {
fsMock.readdir.mockResolvedValue(['main.js'] as any);
readFileMock.mockImplementation(
async () =>
mockDir.setContent({
'main.js':
'({a:"__APP_INJECTED_RUNTIME_CONFIG__",b:"__APP_INJECTED_RUNTIME_CONFIG__"})',
);
await injectConfig(baseOptions);
expect(fsMock.readdir).toHaveBeenCalledTimes(1);
expect(fsMock.readFile).toHaveBeenCalledTimes(1);
expect(fsMock.writeFile).toHaveBeenCalledTimes(1);
expect(fsMock.writeFile).toHaveBeenCalledWith(
resolvePath(MOCK_DIR, 'main.js'),
'({a:/*__APP_INJECTED_CONFIG_MARKER__*/"[]"/*__INJECTED_END__*/,b:/*__APP_INJECTED_CONFIG_MARKER__*/"[]"/*__INJECTED_END__*/})',
'utf8',
);
});
// eslint-disable-next-line no-eval
expect(JSON.parse(eval(fsMock.writeFile.mock.calls[0][1]).a)).toEqual([]);
// eslint-disable-next-line no-eval
expect(JSON.parse(eval(fsMock.writeFile.mock.calls[0][1]).b)).toEqual([]);
await injectConfig(baseOptions);
expect(mockDir.content()).toEqual({
'main.js':
'({a:/*__APP_INJECTED_CONFIG_MARKER__*/"[]"/*__INJECTED_END__*/,b:/*__APP_INJECTED_CONFIG_MARKER__*/"[]"/*__INJECTED_END__*/})',
});
});
it('should find the correct file to inject', async () => {
fsMock.readdir.mockResolvedValue([
'before.js',
'not-js.txt',
'main.js',
'after.js',
] as any);
readFileMock.mockImplementation(async (file: string) => {
if (file.endsWith('main.js')) {
return '"__APP_INJECTED_RUNTIME_CONFIG__"';
}
return 'NO_PLACEHOLDER_HERE';
mockDir.setContent({
'before.js': 'NO_PLACEHOLDER_HERE',
'not-js.txt': 'NO_PLACEHOLDER_HERE',
'main.js': '"__APP_INJECTED_RUNTIME_CONFIG__"',
'after.js': 'NO_PLACEHOLDER_HERE',
});
await injectConfig({
...baseOptions,
appConfigs: [{ data: { x: 0 }, context: 'test' }],
});
expect(fsMock.readFile).toHaveBeenCalledTimes(2);
expect(fsMock.readFile).toHaveBeenNthCalledWith(
1,
resolvePath(MOCK_DIR, 'before.js'),
'utf8',
);
expect(fsMock.readFile).toHaveBeenNthCalledWith(
2,
resolvePath(MOCK_DIR, 'main.js'),
'utf8',
);
expect(fsMock.writeFile).toHaveBeenCalledTimes(1);
expect(fsMock.writeFile).toHaveBeenCalledWith(
resolvePath(MOCK_DIR, 'main.js'),
'/*__APP_INJECTED_CONFIG_MARKER__*/"[{\\"data\\":{\\"x\\":0},\\"context\\":\\"test\\"}]"/*__INJECTED_END__*/',
'utf8',
);
// eslint-disable-next-line no-eval
expect(JSON.parse(eval(fsMock.writeFile.mock.calls[0][1]))).toEqual([
{
data: {
x: 0,
},
context: 'test',
},
]);
expect(mockDir.content()).toEqual({
'before.js': 'NO_PLACEHOLDER_HERE',
'not-js.txt': 'NO_PLACEHOLDER_HERE',
'main.js':
'/*__APP_INJECTED_CONFIG_MARKER__*/"[{\\"data\\":{\\"x\\":0},\\"context\\":\\"test\\"}]"/*__INJECTED_END__*/',
'after.js': 'NO_PLACEHOLDER_HERE',
});
});
it('should re-inject config', async () => {
fsMock.readdir.mockResolvedValue(['main.js'] as any);
readFileMock.mockResolvedValue(
'JSON.parse("__APP_INJECTED_RUNTIME_CONFIG__")',
);
mockDir.setContent({
'main.js': 'JSON.parse("__APP_INJECTED_RUNTIME_CONFIG__")',
});
await injectConfig({
...baseOptions,
appConfigs: [{ data: { x: 0 }, context: 'test' }],
});
expect(fsMock.writeFile).toHaveBeenCalledTimes(1);
expect(fsMock.writeFile).toHaveBeenCalledWith(
resolvePath(MOCK_DIR, 'main.js'),
'JSON.parse(/*__APP_INJECTED_CONFIG_MARKER__*/"[{\\"data\\":{\\"x\\":0},\\"context\\":\\"test\\"}]"/*__INJECTED_END__*/)',
'utf8',
);
// eslint-disable-next-line no-eval
expect(eval(fsMock.writeFile.mock.calls[0][1])).toEqual([
{ data: { x: 0 }, context: 'test' },
]);
readFileMock.mockResolvedValue(fsMock.writeFile.mock.calls[0][1]);
expect(mockDir.content()).toEqual({
'main.js':
'JSON.parse(/*__APP_INJECTED_CONFIG_MARKER__*/"[{\\"data\\":{\\"x\\":0},\\"context\\":\\"test\\"}]"/*__INJECTED_END__*/)',
});
await injectConfig({
...baseOptions,
appConfigs: [{ data: { x: 1, y: 2 }, context: 'test' }],
});
expect(fsMock.writeFile).toHaveBeenCalledTimes(2);
expect(fsMock.writeFile).toHaveBeenLastCalledWith(
resolvePath(MOCK_DIR, 'main.js'),
'JSON.parse(/*__APP_INJECTED_CONFIG_MARKER__*/"[{\\"data\\":{\\"x\\":1,\\"y\\":2},\\"context\\":\\"test\\"}]"/*__INJECTED_END__*/)',
'utf8',
);
// eslint-disable-next-line no-eval
expect(eval(fsMock.writeFile.mock.calls[1][1])).toEqual([
{ data: { x: 1, y: 2 }, context: 'test' },
]);
expect(mockDir.content()).toEqual({
'main.js':
'JSON.parse(/*__APP_INJECTED_CONFIG_MARKER__*/"[{\\"data\\":{\\"x\\":1,\\"y\\":2},\\"context\\":\\"test\\"}]"/*__INJECTED_END__*/)',
});
});
it('should re-inject config repeatedly if needed', async () => {
fsMock.readdir.mockResolvedValue(['main.js'] as any);
readFileMock.mockResolvedValue(
'({ a: JSON.parse("__APP_INJECTED_RUNTIME_CONFIG__"), b: JSON.parse("__APP_INJECTED_RUNTIME_CONFIG__") })',
);
mockDir.setContent({
'main.js':
'({ a: JSON.parse("__APP_INJECTED_RUNTIME_CONFIG__"), b: JSON.parse("__APP_INJECTED_RUNTIME_CONFIG__") })',
});
await injectConfig({
...baseOptions,
appConfigs: [{ data: { x: 0 }, context: 'test' }],
});
expect(fsMock.writeFile).toHaveBeenCalledTimes(1);
expect(fsMock.writeFile).toHaveBeenCalledWith(
resolvePath(MOCK_DIR, 'main.js'),
'({ a: JSON.parse(/*__APP_INJECTED_CONFIG_MARKER__*/"[{\\"data\\":{\\"x\\":0},\\"context\\":\\"test\\"}]"/*__INJECTED_END__*/), b: JSON.parse(/*__APP_INJECTED_CONFIG_MARKER__*/"[{\\"data\\":{\\"x\\":0},\\"context\\":\\"test\\"}]"/*__INJECTED_END__*/) })',
'utf8',
);
// eslint-disable-next-line no-eval
expect(eval(fsMock.writeFile.mock.calls[0][1]).a).toEqual([
{ data: { x: 0 }, context: 'test' },
]);
// eslint-disable-next-line no-eval
expect(eval(fsMock.writeFile.mock.calls[0][1]).b).toEqual([
{ data: { x: 0 }, context: 'test' },
]);
readFileMock.mockResolvedValue(fsMock.writeFile.mock.calls[0][1]);
expect(mockDir.content()).toEqual({
'main.js':
'({ a: JSON.parse(/*__APP_INJECTED_CONFIG_MARKER__*/"[{\\"data\\":{\\"x\\":0},\\"context\\":\\"test\\"}]"/*__INJECTED_END__*/), b: JSON.parse(/*__APP_INJECTED_CONFIG_MARKER__*/"[{\\"data\\":{\\"x\\":0},\\"context\\":\\"test\\"}]"/*__INJECTED_END__*/) })',
});
await injectConfig({
...baseOptions,
appConfigs: [{ data: { x: 1, y: 2 }, context: 'test' }],
});
expect(fsMock.writeFile).toHaveBeenCalledTimes(2);
expect(fsMock.writeFile).toHaveBeenLastCalledWith(
resolvePath(MOCK_DIR, 'main.js'),
'({ a: JSON.parse(/*__APP_INJECTED_CONFIG_MARKER__*/"[{\\"data\\":{\\"x\\":1,\\"y\\":2},\\"context\\":\\"test\\"}]"/*__INJECTED_END__*/), b: JSON.parse(/*__APP_INJECTED_CONFIG_MARKER__*/"[{\\"data\\":{\\"x\\":1,\\"y\\":2},\\"context\\":\\"test\\"}]"/*__INJECTED_END__*/) })',
'utf8',
);
// eslint-disable-next-line no-eval
expect(eval(fsMock.writeFile.mock.calls[1][1]).a).toEqual([
{ data: { x: 1, y: 2 }, context: 'test' },
]);
// eslint-disable-next-line no-eval
expect(eval(fsMock.writeFile.mock.calls[1][1]).b).toEqual([
{ data: { x: 1, y: 2 }, context: 'test' },
]);
expect(mockDir.content()).toEqual({
'main.js':
'({ a: JSON.parse(/*__APP_INJECTED_CONFIG_MARKER__*/"[{\\"data\\":{\\"x\\":1,\\"y\\":2},\\"context\\":\\"test\\"}]"/*__INJECTED_END__*/), b: JSON.parse(/*__APP_INJECTED_CONFIG_MARKER__*/"[{\\"data\\":{\\"x\\":1,\\"y\\":2},\\"context\\":\\"test\\"}]"/*__INJECTED_END__*/) })',
});
});
});
@@ -26,21 +26,23 @@ jest.mock(
(...args: any[]) =>
commandExists(...args),
);
jest.mock('fs-extra');
import { ContainerRunner } from '@backstage/backend-common';
import fs from 'fs-extra';
import path from 'path';
import { PassThrough } from 'stream';
import { RailsNewRunner } from './railsNewRunner';
import { createMockDirectory } from '@backstage/backend-test-utils';
describe('Rails Templater', () => {
const containerRunner: jest.Mocked<ContainerRunner> = {
runContainer: jest.fn(),
};
const mockDir = createMockDirectory();
beforeEach(() => {
jest.clearAllMocks();
mockDir.clear();
});
describe('when running on docker', () => {
@@ -53,14 +55,15 @@ describe('Rails Templater', () => {
imageName: 'foo/rails-custom-image',
};
jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any);
jest
.spyOn(fs, 'realpath')
.mockImplementation(x => Promise.resolve(x.toString()));
mockDir.setContent({
intermediate: {
fakeGeneratedOutput: 'a',
},
});
const templater = new RailsNewRunner({ containerRunner });
await templater.run({
workspacePath: 'tempdir',
workspacePath: mockDir.path,
values,
logStream,
});
@@ -71,8 +74,8 @@ describe('Rails Templater', () => {
args: ['new', '/output/rails-project'],
envVars: { HOME: '/tmp' },
mountDirs: {
['tempdir']: '/input',
[path.join('tempdir', 'intermediate')]: '/output',
[mockDir.path]: '/input',
[path.join(mockDir.path, 'intermediate')]: '/output',
},
workingDir: '/input',
logStream: logStream,
@@ -88,11 +91,15 @@ describe('Rails Templater', () => {
imageName: 'foo/rails-custom-image',
};
jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any);
mockDir.setContent({
intermediate: {
fakeGeneratedOutput: 'a',
},
});
const templater = new RailsNewRunner({ containerRunner });
await templater.run({
workspacePath: 'tempdir',
workspacePath: mockDir.path,
values,
logStream,
});
@@ -114,11 +121,15 @@ describe('Rails Templater', () => {
imageName: 'foo/rails-custom-image',
};
jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any);
mockDir.setContent({
intermediate: {
fakeGeneratedOutput: 'a',
},
});
const templater = new RailsNewRunner({ containerRunner });
await templater.run({
workspacePath: 'tempdir',
workspacePath: mockDir.path,
values,
logStream: stream,
});
@@ -129,8 +140,8 @@ describe('Rails Templater', () => {
args: ['new', '/output/rails-project'],
envVars: { HOME: '/tmp' },
mountDirs: {
['tempdir']: '/input',
[path.join('tempdir', 'intermediate')]: '/output',
[mockDir.path]: '/input',
[path.join(mockDir.path, 'intermediate')]: '/output',
},
workingDir: '/input',
logStream: stream,
@@ -147,14 +158,15 @@ describe('Rails Templater', () => {
imageName: 'foo/rails-custom-image',
};
jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any);
jest
.spyOn(fs, 'realpath')
.mockImplementation(x => Promise.resolve(x.toString()));
mockDir.setContent({
intermediate: {
fakeGeneratedOutput: 'a',
},
});
const templater = new RailsNewRunner({ containerRunner });
await templater.run({
workspacePath: 'tempdir',
workspacePath: mockDir.path,
values,
logStream,
});
@@ -170,8 +182,8 @@ describe('Rails Templater', () => {
],
envVars: { HOME: '/tmp' },
mountDirs: {
['tempdir']: '/input',
[path.join('tempdir', 'intermediate')]: '/output',
[mockDir.path]: '/input',
[path.join(mockDir.path, 'intermediate')]: '/output',
},
workingDir: '/input',
logStream: logStream,
@@ -190,12 +202,16 @@ describe('Rails Templater', () => {
imageName: 'foo/rails-custom-image',
};
jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any);
mockDir.setContent({
intermediate: {
fakeGeneratedOutput: 'a',
},
});
commandExists.mockImplementationOnce(() => () => true);
const templater = new RailsNewRunner({ containerRunner });
await templater.run({
workspacePath: 'tempdir',
workspacePath: mockDir.path,
values,
logStream: stream,
});
@@ -204,11 +220,12 @@ describe('Rails Templater', () => {
command: 'rails',
args: expect.arrayContaining([
'new',
path.join('tempdir', 'intermediate', 'rails-project'),
path.join(mockDir.path, 'intermediate', 'rails-project'),
]),
logStream: stream,
});
});
it('update the template path to correct location', async () => {
const stream = new PassThrough();
@@ -220,12 +237,16 @@ describe('Rails Templater', () => {
imageName: 'foo/rails-custom-image',
};
jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any);
mockDir.setContent({
intermediate: {
fakeGeneratedOutput: 'a',
},
});
commandExists.mockImplementationOnce(() => () => true);
const templater = new RailsNewRunner({ containerRunner });
await templater.run({
workspacePath: 'tempdir',
workspacePath: mockDir.path,
values,
logStream: stream,
});
@@ -234,9 +255,9 @@ describe('Rails Templater', () => {
command: 'rails',
args: expect.arrayContaining([
'new',
path.join('tempdir', 'intermediate', 'rails-project'),
path.join(mockDir.path, 'intermediate', 'rails-project'),
'--template',
path.join('tempdir', './something.rb'),
path.join(mockDir.path, './something.rb'),
]),
logStream: stream,
});
@@ -247,14 +268,14 @@ describe('Rails Templater', () => {
it('throws an error', async () => {
const stream = new PassThrough();
jest
.spyOn(fs, 'readdir')
.mockImplementationOnce(() => Promise.resolve([]));
mockDir.setContent({
intermediate: {},
});
const templater = new RailsNewRunner({ containerRunner });
await expect(
templater.run({
workspacePath: 'tempdir',
workspacePath: mockDir.path,
values: {
owner: 'angeliski',
storePath: 'https://github.com/angeliski/rails-project',