Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
yoannmoinet committed Oct 4, 2024
1 parent cc8cc43 commit 5333b35
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 5 deletions.
179 changes: 179 additions & 0 deletions packages/tests/src/tools/src/commands/create-plugin/ask.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import {
getCodeowners,
getDescription,
getHooksToInclude,
getName,
getTypeOfPlugin,
listHooks,
sanitizeCodeowners,
validateHooks,
} from '@dd/tools/commands/create-plugin/ask';
import { bundlerHookNames, universalHookNames } from '@dd/tools/commands/create-plugin/constants';
import { bundlerHooks, universalHooks } from '@dd/tools/commands/create-plugin/hooks';
import type { AnyHook, TypeOfPlugin } from '@dd/tools/commands/create-plugin/types';
import checkbox from '@inquirer/checkbox';
import input from '@inquirer/input';
import select from '@inquirer/select';

jest.mock('@inquirer/checkbox', () => jest.fn());
jest.mock('@inquirer/input', () => jest.fn());
jest.mock('@inquirer/select', () => jest.fn());

const checkboxMocked = jest.mocked(checkbox);
const inputMocked = jest.mocked(input);
const selectMocked = jest.mocked(select);

describe('ask.ts', () => {
describe('getName', () => {
test.each([
['Testing #1', 'testing-1'],
['Some, Name. With punctuation.', 'some-name-with-punctuation'],
['Âñy Wëîrd Nâmë', 'any-weird-name'],
])('Should slugify "%s" into "%s".', async (nameInput, expectation) => {
const name = await getName(nameInput);
expect(name).toBe(expectation);
});

test('Should ask for a name if none is provided.', async () => {
inputMocked.mockResolvedValueOnce('Testing #1');
const name = await getName();
expect(name).toBe('testing-1');
expect(inputMocked).toHaveBeenCalledTimes(1);
});
});

describe('getDescription', () => {
test('Should return the description if provided.', async () => {
const description = await getDescription('Some description.');
expect(description).toBe('Some description.');
});

test('Should ask for a description if none is provided.', async () => {
inputMocked.mockResolvedValueOnce('Some description.');
const description = await getDescription();
expect(description).toBe('Some description.');
expect(inputMocked).toHaveBeenCalledTimes(1);
});
});

describe('sanitizeCodeowners', () => {
test.each([
['@codeowners-1 @codeowners-2', '@codeowners-1 @codeowners-2'],
['codeowners-1 codeowners-2', '@codeowners-1 @codeowners-2'],
['@codeowners-1 , codeowners-2', '@codeowners-1 @codeowners-2'],
['@codeowners-1,codeowners-2', '@codeowners-1 @codeowners-2'],
])('Should sanitize "%s" into "%s".', (stringInput, expectation) => {
const codeowners = sanitizeCodeowners(stringInput);
expect(codeowners).toBe(expectation);
});
});

describe('getCodeowners', () => {
test('Should return the codeowners if provided.', async () => {
const codeowners = await getCodeowners(['@codeowners-1', '@codeowners-2']);
expect(codeowners).toBe('@codeowners-1 @codeowners-2');
});

test('Should ask for codeowners if none are provided.', async () => {
inputMocked.mockResolvedValueOnce('@codeowners-1 @codeowners-2');
const codeowners = await getCodeowners();
expect(codeowners).toBe('@codeowners-1 @codeowners-2');
expect(inputMocked).toHaveBeenCalledTimes(1);
});

test('Should sanitize the codeowners.', async () => {
const codeowners = await getCodeowners(['codeowners-1', 'codeowners-2']);
expect(codeowners).toBe('@codeowners-1 @codeowners-2');
});
});

describe('listHooks', () => {
test.each([
[bundlerHooks, bundlerHookNames],
[universalHooks, universalHookNames],
])('Should return the hooks in a formated list.', (hooksInput, expectedHookNames) => {
const hooksReturned = listHooks(hooksInput);
expect(hooksReturned).toEqual(
expectedHookNames.map((hook) => ({
name: expect.any(String),
value: hook,
checked: false,
})),
);
});
});

describe('getTypeOfPlugin', () => {
test('Should return the type if provided.', async () => {
const type = await getTypeOfPlugin('universal');
expect(type).toBe('universal');
});

test('Should ask for a type if an invalid one is provided.', async () => {
selectMocked.mockResolvedValueOnce('universal');
// @ts-expect-error We are testing the error case.
const type = await getTypeOfPlugin('invalid');
expect(type).toBe('universal');
expect(selectMocked).toHaveBeenCalledTimes(1);
});

test('Should ask for a type if none is provided.', async () => {
selectMocked.mockResolvedValueOnce('universal');
const type = await getTypeOfPlugin();
expect(type).toBe('universal');
expect(selectMocked).toHaveBeenCalledTimes(1);
});
});

describe('validateHooks', () => {
test.each<[TypeOfPlugin, AnyHook[], string[]]>([
['universal', ['enforce', 'buildStart'], ['enforce', 'buildStart']],
['universal', ['enforce', 'buildStart', 'webpack'], ['enforce', 'buildStart']],
['bundler', ['webpack', 'esbuild'], ['webpack', 'esbuild']],
['bundler', ['enforce', 'buildStart', 'webpack'], ['webpack']],
['bundler', ['enforce', 'buildStart'], []],
])(
'Should return the the expected set of hooks for "%s" plugin.',
(pluginType, hooksInput, expectation) => {
const hooksReturned = validateHooks(pluginType, hooksInput);
expect(hooksReturned).toEqual(expectation);
},
);
});

describe('getHooksToInclude', () => {
test('Should return the hooks if provided.', async () => {
const hooksReturned = await getHooksToInclude('universal', ['enforce', 'buildStart']);
expect(hooksReturned).toEqual(['enforce', 'buildStart']);
});

test('Should filter out invalid hooks when provided.', async () => {
const hooksReturned = await getHooksToInclude('bundler', [
'enforce',
'buildStart',
'webpack',
]);
expect(hooksReturned).toEqual(['webpack']);
});

test('Should ask for hooks if none are provided.', async () => {
checkboxMocked.mockResolvedValueOnce(['enforce', 'buildStart']);
const hooksReturned = await getHooksToInclude('universal');
expect(hooksReturned).toEqual(['enforce', 'buildStart']);
expect(checkboxMocked).toHaveBeenCalledTimes(1);
});

test.each<[TypeOfPlugin, any[]]>([
['universal', listHooks(universalHooks)],
['bundler', listHooks(bundlerHooks)],
])(
'Should offer a specific list of hooks for "%s" plugins.',
async (pluginType, expectedHooks) => {
await getHooksToInclude(pluginType);
expect(checkboxMocked).toHaveBeenCalledWith(
expect.objectContaining({ choices: expectedHooks }),
);
},
);
});
});
10 changes: 5 additions & 5 deletions packages/tools/src/commands/create-plugin/ask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const getDescription = async (descriptionInput?: string) => {
});
};

const sanitizeCodeowners = (codeowners: string) => {
export const sanitizeCodeowners = (codeowners: string) => {
return (
codeowners
// Remove potential commas and spaces
Expand All @@ -59,7 +59,7 @@ export const getCodeowners = async (codeownersInput?: string[]) => {
return sanitizeCodeowners(codeowners);
};

const listHooks = (list: EitherHookList) => {
export const listHooks = (list: EitherHookList) => {
return (Object.entries(list) as [AnyHook, Hook][]).map(([value, hook]) => ({
name: `${bold(hook.name)}\n ${dim(hook.descriptions.join('\n '))}`,
value,
Expand All @@ -70,10 +70,10 @@ const listHooks = (list: EitherHookList) => {
export const getTypeOfPlugin = async (typeInput?: TypeOfPlugin) => {
if (typeInput) {
if (!typesOfPlugin.includes(typeInput)) {
throw new Error(`Invalid plugin type: ${red(typeInput)}`);
console.error(`Invalid plugin type: ${red(typeInput)}`);
} else {
return typeInput;
}

return typeInput;
}

return select<TypeOfPlugin>({
Expand Down

0 comments on commit 5333b35

Please sign in to comment.