From eac2699a9f4e27fdd147cec6ca3e138e6b6e81b7 Mon Sep 17 00:00:00 2001 From: Zeyu Li Date: Mon, 27 Nov 2023 10:12:55 -0800 Subject: [PATCH] test: add codegen test matrix --- .../src/categories/codegen.ts | 13 +- .../src/configure/index.ts | 118 ++++++++++++++++-- .../src/init/initProjectHelper.ts | 11 +- .../src/utils/frontend-config-helper.ts | 43 +++++-- .../src/__tests__/add-codegen-js.test.ts | 16 ++- .../uninitialized-project-codegen-js.test.ts | 6 +- .../src/codegen-tests-base/add-codegen.ts | 31 +++-- 7 files changed, 201 insertions(+), 37 deletions(-) diff --git a/packages/amplify-codegen-e2e-core/src/categories/codegen.ts b/packages/amplify-codegen-e2e-core/src/categories/codegen.ts index ab5a83a1f..80808b024 100644 --- a/packages/amplify-codegen-e2e-core/src/categories/codegen.ts +++ b/packages/amplify-codegen-e2e-core/src/categories/codegen.ts @@ -1,4 +1,4 @@ -import { AmplifyFrontend } from '../utils'; +import { AmplifyFrontend, singleSelect } from '../utils'; import { getCLIPath, nspawn as spawn } from '..'; export function generateModels(cwd: string, outputDir?: string, settings: { errMessage?: string } = {}): Promise { @@ -90,7 +90,12 @@ export function addCodegen(cwd: string, settings: any = {}): Promise { } else { if (settings.frontendType === AmplifyFrontend.javascript) { - chain.wait('Choose the code generation language target').sendCarriageReturn(); + chain.wait('Choose the code generation language target'); + if (settings.framework === 'angular' || settings.framework === 'ionic') { + singleSelect(chain, settings.codegenTarget, ['angular', 'typescript']); + } else { + singleSelect(chain, settings.codegenTarget, ['javascript', 'typescript', 'flow']); + } } chain .wait('Enter the file name pattern of graphql queries, mutations and subscriptions') @@ -99,7 +104,9 @@ export function addCodegen(cwd: string, settings: any = {}): Promise { .sendLine('y') .wait('Enter maximum statement depth [increase from default if your schema is deeply') .sendCarriageReturn(); - if (settings.frontendType === AmplifyFrontend.ios) { + const isTypeGenIncluded = settings.frontendType === AmplifyFrontend.ios + || (settings.frontendType === AmplifyFrontend.javascript && settings.codegenTarget !== 'javascript'); + if (isTypeGenIncluded) { chain .wait('Enter the file name for the generated code') .sendCarriageReturn() diff --git a/packages/amplify-codegen-e2e-core/src/configure/index.ts b/packages/amplify-codegen-e2e-core/src/configure/index.ts index 40c08718e..8c8b5c339 100644 --- a/packages/amplify-codegen-e2e-core/src/configure/index.ts +++ b/packages/amplify-codegen-e2e-core/src/configure/index.ts @@ -13,6 +13,18 @@ const defaultSettings = { userName: '\r', }; +const defaultProjectSettings = { + name: '\r', + envName: 'integtest', + editor: '\r', + appType: 'javascript', + framework: 'none', + srcDir: '\r', + distDir: '\r', + buildCmd: '\r', + startCmd: '\r', +}; + export const amplifyRegions = [ 'us-east-1', 'us-east-2', @@ -34,8 +46,11 @@ export const amplifyRegions = [ 'sa-east-1', ]; -const configurationOptions = ['project', 'profile', 'containers']; -const profileOptions = ['cancel', 'update', 'remove']; +const configurationOptions = ['Project information', 'AWS Profile setting', 'Advanced: Container-based deployments']; +const profileOptions = ['No', 'Update AWS Profile', 'Remove AWS Profile']; +const authenticationOptions = ['AWS profile', 'AWS access keys']; +const javaScriptFrameworkList = [ 'none', 'angluar', 'ember', 'ionic', 'react', 'react-native', 'vue' ]; + const MANDATORY_PARAMS = ['accessKeyId', 'secretAccessKey', 'region']; @@ -77,18 +92,52 @@ export function amplifyConfigure(settings: AmplifyConfiguration): Promise }); } -export function amplifyConfigureProject(settings: { cwd: string; enableContainers: boolean }): Promise { - const { enableContainers = false, cwd } = settings; +export function amplifyConfigureProject(settings: { + cwd: string; + enableContainers?: boolean; + configLevel?: string; + profileOption?: string; + authenticationOption?: string; + region?: string; +}): Promise { + const { + cwd, + enableContainers = false, + profileOption = profileOptions[0], + authenticationOption, + configLevel = 'project', + region = defaultSettings.region, + } = settings; return new Promise((resolve, reject) => { const chain = spawn(getCLIPath(), ['configure', 'project'], { cwd, stripColors: true }).wait('Which setting do you want to configure?'); + if (enableContainers) { - singleSelect(chain, 'containers', configurationOptions); - chain.wait('Do you want to enable container-based deployments?').sendLine('y'); + singleSelect(chain, configurationOptions[2], configurationOptions); + chain.wait('Do you want to enable container-based deployments?').sendConfirmYes(); } else { - singleSelect(chain, 'profile', configurationOptions); - chain.wait('Do you want to update or remove the project level AWS profile?'); - singleSelect(chain, profileOptions[0], profileOptions); + singleSelect(chain, configurationOptions[1], configurationOptions); + + if (configLevel === 'project') { + chain.wait('Do you want to update or remove the project level AWS profile?'); + singleSelect(chain, profileOption, profileOptions); + } else { + chain.wait('Do you want to set the project level configuration').sendConfirmYes(); + } + + if (profileOption === profileOptions[1] || configLevel === 'general') { + chain.wait('Select the authentication method you want to use:'); + singleSelect(chain, authenticationOption, authenticationOptions); + + if (authenticationOption === authenticationOptions[0]) { + chain.wait('Please choose the profile you want to use').sendCarriageReturn(); // Default profile + } else if (authenticationOption === authenticationOptions[1]) { + chain.wait('accessKeyId:').sendLine(process.env.AWS_ACCESS_KEY_ID); + chain.wait('secretAccessKey:').sendLine(process.env.AWS_SECRET_ACCESS_KEY); + chain.wait('region:'); + singleSelect(chain, region, amplifyRegions); + } + } } chain.wait('Successfully made configuration changes to your project.').run((err: Error) => { @@ -100,3 +149,54 @@ export function amplifyConfigureProject(settings: { cwd: string; enableContainer }); }); } + +export function amplifyConfigureProjectInfo(settings: { + cwd: string, +}): Promise { + const { + cwd, + } = settings; + const s = { ...defaultProjectSettings, ...settings }; + return new Promise((resolve, reject) => { + const chain = spawn(getCLIPath(), ['configure', 'project'], { cwd, stripColors: true }).wait('Which setting do you want to configure?'); + singleSelect(chain, configurationOptions[0], configurationOptions); + chain + .wait('Enter a name for the project') + .sendLine(s.name) + .wait('Choose your default editor:') + .sendLine(s.editor) + .wait("Choose the type of app that you're building") + .sendLine(s.appType); + + switch (s.appType) { + case 'javascript': + chain.wait('What javascript framework are you using'); + singleSelect(chain, s.framework, javaScriptFrameworkList); + chain + .wait('Source Directory Path:') + .sendLine(s.srcDir) + .wait('Distribution Directory Path:') + .sendLine(s.distDir) + .wait('Build Command:') + .sendLine(s.buildCmd) + .wait('Start Command:') + .sendLine(s.startCmd); + break; + case 'android': + chain + .wait('Where is your Res directory') + .sendLine(s.srcDir); + break; + case 'ios': + break; + case 'flutter': + chain + .wait('Where do you want to store your configuration file?') + .sendLine(s.srcDir) + default: + throw new Error(`Frontend type ${s.appType} is not supported.`); + } + + chain.wait('Successfully made configuration changes to your project.'); + }) +} \ No newline at end of file diff --git a/packages/amplify-codegen-e2e-core/src/init/initProjectHelper.ts b/packages/amplify-codegen-e2e-core/src/init/initProjectHelper.ts index b8c888e41..41f0ae7c3 100644 --- a/packages/amplify-codegen-e2e-core/src/init/initProjectHelper.ts +++ b/packages/amplify-codegen-e2e-core/src/init/initProjectHelper.ts @@ -8,7 +8,7 @@ const defaultSettings = { envName: 'integtest', editor: '\r', appType: '\r', - framework: '\r', + framework: 'none', srcDir: '\r', distDir: '\r', buildCmd: '\r', @@ -22,6 +22,8 @@ const defaultSettings = { providerConfig: undefined, }; +const javaScriptFrameworkList = [ 'none', 'angluar', 'ember', 'ionic', 'react', 'react-native', 'vue' ]; + export function initJSProjectWithProfile(cwd: string, settings: Object = {}): Promise { const s = { ...defaultSettings, ...settings }; let env; @@ -52,8 +54,11 @@ export function initJSProjectWithProfile(cwd: string, settings: Object = {}): Pr .sendLine(s.editor) .wait("Choose the type of app that you're building") .sendLine(s.appType) - .wait('What javascript framework are you using') - .sendLine(s.framework) + .wait('What javascript framework are you using'); + + singleSelect(chain, s.framework, javaScriptFrameworkList); + + chain .wait('Source Directory Path:') .sendLine(s.srcDir) .wait('Distribution Directory Path:') diff --git a/packages/amplify-codegen-e2e-core/src/utils/frontend-config-helper.ts b/packages/amplify-codegen-e2e-core/src/utils/frontend-config-helper.ts index 8d8452ca6..626251f1c 100644 --- a/packages/amplify-codegen-e2e-core/src/utils/frontend-config-helper.ts +++ b/packages/amplify-codegen-e2e-core/src/utils/frontend-config-helper.ts @@ -1,23 +1,52 @@ export enum AmplifyFrontend { javascript = 'javascript', - typescript = 'typescript', ios = 'ios', android = 'android', flutter = 'flutter' } -export type AmplifyFrontendConfig = { - frontendType: AmplifyFrontend; - srcDir: string; - modelgenDir: string; - graphqlCodegenDir?: string; +export type JavaScriptFramework = 'none' | 'angular' | 'ember' | 'ionic' | 'react' | 'react-native' | 'vue'; + +export type JavaScriptCodegenTarget = 'javascript' | 'typescript' | 'flow' | 'angluar'; + +export type JavaScriptConfig = { + frontendType: AmplifyFrontend.javascript, + framework: JavaScriptFramework, + codegenTarget?: JavaScriptCodegenTarget, + srcDir: string, + modelgenDir?: string, + graphqlCodegenDir?: string, +} + +export type AndroidConfig = { + frontendType: AmplifyFrontend.android, + srcDir: string, + modelgenDir?: string, + graphqlCodegenDir?: string, +} + +export type IOSConfig = { + frontendType: AmplifyFrontend.ios, + srcDir: string, + modelgenDir?: string, + graphqlCodegenDir?: string, +} + +export type FlutterConfig = { + frontendType: AmplifyFrontend.flutter, + srcDir: string, + modelgenDir?: string, + graphqlCodegenDir?: string, } +export type AmplifyFrontendConfig = JavaScriptConfig | AndroidConfig | IOSConfig | FlutterConfig; export const DEFAULT_JS_CONFIG: AmplifyFrontendConfig = { frontendType: AmplifyFrontend.javascript, + framework: 'none', + codegenTarget: 'javascript', srcDir: 'src', modelgenDir: 'src/models', - graphqlCodegenDir : 'src/graphql' + graphqlCodegenDir : 'src/graphql', }; export const DEFAULT_ANDROID_CONFIG: AmplifyFrontendConfig = { diff --git a/packages/amplify-codegen-e2e-tests/src/__tests__/add-codegen-js.test.ts b/packages/amplify-codegen-e2e-tests/src/__tests__/add-codegen-js.test.ts index 2a23c972d..7a82720ff 100644 --- a/packages/amplify-codegen-e2e-tests/src/__tests__/add-codegen-js.test.ts +++ b/packages/amplify-codegen-e2e-tests/src/__tests__/add-codegen-js.test.ts @@ -6,6 +6,7 @@ import { createRandomName, addApiWithoutSchema, updateApiSchema, + AmplifyFrontend, } from "@aws-amplify/amplify-codegen-e2e-core"; import { existsSync } from "fs"; import path from 'path'; @@ -22,7 +23,7 @@ const schema = 'simple_model.graphql'; describe('codegen add tests - JS', () => { let projectRoot: string; - const config = DEFAULT_JS_CONFIG; + let config = DEFAULT_JS_CONFIG; beforeEach(async () => { projectRoot = await createNewProjectDir('addCodegenJS'); @@ -81,4 +82,17 @@ describe('codegen add tests - JS', () => { it(`supports add codegen with redundant region parameter`, async () => { await testAddCodegen(config, projectRoot, schema, ['--region', 'us-fake-1']); }); + + describe.only('JS codegen matrix test', async () => { + it('Adding codegen works as expected', async () => { + config = { + frontendType: AmplifyFrontend.javascript, + framework: 'angular', + codegenTarget: 'angluar', + srcDir: 'src', + graphqlCodegenDir : 'src/graphql' + } + await testAddCodegen(config, projectRoot, schema); + }); + }); }); diff --git a/packages/amplify-codegen-e2e-tests/src/__tests__/uninitialized-project-codegen-js.test.ts b/packages/amplify-codegen-e2e-tests/src/__tests__/uninitialized-project-codegen-js.test.ts index 076e7b952..0cba9a60a 100644 --- a/packages/amplify-codegen-e2e-tests/src/__tests__/uninitialized-project-codegen-js.test.ts +++ b/packages/amplify-codegen-e2e-tests/src/__tests__/uninitialized-project-codegen-js.test.ts @@ -1,4 +1,4 @@ -import { createNewProjectDir, DEFAULT_JS_CONFIG, AmplifyFrontend, generateStatementsAndTypes } from '@aws-amplify/amplify-codegen-e2e-core'; +import { createNewProjectDir, DEFAULT_JS_CONFIG, generateStatementsAndTypes, AmplifyFrontendConfig } from '@aws-amplify/amplify-codegen-e2e-core'; import path from 'path'; import { deleteAmplifyProject, testAddCodegenUninitialized } from '../codegen-tests-base'; import { rmSync } from "fs-extra"; @@ -6,9 +6,9 @@ import { rmSync } from "fs-extra"; describe('codegen add tests - JS', () => { let projectRoot: string; const javascriptConfig = DEFAULT_JS_CONFIG; - const typescriptConfig = { + const typescriptConfig: any = { ...DEFAULT_JS_CONFIG, - frontendType: AmplifyFrontend.typescript, + codegenTarget: 'typescript', }; beforeEach(async () => { diff --git a/packages/amplify-codegen-e2e-tests/src/codegen-tests-base/add-codegen.ts b/packages/amplify-codegen-e2e-tests/src/codegen-tests-base/add-codegen.ts index 4ae362489..43f33df7b 100644 --- a/packages/amplify-codegen-e2e-tests/src/codegen-tests-base/add-codegen.ts +++ b/packages/amplify-codegen-e2e-tests/src/codegen-tests-base/add-codegen.ts @@ -83,18 +83,27 @@ export async function testAddCodegenUninitialized({ writeFileSync(path.join(projectRoot, sdlFilename), sdlSchema); } + let isTypeGenIncluded = false; // add codegen without init switch (config.frontendType) { - case AmplifyFrontend.javascript: - await addCodegenNonAmplifyJS(projectRoot, additionalParams ?? [], initialFailureMessage); - break; - case AmplifyFrontend.typescript: - await addCodegenNonAmplifyTS(projectRoot, additionalParams ?? [], initialFailureMessage); - break; - default: - throw new Error(`Received unexpected frontendType ${config.frontendType}`); + case AmplifyFrontend.javascript: + switch (config.codegenTarget) { + case 'javascript': + await addCodegenNonAmplifyJS(projectRoot, additionalParams ?? [], initialFailureMessage); + break; + case 'typescript': + isTypeGenIncluded = true; + await addCodegenNonAmplifyTS(projectRoot, additionalParams ?? [], initialFailureMessage); + break; + default: + throw new Error(`Received unexpected codegen target ${config.codegenTarget}`); + } + break; + default: + throw new Error(`Received unexpected frontendType ${config.frontendType}`); } + // return if we expected the add command to fail if (initialFailureMessage) { return; @@ -106,7 +115,7 @@ export async function testAddCodegenUninitialized({ ensureAllExpectedValuesAreReceived(expectedFilenames, readdirSync(path.join(projectRoot, config.graphqlCodegenDir))) // graphql configuration should be added expect(existsSync(getGraphQLConfigFilePath(projectRoot))).toBe(true); - if (config.frontendType === AmplifyFrontend.typescript) { + if (isTypeGenIncluded) { assertTypeFileExists(projectRoot) } @@ -124,7 +133,7 @@ export async function testAddCodegenUninitialized({ // GraphQL statements are regenerated ensureAllExpectedValuesAreReceived(expectedFilenames, readdirSync(path.join(projectRoot, config.graphqlCodegenDir))) - if (config.frontendType === AmplifyFrontend.typescript) { + if (isTypeGenIncluded) { assertTypeFileExists(projectRoot) } } @@ -139,7 +148,7 @@ export async function testAddCodegenUninitialized({ if (dropAndRunCodegenTypes) { await generateTypes(projectRoot); - if (config.frontendType === AmplifyFrontend.typescript) { + if (isTypeGenIncluded) { assertTypeFileExists(projectRoot) } }