Skip to content

Commit

Permalink
test(app-builder): add test for clean command
Browse files Browse the repository at this point in the history
  • Loading branch information
EdieLemoine committed Oct 19, 2023
1 parent 43ad5ba commit 5a39064
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 16 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
**/coverage
**/dist
**/.tmp

# We use tsconfig.base.json, tsconfig.json is generated by vite and may accidentally be left behind sometimes
apps/**/tsconfig.json
Expand Down
5 changes: 5 additions & 0 deletions apps/app-builder/src/__tests__/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import path from 'path';

const dirname = new URL('.', import.meta.url).pathname;

export const MOCK_ROOT_DIR = path.resolve(dirname, '../..', '.tmp');
37 changes: 21 additions & 16 deletions apps/app-builder/src/__tests__/createTestContext.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,36 @@
import {Command} from 'commander';
import {type RecursivePartial} from '@myparcel/ts-utils';
import {createDebugger, mergeDefaultConfig} from '../utils';
import {type PdkBuilderContext, PdkPlatformName} from '../types';
import {type CommandArgs, type PdkBuilderContext, PdkPlatformName} from '../types';
import {MOCK_ROOT_DIR} from './constants';

export const createTestContext = (context?: Partial<PdkBuilderContext>): PdkBuilderContext => {
const verbose = 0;
type Input = RecursivePartial<PdkBuilderContext>;

export const createTestContext = (context?: Input): PdkBuilderContext => {
const args = {
arguments: [],
command: new Command(),
dryRun: false,
parallel: false,
quiet: true,
verbose: 0,
version: '1.0.0',
...context?.args,
} as CommandArgs;

return {
args: {
arguments: [],
command: new Command(),
dryRun: false,
parallel: false,
quiet: true,
verbose,
version: '1.0.0',
...context?.args,
},
args,
config: mergeDefaultConfig({
name: 'test',
platforms: [PdkPlatformName.MyParcelNl, PdkPlatformName.MyParcelBe, PdkPlatformName.Flespakket],
source: [],
// @ts-expect-error todo
versionSource: [],
...context?.config,
}),
debug: createDebugger('test', {verbose}),
debug: createDebugger('test', args),
env: {
cwd: 'CWD',
cwd: MOCK_ROOT_DIR,
config: {},
configFiles: {},
modulePackage: {},
Expand All @@ -38,5 +43,5 @@ export const createTestContext = (context?: Partial<PdkBuilderContext>): PdkBuil
...context?.env,
},
...context,
};
} as PdkBuilderContext;
};
56 changes: 56 additions & 0 deletions apps/app-builder/src/__tests__/mockFileSystem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import path from 'path';
import fs from 'fs';
import {vi} from 'vitest';
import {isObject, merge} from 'lodash-unified';
import {createDirectory} from '../utils';
import {MOCK_ROOT_DIR} from './constants';

type Directories = Record<string, unknown>;

const recursiveCreate = async (entries: Record<string, unknown>, rootDir = MOCK_ROOT_DIR): Promise<unknown[]> => {
return Promise.all(
Object.entries(entries).map(async ([filePath, contents]) => {
const fullPath = path.resolve(rootDir, filePath);
const directory = path.dirname(fullPath);

await createDirectory(directory, {recursive: true});

if (isObject(contents)) {
return recursiveCreate(contents as Record<string, unknown>, fullPath);
}

if (typeof contents === 'string') {
await fs.promises.writeFile(fullPath, contents);
}
}),
);
};

export const mockFileSystem = async (fileSystem?: Directories): Promise<void> => {
const base = {
config: {
'pdk.php': '<?php return [];',
},
src: {
Pdk: {
'MyParcelNLController.php': '<?php echo "Hello from MyParcelNL";',
},
'index.php': '<?php echo "Version: 1.0.0";',
},
'composer.json': JSON.stringify({
name: 'myparcelnl/app',
version: '1.0.0',
}),
'package.json': JSON.stringify({
name: '@myparcel/app',
version: '1.0.0',
}),
'readme.txt': 'Hello world!',
};

await recursiveCreate(merge({}, base, fileSystem));

vi.restoreAllMocks();
};

