From fb9e00a54a68402e25754799e40056c08493bd61 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 10 Sep 2022 14:37:49 +0200 Subject: [PATCH] create-app: move mock-fs calls into describe blocks Signed-off-by: Patrik Oldsberg --- packages/create-app/src/createApp.test.ts | 22 +- packages/create-app/src/lib/tasks.test.ts | 352 +++++++++++----------- 2 files changed, 190 insertions(+), 184 deletions(-) diff --git a/packages/create-app/src/createApp.test.ts b/packages/create-app/src/createApp.test.ts index d339460243..8e7b3bae7d 100644 --- a/packages/create-app/src/createApp.test.ts +++ b/packages/create-app/src/createApp.test.ts @@ -28,17 +28,6 @@ jest.mock('./lib/versions', () => ({ packageVersions: { root: '1.0.0' }, })); -beforeAll(() => { - mockFs({ - [`${__dirname}/package.json`]: '', // required by `findPaths(__dirname)` - 'templates/': mockFs.load(path.resolve(__dirname, '../templates/')), - }); -}); - -afterAll(() => { - mockFs.restore(); -}); - const promptMock = jest.spyOn(inquirer, 'prompt'); const checkPathExistsMock = jest.spyOn(tasks, 'checkPathExistsTask'); const templatingMock = jest.spyOn(tasks, 'templatingTask'); @@ -51,6 +40,17 @@ const moveAppMock = jest.spyOn(tasks, 'moveAppTask'); const buildAppMock = jest.spyOn(tasks, 'buildAppTask'); describe('command entrypoint', () => { + beforeAll(() => { + mockFs({ + [`${__dirname}/package.json`]: '', // required by `findPaths(__dirname)` + 'templates/': mockFs.load(path.resolve(__dirname, '../templates/')), + }); + }); + + afterAll(() => { + mockFs.restore(); + }); + beforeEach(() => { promptMock.mockResolvedValueOnce({ name: 'MyApp', diff --git a/packages/create-app/src/lib/tasks.test.ts b/packages/create-app/src/lib/tasks.test.ts index d2efe81b90..decc89fbd4 100644 --- a/packages/create-app/src/lib/tasks.test.ts +++ b/packages/create-app/src/lib/tasks.test.ts @@ -86,185 +86,191 @@ jest.mock('./versions', () => ({ }, })); -beforeEach(() => { - mockFs({ - 'projects/my-module.ts': '', - 'projects/dir/my-file.txt': '', - 'tmp/mockApp/.gitignore': '', - 'tmp/mockApp/package.json': '', - 'tmp/mockApp/packages/app/package.json': '', - // load templates into mock filesystem - 'templates/': mockFs.load(path.resolve(__dirname, '../../templates/')), - }); -}); - -afterEach(() => { - mockFs.restore(); -}); - -describe('checkAppExistsTask', () => { - it('should do nothing if the directory does not exist', async () => { - const dir = 'projects/'; - const name = 'MyNewApp'; - await expect(checkAppExistsTask(dir, name)).resolves.not.toThrow(); +describe('tasks', () => { + beforeEach(() => { + mockFs({ + 'projects/my-module.ts': '', + 'projects/dir/my-file.txt': '', + 'tmp/mockApp/.gitignore': '', + 'tmp/mockApp/package.json': '', + 'tmp/mockApp/packages/app/package.json': '', + // load templates into mock filesystem + 'templates/': mockFs.load(path.resolve(__dirname, '../../templates/')), + }); }); - it('should throw an error when a file of the same name exists', async () => { - const dir = 'projects/'; - const name = 'my-module.ts'; - await expect(checkAppExistsTask(dir, name)).rejects.toThrow( - 'already exists', - ); + afterEach(() => { + mockFs.restore(); }); - it('should throw an error when a directory of the same name exists', async () => { - const dir = 'projects/'; - const name = 'dir'; - await expect(checkAppExistsTask(dir, name)).rejects.toThrow( - 'already exists', - ); - }); -}); - -describe('checkPathExistsTask', () => { - it('should create a directory at the given path', async () => { - const appDir = 'projects/newProject'; - await expect(checkPathExistsTask(appDir)).resolves.not.toThrow(); - expect(fs.existsSync(appDir)).toBe(true); - }); - - it('should do nothing if a directory of the same name exists', async () => { - const appDir = 'projects/dir'; - await expect(checkPathExistsTask(appDir)).resolves.not.toThrow(); - expect(fs.existsSync(appDir)).toBe(true); - }); - - it('should fail if a file of the same name exists', async () => { - await expect(checkPathExistsTask('projects/my-module.ts')).rejects.toThrow( - 'already exists', - ); - }); -}); - -describe('createTemporaryAppFolderTask', () => { - it('should create a directory at a given path', async () => { - const tempDir = 'projects/tmpFolder'; - await expect(createTemporaryAppFolderTask(tempDir)).resolves.not.toThrow(); - expect(fs.existsSync(tempDir)).toBe(true); - }); - - it('should fail if a directory of the same name exists', async () => { - const tempDir = 'projects/dir'; - await expect(createTemporaryAppFolderTask(tempDir)).rejects.toThrow( - 'file already exists', - ); - }); - - it('should fail if a file of the same name exists', async () => { - const tempDir = 'projects/dir/my-file.txt'; - await expect(createTemporaryAppFolderTask(tempDir)).rejects.toThrow( - 'file already exists', - ); - }); -}); - -describe('buildAppTask', () => { - it('should change to `appDir` and run `yarn install` and `yarn tsc`', async () => { - const mockChdir = jest.spyOn(process, 'chdir'); - const mockExec = child_process.exec as unknown as jest.MockedFunction< - ( - command: string, - callback: (error: null, stdout: string, stderr: string) => void, - ) => void - >; - - // requires callback implementation to support `promisify` wrapper - // https://stackoverflow.com/a/60579617/10044859 - mockExec.mockImplementation((_command, callback) => { - callback(null, 'standard out', 'standard error'); + describe('checkAppExistsTask', () => { + it('should do nothing if the directory does not exist', async () => { + const dir = 'projects/'; + const name = 'MyNewApp'; + await expect(checkAppExistsTask(dir, name)).resolves.not.toThrow(); }); - const appDir = 'projects/dir'; - await expect(buildAppTask(appDir)).resolves.not.toThrow(); - expect(mockChdir).toHaveBeenCalledTimes(2); - expect(mockChdir).toHaveBeenNthCalledWith(1, appDir); - expect(mockChdir).toHaveBeenNthCalledWith(2, appDir); - expect(mockExec).toHaveBeenCalledTimes(2); - expect(mockExec).toHaveBeenNthCalledWith( - 1, - 'yarn install', - expect.any(Function), - ); - expect(mockExec).toHaveBeenNthCalledWith( - 2, - 'yarn tsc', - expect.any(Function), - ); - }); - - it('should fail if project directory does not exist', async () => { - const appDir = 'projects/missingProject'; - await expect(buildAppTask(appDir)).rejects.toThrow( - 'no such file or directory', - ); - }); -}); - -describe('moveAppTask', () => { - const tempDir = 'tmp/mockApp/'; - const id = 'myApp'; - - it('should move all files in the temp dir to the target dir', async () => { - const destination = 'projects/mockApp'; - await moveAppTask(tempDir, destination, id); - expect(fs.existsSync('projects/mockApp/.gitignore')).toBe(true); - expect(fs.existsSync('projects/mockApp/package.json')).toBe(true); - expect(fs.existsSync('projects/mockApp/packages/app/package.json')).toBe( - true, - ); - }); - - it('should fail to move files if destination already exists', async () => { - const destination = 'projects'; - await expect(moveAppTask(tempDir, destination, id)).rejects.toThrow( - 'dest already exists', - ); - }); - - it('should remove temporary files if move succeeded', async () => { - const destination = 'projects/mockApp'; - await moveAppTask(tempDir, destination, id); - expect(fs.existsSync('tmp/mockApp')).toBe(false); - }); - - it('should remove temporary files if move failed', async () => { - const destination = 'projects'; - await expect(moveAppTask(tempDir, destination, id)).rejects.toThrow(); - expect(fs.existsSync('tmp/mockApp')).toBe(false); - }); -}); - -describe('templatingTask', () => { - it('should generate a project populating context parameters', async () => { - const templateDir = 'templates/default-app'; - const destinationDir = 'templatedApp'; - const context = { - name: 'SuperCoolBackstageInstance', - dbTypeSqlite: true, - }; - await templatingTask(templateDir, destinationDir, context); - expect(fs.existsSync('templatedApp/package.json')).toBe(true); - expect(fs.existsSync('templatedApp/.dockerignore')).toBe(true); - await expect(fs.readJson('templatedApp/backstage.json')).resolves.toEqual({ - version: '1.2.3', + it('should throw an error when a file of the same name exists', async () => { + const dir = 'projects/'; + const name = 'my-module.ts'; + await expect(checkAppExistsTask(dir, name)).rejects.toThrow( + 'already exists', + ); + }); + + it('should throw an error when a directory of the same name exists', async () => { + const dir = 'projects/'; + const name = 'dir'; + await expect(checkAppExistsTask(dir, name)).rejects.toThrow( + 'already exists', + ); + }); + }); + + describe('checkPathExistsTask', () => { + it('should create a directory at the given path', async () => { + const appDir = 'projects/newProject'; + await expect(checkPathExistsTask(appDir)).resolves.not.toThrow(); + expect(fs.existsSync(appDir)).toBe(true); + }); + + it('should do nothing if a directory of the same name exists', async () => { + const appDir = 'projects/dir'; + await expect(checkPathExistsTask(appDir)).resolves.not.toThrow(); + expect(fs.existsSync(appDir)).toBe(true); + }); + + it('should fail if a file of the same name exists', async () => { + await expect( + checkPathExistsTask('projects/my-module.ts'), + ).rejects.toThrow('already exists'); + }); + }); + + describe('createTemporaryAppFolderTask', () => { + it('should create a directory at a given path', async () => { + const tempDir = 'projects/tmpFolder'; + await expect( + createTemporaryAppFolderTask(tempDir), + ).resolves.not.toThrow(); + expect(fs.existsSync(tempDir)).toBe(true); + }); + + it('should fail if a directory of the same name exists', async () => { + const tempDir = 'projects/dir'; + await expect(createTemporaryAppFolderTask(tempDir)).rejects.toThrow( + 'file already exists', + ); + }); + + it('should fail if a file of the same name exists', async () => { + const tempDir = 'projects/dir/my-file.txt'; + await expect(createTemporaryAppFolderTask(tempDir)).rejects.toThrow( + 'file already exists', + ); + }); + }); + + describe('buildAppTask', () => { + it('should change to `appDir` and run `yarn install` and `yarn tsc`', async () => { + const mockChdir = jest.spyOn(process, 'chdir'); + const mockExec = child_process.exec as unknown as jest.MockedFunction< + ( + command: string, + callback: (error: null, stdout: string, stderr: string) => void, + ) => void + >; + + // requires callback implementation to support `promisify` wrapper + // https://stackoverflow.com/a/60579617/10044859 + mockExec.mockImplementation((_command, callback) => { + callback(null, 'standard out', 'standard error'); + }); + + const appDir = 'projects/dir'; + await expect(buildAppTask(appDir)).resolves.not.toThrow(); + expect(mockChdir).toHaveBeenCalledTimes(2); + expect(mockChdir).toHaveBeenNthCalledWith(1, appDir); + expect(mockChdir).toHaveBeenNthCalledWith(2, appDir); + expect(mockExec).toHaveBeenCalledTimes(2); + expect(mockExec).toHaveBeenNthCalledWith( + 1, + 'yarn install', + expect.any(Function), + ); + expect(mockExec).toHaveBeenNthCalledWith( + 2, + 'yarn tsc', + expect.any(Function), + ); + }); + + it('should fail if project directory does not exist', async () => { + const appDir = 'projects/missingProject'; + await expect(buildAppTask(appDir)).rejects.toThrow( + 'no such file or directory', + ); + }); + }); + + describe('moveAppTask', () => { + const tempDir = 'tmp/mockApp/'; + const id = 'myApp'; + + it('should move all files in the temp dir to the target dir', async () => { + const destination = 'projects/mockApp'; + await moveAppTask(tempDir, destination, id); + expect(fs.existsSync('projects/mockApp/.gitignore')).toBe(true); + expect(fs.existsSync('projects/mockApp/package.json')).toBe(true); + expect(fs.existsSync('projects/mockApp/packages/app/package.json')).toBe( + true, + ); + }); + + it('should fail to move files if destination already exists', async () => { + const destination = 'projects'; + await expect(moveAppTask(tempDir, destination, id)).rejects.toThrow( + 'dest already exists', + ); + }); + + it('should remove temporary files if move succeeded', async () => { + const destination = 'projects/mockApp'; + await moveAppTask(tempDir, destination, id); + expect(fs.existsSync('tmp/mockApp')).toBe(false); + }); + + it('should remove temporary files if move failed', async () => { + const destination = 'projects'; + await expect(moveAppTask(tempDir, destination, id)).rejects.toThrow(); + expect(fs.existsSync('tmp/mockApp')).toBe(false); + }); + }); + + describe('templatingTask', () => { + it('should generate a project populating context parameters', async () => { + const templateDir = 'templates/default-app'; + const destinationDir = 'templatedApp'; + const context = { + name: 'SuperCoolBackstageInstance', + dbTypeSqlite: true, + }; + await templatingTask(templateDir, destinationDir, context); + expect(fs.existsSync('templatedApp/package.json')).toBe(true); + expect(fs.existsSync('templatedApp/.dockerignore')).toBe(true); + await expect(fs.readJson('templatedApp/backstage.json')).resolves.toEqual( + { + version: '1.2.3', + }, + ); + // catalog was populated with `context.name` + expect( + fs.readFileSync('templatedApp/catalog-info.yaml', 'utf-8'), + ).toContain('name: SuperCoolBackstageInstance'); + // backend dependencies include `sqlite3` from `context.SQLite` + expect( + fs.readFileSync('templatedApp/packages/backend/package.json', 'utf-8'), + ).toContain('sqlite3"'); }); - // catalog was populated with `context.name` - expect( - fs.readFileSync('templatedApp/catalog-info.yaml', 'utf-8'), - ).toContain('name: SuperCoolBackstageInstance'); - // backend dependencies include `sqlite3` from `context.SQLite` - expect( - fs.readFileSync('templatedApp/packages/backend/package.json', 'utf-8'), - ).toContain('sqlite3"'); }); });