Skip to content

Commit

Permalink
revert createMockedGenerator to sync
Browse files Browse the repository at this point in the history
  • Loading branch information
mshima committed May 12, 2023
1 parent 6fc1624 commit 201d77b
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 143 deletions.
27 changes: 11 additions & 16 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ import RunContext, { BasicRunContext, type RunContextSettings } from './run-cont
import testContext from './test-context.js';
import type { DefaultEnvironmentApi, DefaultGeneratorApi } from './type-helpers.js';

let GeneratorImplementation;
try {
const GeneratorImport = await import('yeoman-generator');
GeneratorImplementation = GeneratorImport.default ?? GeneratorImport;
} catch {}

const { cloneDeep } = _;

/**
Expand Down Expand Up @@ -147,12 +153,7 @@ export class YeomanTest {
/**
* Create a mocked generator
*/
async createMockedGenerator(GeneratorClass): Promise<SinonSpiedInstance<DefaultGeneratorApi>> {
if (!GeneratorClass) {
const GeneratorImplementation = await import('yeoman-generator');
GeneratorClass = (GeneratorImplementation.default ?? GeneratorImplementation) as any;
}

createMockedGenerator(GeneratorClass = GeneratorImplementation): SinonSpiedInstance<DefaultGeneratorApi> {
class MockedGenerator extends GeneratorClass {}
const generator = sinonSpy(MockedGenerator);
for (const methodName of ['run', 'queueTasks', 'runWithOptions', 'queueOwnTasks']) {
Expand All @@ -167,21 +168,15 @@ export class YeomanTest {
/**
* Create a simple, dummy generator
*/
async createDummyGenerator<GenParameter extends BaseGenerator = DefaultGeneratorApi>(
Generator?: GetGeneratorConstructor<GenParameter>,
createDummyGenerator<GenParameter extends BaseGenerator = DefaultGeneratorApi>(
Generator: GetGeneratorConstructor<GenParameter> = GeneratorImplementation,
contents: Record<string, (...args: any[]) => void> = {
test(this: any) {
this.shouldRun = true;
},
},
): Promise<new (...args: any[]) => GenParameter> {
if (!Generator) {
const GeneratorImplementation = await import('yeoman-generator');
Generator = (GeneratorImplementation.default ?? GeneratorImplementation) as any;
}

const GeneratorConstructor: GetGeneratorConstructor<GenParameter> = Generator as any;
class DummyGenerator extends GeneratorConstructor {
): new (...args: any[]) => GenParameter {
class DummyGenerator extends Generator {
constructor(...args: any[]) {
const optIndex = Array.isArray(args[0]) ? 1 : 0;
args[optIndex] = args[optIndex] ?? {};
Expand Down
13 changes: 5 additions & 8 deletions src/run-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export type RunContextSettings = {
type PromiseRunResult<GeneratorType extends BaseGenerator> = Promise<RunResult<GeneratorType>>;
type MockedGeneratorFactory<GenParameter extends BaseGenerator = DefaultGeneratorApi> = (
GeneratorClass?: GetGeneratorConstructor<GenParameter>,
) => Promise<GenParameter>;
) => GenParameter;
type EnvOptions = BaseEnvironmentOptions & { createEnv?: any };

export class RunContextBase<GeneratorType extends BaseGenerator = DefaultGeneratorApi> extends EventEmitter {
Expand Down Expand Up @@ -422,13 +422,10 @@ export class RunContextBase<GeneratorType extends BaseGenerator = DefaultGenerat

withMockedGenerators(namespaces: string[]): this {
assert(Array.isArray(namespaces), 'namespaces should be an array');
return this.onBeforePrepare(async () => {
const MockedGenerator = await this.mockedGeneratorFactory();
const dependencies: Dependency[] = namespaces.map(namespace => [MockedGenerator, namespace]) as any;
const entries = dependencies.map(([generator, namespace]) => [namespace, generator]);
Object.assign(this.mockedGenerators, Object.fromEntries(entries));
this.withGenerators(dependencies);
});
const dependencies: Dependency[] = namespaces.map(namespace => [this.mockedGeneratorFactory(), namespace]) as any;
const entries = dependencies.map(([generator, namespace]) => [namespace, generator]);
Object.assign(this.mockedGenerators, Object.fromEntries(entries));
return this.withGenerators(dependencies);
}

/**
Expand Down
135 changes: 59 additions & 76 deletions test/helpers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ describe('yeoman-test', function () {

describe('.mockPrompt()', function () {
beforeEach(async function () {
this.generator = await env.instantiate(await helpers.createDummyGenerator(), [], {});
this.generator = await env.instantiate(helpers.createDummyGenerator(), [], {});
helpers.mockPrompt(this.generator, { answer: 'foo' });
});

Expand All @@ -71,15 +71,15 @@ describe('yeoman-test', function () {
});

it('uses default values when no answer is passed', async function () {
const generator = await env.instantiate(await helpers.createDummyGenerator(), [], {});
const generator = await env.instantiate(helpers.createDummyGenerator(), [], {});
helpers.mockPrompt(generator);
return generator.prompt([{ name: 'respuesta', message: 'foo', type: 'input', default: 'bar' }]).then(function (answers) {
assert.equal(answers.respuesta, 'bar');
});
});

it('supports `null` answer for `list` type', async function () {
const generator = await env.instantiate(await helpers.createDummyGenerator(), [], {});
const generator = await env.instantiate(helpers.createDummyGenerator(), [], {});

helpers.mockPrompt(generator, {
respuesta: null,
Expand All @@ -91,7 +91,7 @@ describe('yeoman-test', function () {
});

it('treats `null` as no answer for `input` type', async function () {
const generator = await env.instantiate(await helpers.createDummyGenerator(), [], {});
const generator = await env.instantiate(helpers.createDummyGenerator(), [], {});

helpers.mockPrompt(generator, {
respuesta: null,
Expand All @@ -103,7 +103,7 @@ describe('yeoman-test', function () {
});

it('uses `true` as the default value for `confirm` type', async function () {
const generator = await env.instantiate(await helpers.createDummyGenerator(), [], {});
const generator = await env.instantiate(helpers.createDummyGenerator(), [], {});
helpers.mockPrompt(generator, {});

return generator.prompt([{ name: 'respuesta', message: 'foo', type: 'confirm' }]).then(function (answers) {
Expand All @@ -112,7 +112,7 @@ describe('yeoman-test', function () {
});

it('supports `false` answer for `confirm` type', async function () {
const generator = await env.instantiate(await helpers.createDummyGenerator(), [], {});
const generator = await env.instantiate(helpers.createDummyGenerator(), [], {});
helpers.mockPrompt(generator, { respuesta: false });

return generator.prompt([{ name: 'respuesta', message: 'foo', type: 'confirm' }]).then(function (answers) {
Expand All @@ -127,7 +127,7 @@ describe('yeoman-test', function () {
});

it('can be call multiple time on the same generator', async function () {
const generator = await env.instantiate(await helpers.createDummyGenerator(), [], {});
const generator = await env.instantiate(helpers.createDummyGenerator(), [], {});
helpers.mockPrompt(generator, { foo: 1 });
helpers.mockPrompt(generator, { foo: 2 });
return generator.prompt({ message: 'bar', name: 'foo' }).then(function (answers) {
Expand All @@ -136,7 +136,7 @@ describe('yeoman-test', function () {
});

it('throws if answer is not provided', async function () {
const generator = await env.instantiate(await helpers.createDummyGenerator(), [], {});
const generator = await env.instantiate(helpers.createDummyGenerator(), [], {});
helpers.mockPrompt(generator, { foo: 1 }, { throwOnMissingAnswer: true });
return this.generator.prompt([{ message: 'bar', name: 'notFound' }]).then(
() => assert.fail(),
Expand All @@ -160,88 +160,76 @@ describe('yeoman-test', function () {

describe('.run()', function () {
describe('with a generator', function () {
it('return a RunContext object', async function () {
const context = helpers.run(await helpers.createDummyGenerator());
it('return a RunContext object', function (done) {
const context = helpers.run(helpers.createDummyGenerator());
assert(context instanceof RunContext);
await new Promise(done => {
context.on('end', done);
});
context.on('end', done);
});
});

describe('with a namespace', function () {
it('return a RunContext object', async function () {
await new Promise(done => {
const context = helpers.run('simple:app').withEnvironment(env => {
helpers.registerDependencies(env, [require.resolve('./fixtures/generator-simple/app')]);
});
assert(context instanceof RunContext);
context.on('end', done);
it('return a RunContext object', function (done) {
const context = helpers.run('simple:app').withEnvironment(env => {
helpers.registerDependencies(env, [require.resolve('./fixtures/generator-simple/app')]);
});
assert(context instanceof RunContext);
context.on('end', done);
});
});

it('pass settings to RunContext', async function () {
const runContext = helpers.run(await helpers.createDummyGenerator(), {
it('pass settings to RunContext', function () {
const runContext = helpers.run(helpers.createDummyGenerator(), {
namespace: 'foo',
});
assert.equal(runContext.settings.namespace, 'foo');
});

it('pass envOptions to RunContext', async function () {
it('pass envOptions to RunContext', function () {
const envOptions = { foo: 2 };
const runContext = helpers.run(await helpers.createDummyGenerator(), undefined, envOptions);
const runContext = helpers.run(helpers.createDummyGenerator(), undefined, envOptions);
assert.equal(runContext.envOptions, envOptions);
});

it('catch env errors', async function () {
await new Promise<void>(done => {
helpers.createDummyGenerator().then(DummyGenerator => {
helpers
.run(
class extends DummyGenerator {
throws() {
this.env.emit('error', new Error('an error'));
}
},
)
.on('error', _ => {
done();
});
it('catch env errors', function (done) {
helpers
.run(
class extends helpers.createDummyGenerator() {
throws() {
this.env.emit('error', new Error('an error'));
}
},
)
.on('error', _ => {
done();
});
});
});

it('catch generator emitted errors', async function () {
await new Promise<void>(done => {
helpers.createDummyGenerator().then(DummyGenerator => {
helpers
.run(
class extends DummyGenerator {
throws() {
this.emit('error', new Error('an error'));
}
},
)
.on('error', _ => {
done();
});
it('catch generator emitted errors', function (done) {
helpers
.run(
class extends helpers.createDummyGenerator() {
throws() {
this.emit('error', new Error('an error'));
}
},
)
.on('error', _ => {
done();
});
});
});

it('catch generator thrown errors', function (done) {
helpers.createDummyGenerator().then(DummyGenerator => {
const ThrowingDummy = class extends DummyGenerator {
throws() {
console.log('bar;');
throw new Error('Some error.');
}
};
helpers.run(ThrowingDummy).catch(() => {
helpers
.run(
class extends helpers.createDummyGenerator() {
throws() {
throw new Error('Some error.');
}
},
)
.on('error', _ => {
done();
});
});
});

// This is a workaround for corner case were an error is not correctly emitted
Expand All @@ -254,9 +242,7 @@ describe('yeoman-test', function () {

describe('with files', function () {
it('write files to mem-fs', async function () {
const runResult = await helpers
.run(await helpers.createDummyGenerator())
.withFiles({ 'foo.txt': 'foo', 'foo.json': { foo: 'bar' } });
const runResult = await helpers.run(helpers.createDummyGenerator()).withFiles({ 'foo.txt': 'foo', 'foo.json': { foo: 'bar' } });
expect(runResult.getSnapshot()).toMatchInlineSnapshot(`
{
"foo.json": {
Expand All @@ -276,7 +262,7 @@ describe('yeoman-test', function () {

it('write files with relative path to mem-fs', async function () {
const runResult = await helpers
.run(await helpers.createDummyGenerator())
.run(helpers.createDummyGenerator())
.withFiles('sub', { 'foo.txt': 'foo', 'foo.json': { foo: 'bar' } });
expect(runResult.getSnapshot()).toMatchInlineSnapshot(`
{
Expand All @@ -296,7 +282,7 @@ describe('yeoman-test', function () {
});

it('write string .yo-rc.json to mem-fs', async function () {
const runResult = await helpers.run(await helpers.createDummyGenerator()).withYoRc('{"foo": "bar"}');
const runResult = await helpers.run(helpers.createDummyGenerator()).withYoRc('{"foo": "bar"}');
expect(runResult.getSnapshot()).toMatchInlineSnapshot(`
{
".yo-rc.json": {
Expand All @@ -308,7 +294,7 @@ describe('yeoman-test', function () {
});

it('write object .yo-rc.json to mem-fs', async function () {
const runResult = await helpers.run(await helpers.createDummyGenerator()).withYoRc({ foo: 'bar' });
const runResult = await helpers.run(helpers.createDummyGenerator()).withYoRc({ foo: 'bar' });
expect(runResult.getSnapshot()).toMatchInlineSnapshot(`
{
".yo-rc.json": {
Expand All @@ -323,10 +309,7 @@ describe('yeoman-test', function () {
});

it('merges object .yo-rc.json to mem-fs', async function () {
const runResult = await helpers
.run(await helpers.createDummyGenerator())
.withYoRc({ foo: 'bar' })
.withYoRc({ bar: 'foo' });
const runResult = await helpers.run(helpers.createDummyGenerator()).withYoRc({ foo: 'bar' }).withYoRc({ bar: 'foo' });
expect(runResult.getSnapshot()).toMatchInlineSnapshot(`
{
".yo-rc.json": {
Expand All @@ -343,7 +326,7 @@ describe('yeoman-test', function () {

it('writes object GeneratorConfig to mem-fs', async function () {
const runResult = await helpers
.run(await helpers.createDummyGenerator())
.run(helpers.createDummyGenerator())
.withYoRcConfig('ns', { foo: 'bar' })
.withYoRcConfig('ns.child', { bar: 'foo' });
expect(runResult.getSnapshot()).toMatchInlineSnapshot(`
Expand All @@ -366,7 +349,7 @@ describe('yeoman-test', function () {

it('write files to mem-fs', async function () {
const runResult = await helpers
.run(await helpers.createDummyGenerator())
.run(helpers.createDummyGenerator())
.withFiles({ 'foo.txt': 'foo', 'foo.json': { foo: 'bar' } })
.commitFiles();
assert(existsSync(resolve(runResult.cwd, 'foo.txt')));
Expand All @@ -378,7 +361,7 @@ describe('yeoman-test', function () {
it('calls in order', async function () {
const order: string[] = [];

const runContext = helpers.run(await helpers.createDummyGenerator());
const runContext = helpers.run(helpers.createDummyGenerator());
await runContext
.onGenerator(function (generator) {
assert.strictEqual(this, runContext);
Expand Down
4 changes: 2 additions & 2 deletions test/run-context-environment.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ describe('RunContext running environment', function () {
build = false;
});
beforeEach(() => {
ctx.withEnvironment(async env => {
const FakeGenerator = await helpers.createDummyGenerator();
ctx.withEnvironment(env => {
const FakeGenerator = helpers.createDummyGenerator();
const fake = sinonFake.returns(Promise.resolve(new FakeGenerator([], { env })));
sinonReplace(env, 'create', fake);
});
Expand Down
Loading

0 comments on commit 201d77b

Please sign in to comment.