export const restoreFileSystem = async (): Promise<void> => {};
36 changes: 36 additions & 0 deletions apps/app-builder/src/__tests__/spies/fs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// make a spy for all methods on fs.promises that modify the file system
import fs from 'fs';
import {vi} from 'vitest';

const fsAppendFile = vi.spyOn(fs, 'appendFile');
const fsCopyFile = vi.spyOn(fs, 'copyFile');
const fsMkdir = vi.spyOn(fs, 'mkdir');
const fsRm = vi.spyOn(fs, 'rm');
const fsRmdir = vi.spyOn(fs, 'rmdir');
const fsUnlink = vi.spyOn(fs, 'unlink');
const fsWriteFile = vi.spyOn(fs, 'writeFile');

const fsPromisesAppendFile = vi.spyOn(fs.promises, 'appendFile');
const fsPromisesCopyFile = vi.spyOn(fs.promises, 'copyFile');
const fsPromisesMkdir = vi.spyOn(fs.promises, 'mkdir');
const fsPromisesRm = vi.spyOn(fs.promises, 'rm');
const fsPromisesRmdir = vi.spyOn(fs.promises, 'rmdir');
const fsPromisesUnlink = vi.spyOn(fs.promises, 'unlink');
const fsPromisesWriteFile = vi.spyOn(fs.promises, 'writeFile');

export const fsModifyingMethodSpies = [
fsAppendFile,
fsCopyFile,
fsMkdir,
fsRm,
fsRmdir,
fsUnlink,
fsWriteFile,
fsPromisesAppendFile,
fsPromisesCopyFile,
fsPromisesMkdir,
fsPromisesRm,
fsPromisesRmdir,
fsPromisesUnlink,
fsPromisesWriteFile,
] as const;
50 changes: 50 additions & 0 deletions apps/app-builder/src/commands/clean.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import {afterEach, describe, expect, it, vi} from 'vitest';
import {exists} from '../utils';
import {fsModifyingMethodSpies} from '../__tests__/spies/fs';
import {mockFileSystem, restoreFileSystem} from '../__tests__/mockFileSystem';
import {createTestContext} from '../__tests__/createTestContext';
import {MOCK_ROOT_DIR} from '../__tests__/constants';
import clean from './clean';

describe('command: clean', () => {
afterEach(async () => {
await restoreFileSystem();
vi.restoreAllMocks();
});

it('does nothing when dry run is passed', async () => {
expect.assertions(fsModifyingMethodSpies.length);

await mockFileSystem({dist: {'text.txt': ''}});

await clean(createTestContext({args: {dryRun: true}}));

fsModifyingMethodSpies.forEach((spy) => {
expect(spy).not.toHaveBeenCalled();
});
});

it('does nothing when outDir does not exist', async () => {
expect.assertions(fsModifyingMethodSpies.length);

await mockFileSystem();

await clean(createTestContext());

fsModifyingMethodSpies.forEach((spy) => {
expect(spy).not.toHaveBeenCalled();
});
});

it('cleans dir', async () => {
expect.assertions(2);

await mockFileSystem({dist: {'text.txt': ''}});

expect(await exists(`${MOCK_ROOT_DIR}/dist/text.txt`)).toBe(true);

await clean(createTestContext({args: {dryRun: false}}));

expect(await exists(`${MOCK_ROOT_DIR}/dist/text.txt`)).toBe(false);
});
});
11 changes: 11 additions & 0 deletions apps/app-builder/src/utils/createDirectory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {type MakeDirectoryOptions} from 'node:fs';
import fs from 'fs';
import {exists} from './exists';

export const createDirectory = async (directory: string, options: MakeDirectoryOptions): Promise<void> => {
if (await exists(directory)) {
return;
}

await fs.promises.mkdir(directory, options);
};
1 change: 1 addition & 0 deletions apps/app-builder/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ export * from './resolveFileName';
export * from './resolveString';
export * from './transformer';
export * from './validateDistPath';
export {createDirectory} from './createDirectory';

0 comments on commit 5a39064

Please sign in to comment.