@strivacity/sdk-angular 4.0.0-beta.0 → 4.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -62
- package/dist/fesm2022/strivacity-sdk-angular.mjs +36 -131
- package/package.json +2 -2
- package/src/lib/services/auth.service.ts +2 -2
- package/src/lib/services/native-login.service.ts +20 -140
- package/src/server/sdk.ts +1 -1
- package/src/server/session.ts +17 -3
- package/src/server/types.ts +3 -3
- package/src/types/index.ts +5 -33
- package/testing/tests/auth.service.spec.ts +1 -1
- package/testing/tests/index.spec.ts +7 -0
- package/testing/tests/native-login.service.spec.ts +11 -15
- package/testing/tests/server/sdk.spec.ts +1 -1
- package/testing/tests/server/session.spec.ts +51 -6
- package/dist/README.md +0 -2217
- package/dist/fesm2022/strivacity-sdk-angular-src-server.mjs +0 -221
- package/dist/fesm2022/strivacity-sdk-angular-src-server.mjs.map +0 -1
- package/dist/fesm2022/strivacity-sdk-angular-src-types.mjs +0 -6
- package/dist/fesm2022/strivacity-sdk-angular-src-types.mjs.map +0 -1
- package/dist/fesm2022/strivacity-sdk-angular.mjs.map +0 -1
- package/dist/types/strivacity-sdk-angular-src-server.d.ts +0 -82
- package/dist/types/strivacity-sdk-angular-src-types.d.ts +0 -41
- package/dist/types/strivacity-sdk-angular.d.ts +0 -147
|
@@ -108,7 +108,7 @@ describe('StrivacityNativeLoginService', () => {
|
|
|
108
108
|
});
|
|
109
109
|
|
|
110
110
|
test('calls onLogin and leaves the tracked state untouched when the sdk already has a session', async () => {
|
|
111
|
-
const session = { access_token: 'access-token' } as unknown as SessionData;
|
|
111
|
+
const session = { access_token: 'access-token', expires_at: Math.floor(Date.now() / 1000) + 3600 } as unknown as SessionData;
|
|
112
112
|
const flow = createMockFlow<NativeFlow>({ session });
|
|
113
113
|
vi.mocked(flow.startSession).mockResolvedValue({ screen: 'identifier' });
|
|
114
114
|
const onLogin = vi.fn();
|
|
@@ -149,19 +149,17 @@ describe('StrivacityNativeLoginService', () => {
|
|
|
149
149
|
expect(login.loading()).toBe(true);
|
|
150
150
|
});
|
|
151
151
|
|
|
152
|
-
test('
|
|
153
|
-
// the AbortError short-circuit in start()'s own catch guards `this.startSession(...)`, not `await this.sdk.init()`
|
|
154
|
-
// above it - startSession() also swallows every error itself (including AbortError) and reports it through onError,
|
|
155
|
-
// so that branch is unreachable via a mocked flow; a rejecting init() is the one thing genuinely uncaught here.
|
|
152
|
+
test('reports a rejection from sdk.init() to onError and stops loading, without starting a session', async () => {
|
|
156
153
|
const flow = createMockFlow<NativeFlow>();
|
|
157
|
-
const
|
|
158
|
-
vi.mocked(flow.init).mockRejectedValue(
|
|
154
|
+
const error = new Error('init failed');
|
|
155
|
+
vi.mocked(flow.init).mockRejectedValue(error);
|
|
159
156
|
const onError = vi.fn();
|
|
160
157
|
const login = configure(flow);
|
|
161
158
|
|
|
162
|
-
await
|
|
159
|
+
await login.start({ onError });
|
|
163
160
|
|
|
164
|
-
expect(onError).
|
|
161
|
+
expect(onError).toHaveBeenCalledWith(error);
|
|
162
|
+
expect(login.loading()).toBe(false);
|
|
165
163
|
expect(flow.startSession).not.toHaveBeenCalled();
|
|
166
164
|
});
|
|
167
165
|
});
|
|
@@ -293,19 +291,17 @@ describe('StrivacityNativeLoginService', () => {
|
|
|
293
291
|
expect(flow.logging!.debug).toHaveBeenCalledWith('Triggering close');
|
|
294
292
|
});
|
|
295
293
|
|
|
296
|
-
test('
|
|
294
|
+
test('stops tracking the flow state when the owning injector is destroyed', () => {
|
|
297
295
|
const flow = createMockFlow<NativeFlow>();
|
|
298
296
|
vi.mocked(initFlow).mockReturnValue(flow);
|
|
299
297
|
TestBed.configureTestingModule({ providers: [{ provide: STRIVACITY_SDK, useValue: createOptions({ mode: 'native' }) }, StrivacityAuthService] });
|
|
300
298
|
|
|
301
|
-
const abortSpy = vi.spyOn(AbortController.prototype, 'abort');
|
|
302
|
-
|
|
303
299
|
// both services must live on the component's own injector for fixture.destroy() to fire their DestroyRef callbacks
|
|
304
|
-
const { destroy } = mountWithProviders([StrivacityAuthService, StrivacityNativeLoginService], () => inject(StrivacityNativeLoginService));
|
|
300
|
+
const { value: login, destroy } = mountWithProviders([StrivacityAuthService, StrivacityNativeLoginService], () => inject(StrivacityNativeLoginService));
|
|
305
301
|
|
|
306
302
|
destroy();
|
|
303
|
+
login.setFormValue('form1', 'email', 'a@b.c');
|
|
307
304
|
|
|
308
|
-
expect(
|
|
309
|
-
abortSpy.mockRestore();
|
|
305
|
+
expect(login.forms()).toEqual({});
|
|
310
306
|
});
|
|
311
307
|
});
|
|
@@ -101,7 +101,7 @@ describe('createServerSDK', () => {
|
|
|
101
101
|
});
|
|
102
102
|
|
|
103
103
|
test.each([
|
|
104
|
-
['getSession', [{} as never], null],
|
|
104
|
+
['getSession', [{} as never, { autoRefresh: false }], null],
|
|
105
105
|
['updateSession', [{ access_token: 'a' } as never, {} as never], undefined],
|
|
106
106
|
['refreshSession', [{} as never], { access_token: 'refreshed' }],
|
|
107
107
|
['revokeSession', [{} as never], undefined],
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { AngularServerSDK } from '../../../src/server/types';
|
|
2
|
-
import { ApplicationInitStatus, REQUEST, TransferState } from '@angular/core';
|
|
2
|
+
import { ApplicationInitStatus, REQUEST, RESPONSE_INIT, TransferState } from '@angular/core';
|
|
3
3
|
import { TestBed } from '@angular/core/testing';
|
|
4
4
|
import { describe, test, expect, vi } from 'vitest';
|
|
5
|
+
import { pushSetCookie } from '@strivacity/sdk-core/utils';
|
|
5
6
|
import { SESSION_TRANSFER_KEY, provideStrivacityServerSession } from '../../../src/server/session';
|
|
6
7
|
|
|
7
|
-
function configure(request: Request | undefined, serverSdk: AngularServerSDK | undefined) {
|
|
8
|
+
function configure(request: Request | undefined, serverSdk: AngularServerSDK | undefined, responseInit?: ResponseInit) {
|
|
8
9
|
TestBed.configureTestingModule({
|
|
9
|
-
providers: [{ provide: REQUEST, useValue: request }, provideStrivacityServerSession(serverSdk)],
|
|
10
|
+
providers: [{ provide: REQUEST, useValue: request }, { provide: RESPONSE_INIT, useValue: responseInit ?? null }, provideStrivacityServerSession(serverSdk)],
|
|
10
11
|
});
|
|
11
12
|
|
|
12
13
|
return TestBed.inject(ApplicationInitStatus).donePromise;
|
|
@@ -18,17 +19,61 @@ describe('provideStrivacityServerSession', () => {
|
|
|
18
19
|
const session = { access_token: 'access-token' };
|
|
19
20
|
const getSession = vi.fn().mockResolvedValue(session);
|
|
20
21
|
|
|
21
|
-
await configure(request, { getSession } as unknown as AngularServerSDK);
|
|
22
|
+
await configure(request, { getSession: getSession } as unknown as AngularServerSDK);
|
|
22
23
|
|
|
23
24
|
expect(getSession).toHaveBeenCalledWith(request);
|
|
24
25
|
expect(TestBed.inject(TransferState).get(SESSION_TRANSFER_KEY, undefined)).toEqual(session);
|
|
25
26
|
});
|
|
26
27
|
|
|
28
|
+
test('never transfers the refresh token or the ID token to the client', async () => {
|
|
29
|
+
const request = new Request('https://brandtegrity.io');
|
|
30
|
+
const session = { access_token: 'access-token', refresh_token: 'refresh-token', id_token: 'id-token', expires_at: 9999999999, claims: { sub: 'user' } };
|
|
31
|
+
const getSession = vi.fn().mockResolvedValue(session);
|
|
32
|
+
|
|
33
|
+
await configure(request, { getSession: getSession } as unknown as AngularServerSDK);
|
|
34
|
+
|
|
35
|
+
expect(TestBed.inject(TransferState).get(SESSION_TRANSFER_KEY, undefined)).toEqual({
|
|
36
|
+
access_token: 'access-token',
|
|
37
|
+
expires_at: 9999999999,
|
|
38
|
+
claims: { sub: 'user' },
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('refreshes a near-expiry session on the server and writes the rotated cookie to the rendered response', async () => {
|
|
43
|
+
const request = new Request('https://brandtegrity.io/profile');
|
|
44
|
+
const rotated = { access_token: 'new', refresh_token: 'refresh-2', id_token: 'id-2', expires_at: 9999999999, claims: { sub: 'user' } };
|
|
45
|
+
const getSession = vi.fn().mockImplementation((req: Request) => {
|
|
46
|
+
pushSetCookie(req, 'sty.session=rotated; Path=/');
|
|
47
|
+
return Promise.resolve(rotated);
|
|
48
|
+
});
|
|
49
|
+
const responseInit: ResponseInit = { headers: { 'x-existing': '1' } };
|
|
50
|
+
|
|
51
|
+
await configure(request, { getSession } as unknown as AngularServerSDK, responseInit);
|
|
52
|
+
|
|
53
|
+
expect(getSession).toHaveBeenCalledWith(request);
|
|
54
|
+
expect(TestBed.inject(TransferState).get(SESSION_TRANSFER_KEY, undefined)).toEqual({
|
|
55
|
+
access_token: 'new',
|
|
56
|
+
expires_at: 9999999999,
|
|
57
|
+
claims: { sub: 'user' },
|
|
58
|
+
});
|
|
59
|
+
const headers = responseInit.headers as Headers;
|
|
60
|
+
expect(headers.getSetCookie()).toEqual(['sty.session=rotated; Path=/']);
|
|
61
|
+
expect(headers.get('x-existing')).toBe('1');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('transfers null when the server-side refresh fails', async () => {
|
|
65
|
+
const request = new Request('https://brandtegrity.io/profile');
|
|
66
|
+
|
|
67
|
+
await configure(request, { getSession: vi.fn().mockResolvedValue(null) } as unknown as AngularServerSDK, {});
|
|
68
|
+
|
|
69
|
+
expect(TestBed.inject(TransferState).get(SESSION_TRANSFER_KEY, undefined)).toBeNull();
|
|
70
|
+
});
|
|
71
|
+
|
|
27
72
|
test('transfers null when the server sdk finds no session for the request', async () => {
|
|
28
73
|
const request = new Request('https://brandtegrity.io');
|
|
29
74
|
const getSession = vi.fn().mockResolvedValue(null);
|
|
30
75
|
|
|
31
|
-
await configure(request, { getSession } as unknown as AngularServerSDK);
|
|
76
|
+
await configure(request, { getSession: getSession } as unknown as AngularServerSDK);
|
|
32
77
|
|
|
33
78
|
expect(TestBed.inject(TransferState).get(SESSION_TRANSFER_KEY, undefined)).toBeNull();
|
|
34
79
|
});
|
|
@@ -36,7 +81,7 @@ describe('provideStrivacityServerSession', () => {
|
|
|
36
81
|
test('is a no-op when there is no incoming request (e.g. not running under SSR)', async () => {
|
|
37
82
|
const getSession = vi.fn().mockResolvedValue({ access_token: 'access-token' });
|
|
38
83
|
|
|
39
|
-
await configure(undefined, { getSession } as unknown as AngularServerSDK);
|
|
84
|
+
await configure(undefined, { getSession: getSession } as unknown as AngularServerSDK);
|
|
40
85
|
|
|
41
86
|
expect(getSession).not.toHaveBeenCalled();
|
|
42
87
|
expect(TestBed.inject(TransferState).hasKey(SESSION_TRANSFER_KEY)).toBe(false);
|