From 2f81fd8bf46291a8bfe13156e109c14e5db29150 Mon Sep 17 00:00:00 2001 From: ChristopherPHolder Date: Fri, 23 Feb 2024 14:56:45 +0100 Subject: [PATCH 1/8] test: decouple load flow test from filesystem --- .../collect/utils/user-flow/load-flow.test.ts | 96 ------------------- .../collect/utils/user-flow/load-flow.ts | 6 +- .../utils/user-flow/load-flow.unit.test.ts | 60 ++++++++++++ 3 files changed, 63 insertions(+), 99 deletions(-) delete mode 100644 packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.test.ts create mode 100644 packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts diff --git a/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.test.ts b/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.test.ts deleted file mode 100644 index f31729a8c..000000000 --- a/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.test.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { join } from 'path'; -import { DEFAULT_COLLECT_UF_PATH } from '../../options/ufPath.constant'; -import { DEFAULT_PERSIST_OUT_PATH } from '../../options/outPath.constant'; -import { loadFlow } from './load-flow'; -import { - INITIATED_PRJ_CFG, - INITIATED_RC_JSON, - VALIDE_EXAMPLE_USERFLOW_CONTENT, - VALIDE_EXAMPLE_USERFLOW_NAME, - WRONG_EXT_USERFLOW_CONTENT, - WRONG_EXT_USERFLOW_NAME, - WRONG_MOD_EXPORT_USERFLOW_CONTENT, - WRONG_MOD_EXPORT_USERFLOW_NAME -} from 'test-data'; -import { - UserFlowCliProject, - UserFlowCliProjectFactory, - UserFlowProjectConfig -} from '@push-based/user-flow-cli-testing'; - - -const prjRelativeOutPath = INITIATED_RC_JSON?.persist?.outPath || DEFAULT_PERSIST_OUT_PATH; - -// prj.readUserFlow('name.uf.ts') => process.cwd() + sandbox-setup/src/lib/user-flows/name.uf.ts -// prj.readUserFlow('name.uf.ts') => ./sandbox-setup/src/lib/user-flows/name.uf.ts - -// ./src/lib/user-flows (from rc.json) -const prjRelativeUfPath = INITIATED_RC_JSON?.collect?.ufPath || DEFAULT_COLLECT_UF_PATH; -const flowValidationCfg: UserFlowProjectConfig = { - ...INITIATED_PRJ_CFG, - create: { - [join(prjRelativeUfPath, VALIDE_EXAMPLE_USERFLOW_NAME)]: VALIDE_EXAMPLE_USERFLOW_CONTENT, - [join(prjRelativeUfPath, WRONG_EXT_USERFLOW_NAME)]: WRONG_EXT_USERFLOW_CONTENT, - [join(prjRelativeUfPath, WRONG_MOD_EXPORT_USERFLOW_NAME)]: WRONG_MOD_EXPORT_USERFLOW_CONTENT - } -}; -let initializedPrj: UserFlowCliProject; -let originalCwd = process.cwd(); - -describe('loading user-flow scripts for execution', () => { - beforeAll(async () => { - process.chdir(INITIATED_PRJ_CFG.root); - }); - beforeEach(async () => { - process.chdir(flowValidationCfg.root); - if (!initializedPrj) { - initializedPrj = await UserFlowCliProjectFactory.create(flowValidationCfg); - } - await initializedPrj.setup(); - }); - afterEach(async () => { - await initializedPrj.teardown(); - }); - afterAll(async () => { - process.chdir(originalCwd); - }); - - it('should return flows if files with ts or js are in ufPath', async () => { - let validUfDirPath = prjRelativeUfPath; - const ufPath = validUfDirPath; - const collectOptions = { url: 'example.com', ufPath }; - - expect(initializedPrj.userFlowPath()).toBe(join(process.cwd(), ufPath)); - const userFlows = loadFlow(collectOptions); - expect(userFlows.length).toBe(2); - }); - - it('should return flows if ufPath points a user-flow file and not a directory', () => { - let validUfPath = join(prjRelativeUfPath, VALIDE_EXAMPLE_USERFLOW_NAME); - const ufPath = validUfPath; - const collectOptions = { url: 'example.com', ufPath }; - - expect(initializedPrj.userFlowPath(VALIDE_EXAMPLE_USERFLOW_NAME)).toBe(join(process.cwd(), ufPath)); - const userFlows = loadFlow(collectOptions); - expect(userFlows.length).toBe(1); - }); - - it('should return flows if files with ts or js are in ufPath and ignore files with other extensions', () => { - let dirtyUfDirPath = join(prjRelativeUfPath); - const ufPath = dirtyUfDirPath; - const collectOptions = { url: 'example.com', ufPath }; - expect(initializedPrj.userFlowPath()).toBe(join(process.cwd(), ufPath)); - const userFlows = loadFlow(collectOptions); - expect(userFlows.length).toBe(2); - }); - - it('should throw if no user flows are in the directory', () => { - let emptyUfDirPath = join(prjRelativeOutPath); - const ufPath = emptyUfDirPath; - const collectOptions = { url: 'example.com', ufPath }; - const userFlows = () => loadFlow(collectOptions); - expect(initializedPrj.outputPath()).toBe(join(process.cwd(), ufPath)); - expect(userFlows).toThrow(`No user flows found in ${ufPath}`); - }); -}); - diff --git a/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.ts b/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.ts index 11fa6580f..3bf1bdd45 100644 --- a/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.ts +++ b/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.ts @@ -1,6 +1,6 @@ +import { join } from 'node:path'; +import { existsSync, lstatSync, readdirSync } from 'node:fs'; import { UserFlowProvider } from './types'; -import { join } from 'path'; -import { existsSync, lstatSync, readdirSync } from 'fs'; import { resolveAnyFile } from '../../../../core/file'; import { CollectRcOptions } from '../../options/types'; @@ -8,7 +8,7 @@ export function loadFlow(collect: Pick): ({ exports: const { ufPath } = collect; const path = join(process.cwd(), ufPath); if (!existsSync(path)) { - throw new Error(`ufPath: ${path} is no directory`); + throw new Error(`ufPath: ${path} is not file or directory`); } let files: string[]; diff --git a/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts b/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts new file mode 100644 index 000000000..0a44705a5 --- /dev/null +++ b/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts @@ -0,0 +1,60 @@ +import { loadFlow } from './load-flow'; +import * as fileHelpers from '../../../../core/file'; +import * as fs from 'node:fs'; + +jest.mock('node:fs'); +jest.mock('../../../../core/file'); + +describe('loading user-flow scripts for execution', () => { + + beforeEach(() => { + jest.resetAllMocks(); + }) + + it('should throw if ufPath does not exist', () => { + const existsSyncSpy = jest.spyOn(fs, 'existsSync').mockReturnValue(false); + const loadFlowFn = () => loadFlow({ ufPath: './path' }); + expect(loadFlowFn).toThrow(); + expect(existsSyncSpy).toHaveBeenCalled(); + }); + + it('should throw if ufPath points to a file and it does not end in with ts or js', () => { + jest.spyOn(fs, 'existsSync').mockReturnValue(true); + jest.spyOn(fs, 'lstatSync').mockReturnValue({ isDirectory: () => false } as fs.Stats); + const resolveAnyFileSpy = jest.spyOn(fileHelpers, 'resolveAnyFile'); + const loadFlowFn = () => loadFlow({ ufPath: './path' }); + expect(loadFlowFn).toThrow(); + expect(resolveAnyFileSpy).not.toHaveBeenCalled(); + }); + + it('should throw if ufPath points to a directory and it does not contain any files that end with ts or js', () => { + jest.spyOn(fs, 'existsSync').mockReturnValue(true); + jest.spyOn(fs, 'lstatSync').mockReturnValue({ isDirectory: () => true } as fs.Stats); + jest.spyOn(fs, 'readdirSync').mockReturnValue(['file.json' as unknown as fs.Dirent]) + const resolveAnyFileSpy = jest.spyOn(fileHelpers, 'resolveAnyFile'); + const loadFlowFn = () => loadFlow({ ufPath: './path' }); + expect(loadFlowFn).toThrow(); + expect(resolveAnyFileSpy).not.toHaveBeenCalled(); + }); + + it('should extract all file paths in the directory if ufPath points to a directory', () => { + jest.spyOn(fs, 'existsSync').mockReturnValue(true); + jest.spyOn(fileHelpers, 'resolveAnyFile').mockReturnValue('Flow Dummy' as any); + const isDirectorySpy = jest.spyOn(fs, 'lstatSync').mockReturnValue({ isDirectory: () => true } as fs.Stats); + const readdirSyncSpy = jest.spyOn(fs, 'readdirSync').mockReturnValue(['file.ts' as unknown as fs.Dirent]) + loadFlow({ ufPath: './path' }); + expect(isDirectorySpy).toHaveBeenCalled(); + expect(readdirSyncSpy).toHaveBeenCalled(); + }); + + it('should only resolve files ending in ts or js', () => { + jest.spyOn(fs, 'existsSync').mockReturnValue(true); + jest.spyOn(fs, 'lstatSync').mockReturnValue({ isDirectory: () => true } as fs.Stats); + jest.spyOn(fs, 'readdirSync') + .mockReturnValue(['file.ts', 'file.js', 'file.tsx', 'file.json', 'file.js.json'] as unknown as fs.Dirent[]); + const resolveAnyFileSpy = jest.spyOn(fileHelpers, 'resolveAnyFile'); + loadFlow({ ufPath: './path' }); + expect(resolveAnyFileSpy).toHaveBeenCalledTimes(2); + }) +}); + From 92316386808de80419d37acbf2292c661d098722 Mon Sep 17 00:00:00 2001 From: Christopher Holder <40126819+ChristopherPHolder@users.noreply.github.com> Date: Fri, 23 Feb 2024 19:32:46 +0100 Subject: [PATCH 2/8] test: properly clear mocks between test cases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Katka Pilátová --- .../lib/commands/collect/utils/user-flow/load-flow.unit.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts b/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts index 0a44705a5..ba21aece6 100644 --- a/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts +++ b/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts @@ -8,7 +8,7 @@ jest.mock('../../../../core/file'); describe('loading user-flow scripts for execution', () => { beforeEach(() => { - jest.resetAllMocks(); + jest.clearAllMocks(); }) it('should throw if ufPath does not exist', () => { From 7aee4682b0944439c9efededa3692196ba05b31e Mon Sep 17 00:00:00 2001 From: Christopher Holder <40126819+ChristopherPHolder@users.noreply.github.com> Date: Fri, 23 Feb 2024 19:33:42 +0100 Subject: [PATCH 3/8] test: improve lexical error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Katka Pilátová --- .../cli/src/lib/commands/collect/utils/user-flow/load-flow.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.ts b/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.ts index 3bf1bdd45..6f4119bf3 100644 --- a/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.ts +++ b/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.ts @@ -8,7 +8,7 @@ export function loadFlow(collect: Pick): ({ exports: const { ufPath } = collect; const path = join(process.cwd(), ufPath); if (!existsSync(path)) { - throw new Error(`ufPath: ${path} is not file or directory`); + throw new Error(`ufPath: ${path} is neither a file nor a directory`); } let files: string[]; From 34431ce75c326ebe19f56e69fbf1bcf1c0aad9ba Mon Sep 17 00:00:00 2001 From: Christopher Holder <40126819+ChristopherPHolder@users.noreply.github.com> Date: Fri, 23 Feb 2024 19:34:30 +0100 Subject: [PATCH 4/8] test: extend test case to check which files where processed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Katka Pilátová --- .../collect/utils/user-flow/load-flow.unit.test.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts b/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts index ba21aece6..f17dabc91 100644 --- a/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts +++ b/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts @@ -55,6 +55,14 @@ describe('loading user-flow scripts for execution', () => { const resolveAnyFileSpy = jest.spyOn(fileHelpers, 'resolveAnyFile'); loadFlow({ ufPath: './path' }); expect(resolveAnyFileSpy).toHaveBeenCalledTimes(2); + expect(resolveAnyFileSpy).toHaveBeenNthCalledWith( + 1, + expect.stringContaining('file.ts') + ); + expect(resolveAnyFileSpy).toHaveBeenNthCalledWith( + 2, + expect.stringContaining('file.js') + ); }) }); From 48021648aa0fc422672d29c728f5899af83bfc52 Mon Sep 17 00:00:00 2001 From: Christopher Holder <40126819+ChristopherPHolder@users.noreply.github.com> Date: Fri, 23 Feb 2024 19:35:53 +0100 Subject: [PATCH 5/8] test: remove unnecessary named variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Katka Pilátová --- .../commands/collect/utils/user-flow/load-flow.unit.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts b/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts index f17dabc91..bc061d194 100644 --- a/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts +++ b/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts @@ -22,8 +22,7 @@ describe('loading user-flow scripts for execution', () => { jest.spyOn(fs, 'existsSync').mockReturnValue(true); jest.spyOn(fs, 'lstatSync').mockReturnValue({ isDirectory: () => false } as fs.Stats); const resolveAnyFileSpy = jest.spyOn(fileHelpers, 'resolveAnyFile'); - const loadFlowFn = () => loadFlow({ ufPath: './path' }); - expect(loadFlowFn).toThrow(); + expect(() => loadFlow({ ufPath: './path' })).toThrow(); expect(resolveAnyFileSpy).not.toHaveBeenCalled(); }); From e7d9ed1ff1c1a6041ae6580e6bb564f859d94e29 Mon Sep 17 00:00:00 2001 From: ChristopherPHolder Date: Fri, 23 Feb 2024 19:45:57 +0100 Subject: [PATCH 6/8] test: reduce named vars --- .../commands/collect/utils/user-flow/load-flow.unit.test.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts b/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts index bc061d194..2f23b4866 100644 --- a/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts +++ b/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts @@ -13,8 +13,7 @@ describe('loading user-flow scripts for execution', () => { it('should throw if ufPath does not exist', () => { const existsSyncSpy = jest.spyOn(fs, 'existsSync').mockReturnValue(false); - const loadFlowFn = () => loadFlow({ ufPath: './path' }); - expect(loadFlowFn).toThrow(); + expect(() => loadFlow({ ufPath: './path' })).toThrow(); expect(existsSyncSpy).toHaveBeenCalled(); }); @@ -31,8 +30,7 @@ describe('loading user-flow scripts for execution', () => { jest.spyOn(fs, 'lstatSync').mockReturnValue({ isDirectory: () => true } as fs.Stats); jest.spyOn(fs, 'readdirSync').mockReturnValue(['file.json' as unknown as fs.Dirent]) const resolveAnyFileSpy = jest.spyOn(fileHelpers, 'resolveAnyFile'); - const loadFlowFn = () => loadFlow({ ufPath: './path' }); - expect(loadFlowFn).toThrow(); + expect(() => loadFlow({ ufPath: './path' })).toThrow(); expect(resolveAnyFileSpy).not.toHaveBeenCalled(); }); From 6dcc007c3f40a8ada6dfcc86cea5f44a09b532d3 Mon Sep 17 00:00:00 2001 From: ChristopherPHolder Date: Fri, 23 Feb 2024 19:46:24 +0100 Subject: [PATCH 7/8] test: make test more expressive --- .../lib/commands/collect/utils/user-flow/load-flow.unit.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts b/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts index 2f23b4866..7007e5f0a 100644 --- a/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts +++ b/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts @@ -21,7 +21,7 @@ describe('loading user-flow scripts for execution', () => { jest.spyOn(fs, 'existsSync').mockReturnValue(true); jest.spyOn(fs, 'lstatSync').mockReturnValue({ isDirectory: () => false } as fs.Stats); const resolveAnyFileSpy = jest.spyOn(fileHelpers, 'resolveAnyFile'); - expect(() => loadFlow({ ufPath: './path' })).toThrow(); + expect(() => loadFlow({ ufPath: './path/file.json' })).toThrow(); expect(resolveAnyFileSpy).not.toHaveBeenCalled(); }); From 33d469e209af372dda2ff877a39c318443c3204f Mon Sep 17 00:00:00 2001 From: ChristopherPHolder Date: Fri, 23 Feb 2024 19:53:09 +0100 Subject: [PATCH 8/8] test: make test more expressive --- .../commands/collect/utils/user-flow/load-flow.unit.test.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts b/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts index 7007e5f0a..5cd312634 100644 --- a/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts +++ b/packages/cli/src/lib/commands/collect/utils/user-flow/load-flow.unit.test.ts @@ -39,9 +39,11 @@ describe('loading user-flow scripts for execution', () => { jest.spyOn(fileHelpers, 'resolveAnyFile').mockReturnValue('Flow Dummy' as any); const isDirectorySpy = jest.spyOn(fs, 'lstatSync').mockReturnValue({ isDirectory: () => true } as fs.Stats); const readdirSyncSpy = jest.spyOn(fs, 'readdirSync').mockReturnValue(['file.ts' as unknown as fs.Dirent]) - loadFlow({ ufPath: './path' }); + loadFlow({ ufPath: './user-flow-dir-path' }); expect(isDirectorySpy).toHaveBeenCalled(); - expect(readdirSyncSpy).toHaveBeenCalled(); + expect(readdirSyncSpy).toHaveBeenCalledWith( + expect.stringContaining('user-flow-dir-path') + ); }); it('should only resolve files ending in ts or js', () => {