Skip to content

Commit 4f643b0

Browse files
authored
chore(ui): fix defaultAuthHubListener unit tests, remove asynchronous declaration (#4777)
* chore(ui): fix defaultAuthHubListener unit tests, remove asynchronous declaration * Create light-zoos-raise.md
1 parent 8a564b8 commit 4f643b0

File tree

8 files changed

+90
-154
lines changed

8 files changed

+90
-154
lines changed

Diff for: .changeset/light-zoos-raise.md

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"@aws-amplify/ui-react-core": patch
3+
"@aws-amplify/ui": patch
4+
"@aws-amplify/ui-vue": patch
5+
"@aws-amplify/ui-angular": patch
6+
---
7+
8+
chore(ui): fix defaultAuthHubListener unit tests, remove asynchronous declaration

Diff for: packages/angular/projects/ui-angular/src/lib/services/authenticator.service.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,8 @@ export class AuthenticatorService implements OnDestroy {
220220

221221
this._unsubscribeHub = listenToAuthHub(
222222
this._authService,
223-
async (data, service) => {
224-
await defaultAuthHubHandler(data, service, { onSignIn, onSignOut });
223+
(data, service) => {
224+
defaultAuthHubHandler(data, service, { onSignIn, onSignOut });
225225
this._hubSubject.next();
226226
}
227227
);

Diff for: packages/react-core/src/Authenticator/context/AuthenticatorProvider.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ type Options = Parameters<AuthMachineHubHandler>[2];
1616

1717
const createHubHandler =
1818
(options: Options): AuthMachineHubHandler =>
19-
async (data, service) => {
20-
await defaultAuthHubHandler(data, service, options);
19+
(data, service) => {
20+
defaultAuthHubHandler(data, service, options);
2121
};
2222

2323
export default function AuthenticatorProvider({

Diff for: packages/ui/jest.config.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ const config: Config = {
1111
],
1212
coverageThreshold: {
1313
global: {
14-
branches: 50,
15-
functions: 50,
16-
lines: 50,
17-
statements: 50,
14+
branches: 77,
15+
functions: 70,
16+
lines: 87,
17+
statements: 88,
1818
// @todo-migration: put back after fixing tests
1919
// branches: 80,
2020
// functions: 85,
Original file line numberDiff line numberDiff line change
@@ -1,155 +1,93 @@
1-
import { defaultAuthHubHandler } from '../defaultAuthHubHandler';
1+
import { Hub } from 'aws-amplify/utils';
2+
import {
3+
defaultAuthHubHandler,
4+
listenToAuthHub,
5+
} from '../defaultAuthHubHandler';
26
import { AuthInterpreter } from '../types';
37

4-
jest.mock('xstate/lib/waitFor', () => ({
5-
waitFor: jest.fn(),
6-
}));
7-
8-
jest.mock('../actor', () => ({
9-
getActorState: () => ({ matches: () => true }),
10-
}));
11-
12-
const authenticatedStateMachine = {
13-
getSnapshot: () => ({
14-
// this is the state.matches function
15-
matches: (state: string) => state === 'authenticated.idle',
16-
}),
17-
send: jest.fn(),
18-
} as unknown as AuthInterpreter;
19-
20-
const unauthenticatedStateMachine = {
21-
getSnapshot: () => ({
22-
// this is the state.matches function
23-
matches: (state: string) => state === 'signIn',
24-
}),
25-
send: jest.fn(),
26-
} as unknown as AuthInterpreter;
27-
28-
const authSendSpy = jest.spyOn(authenticatedStateMachine, 'send');
29-
const unauthSendSpy = jest.spyOn(unauthenticatedStateMachine, 'send');
30-
318
const onSignIn = jest.fn();
329
const onSignOut = jest.fn();
10+
const service = { send: jest.fn() } as unknown as AuthInterpreter;
3311

3412
describe('defaultAuthHubHandler', () => {
3513
beforeEach(() => {
36-
authSendSpy.mockClear();
37-
unauthSendSpy.mockClear();
38-
onSignIn.mockClear();
39-
onSignOut.mockClear();
14+
jest.clearAllMocks();
4015
});
4116

42-
// @todo-migration probably remove token refresh event handling
43-
it.skip('responds to token refresh event when state is authenticated', async () => {
44-
await defaultAuthHubHandler(
45-
{ channel: 'auth', payload: { event: 'tokenRefresh' } },
46-
authenticatedStateMachine
47-
);
48-
expect(authSendSpy).toHaveBeenCalledWith('TOKEN_REFRESH');
49-
});
17+
it.each(['tokenRefresh_failure', 'signedOut'])(
18+
'handles a %s event as expected',
19+
(event) => {
20+
defaultAuthHubHandler({ channel: 'auth', payload: { event } }, service);
21+
expect(service.send).toHaveBeenCalledTimes(1);
22+
expect(service.send).toHaveBeenCalledWith('SIGN_OUT');
23+
}
24+
);
5025

51-
it('ignores token refresh event when state is unauthenticated', async () => {
52-
await defaultAuthHubHandler(
53-
{ channel: 'auth', payload: { event: 'tokenRefresh' } },
54-
unauthenticatedStateMachine
26+
it('handles a signInWithRedirect event as expected', () => {
27+
defaultAuthHubHandler(
28+
{ channel: 'auth', payload: { event: 'signInWithRedirect' } },
29+
service
5530
);
56-
expect(unauthSendSpy).not.toHaveBeenCalled();
31+
expect(service.send).toHaveBeenCalledTimes(1);
32+
expect(service.send).toHaveBeenCalledWith('SIGN_IN_WITH_REDIRECT');
5733
});
5834

59-
// @todo-migration
60-
// expect(jest.fn()).toHaveBeenCalledWith(...expected)
61-
// Expected: "SIGN_OUT"
62-
// Number of calls: 0
63-
it.skip('responds to signOut event when state is authenticated', async () => {
64-
await defaultAuthHubHandler(
65-
{ channel: 'auth', payload: { event: 'signOut' } },
66-
authenticatedStateMachine
35+
it('calls onSignOut callabck on signedOut event if provided', () => {
36+
defaultAuthHubHandler(
37+
{ channel: 'auth', payload: { event: 'signedOut' } },
38+
service,
39+
{ onSignOut }
6740
);
68-
expect(authSendSpy).toHaveBeenCalledWith('SIGN_OUT');
41+
expect(onSignOut).toHaveBeenCalledTimes(1);
6942
});
7043

71-
it('ignores signOut event when state is unauthenticated', async () => {
72-
await defaultAuthHubHandler(
73-
{ channel: 'auth', payload: { event: 'signOut' } },
74-
unauthenticatedStateMachine
44+
it('does not call onSignOut callback on tokenRefreh_failure event if provided', () => {
45+
defaultAuthHubHandler(
46+
{ channel: 'auth', payload: { event: 'tokenRefreh_failure' } },
47+
service,
48+
{ onSignOut }
7549
);
76-
expect(unauthSendSpy).not.toHaveBeenCalled();
50+
expect(onSignOut).not.toHaveBeenCalled();
7751
});
7852

79-
it('signs user out when token refresh failed in authenticated state', async () => {
80-
await defaultAuthHubHandler(
81-
{ channel: 'auth', payload: { event: 'tokenRefresh_failure' } },
82-
authenticatedStateMachine
53+
it('calls onSignIn callabck on signedIn event if provided', () => {
54+
defaultAuthHubHandler(
55+
{ channel: 'auth', payload: { event: 'signedIn' } },
56+
service,
57+
{ onSignIn }
8358
);
84-
expect(authSendSpy).toHaveBeenCalledWith('SIGN_OUT');
59+
expect(onSignIn).toHaveBeenCalledTimes(1);
8560
});
61+
});
8662

87-
// @todo-migration potentially remove
88-
it.skip('ignores token refresh failure event when state is unauthenticated', async () => {
89-
await defaultAuthHubHandler(
90-
{ channel: 'auth', payload: { event: 'tokenRefresh_failure' } },
91-
unauthenticatedStateMachine
92-
);
93-
expect(unauthSendSpy).not.toHaveBeenCalled();
94-
});
63+
describe('listenToAuthHub', () => {
64+
it('creates a Hub listener', () => {
65+
// add empty mockImplementation to prevent logging "auth channel" warning output to the console
66+
jest.spyOn(console, 'warn').mockImplementation();
9567

96-
// @todo-migration
97-
// expect(jest.fn()).toHaveBeenCalledWith(...expected)
98-
// Expected: {"type": "AUTO_SIGN_IN"}
99-
// Number of calls: 0
100-
it.skip('responds to autoSignIn event when state is unauthenticated', async () => {
101-
await defaultAuthHubHandler(
102-
{ channel: 'auth', payload: { event: 'autoSignIn' } },
103-
unauthenticatedStateMachine
104-
);
105-
expect(unauthSendSpy).toHaveBeenCalledWith({ type: 'AUTO_SIGN_IN' });
106-
});
68+
const hubListenSpy = jest.spyOn(Hub, 'listen');
69+
const handler = jest.fn();
10770

108-
it('ignores autoSignIn event when state is authenticated', async () => {
109-
await defaultAuthHubHandler(
110-
{ channel: 'auth', payload: { event: 'autoSignIn' } },
111-
authenticatedStateMachine
112-
);
113-
expect(unauthSendSpy).not.toHaveBeenCalled();
114-
});
71+
listenToAuthHub(service, handler);
11572

116-
// @todo-migration
117-
// expect(jest.fn()).toHaveBeenCalledWith(...expected)
118-
// Expected: {"type": "AUTO_SIGN_IN_FAILURE"}
119-
// Number of calls: 0
120-
it.skip('responds to autoSignIn_failure event', async () => {
121-
await defaultAuthHubHandler(
122-
{ channel: 'auth', payload: { event: 'autoSignIn_failure' } },
123-
unauthenticatedStateMachine
73+
expect(hubListenSpy).toHaveBeenCalledTimes(1);
74+
expect(hubListenSpy).toHaveBeenCalledWith(
75+
'auth',
76+
expect.any(Function),
77+
'authenticator-hub-handler'
12478
);
125-
expect(unauthSendSpy).toHaveBeenCalledWith({
126-
type: 'AUTO_SIGN_IN_FAILURE',
127-
});
128-
});
129-
130-
// @todo-migration
131-
// Expected number of calls: 1
132-
// Received number of calls: 0
133-
it.skip.each(['signIn', 'signOut'])(
134-
'calls the %s event handler as expected',
135-
async (event) => {
136-
const handler = event === 'signIn' ? onSignIn : onSignOut;
137-
const handlerKey = event === 'signIn' ? 'onSignIn' : 'onSignOut';
138-
await defaultAuthHubHandler(
139-
{ channel: 'auth', payload: { event } },
140-
authenticatedStateMachine,
141-
{ [handlerKey]: handler }
142-
);
143-
expect(handler).toHaveBeenCalledTimes(1);
144-
}
145-
);
14679

147-
it("doesn't break when unsupported event is passed", async () => {
148-
const spyError = jest.spyOn(console, 'error');
149-
await defaultAuthHubHandler(
150-
{ channel: 'auth', payload: { event: 'unsupported' } },
151-
unauthenticatedStateMachine
80+
Hub.dispatch('auth', { event: 'signedIn' }, 'authenticator-hub-handler');
81+
82+
expect(handler).toHaveBeenCalledTimes(1);
83+
expect(handler).toHaveBeenCalledWith(
84+
{
85+
channel: 'auth',
86+
patternInfo: [],
87+
payload: { event: 'signedIn' },
88+
source: 'authenticator-hub-handler',
89+
},
90+
{ send: expect.any(Function) }
15291
);
153-
expect(spyError).not.toHaveBeenCalled();
15492
});
15593
});

Diff for: packages/ui/src/helpers/authenticator/defaultAuthHubHandler.ts

+7-17
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { AuthInterpreter, AuthMachineHubHandler } from './types';
88
* Handles Amplify JS Auth hub events, by forwarding hub events as appropriate
99
* xstate events.
1010
*/
11-
export const defaultAuthHubHandler: AuthMachineHubHandler = async (
11+
export const defaultAuthHubHandler: AuthMachineHubHandler = (
1212
{ payload },
1313
service,
1414
options
@@ -42,29 +42,19 @@ export const defaultAuthHubHandler: AuthMachineHubHandler = async (
4242
}
4343
};
4444

45-
type HubHandler = Parameters<typeof Hub.listen>[1];
46-
const getHubEventHandler =
47-
(service: AuthInterpreter, handler: AuthMachineHubHandler): HubHandler =>
48-
(data) => {
49-
handler(data, service);
50-
};
51-
5245
/**
5346
* Listens to external auth Hub events and sends corresponding event to
54-
* the `authService` of interest
55-
*
56-
* @param send - `send` function associated with the `authService` of interest
47+
* the `service.send` of interest
5748
*
49+
* @param service - contains state machine `send` function
50+
* @param handler - auth event handler
5851
* @returns function that unsubscribes to the hub evenmt
5952
*/
6053
export const listenToAuthHub = (
6154
service: AuthInterpreter,
62-
// angular passes its own `handler` param
6355
handler: AuthMachineHubHandler = defaultAuthHubHandler
6456
) => {
65-
return Hub.listen(
66-
'auth',
67-
getHubEventHandler(service, handler),
68-
'authenticator-hub-handler'
69-
);
57+
const eventHandler: Parameters<typeof Hub.listen>[1] = (data) =>
58+
handler(data, service);
59+
return Hub.listen('auth', eventHandler, 'authenticator-hub-handler');
7060
};

Diff for: packages/ui/src/helpers/authenticator/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,4 @@ export type AuthMachineHubHandler = (
3737
onSignIn?: (user: AuthUser) => void;
3838
onSignOut?: () => void;
3939
}
40-
) => Promise<void>;
40+
) => void;

Diff for: packages/vue/src/composables/useAuth.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ export const useAuth = createSharedComposable((): UseAuth => {
3838
authStatus.value = 'unauthenticated';
3939
};
4040

41-
const unsubscribeHub = listenToAuthHub(service, async (data, service) => {
42-
await defaultAuthHubHandler(data, service, { onSignIn, onSignOut });
43-
});
41+
const unsubscribeHub = listenToAuthHub(service, (data, service) =>
42+
defaultAuthHubHandler(data, service, { onSignIn, onSignOut })
43+
);
4444

4545
getCurrentUser()
4646
.then(() => {

0 commit comments

Comments
 (0)