Skip to content

Commit

Permalink
feat(plugins): moved the vcs-host plugins under the plugins map
Browse files Browse the repository at this point in the history
BREAKING CHANGE: vcs-host plugins must now be supplied under the `plugins` property rather than as a
direct property and must be a full plugin
  • Loading branch information
travi committed Jul 24, 2024
1 parent 7ce0013 commit a464362
Show file tree
Hide file tree
Showing 9 changed files with 41 additions and 31 deletions.
7 changes: 5 additions & 2 deletions src/options-validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ import {decisionsSchema} from './options-schemas.js';

export function validate(options) {
return validateOptions(joi.object({
vcsHosts: vcsHostPluginsSchema,
decisions: decisionsSchema,
plugins: joi.object({dependencyUpdaters: dependencyUpdaterPluginsSchema, languages: languagePluginsSchema})
plugins: joi.object({
dependencyUpdaters: dependencyUpdaterPluginsSchema,
languages: languagePluginsSchema,
vcsHosts: vcsHostPluginsSchema
})
}), options) || {};
}
17 changes: 12 additions & 5 deletions src/options-validator.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import joi from 'joi';
import {validateOptions} from '@form8ion/core';
import * as core from '@form8ion/core';

import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
import any from '@travi/any';
Expand All @@ -11,7 +11,11 @@ import vcsHostPluginsSchema from './vcs/host/schema.js';
import dependencyUpdaterPluginsSchema from './dependency-updater/schema.js';
import {validate} from './options-validator.js';

vi.mock('@form8ion/core');
vi.mock('@form8ion/core', async () => ({
validateOptions: vi.fn(),
optionsSchemas: {form8ionPlugin: joi.object()}
}));
vi.mock('./vcs/host/schema.js');

