Skip to content

Commit

Permalink
chore: Sync console-preview with next/main (#12203)
Browse files Browse the repository at this point in the history
  • Loading branch information
jimblanc authored Oct 5, 2023
2 parents 4ae78ed + cc776cb commit 9607e4a
Show file tree
Hide file tree
Showing 16 changed files with 362 additions and 31 deletions.
1 change: 1 addition & 0 deletions lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"packages/datastore",
"packages/rtn-web-browser",
"packages/notifications",
"packages/rtn-push-notification",
"packages/react-native",
"packages/react-native/example",
"scripts/tsc-compliance-test"
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"packages/api",
"packages/datastore",
"packages/notifications",
"packages/rtn-push-notification",
"packages/aws-amplify",
"packages/rtn-web-browser",
"packages/react-native",
Expand Down
248 changes: 247 additions & 1 deletion packages/api-graphql/__tests__/v6-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,18 @@ import {
GraphqlSubscriptionMessage,
GraphQLQuery,
GraphQLSubscription,
GraphQLReturnType,
} from '../src/types';

import {
CreateThreadMutation,
UpdateThreadMutation,
DeleteThreadMutation,
GetThreadQuery,
ListThreadsQuery,
OnCreateThreadSubscription,
Thread,
Comment,
} from './fixtures/with-types/API';

const serverManagedFields = {
Expand Down Expand Up @@ -337,6 +341,248 @@ describe('client', () => {
});
});

describe('type-tagged graphql with util type adapter', () => {
test('create', async () => {
const threadToCreate = { topic: 'a very engaging discussion topic' };

const graphqlResponse = {
data: {
createThread: {
__typename: 'Thread',
...serverManagedFields,
...threadToCreate,
},
},
};

const spy = jest
.spyOn((raw.GraphQLAPI as any)._api, 'post')
.mockImplementation(() => ({
body: {
json: () => graphqlResponse,
},
}));

// If the update fails, we get an error which we'll need to catch.
// If it succeeds, we get a result back and no need to look for `null | undefined`
const thread: GraphQLReturnType<Thread> = (
await client.graphql({
query: typedMutations.createThread,
authMode: 'apiKey',
variables: {
input: threadToCreate,
},
})
).data.createThread;
});

test('update', async () => {
const threadToUpdate = {
id: 'abc',
topic: 'a new (but still very stimulating) topic',
};

const graphqlResponse = {
data: {
updateThread: {
__typename: 'Thread',
...serverManagedFields,
...threadToUpdate,
},
},
};

const spy = jest
.spyOn((raw.GraphQLAPI as any)._api, 'post')
.mockImplementation(() => ({
body: {
json: () => graphqlResponse,
},
}));

// Not sure yet what happens if an update failes to find a matching record ... pretty sure
// it's an error though! This would indicate update queries can omit
const thread: GraphQLReturnType<Thread> = (
await client.graphql({
query: typedMutations.updateThread,
variables: {
input: threadToUpdate,
},
authMode: 'apiKey',
})
).data.updateThread;
});

test('delete', async () => {
const threadToDelete = { id: 'abc' };

const graphqlResponse = {
data: {
deleteThread: {
__typename: 'Thread',
...serverManagedFields,
...threadToDelete,
topic: 'not a very interesting topic (hence the deletion)',
},
},
};

const spy = jest
.spyOn((raw.GraphQLAPI as any)._api, 'post')
.mockImplementation(() => ({
body: {
json: () => graphqlResponse,
},
}));

// If a delete fails, an error is raised. So, we don't need to handle null or
// undefined return values in the happy path.
const thread: GraphQLReturnType<Thread> = (
await client.graphql({
query: typedMutations.deleteThread,
variables: {
input: threadToDelete,
},
authMode: 'apiKey',
})
).data.deleteThread;
});

test('get', async () => {
const threadToGet = {
id: 'some-thread-id',
topic: 'something reasonably interesting',
};

const graphqlVariables = { id: 'some-thread-id' };

const graphqlResponse = {
data: {
getThread: {
__typename: 'Thread',
...serverManagedFields,
...threadToGet,
},
},
};

const spy = jest
.spyOn((raw.GraphQLAPI as any)._api, 'post')
.mockImplementation(() => ({
body: {
json: () => graphqlResponse,
},
}));

// a get query might not actually find anything.
const thread: GraphQLReturnType<Thread> | null | undefined = (
await client.graphql({
query: typedQueries.getThread,
variables: graphqlVariables,
authMode: 'apiKey',
})
).data.getThread;

// we SHOULD get a type error if we blindly try to assign a get result
// to a type that doesn't account for `null | undefined` returns.
// TODO: change to ts-expect-error
// @ts-ignore
const badthread: GraphQLReturnType<Thread> = (
await client.graphql({
query: typedQueries.getThread,
variables: graphqlVariables,
authMode: 'apiKey',
})
).data.getThread;
});

test('list', async () => {
const threadsToList = [
{
__typename: 'Thread',
...serverManagedFields,
topic: 'really cool stuff',
},
];

const graphqlVariables = {
filter: {
topic: { contains: 'really cool stuff' },
},
nextToken: null,
};

const graphqlResponse = {
data: {
listThreads: {
items: threadsToList,
nextToken: null,
},
},
};

const spy = jest
.spyOn((raw.GraphQLAPI as any)._api, 'post')
.mockImplementation(() => ({
body: {
json: () => graphqlResponse,
},
}));

// If a list query succeeds, we always get a list back, even if it's empty.
// and there are no empty values.
const threads: GraphQLReturnType<Thread>[] = (
await client.graphql({
query: typedQueries.listThreads,
variables: graphqlVariables,
authMode: 'apiKey',
})
).data.listThreads.items;
});

test('subscribe', done => {
const threadToSend = {
__typename: 'Thread',
...serverManagedFields,
topic: 'really cool stuff',
};

const graphqlMessage = {
data: {
onCreateThread: threadToSend,
},
};

const spy = jest.fn(() => from([graphqlMessage]));
(raw.GraphQLAPI as any).appSyncRealTime = { subscribe: spy };

const graphqlVariables = {
filter: {
topic: { contains: 'really cool stuff' },
},
};

const result = client.graphql({
query: typedSubscriptions.onCreateThread,
variables: graphqlVariables,
authMode: 'apiKey',
});

const threads: GraphQLReturnType<Thread>[] = [];

result.subscribe({
next(message) {
threads.push(message.data.onCreateThread);
done();
},
error(error) {
expect(error).toBeUndefined();
done('bad news!');
},
});
});
});

