From 262f03c11e43d3755d66d8b29bbfa1f718d4ee08 Mon Sep 17 00:00:00 2001 From: Peter Smith Date: Wed, 15 May 2024 10:48:53 +0100 Subject: [PATCH 1/7] Moved setupProgram and related tests --- packages/create-fuels/src/cli.ts | 21 ++----------- .../create-fuels/src/lib/setupProgram.test.ts | 30 +++++++++++++++++++ packages/create-fuels/src/lib/setupProgram.ts | 18 +++++++++++ packages/create-fuels/test/cli.test.ts | 27 ----------------- 4 files changed, 51 insertions(+), 45 deletions(-) create mode 100644 packages/create-fuels/src/lib/setupProgram.test.ts create mode 100644 packages/create-fuels/src/lib/setupProgram.ts diff --git a/packages/create-fuels/src/cli.ts b/packages/create-fuels/src/cli.ts index 98d7c040949..2f747e785bd 100644 --- a/packages/create-fuels/src/cli.ts +++ b/packages/create-fuels/src/cli.ts @@ -1,14 +1,12 @@ import toml from '@iarna/toml'; import chalk from 'chalk'; import { execSync } from 'child_process'; -import { Command } from 'commander'; +import type { Command } from 'commander'; import { existsSync, readFileSync, rmSync, writeFileSync } from 'fs'; import { cp, mkdir, rename } from 'fs/promises'; import ora from 'ora'; import { join } from 'path'; -import packageJson from '../package.json'; - import { tryInstallFuelUp } from './lib'; import { promptForProgramsToInclude, @@ -17,6 +15,8 @@ import { } from './prompts'; import { error, log } from './utils/logger'; +export { setupProgram } from './lib/setupProgram'; + export type ProgramsToInclude = { contract: boolean; predicate: boolean; @@ -52,21 +52,6 @@ function writeEnvFile(envFilePath: string, programsToInclude: ProgramsToInclude) writeFileSync(envFilePath, newFileContents); } -export const setupProgram = () => { - const program = new Command(packageJson.name) - .version(packageJson.version) - .arguments('[projectDirectory]') - .option('-c, --contract', 'Include contract program') - .option('-p, --predicate', 'Include predicate program') - .option('-s, --script', 'Include script program') - .option('--pnpm', 'Use pnpm as the package manager') - .option('--npm', 'Use npm as the package manager') - .option('--verbose', 'Enable verbose logging') - .addHelpCommand() - .showHelpAfterError(true); - return program; -}; - export const runScaffoldCli = async ({ program, args = process.argv, diff --git a/packages/create-fuels/src/lib/setupProgram.test.ts b/packages/create-fuels/src/lib/setupProgram.test.ts new file mode 100644 index 00000000000..6351950189a --- /dev/null +++ b/packages/create-fuels/src/lib/setupProgram.test.ts @@ -0,0 +1,30 @@ +import { setupProgram } from "./setupProgram"; + +describe(() => { + test('setupProgram takes in args properly', () => { + const program = setupProgram(); + program.parse(['', '', 'test-project-name', '-c', '-p', '-s', '--pnpm', '--npm']); + expect(program.args[0]).toBe('test-project-name'); + expect(program.opts().contract).toBe(true); + expect(program.opts().predicate).toBe(true); + expect(program.opts().script).toBe(true); + expect(program.opts().pnpm).toBe(true); + expect(program.opts().npm).toBe(true); + }); + + test('setupProgram takes in combined args properly', () => { + const program = setupProgram(); + program.parse(['', '', '-cps']); + expect(program.opts().contract).toBe(true); + expect(program.opts().predicate).toBe(true); + expect(program.opts().script).toBe(true); + }); + + test('setupProgram - no args', () => { + const program = setupProgram(); + program.parse([]); + expect(program.opts().contract).toBe(undefined); + expect(program.opts().predicate).toBe(undefined); + expect(program.opts().script).toBe(undefined); + }); +}) diff --git a/packages/create-fuels/src/lib/setupProgram.ts b/packages/create-fuels/src/lib/setupProgram.ts new file mode 100644 index 00000000000..99d093a3624 --- /dev/null +++ b/packages/create-fuels/src/lib/setupProgram.ts @@ -0,0 +1,18 @@ +import { Command } from "commander"; + +import packageJson from '../../package.json'; + +export const setupProgram = () => { + const program = new Command(packageJson.name) + .version(packageJson.version) + .arguments('[projectDirectory]') + .option('-c, --contract', 'Include contract program') + .option('-p, --predicate', 'Include predicate program') + .option('-s, --script', 'Include script program') + .option('--pnpm', 'Use pnpm as the package manager') + .option('--npm', 'Use npm as the package manager') + .option('--verbose', 'Enable verbose logging') + .addHelpCommand() + .showHelpAfterError(true); + return program; +}; diff --git a/packages/create-fuels/test/cli.test.ts b/packages/create-fuels/test/cli.test.ts index efd374c6aa4..d6d5bc3cc32 100644 --- a/packages/create-fuels/test/cli.test.ts +++ b/packages/create-fuels/test/cli.test.ts @@ -166,31 +166,4 @@ describe('CLI', () => { expect.stringContaining('You must include at least one Sway program.') ); }); - - test('setupProgram takes in args properly', () => { - const program = setupProgram(); - program.parse(['', '', 'test-project-name', '-c', '-p', '-s', '--pnpm', '--npm']); - expect(program.args[0]).toBe('test-project-name'); - expect(program.opts().contract).toBe(true); - expect(program.opts().predicate).toBe(true); - expect(program.opts().script).toBe(true); - expect(program.opts().pnpm).toBe(true); - expect(program.opts().npm).toBe(true); - }); - - test('setupProgram takes in combined args properly', () => { - const program = setupProgram(); - program.parse(['', '', '-cps']); - expect(program.opts().contract).toBe(true); - expect(program.opts().predicate).toBe(true); - expect(program.opts().script).toBe(true); - }); - - test('setupProgram - no args', () => { - const program = setupProgram(); - program.parse([]); - expect(program.opts().contract).toBe(undefined); - expect(program.opts().predicate).toBe(undefined); - expect(program.opts().script).toBe(undefined); - }); }); From e228f87892942088715f5cc13f6f5da8ec881fd7 Mon Sep 17 00:00:00 2001 From: Peter Smith Date: Wed, 15 May 2024 11:09:52 +0100 Subject: [PATCH 2/7] lint --- packages/create-fuels/src/lib/setupProgram.test.ts | 4 ++-- packages/create-fuels/src/lib/setupProgram.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/create-fuels/src/lib/setupProgram.test.ts b/packages/create-fuels/src/lib/setupProgram.test.ts index 6351950189a..ae006c264ff 100644 --- a/packages/create-fuels/src/lib/setupProgram.test.ts +++ b/packages/create-fuels/src/lib/setupProgram.test.ts @@ -1,4 +1,4 @@ -import { setupProgram } from "./setupProgram"; +import { setupProgram } from './setupProgram'; describe(() => { test('setupProgram takes in args properly', () => { @@ -27,4 +27,4 @@ describe(() => { expect(program.opts().predicate).toBe(undefined); expect(program.opts().script).toBe(undefined); }); -}) +}); diff --git a/packages/create-fuels/src/lib/setupProgram.ts b/packages/create-fuels/src/lib/setupProgram.ts index 99d093a3624..3c70f2c0a50 100644 --- a/packages/create-fuels/src/lib/setupProgram.ts +++ b/packages/create-fuels/src/lib/setupProgram.ts @@ -1,4 +1,4 @@ -import { Command } from "commander"; +import { Command } from 'commander'; import packageJson from '../../package.json'; From 4fce02f6e509bf09cd832555c72529fe886c8a7f Mon Sep 17 00:00:00 2001 From: Peter Smith Date: Wed, 15 May 2024 11:10:20 +0100 Subject: [PATCH 3/7] Added better handling of filesystem for create fuels CLI tests --- packages/create-fuels/.gitignore | 3 +- packages/create-fuels/test/cli.test.ts | 70 +++++++++---------- .../test/utils/bootstrapProject.ts | 54 ++++++++++++++ 3 files changed, 89 insertions(+), 38 deletions(-) create mode 100644 packages/create-fuels/test/utils/bootstrapProject.ts diff --git a/packages/create-fuels/.gitignore b/packages/create-fuels/.gitignore index f10e14abd57..8ac2fcd4a9a 100644 --- a/packages/create-fuels/.gitignore +++ b/packages/create-fuels/.gitignore @@ -1 +1,2 @@ -templates \ No newline at end of file +templates +test/__temp__* \ No newline at end of file diff --git a/packages/create-fuels/test/cli.test.ts b/packages/create-fuels/test/cli.test.ts index d6d5bc3cc32..39ba46471d3 100644 --- a/packages/create-fuels/test/cli.test.ts +++ b/packages/create-fuels/test/cli.test.ts @@ -1,10 +1,11 @@ -import fs, { cp } from 'fs/promises'; +import { mkdirSync } from 'fs'; import { glob } from 'glob'; -import { join } from 'path'; import type { ProgramsToInclude } from '../src/cli'; import { runScaffoldCli, setupProgram } from '../src/cli'; +import type { ProjectPaths } from './utils/bootstrapProject'; +import { bootstrapProject, cleanupFilesystem, resetFilesystem } from './utils/bootstrapProject'; import { mockLogger } from './utils/mockLogger'; const getAllFiles = async (pathToDir: string) => { @@ -70,63 +71,63 @@ const filterOriginalTemplateFiles = (files: string[], programsToInclude: Program return newFiles; }; -beforeEach(async () => { - // move the templates folder from the root of the project to the root of the create-fuels package temporarily. - // this is needed because of the way the create-fuels package is setup. - // it expects the templates folder to be in the root of the create-fuels package. we move it there in the prepublishOnly script - await cp(join(__dirname, '../../../templates'), join(__dirname, '../templates'), { - recursive: true, - }); -}); - -afterEach(async () => { - await fs.rm(join(__dirname, '../templates'), { recursive: true }); -}); - /** * @group node */ describe('CLI', () => { + const { error } = mockLogger(); + let paths: ProjectPaths; + + beforeEach(() => { + paths = bootstrapProject(__filename); + }); + + afterEach(() => { + resetFilesystem(paths.root); + resetFilesystem(paths.template); + vi.resetAllMocks(); + }); + + afterAll(() => { + cleanupFilesystem(); + }); + test.each(possibleProgramsToInclude)( 'create-fuels extracts the template to the specified directory', async (programsToInclude) => { - const args = generateArgs(programsToInclude, 'test-project'); - const program = setupProgram(); - program.parse(args); + const args = generateArgs(programsToInclude, paths.root); await runScaffoldCli({ - program, + program: setupProgram(), args, shouldInstallDeps: false, }); - let originalTemplateFiles = await getAllFiles(join(__dirname, '../templates/nextjs')); + let originalTemplateFiles = await getAllFiles(paths.template); originalTemplateFiles = filterOriginalTemplateFiles(originalTemplateFiles, programsToInclude); - const testProjectFiles = await getAllFiles('test-project'); + const testProjectFiles = await getAllFiles(paths.root); expect(originalTemplateFiles.sort()).toEqual(testProjectFiles.sort()); - - await fs.rm('test-project', { recursive: true }); } ); test('create-fuels reports an error if the project directory already exists', async () => { - await fs.mkdir('test-project-2'); - const { error } = mockLogger(); const args = generateArgs( { contract: true, predicate: true, script: true, }, - 'test-project-2' + paths.root ); - const program = setupProgram(); - program.parse(args); + // Generate the project once + mkdirSync(paths.root, { recursive: true }); + + // Generate the project again await runScaffoldCli({ - program, + program: setupProgram(), args, shouldInstallDeps: false, }).catch((e) => { @@ -134,27 +135,22 @@ describe('CLI', () => { }); expect(error).toHaveBeenCalledWith( - expect.stringContaining('A folder already exists at test-project-2') + expect.stringContaining(`A folder already exists at ${paths.root}`) ); - - await fs.rm('test-project-2', { recursive: true }); }); test('create-fuels reports an error if no programs are chosen to be included', async () => { - const { error } = mockLogger(); const args = generateArgs( { contract: false, predicate: false, script: false, }, - 'test-project-3' + paths.root ); - const program = setupProgram(); - program.parse(args); await runScaffoldCli({ - program, + program: setupProgram(), args, shouldInstallDeps: false, forceDisablePrompts: true, diff --git a/packages/create-fuels/test/utils/bootstrapProject.ts b/packages/create-fuels/test/utils/bootstrapProject.ts new file mode 100644 index 00000000000..ba0828c6b3e --- /dev/null +++ b/packages/create-fuels/test/utils/bootstrapProject.ts @@ -0,0 +1,54 @@ +import { cpSync, existsSync, readdirSync, rmSync } from 'fs'; +import { basename, join } from 'path'; + +export type ProjectPaths = { + root: string; + template: string; +}; + +/** + * Path and Directory utils + */ +const testDir = join(__dirname, '..'); +const createFuelsDir = join(__dirname, '../..'); +const testTemplateDir = join(createFuelsDir, 'templates'); +const templatesDir = join(__dirname, '../../../../templates'); + +export const bootstrapProject = ( + testFilepath: string, + templateName: string = 'nextjs' +): ProjectPaths => { + // Template paths + const templateDir = join(templatesDir, templateName); + const localTemplateDir = join(testTemplateDir, templateName); + if (!existsSync(localTemplateDir)) { + cpSync(templateDir, localTemplateDir, { recursive: true }); + } + + // Unique name + const testFilename = basename(testFilepath.replace(/\./g, '-')); + const projectName = `__temp__${testFilename}_${new Date().getTime()}`; + + // Test paths + const root = join(testDir, projectName); + + return { + root, + template: localTemplateDir, + }; +}; + +export const resetFilesystem = (dirPath: string) => { + if (existsSync(dirPath)) { + rmSync(dirPath, { recursive: true }); + } +}; + +export const cleanupFilesystem = (dirPath: string = testDir) => { + const dirs = readdirSync(dirPath).filter((dir) => dir.startsWith('__temp__')); + dirs.forEach((dir) => { + resetFilesystem(join(dirPath, dir)); + }); + + resetFilesystem(testTemplateDir); +}; From cf11c02dd6eb47790bc6142c1e3c804d26e1a96b Mon Sep 17 00:00:00 2001 From: Peter Smith Date: Wed, 15 May 2024 11:30:44 +0100 Subject: [PATCH 4/7] Changeset --- .changeset/hip-rules-serve.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/hip-rules-serve.md diff --git a/.changeset/hip-rules-serve.md b/.changeset/hip-rules-serve.md new file mode 100644 index 00000000000..686fbdf0d2c --- /dev/null +++ b/.changeset/hip-rules-serve.md @@ -0,0 +1,5 @@ +--- +"create-fuels": patch +--- + +chore: `create fuels` tests clean up the filesystem \ No newline at end of file From 1d1f8f54f849914095e11544b4575eb190528f1b Mon Sep 17 00:00:00 2001 From: Peter Smith Date: Wed, 15 May 2024 11:31:26 +0100 Subject: [PATCH 5/7] Add group --- packages/create-fuels/src/lib/setupProgram.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/create-fuels/src/lib/setupProgram.test.ts b/packages/create-fuels/src/lib/setupProgram.test.ts index ae006c264ff..1f9160bac04 100644 --- a/packages/create-fuels/src/lib/setupProgram.test.ts +++ b/packages/create-fuels/src/lib/setupProgram.test.ts @@ -1,5 +1,8 @@ import { setupProgram } from './setupProgram'; +/** + * @group node + */ describe(() => { test('setupProgram takes in args properly', () => { const program = setupProgram(); From c017675f2f6b19e9127281e8eae00f334d574eaa Mon Sep 17 00:00:00 2001 From: Peter Smith Date: Wed, 15 May 2024 11:49:11 +0100 Subject: [PATCH 6/7] Rebuild From 857307fd4224fd49b80b20490fe42cd8c713be50 Mon Sep 17 00:00:00 2001 From: Peter Smith Date: Wed, 15 May 2024 12:20:49 +0100 Subject: [PATCH 7/7] Added test name --- packages/create-fuels/src/lib/setupProgram.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/create-fuels/src/lib/setupProgram.test.ts b/packages/create-fuels/src/lib/setupProgram.test.ts index 1f9160bac04..85df84267a0 100644 --- a/packages/create-fuels/src/lib/setupProgram.test.ts +++ b/packages/create-fuels/src/lib/setupProgram.test.ts @@ -3,7 +3,7 @@ import { setupProgram } from './setupProgram'; /** * @group node */ -describe(() => { +describe('setupProgram', () => { test('setupProgram takes in args properly', () => { const program = setupProgram(); program.parse(['', '', 'test-project-name', '-c', '-p', '-s', '--pnpm', '--npm']);