describe('options validator', () => {
beforeEach(() => {
Expand All @@ -29,14 +33,17 @@ describe('options validator', () => {
const fullSchema = any.simpleObject();
const validatedOptions = any.simpleObject();
when(joi.object)
.calledWith({dependencyUpdaters: dependencyUpdaterPluginsSchema, languages: languagePluginsSchema})
.calledWith({
dependencyUpdaters: dependencyUpdaterPluginsSchema,
languages: languagePluginsSchema,
vcsHosts: vcsHostPluginsSchema
})
.mockReturnValue(pluginsSchema);
when(joi.object).calledWith({
vcsHosts: vcsHostPluginsSchema,
decisions: decisionsSchema,
plugins: pluginsSchema
}).mockReturnValue(fullSchema);
when(validateOptions).calledWith(fullSchema, options).mockReturnValue(validatedOptions);
when(core.validateOptions).calledWith(fullSchema, options).mockReturnValue(validatedOptions);

expect(validate(options)).toEqual(validatedOptions);
});
Expand Down
2 changes: 1 addition & 1 deletion src/scaffolder.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import lift from './lift.js';

export async function scaffold(options) {
const projectRoot = process.cwd();
const {vcsHosts = {}, decisions, plugins: {dependencyUpdaters, languages}} = validate(options);
const {decisions, plugins: {dependencyUpdaters, languages, vcsHosts = {}}} = validate(options);

const {
[coreQuestionNames.PROJECT_NAME]: projectName,
Expand Down
4 changes: 2 additions & 2 deletions src/scaffolder.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ describe('project scaffolder', () => {
const contributingResults = any.simpleObject();
when(optionsValidator.validate)
.calledWith(options)
.mockReturnValue({vcsHosts, decisions, plugins: {dependencyUpdaters, languages}});
.mockReturnValue({decisions, plugins: {dependencyUpdaters, languages, vcsHosts}});
when(prompts.promptForBaseDetails)
.calledWith(projectPath, decisions)
.mockResolvedValue({
Expand Down Expand Up @@ -259,7 +259,7 @@ describe('project scaffolder', () => {
};
when(optionsValidator.validate)
.calledWith(options)
.mockReturnValue({vcsHosts, decisions, plugins: {languages}});
.mockReturnValue({decisions, plugins: {languages, vcsHosts}});
scaffoldGit.mockResolvedValue(vcs);
liftGit.mockResolvedValue({nextSteps: gitNextSteps});
prompts.promptForBaseDetails.mockResolvedValue({
Expand Down
2 changes: 1 addition & 1 deletion src/vcs/host/scaffolder.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export default function (hosts, options) {
const {host: chosenHost, ...rest} = options;
const host = lowercasedHosts[chosenHost];

if (host) return host.scaffolder(rest);
if (host) return host.scaffold(rest);

return {};
}
2 changes: 1 addition & 1 deletion src/vcs/host/scaffolder.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ describe('vcs host scaffolder', () => {
const otherOptions = any.simpleObject();
const results = any.simpleObject();
const chosenHostScaffolder = vi.fn();
const hostScaffolders = {...any.simpleObject(), [chosenHost]: {scaffolder: chosenHostScaffolder}};
const hostScaffolders = {...any.simpleObject(), [chosenHost]: {scaffold: chosenHostScaffolder}};
when(chosenHostScaffolder).calledWith(otherOptions).mockResolvedValue(results);

expect(await scaffoldVcsHost(hostScaffolders, {...otherOptions, host: chosenHost.toLowerCase()})).toEqual(results);
Expand Down
4 changes: 2 additions & 2 deletions src/vcs/host/schema.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import joi from 'joi';
import {optionsSchemas} from '@form8ion/core';

export default joi.object().pattern(/^/, joi.object({
scaffolder: joi.func().arity(1).required(),
export default joi.object().pattern(/^/, optionsSchemas.form8ionPlugin.keys({
prompt: joi.func().required(),
public: joi.bool(),
private: joi.bool()
Expand Down
20 changes: 10 additions & 10 deletions src/vcs/host/schema.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe('vcs-host plugins schema', () => {
any.listOf(any.string),
{
factory: () => ({
scaffolder: foo => foo,
scaffold: foo => foo,
prompt: () => undefined,
public: any.boolean(),
private: any.boolean()
Expand All @@ -31,40 +31,40 @@ describe('vcs-host plugins schema', () => {

it('should require a `scaffolder` to be included', () => {
expect(() => validateOptions(vcsHostSchema, {[key]: {}}))
.toThrowError(`"${key}.scaffolder" is required`);
.toThrowError(`"${key}.scaffold" is required`);
});

it('should require `scaffolder` to be a function', () => {
expect(() => validateOptions(vcsHostSchema, {[key]: {scaffolder: any.word()}}))
.toThrowError(`"${key}.scaffolder" must be of type function`);
expect(() => validateOptions(vcsHostSchema, {[key]: {scaffold: any.word()}}))
.toThrowError(`"${key}.scaffold" must be of type function`);
});

it('should require the scaffolder to accept a single argument', () => {
expect(() => validateOptions(vcsHostSchema, {[key]: {scaffolder: () => undefined}}))
.toThrowError(`"${key}.scaffolder" must have an arity of 1`);
expect(() => validateOptions(vcsHostSchema, {[key]: {scaffold: () => undefined}}))
.toThrowError(`"${key}.scaffold" must have an arity of 1`);
});

it('should require a `prompt` property', () => {
expect(() => validateOptions(vcsHostSchema, {[key]: {scaffolder: foo => foo}}))
expect(() => validateOptions(vcsHostSchema, {[key]: {scaffold: foo => foo}}))
.toThrowError(`"${key}.prompt" is required`);
});

it('should require the `prompt` to be a function', () => {
expect(() => validateOptions(vcsHostSchema, {[key]: {scaffolder: foo => foo, prompt: any.word()}}))
expect(() => validateOptions(vcsHostSchema, {[key]: {scaffold: foo => foo, prompt: any.word()}}))
.toThrowError(`"${key}.prompt" must be of type function`);
});

it('should require the `public` property to be a boolean', () => {
expect(() => validateOptions(
vcsHostSchema,
{[key]: {scaffolder: foo => foo, prompt: bar => bar, public: any.word()}}
{[key]: {scaffold: foo => foo, prompt: bar => bar, public: any.word()}}
)).toThrowError(`"${key}.public" must be a boolean`);
});

it('should require the `private` property to be a boolean', () => {
expect(() => validateOptions(
vcsHostSchema,
{[key]: {scaffolder: foo => foo, prompt: bar => bar, private: any.word()}}
{[key]: {scaffold: foo => foo, prompt: bar => bar, private: any.word()}}
)).toThrowError(`"${key}.private" must be a boolean`);
});
});
14 changes: 7 additions & 7 deletions test/integration/features/step_definitions/common-steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,13 @@ When(/^the project is scaffolded$/, async function () {
}
}
}
}
},
...vcsHost && {
vcsHosts: {
[vcsHost]: {
scaffolder: ({name, owner}) => ({sshUrl: this.remoteOriginUrl, name, owner}),
prompt: () => undefined
},
...vcsHost && {
vcsHosts: {
[vcsHost]: {
scaffold: ({name, owner}) => ({sshUrl: this.remoteOriginUrl, name, owner}),
prompt: () => undefined
}
}
}
},
Expand Down

0 comments on commit a464362

Please sign in to comment.