Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: reuse foreign key field in
@belongsTo
transformer (#8557)
* fix: belongsTo uses same foreign key field as hasMany * chore: adding some comments * test: update test
- Loading branch information
1 parent
840ce0f
commit 39fbe6f
Showing
7 changed files
with
232 additions
and
10 deletions.
There are no files selected for viewing
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
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
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
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
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
104 changes: 104 additions & 0 deletions
104
packages/graphql-transformers-e2e-tests/src/__tests__/BelongsToTransformerV2.e2e.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,104 @@ | ||
import { deploySchema } from '../deploySchema'; | ||
import { GraphQLClient } from '../GraphQLClient'; | ||
import { GraphQLTransform } from '@aws-amplify/graphql-transformer-core'; | ||
import { ModelTransformer } from '@aws-amplify/graphql-model-transformer'; | ||
import { BelongsToTransformer, HasManyTransformer, HasOneTransformer } from '@aws-amplify/graphql-relational-transformer'; | ||
|
||
jest.setTimeout(1000 * 60 * 5); // 5 minutes | ||
|
||
describe('@belongsTo transformer', () => { | ||
const transformer = new GraphQLTransform({ | ||
transformers: [new ModelTransformer(), new BelongsToTransformer(), new HasManyTransformer(), new HasOneTransformer()], | ||
sandboxModeEnabled: true, | ||
}); | ||
const validSchema = /* GraphQL */ ` | ||
type Blog @model { | ||
id: ID! | ||
name: String! | ||
post: Post @hasOne | ||
} | ||
type Post @model { | ||
id: ID! | ||
title: String! | ||
blog: Blog @belongsTo | ||
comments: [Comment] @hasMany | ||
} | ||
type Comment @model { | ||
id: ID! | ||
post: Post @belongsTo | ||
content: String! | ||
} | ||
`; | ||
let graphqlClient: GraphQLClient; | ||
let cleanUp: () => Promise<void>; | ||
beforeAll(async () => { | ||
({ graphqlClient, cleanUp } = await deploySchema('belongsToV2Test', transformer, validSchema)); | ||
}); | ||
|
||
afterAll(async () => { | ||
if (typeof cleanUp === 'function') { | ||
await cleanUp(); | ||
} | ||
}); | ||
|
||
it('reuses foreign key fields generated by corresponding hasOne and hasMany directives', async () => { | ||
const mutationResponse = await graphqlClient.query(/* GraphQL */ ` | ||
mutation CreateRecords { | ||
createComment(input: { content: "test comment 1", id: "comment1", postCommentsId: "post1" }) { | ||
id | ||
} | ||
createBlog(input: { id: "blog1", name: "test blog 1", blogPostId: "post1" }) { | ||
id | ||
} | ||
createPost(input: { blogPostId: "blog1", id: "post1", title: "test post 1" }) { | ||
id | ||
} | ||
} | ||
`); | ||
|
||
expect(mutationResponse.errors).toBeUndefined(); | ||
expect(mutationResponse.data.createComment.id).toEqual('comment1'); | ||
expect(mutationResponse.data.createBlog.id).toEqual('blog1'); | ||
expect(mutationResponse.data.createPost.id).toEqual('post1'); | ||
|
||
const queryResponse = await graphqlClient.query(/* GraphQL */ ` | ||
query GetRecords { | ||
getBlog(id: "blog1") { | ||
name | ||
post { | ||
id | ||
title | ||
} | ||
} | ||
getComment(id: "comment1") { | ||
content | ||
post { | ||
id | ||
title | ||
} | ||
} | ||
getPost(id: "post1") { | ||
title | ||
blog { | ||
id | ||
name | ||
} | ||
comments { | ||
items { | ||
content | ||
id | ||
} | ||
} | ||
} | ||
} | ||
`); | ||
|
||
expect(queryResponse.errors).toBeUndefined(); | ||
expect(queryResponse.data.getBlog.post.id).toEqual('post1'); | ||
expect(queryResponse.data.getComment.post.id).toEqual('post1'); | ||
expect(queryResponse.data.getPost.blog.id).toEqual('blog1'); | ||
expect(queryResponse.data.getPost.comments.items[0].id).toEqual('comment1'); | ||
}); | ||
}); |
84 changes: 84 additions & 0 deletions
84
packages/graphql-transformers-e2e-tests/src/deploySchema.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,84 @@ | ||
import { default as S3 } from 'aws-sdk/clients/s3'; | ||
import moment from 'moment'; | ||
import { GraphQLTransform } from '../../amplify-graphql-transformer-core/lib'; | ||
import { CloudFormationClient } from './CloudFormationClient'; | ||
import { GraphQLClient } from './GraphQLClient'; | ||
import { S3Client } from './S3Client'; | ||
import * as path from 'path'; | ||
import * as os from 'os'; | ||
import { cleanupStackAfterTest, deploy } from './deployNestedStacks'; | ||
import { Output } from 'aws-sdk/clients/cloudformation'; | ||
import { ResourceConstants } from 'graphql-transformer-common'; | ||
import * as fs from 'fs-extra'; | ||
|
||
const cf = new CloudFormationClient('us-west-2'); | ||
const customS3Client = new S3Client('us-west-2'); | ||
const awsS3Client = new S3({ region: 'us-west-2' }); | ||
|
||
export type DeploySchemaReturn = { | ||
graphqlClient: GraphQLClient; | ||
cleanUp: () => Promise<void>; | ||
}; | ||
|
||
/** | ||
* Deploys an AppSync API using the given transformer and schema and returns a GraphQL client pointing to the deployed API. | ||
* Also returns a function that can be used to tear down the API after the test is finished. | ||
* | ||
* No other tests are refactored to use this function at this point, | ||
* but it would be nice to extend this function to handle spinning up and cleaning up all test GQL endpoints | ||
* | ||
* @param testId A human readable identifier for the schema / test being provisioned. Should be alphanumeric (no dashes, underscores, etc) | ||
* @param transformer The transformer to run on the schema | ||
* @param schema The schema to transform | ||
* @returns A GraphQL client pointing to an AppSync API with the provided schema deployed to it | ||
*/ | ||
export const deploySchema = async (testId: string, transformer: GraphQLTransform, schema: string): Promise<DeploySchemaReturn> => { | ||
const buildTimestamp = moment().format('YYYYMMDDHHmmss'); | ||
const stackName = `${testId}-${buildTimestamp}`; | ||
const testBucketName = `${testId}-bucket-${buildTimestamp}`.toLowerCase(); | ||
const localBuildDir = path.join(os.tmpdir(), testId); | ||
const s3RootDirKey = 'deployments'; | ||
|
||
try { | ||
await awsS3Client.createBucket({ Bucket: testBucketName }).promise(); | ||
} catch (err) { | ||
console.error(`Failed to create bucket ${testBucketName}: ${err}`); | ||
} | ||
|
||
const out = transformer.transform(schema); | ||
|
||
try { | ||
const finishedStack = await deploy(customS3Client, cf, stackName, out, {}, localBuildDir, testBucketName, s3RootDirKey, buildTimestamp); | ||
|
||
// Arbitrary wait to make sure everything is ready. | ||
await cf.wait(5, () => Promise.resolve()); | ||
|
||
expect(finishedStack).toBeDefined(); | ||
|
||
const getApiEndpoint = outputValueSelector(ResourceConstants.OUTPUTS.GraphQLAPIEndpointOutput); | ||
const getApiKey = outputValueSelector(ResourceConstants.OUTPUTS.GraphQLAPIApiKeyOutput); | ||
const endpoint = getApiEndpoint(finishedStack.Outputs); | ||
const apiKey = getApiKey(finishedStack.Outputs); | ||
|
||
expect(apiKey).toBeDefined(); | ||
expect(endpoint).toBeDefined(); | ||
|
||
return { | ||
graphqlClient: new GraphQLClient(endpoint, { 'x-api-key': apiKey }), | ||
cleanUp: async () => { | ||
await cleanupStackAfterTest(testBucketName, stackName, cf); | ||
await fs.remove(localBuildDir); | ||
}, | ||
}; | ||
} catch (e) { | ||
console.error(e); | ||
expect(true).toEqual(false); | ||
} | ||
}; | ||
|
||
function outputValueSelector(key: string) { | ||
return (outputs: Output[]) => { | ||
const output = outputs.find((o: Output) => o.OutputKey === key); | ||
return output ? output.OutputValue : null; | ||
}; | ||
} |