Skip to content

Commit

Permalink
feat: add mocked generate graphql-client-code to cli
Browse files Browse the repository at this point in the history
  • Loading branch information
alharris-at committed Sep 21, 2023
1 parent f75fa53 commit cb03274
Show file tree
Hide file tree
Showing 8 changed files with 533 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/old-pumpkins-peel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@aws-amplify/backend-cli': minor
---

Add generate graphql-client-code command with mocked implementation
9 changes: 8 additions & 1 deletion packages/cli/src/commands/generate/generate_command.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Argv, CommandModule } from 'yargs';
import { GenerateConfigCommand } from './config/generate_config_command.js';
import { GenerateGraphqlClientCodeCommand } from './graphql-client-code/generate_graphql_client_code_command.js';

/**
* An entry point for generate command.
Expand All @@ -18,7 +19,10 @@ export class GenerateCommand implements CommandModule {
/**
* Creates top level entry point for generate command.
*/
constructor(private readonly generateConfigCommand: GenerateConfigCommand) {
constructor(
private readonly generateConfigCommand: GenerateConfigCommand,
private readonly generateGraphqlClientCodeCommand: GenerateGraphqlClientCodeCommand
) {
this.command = 'generate';
this.describe = 'Generates post deployment artifacts';
}
Expand All @@ -38,6 +42,9 @@ export class GenerateCommand implements CommandModule {
yargs
// Cast to erase options types used in internal sub command implementation. Otherwise, compiler fails here.
.command(this.generateConfigCommand as unknown as CommandModule)
.command(
this.generateGraphqlClientCodeCommand as unknown as CommandModule
)
.demandCommand()
.strictCommands()
.recommendCommands()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@ describe('top level generate command', () => {
const parser = yargs().command(generateCommand);
const commandRunner = new TestCommandRunner(parser);

it('includes generate config in help output', async () => {
it('includes generate config and graphql-client-code in help output', async () => {
const output = await commandRunner.runCommand('generate --help');
assert.match(output, /Commands:/);
assert.match(output, /generate config {2}Generates client config/);
assert.match(output, /generate config\W*Generates client config/);
assert.match(
output,
/generate graphql-client-code\W*Generates graphql API code/
);
});

it('fails if subcommand is not provided', async () => {
Expand Down
15 changes: 14 additions & 1 deletion packages/cli/src/commands/generate/generate_command_factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { fromNodeProviderChain } from '@aws-sdk/credential-providers';
import { ClientConfigGeneratorAdapter } from './config/client_config_generator_adapter.js';
import { LocalAppNameResolver } from '../../local_app_name_resolver.js';
import { CwdPackageJsonLoader } from '../../cwd_package_json_loader.js';
import { GenerateGraphqlClientCodeCommand } from './graphql-client-code/generate_graphql_client_code_command.js';
import { GraphqlClientCodeGeneratorAdapter } from './graphql-client-code/generate_graphql_client_code_generator_adapter.js';

/**
* Creates wired generate command.
Expand All @@ -23,5 +25,16 @@ export const createGenerateCommand = (): CommandModule => {
localAppNameResolver
);

return new GenerateCommand(generateConfigCommand);
const graphqlClientCodeGeneratorAdapter =
new GraphqlClientCodeGeneratorAdapter(credentialProvider);

const generateGraphqlClientCodeCommand = new GenerateGraphqlClientCodeCommand(
graphqlClientCodeGeneratorAdapter,
localAppNameResolver
);

return new GenerateCommand(
generateConfigCommand,
generateGraphqlClientCodeCommand
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import { beforeEach, describe, it, mock } from 'node:test';
import { fromNodeProviderChain } from '@aws-sdk/credential-providers';
import { GenerateGraphqlClientCodeCommand } from './generate_graphql_client_code_command.js';
import yargs, { CommandModule } from 'yargs';
import {
TestCommandError,
TestCommandRunner,
} from '../../../test-utils/command_runner.js';
import assert from 'node:assert';
import path from 'path';
import { GraphqlClientCodeGeneratorAdapter } from './generate_graphql_client_code_generator_adapter.js';

describe('generate graphql-client-code command', () => {
const graphqlClientCodeGeneratorAdapter =
new GraphqlClientCodeGeneratorAdapter(fromNodeProviderChain());

const generateClientConfigMock = mock.method(
graphqlClientCodeGeneratorAdapter,
'generateGraphqlClientCodeToFile',
() => Promise.resolve()
);

const generateGraphqlClientCodeCommand = new GenerateGraphqlClientCodeCommand(
graphqlClientCodeGeneratorAdapter,
{ resolve: () => Promise.resolve('testAppName') }
);
const parser = yargs().command(
generateGraphqlClientCodeCommand as unknown as CommandModule
);
const commandRunner = new TestCommandRunner(parser);

beforeEach(() => {
generateClientConfigMock.mock.resetCalls();
});

it('generates and writes graphql client code for stack', async () => {
await commandRunner.runCommand('graphql-client-code --stack stack_name');
assert.equal(generateClientConfigMock.mock.callCount(), 1);
assert.deepEqual(generateClientConfigMock.mock.calls[0].arguments[0], {
stackName: 'stack_name',
format: 'graphql-codegen',
out: process.cwd(),
statementTarget: 'javascript',
});
});

it('generates and writes graphql client code for branch', async () => {
await commandRunner.runCommand('graphql-client-code --branch branch_name');
assert.equal(generateClientConfigMock.mock.callCount(), 1);
assert.deepEqual(generateClientConfigMock.mock.calls[0].arguments[0], {
appName: 'testAppName',
branchName: 'branch_name',
out: process.cwd(),
format: 'graphql-codegen',
statementTarget: 'javascript',
});
});

it('generates and writes graphql client code for appID and branch', async () => {
await commandRunner.runCommand(
'graphql-client-code --branch branch_name --appId app_id'
);
assert.equal(generateClientConfigMock.mock.callCount(), 1);
assert.deepEqual(generateClientConfigMock.mock.calls[0].arguments[0], {
backendId: 'app_id',
branchName: 'branch_name',
out: process.cwd(),
format: 'graphql-codegen',
statementTarget: 'javascript',
});
});

it('can generate to custom absolute path', async () => {
await commandRunner.runCommand(
'graphql-client-code --stack stack_name --out /foo/bar'
);
assert.equal(generateClientConfigMock.mock.callCount(), 1);
assert.deepEqual(generateClientConfigMock.mock.calls[0].arguments[0], {
stackName: 'stack_name',
out: path.join('/', 'foo', 'bar'),
format: 'graphql-codegen',
statementTarget: 'javascript',
});
});

it('can generate to custom relative path', async () => {
await commandRunner.runCommand(
'graphql-client-code --stack stack_name --out foo/bar'
);
assert.equal(generateClientConfigMock.mock.callCount(), 1);
assert.deepEqual(generateClientConfigMock.mock.calls[0].arguments[0], {
stackName: 'stack_name',
format: 'graphql-codegen',
statementTarget: 'javascript',
out: path.join(process.cwd(), 'foo', 'bar'),
});
});

it('shows available options in help output', async () => {
const output = await commandRunner.runCommand('graphql-client-code --help');
assert.match(output, /--stack/);
assert.match(output, /--appId/);
assert.match(output, /--branch/);
assert.match(output, /--format/);
assert.match(output, /--statementTarget/);
assert.match(output, /--typeTarget/);
assert.match(output, /--modelTarget/);
assert.match(output, /--out/);
});

it('fails if both stack and branch are present', async () => {
await assert.rejects(
() =>
commandRunner.runCommand(
'graphql-client-code --stack foo --branch baz'
),
(err: TestCommandError) => {
assert.equal(err.error.name, 'YError');
assert.match(err.error.message, /Arguments .* mutually exclusive/);
assert.match(err.output, /Arguments .* are mutually exclusive/);
return true;
}
);
});

// it('can be invoked explicitly with graphql-codegen format', async () => {
// await commandRunner.runCommand('graphql-client-code --stack stack_name --format graphql-codegen');
// assert.equal(generateClientConfigMock.mock.callCount(), 1);
// assert.deepEqual(generateClientConfigMock.mock.calls[0].arguments[0], {
// stackName: 'stack_name',
// format: 'graphql-codegen',
// statementType: 'javascript',
// out: process.cwd(),
// });
// });

// it('can be invoked explicitly with modelgen format', async () => {
// await commandRunner.runCommand('graphql-client-code --stack stack_name --format modelgen');
// assert.equal(generateClientConfigMock.mock.callCount(), 1);
// assert.deepEqual(generateClientConfigMock.mock.calls[0].arguments[0], {
// stackName: 'stack_name',
// format: 'modelgen',
// modelType: 'javascript',
// out: process.cwd(),
// });
// });

// it('can be invoked explicitly with introspection format', async () => {
// await commandRunner.runCommand('graphql-client-code --stack stack_name --format introspection');
// assert.equal(generateClientConfigMock.mock.callCount(), 1);
// assert.deepEqual(generateClientConfigMock.mock.calls[0].arguments[0], {
// stackName: 'stack_name',
// format: 'introspection',
// out: process.cwd(),
// });
// });
});
Loading

0 comments on commit cb03274

Please sign in to comment.