describe('un-tagged graphql, with as any casts', () => {
test('create', async () => {
const threadToCreate = { topic: 'a very engaging discussion topic' };
Expand Down Expand Up @@ -611,7 +857,7 @@ describe('client', () => {
const result = rawResult as any;

result.subscribe?.({
next(message) {
next(message: any) {
expectSub(spy, 'onCreateThread', graphqlVariables);
expect(message.data.onCreateThread).toEqual(
graphqlMessage.data.onCreateThread
Expand Down
1 change: 1 addition & 0 deletions packages/api-graphql/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
],
"allowJs": true,
"noEmitOnError": false,
"strictNullChecks": true,
"types": ["@types/jest"]
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -972,8 +972,9 @@ export class AWSAppSyncRealTimeProvider {
body: request.data,
},
{
credentials: creds,
signingRegion: endpointInfo.region,
// TODO: What do we need to do to remove these !'s?
credentials: creds!,
signingRegion: endpointInfo.region!,
signingService: endpointInfo.service,
}
);
Expand Down
16 changes: 9 additions & 7 deletions packages/api-graphql/src/internals/InternalGraphQLAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export class InternalGraphQLAPIClass {
endpoint: appSyncGraphqlEndpoint,
apiKey,
defaultAuthMode,
} = config.API.GraphQL;
} = config.API?.GraphQL || {};

const authenticationType = authMode || defaultAuthMode || 'iam';
let headers = {};
Expand Down Expand Up @@ -215,18 +215,20 @@ export class InternalGraphQLAPIClass {
const config = Amplify.getConfig();

const { region: region, endpoint: appSyncGraphqlEndpoint } =
config.API.GraphQL;
config.API?.GraphQL || {};

const customGraphqlEndpoint = null;
const customEndpointRegion = null;

// TODO: Figure what we need to do to remove `!`'s.
const headers = {
...(!customGraphqlEndpoint &&
(await this._headerBasedAuth(authMode, additionalHeaders))),
...(customGraphqlEndpoint &&
(await this._headerBasedAuth(authMode!, additionalHeaders))),
...((customGraphqlEndpoint &&
(customEndpointRegion
? await this._headerBasedAuth(authMode, additionalHeaders)
: { Authorization: null })),
? await this._headerBasedAuth(authMode!, additionalHeaders)
: { Authorization: null })) ||
{}),
...additionalHeaders,
...(!customGraphqlEndpoint && {
[USER_AGENT_HEADER]: getAmplifyUserAgent(customUserAgentDetails),
Expand All @@ -235,7 +237,7 @@ export class InternalGraphQLAPIClass {

const body = {
query: print(query as DocumentNode),
variables,
variables: variables || null,
};

const endpoint = customGraphqlEndpoint || appSyncGraphqlEndpoint;
Expand Down
2 changes: 1 addition & 1 deletion packages/api-graphql/src/types/PubSub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ export enum ConnectionState {
ConnectedPendingKeepAlive = 'ConnectedPendingKeepAlive',
}

export type PubSubContent = Record<string, unknown> | string;
export type PubSubContent = Record<string, unknown>;
export type PubSubContentObserver = Observer<PubSubContent>;
Loading

0 comments on commit 9607e4a

Please sign in to comment.