-
Notifications
You must be signed in to change notification settings - Fork 76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
test: Add e2e test for lambda data client #2228
Draft
stocaaro
wants to merge
11
commits into
stocaaro/client-schema/main
Choose a base branch
from
stocaaro/client-schema/e2e-test
base: stocaaro/client-schema/main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
0ed0e84
test: Add e2e test for data client
stocaaro ef2e811
Merge branch 'stocaaro/client-schema/main' into stocaaro/client-schem…
stocaaro 65dfd18
fix: integ test and tune user error
stocaaro fa39c8c
Fix test assert
stocaaro efc059c
Remove amplify outputs
stocaaro 7466692
remove comment
stocaaro 82dd679
Merge branch 'stocaaro/client-schema/main' into stocaaro/client-schem…
stocaaro d2ca53b
test: Add e2e test for data client
stocaaro ef954ac
Merge remote-tracking branch 'upstream/stocaaro/client-schema/main' i…
stocaaro c7f2d6b
Remove unneeded tsconfig
stocaaro c934af2
fix: Schema import pattern
stocaaro File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
4 changes: 4 additions & 0 deletions
4
...es/integration-tests/src/test-e2e/deployment/data_and_function_project.deployment.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { defineDeploymentTest } from './deployment.test.template.js'; | ||
import { DataAndFunctionTestProjectCreator } from '../../test-project-setup/data_and_function_project.js'; | ||
|
||
defineDeploymentTest(new DataAndFunctionTestProjectCreator()); |
4 changes: 4 additions & 0 deletions
4
packages/integration-tests/src/test-e2e/sandbox/data_and_function_project.sandbox.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { defineSandboxTest } from './sandbox.test.template.js'; | ||
import { DataAndFunctionTestProjectCreator } from '../../test-project-setup/data_and_function_project.js'; | ||
|
||
defineSandboxTest(new DataAndFunctionTestProjectCreator()); |
192 changes: 192 additions & 0 deletions
192
packages/integration-tests/src/test-project-setup/data_and_function_project.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
import { TestProjectBase } from './test_project_base.js'; | ||
import fs from 'fs/promises'; | ||
import { createEmptyAmplifyProject } from './create_empty_amplify_project.js'; | ||
import { CloudFormationClient } from '@aws-sdk/client-cloudformation'; | ||
import { TestProjectCreator } from './test_project_creator.js'; | ||
import { AmplifyClient } from '@aws-sdk/client-amplify'; | ||
import { BackendIdentifier } from '@aws-amplify/plugin-types'; | ||
import { LambdaClient } from '@aws-sdk/client-lambda'; | ||
import { DeployedResourcesFinder } from '../find_deployed_resource.js'; | ||
import { generateClientConfig } from '@aws-amplify/client-config'; | ||
import { CognitoIdentityProviderClient } from '@aws-sdk/client-cognito-identity-provider'; | ||
import { SemVer } from 'semver'; | ||
import crypto from 'node:crypto'; | ||
import { | ||
ApolloClient, | ||
ApolloLink, | ||
HttpLink, | ||
InMemoryCache, | ||
} from '@apollo/client/core'; | ||
import { AUTH_TYPE, createAuthLink } from 'aws-appsync-auth-link'; | ||
import { gql } from 'graphql-tag'; | ||
import assert from 'assert'; | ||
import { NormalizedCacheObject } from '@apollo/client'; | ||
import { e2eToolingClientConfig } from '../e2e_tooling_client_config.js'; | ||
|
||
// TODO: this is a work around | ||
// it seems like as of amplify v6 , some of the code only runs in the browser ... | ||
// see https://github.com/aws-amplify/amplify-js/issues/12751 | ||
if (process.versions.node) { | ||
// node >= 20 now exposes crypto by default. This workaround is not needed: https://github.com/nodejs/node/pull/42083 | ||
if (new SemVer(process.versions.node).major < 20) { | ||
// @ts-expect-error altering typing for global to make compiler happy is not worth the effort assuming this is temporary workaround | ||
globalThis.crypto = crypto; | ||
} | ||
} | ||
|
||
/** | ||
* Creates the data and function test project. | ||
*/ | ||
export class DataAndFunctionTestProjectCreator implements TestProjectCreator { | ||
readonly name = 'data-and-function'; | ||
|
||
/** | ||
* Creates project creator. | ||
*/ | ||
constructor( | ||
private readonly cfnClient: CloudFormationClient = new CloudFormationClient( | ||
e2eToolingClientConfig | ||
), | ||
private readonly amplifyClient: AmplifyClient = new AmplifyClient( | ||
e2eToolingClientConfig | ||
), | ||
private readonly lambdaClient: LambdaClient = new LambdaClient( | ||
e2eToolingClientConfig | ||
), | ||
private readonly cognitoIdentityProviderClient: CognitoIdentityProviderClient = new CognitoIdentityProviderClient( | ||
e2eToolingClientConfig | ||
), | ||
private readonly resourceFinder: DeployedResourcesFinder = new DeployedResourcesFinder() | ||
) {} | ||
|
||
createProject = async (e2eProjectDir: string): Promise<TestProjectBase> => { | ||
const { projectName, projectRoot, projectAmplifyDir } = | ||
await createEmptyAmplifyProject(this.name, e2eProjectDir); | ||
|
||
const project = new DataAndFunctionTestProject( | ||
projectName, | ||
projectRoot, | ||
projectAmplifyDir, | ||
this.cfnClient, | ||
this.amplifyClient, | ||
this.lambdaClient, | ||
this.cognitoIdentityProviderClient, | ||
this.resourceFinder | ||
); | ||
await fs.cp( | ||
project.sourceProjectAmplifyDirURL, | ||
project.projectAmplifyDirPath, | ||
{ | ||
recursive: true, | ||
} | ||
); | ||
return project; | ||
}; | ||
} | ||
|
||
/** | ||
* The data and function test project. | ||
*/ | ||
class DataAndFunctionTestProject extends TestProjectBase { | ||
readonly sourceProjectDirPath = '../../src/test-projects/data-and-function'; | ||
|
||
readonly sourceProjectAmplifyDirSuffix = `${this.sourceProjectDirPath}/amplify`; | ||
|
||
readonly sourceProjectAmplifyDirURL: URL = new URL( | ||
this.sourceProjectAmplifyDirSuffix, | ||
import.meta.url | ||
); | ||
|
||
/** | ||
* Create a test project instance. | ||
*/ | ||
constructor( | ||
name: string, | ||
projectDirPath: string, | ||
projectAmplifyDirPath: string, | ||
cfnClient: CloudFormationClient, | ||
amplifyClient: AmplifyClient, | ||
private readonly lambdaClient: LambdaClient = new LambdaClient( | ||
e2eToolingClientConfig | ||
), | ||
private readonly cognitoIdentityProviderClient: CognitoIdentityProviderClient = new CognitoIdentityProviderClient( | ||
e2eToolingClientConfig | ||
), | ||
private readonly resourceFinder: DeployedResourcesFinder = new DeployedResourcesFinder() | ||
) { | ||
super( | ||
name, | ||
projectDirPath, | ||
projectAmplifyDirPath, | ||
cfnClient, | ||
amplifyClient | ||
); | ||
} | ||
|
||
override async assertPostDeployment( | ||
backendId: BackendIdentifier | ||
): Promise<void> { | ||
await super.assertPostDeployment(backendId); | ||
|
||
const clientConfig = await generateClientConfig(backendId, '1.1'); | ||
if (!clientConfig.data?.url) { | ||
throw new Error('Data and function project must include data'); | ||
} | ||
if (!clientConfig.data.api_key) { | ||
throw new Error('Data and function project must include api_key'); | ||
} | ||
|
||
// const dataUrl = clientConfig.data?.url; | ||
|
||
const httpLink = new HttpLink({ uri: clientConfig.data.url }); | ||
const link = ApolloLink.from([ | ||
createAuthLink({ | ||
url: clientConfig.data.url, | ||
region: clientConfig.data.aws_region, | ||
auth: { | ||
type: AUTH_TYPE.API_KEY, | ||
apiKey: clientConfig.data.api_key, | ||
}, | ||
}), | ||
// see https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues/473#issuecomment-543029072 | ||
httpLink, | ||
]); | ||
const apolloClient = new ApolloClient({ | ||
link, | ||
cache: new InMemoryCache(), | ||
}); | ||
|
||
await this.assertDataFunctionCallSucceeds(apolloClient); | ||
await this.assertNoopWithImportCallSucceeds(apolloClient); | ||
} | ||
|
||
private assertDataFunctionCallSucceeds = async ( | ||
apolloClient: ApolloClient<NormalizedCacheObject> | ||
): Promise<void> => { | ||
const response = await apolloClient.query<number>({ | ||
query: gql` | ||
query todoCount { | ||
todoCount | ||
} | ||
`, | ||
variables: {}, | ||
}); | ||
|
||
assert.deepEqual(response.data, { todoCount: 0 }); | ||
}; | ||
|
||
private assertNoopWithImportCallSucceeds = async ( | ||
apolloClient: ApolloClient<NormalizedCacheObject> | ||
): Promise<void> => { | ||
const response = await apolloClient.query<number>({ | ||
query: gql` | ||
query noopImport { | ||
noopImport | ||
} | ||
`, | ||
variables: {}, | ||
}); | ||
|
||
assert.deepEqual(response.data, { noopImport: 'STATIC TEST RESPONSE' }); | ||
}; | ||
} |
6 changes: 6 additions & 0 deletions
6
packages/integration-tests/src/test-projects/data-and-function/amplify/backend.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { defineBackend } from '@aws-amplify/backend'; | ||
import { data } from './data/resource.js'; | ||
import { todoCount } from './functions/todo-count/resource.js'; | ||
import { noopImport } from './functions/noop-import/resource.js'; | ||
|
||
const backend = defineBackend({ data, todoCount, noopImport }); |
42 changes: 42 additions & 0 deletions
42
packages/integration-tests/src/test-projects/data-and-function/amplify/data/resource.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { a, ClientSchema, defineData } from '@aws-amplify/backend'; | ||
import { todoCount } from '../functions/todo-count/resource.js'; | ||
import { noopImport } from '../functions/noop-import/resource.js'; | ||
|
||
const schema = a | ||
.schema({ | ||
Todo: a | ||
.model({ | ||
title: a.string().required(), | ||
done: a.boolean().default(false), // default value is false | ||
}) | ||
.authorization((allow) => [allow.publicApiKey()]), | ||
todoCount: a | ||
.query() | ||
.arguments({}) | ||
.returns(a.integer()) | ||
.handler(a.handler.function(todoCount)) | ||
.authorization((allow) => [allow.publicApiKey()]), | ||
noopImport: a | ||
.query() | ||
.arguments({}) | ||
.returns(a.string()) | ||
.handler(a.handler.function(noopImport)) | ||
.authorization((allow) => [allow.publicApiKey()]), | ||
}) | ||
.authorization((allow) => [ | ||
allow.resource(todoCount), | ||
allow.resource(noopImport), | ||
]); | ||
|
||
export type Schema = ClientSchema<typeof schema>; | ||
|
||
export const data = defineData({ | ||
schema, | ||
authorizationModes: { | ||
defaultAuthorizationMode: 'apiKey', | ||
// API Key is used for a.allow.public() rules | ||
apiKeyAuthorizationMode: { | ||
expiresInDays: 30, | ||
}, | ||
}, | ||
}); |
22 changes: 22 additions & 0 deletions
22
...ration-tests/src/test-projects/data-and-function/amplify/functions/noop-import/handler.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import type { Handler } from 'aws-lambda'; | ||
import { Amplify } from 'aws-amplify'; | ||
import { generateClient } from 'aws-amplify/data'; | ||
import type { Schema } from '../../data/resource.js'; | ||
import { getAmplifyDataClientConfig } from '@aws-amplify/backend/function/runtime'; | ||
// @ts-ignore | ||
import { env } from '$amplify/env/noop-import.js'; | ||
import { S3Client } from '@aws-sdk/client-s3'; | ||
|
||
const { resourceConfig, libraryOptions } = await getAmplifyDataClientConfig( | ||
env | ||
); | ||
|
||
Amplify.configure(resourceConfig, libraryOptions); | ||
|
||
const client = generateClient<Schema>(); | ||
|
||
export const handler: Handler = async () => { | ||
const _s3Client = new S3Client(); | ||
const _todos = await client.models.Todo.list(); | ||
return 'STATIC TEST RESPONSE'; | ||
}; |
7 changes: 7 additions & 0 deletions
7
...ation-tests/src/test-projects/data-and-function/amplify/functions/noop-import/resource.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { defineFunction } from '@aws-amplify/backend'; | ||
|
||
export const noopImport = defineFunction({ | ||
name: 'noop-import', | ||
entry: './handler.ts', | ||
timeoutSeconds: 30, | ||
}); |
20 changes: 20 additions & 0 deletions
20
...gration-tests/src/test-projects/data-and-function/amplify/functions/todo-count/handler.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import type { Handler } from 'aws-lambda'; | ||
import { Amplify } from 'aws-amplify'; | ||
import { generateClient } from 'aws-amplify/data'; | ||
import type { Schema } from '../../data/resource.js'; | ||
import { getAmplifyDataClientConfig } from '@aws-amplify/backend/function/runtime'; | ||
// @ts-ignore | ||
import { env } from '$amplify/env/todo-count.js'; | ||
|
||
const { resourceConfig, libraryOptions } = await getAmplifyDataClientConfig( | ||
env | ||
); | ||
|
||
Amplify.configure(resourceConfig, libraryOptions); | ||
|
||
const client = generateClient<Schema>(); | ||
|
||
export const handler: Handler = async () => { | ||
const todos = await client.models.Todo.list(); | ||
return todos.data.length; | ||
}; |
7 changes: 7 additions & 0 deletions
7
...ration-tests/src/test-projects/data-and-function/amplify/functions/todo-count/resource.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { defineFunction } from '@aws-amplify/backend'; | ||
|
||
export const todoCount = defineFunction({ | ||
name: 'todo-count', | ||
entry: './handler.ts', | ||
timeoutSeconds: 30, | ||
}); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Esbuild during synth is fine with all of this, but the ts check before synth is unhappy. It looks like a workaround was used for
data-storage-auth-with-triggers-ts
of setting up fake files to make the pre-synth check happy. Should I replicate that here? It would avoid the exclude change in the tsconfig below too.Seems fine, but also very fake since this file isn't being built in the project.