@strivacity/sdk-core 4.0.0-beta.1 → 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.
Files changed (98) hide show
  1. package/README.md +228 -87
  2. package/dist/assets/oidc.cjs +1 -1
  3. package/dist/assets/oidc.cjs.map +1 -1
  4. package/dist/assets/oidc.mjs +1 -1
  5. package/dist/assets/oidc.mjs.map +1 -1
  6. package/dist/assets/server.cjs +1 -1
  7. package/dist/assets/server.cjs.map +1 -1
  8. package/dist/assets/server.mjs +1 -1
  9. package/dist/assets/server.mjs.map +1 -1
  10. package/dist/flows/base.cjs +1 -1
  11. package/dist/flows/base.cjs.map +1 -1
  12. package/dist/flows/base.d.ts +4 -2
  13. package/dist/flows/base.mjs +1 -1
  14. package/dist/flows/base.mjs.map +1 -1
  15. package/dist/flows/popup.cjs +1 -1
  16. package/dist/flows/popup.cjs.map +1 -1
  17. package/dist/flows/popup.mjs +1 -1
  18. package/dist/flows/popup.mjs.map +1 -1
  19. package/dist/index.cjs +1 -1
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.ts +6 -2
  22. package/dist/index.mjs +1 -1
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/server/base.cjs +1 -1
  25. package/dist/server/base.cjs.map +1 -1
  26. package/dist/server/base.d.ts +2 -4
  27. package/dist/server/base.mjs +1 -1
  28. package/dist/server/base.mjs.map +1 -1
  29. package/dist/server/index.cjs +1 -1
  30. package/dist/server/index.mjs +1 -1
  31. package/dist/storages/cache.cjs.map +1 -1
  32. package/dist/storages/cache.d.ts +1 -1
  33. package/dist/storages/cache.mjs.map +1 -1
  34. package/dist/storages/index.cjs +1 -1
  35. package/dist/storages/index.mjs +1 -1
  36. package/dist/storages/server.cjs +1 -1
  37. package/dist/storages/server.d.ts +29 -1
  38. package/dist/storages/server.mjs +1 -1
  39. package/dist/storages/worker.cjs.map +1 -1
  40. package/dist/storages/worker.d.ts +1 -1
  41. package/dist/storages/worker.mjs.map +1 -1
  42. package/dist/types/native.d.ts +67 -2
  43. package/dist/types/oidc.cjs.map +1 -1
  44. package/dist/types/oidc.d.ts +41 -6
  45. package/dist/types/oidc.mjs.map +1 -1
  46. package/dist/types/popup.d.ts +1 -1
  47. package/dist/types/server.d.ts +21 -9
  48. package/dist/utils/index.cjs +1 -1
  49. package/dist/utils/index.d.ts +1 -0
  50. package/dist/utils/index.mjs +1 -1
  51. package/dist/utils/native-login.cjs +2 -0
  52. package/dist/utils/native-login.cjs.map +1 -0
  53. package/dist/utils/native-login.d.ts +13 -0
  54. package/dist/utils/native-login.mjs +2 -0
  55. package/dist/utils/native-login.mjs.map +1 -0
  56. package/dist/utils/oidc.d.ts +3 -4
  57. package/dist/utils/path.cjs +2 -0
  58. package/dist/utils/path.cjs.map +1 -0
  59. package/dist/utils/path.d.ts +16 -0
  60. package/dist/utils/path.mjs +2 -0
  61. package/dist/utils/path.mjs.map +1 -0
  62. package/dist/utils/server.d.ts +5 -4
  63. package/dist/utils/session.cjs +1 -1
  64. package/dist/utils/session.cjs.map +1 -1
  65. package/dist/utils/session.d.ts +9 -1
  66. package/dist/utils/session.mjs +1 -1
  67. package/dist/utils/session.mjs.map +1 -1
  68. package/package.json +1 -1
  69. package/testing/tests/flows/base.spec.ts +0 -1030
  70. package/testing/tests/flows/embedded.spec.ts +0 -443
  71. package/testing/tests/flows/index.spec.ts +0 -8
  72. package/testing/tests/flows/native.spec.ts +0 -487
  73. package/testing/tests/flows/popup.spec.ts +0 -400
  74. package/testing/tests/flows/redirect.spec.ts +0 -369
  75. package/testing/tests/handlers/embedded.spec.ts +0 -199
  76. package/testing/tests/handlers/index.spec.ts +0 -8
  77. package/testing/tests/handlers/native.spec.ts +0 -283
  78. package/testing/tests/handlers/popup.spec.ts +0 -206
  79. package/testing/tests/handlers/redirect.spec.ts +0 -70
  80. package/testing/tests/index.spec.ts +0 -78
  81. package/testing/tests/server/base.spec.ts +0 -846
  82. package/testing/tests/server/index.spec.ts +0 -15
  83. package/testing/tests/storages/cache.spec.ts +0 -107
  84. package/testing/tests/storages/index.spec.ts +0 -22
  85. package/testing/tests/storages/indexeddb.spec.ts +0 -113
  86. package/testing/tests/storages/local.spec.ts +0 -46
  87. package/testing/tests/storages/memory.spec.ts +0 -51
  88. package/testing/tests/storages/server.spec.ts +0 -435
  89. package/testing/tests/storages/session.spec.ts +0 -46
  90. package/testing/tests/storages/worker.spec.ts +0 -106
  91. package/testing/tests/utils/common.spec.ts +0 -77
  92. package/testing/tests/utils/credentials.spec.ts +0 -195
  93. package/testing/tests/utils/dom.spec.ts +0 -37
  94. package/testing/tests/utils/index.spec.ts +0 -71
  95. package/testing/tests/utils/logging.spec.ts +0 -82
  96. package/testing/tests/utils/oidc.spec.ts +0 -745
  97. package/testing/tests/utils/server.spec.ts +0 -235
  98. package/testing/tests/utils/session.spec.ts +0 -87
@@ -1,369 +0,0 @@
1
- import { beforeEach, describe, test, expect, vi } from 'vitest';
2
- import { createOptions, getMockStorage } from '@strivacity/testing/mocks/sdk';
3
- import { createRedirectFlow } from '../../../src/flows/redirect';
4
-
5
- describe('createRedirectFlow', () => {
6
- let options: ReturnType<typeof createOptions>;
7
- let flow: ReturnType<typeof createRedirectFlow>;
8
-
9
- beforeEach(() => {
10
- options = createOptions({ urlHandler: vi.fn() });
11
- flow = createRedirectFlow(options);
12
- });
13
-
14
- describe('init', () => {
15
- test('lazyLoad: true', async () => {
16
- flow = createRedirectFlow(createOptions({ lazyLoad: true }));
17
-
18
- // We need to wait for the next tick to ensure that any asynchronous initialization logic has a chance to run before we check the initialized state.
19
- await Promise.resolve();
20
-
21
- expect(flow.initialized).toBe(false);
22
-
23
- await flow.init();
24
-
25
- expect(flow.initialized).toBe(true);
26
- });
27
-
28
- test('lazyLoad: false', async () => {
29
- flow = createRedirectFlow(createOptions({ lazyLoad: false }));
30
-
31
- await vi.waitFor(() => expect(flow.initialized).toBe(true));
32
- });
33
- });
34
-
35
- describe('login', () => {
36
- describe('w/o serverSessionUri', () => {
37
- test('w/o params', async () => {
38
- await flow.login();
39
-
40
- expect(flow.options.urlHandler).toHaveBeenCalledWith(expect.any(URL), {});
41
-
42
- const stateData = getMockStorage(options.stateStorage).getLastState();
43
- const [url, params] = vi.mocked(options.urlHandler).mock.calls[0] as [URL, Record<string, unknown>];
44
-
45
- expect(`${url.origin}${url.pathname}`).toBe('https://brandtegrity.io/oauth2/auth');
46
- expect(url.searchParams.get('client_id')).toBe('client-id');
47
- expect(url.searchParams.get('redirect_uri')).toBe('https://brandtegrity.io/callback');
48
- expect(url.searchParams.get('response_type')).toBe('code');
49
- expect(url.searchParams.get('response_mode')).toBe('query');
50
- expect(url.searchParams.get('scope')).toBe('openid');
51
- expect(url.searchParams.get('code_challenge_method')).toBe('S256');
52
- expect(url.searchParams.get('state')).toBe(stateData?.id);
53
- expect(url.searchParams.get('code_challenge')).toBe(stateData?.codeChallenge);
54
- expect(url.searchParams.get('nonce')).toBe(stateData?.nonce);
55
- expect(url.searchParams.has('prompt')).toBeFalsy();
56
- expect(url.searchParams.has('display')).toBeFalsy();
57
- expect(url.searchParams.has('login_hint')).toBeFalsy();
58
- expect(url.searchParams.has('acr_values')).toBeFalsy();
59
- expect(url.searchParams.has('ui_locales')).toBeFalsy();
60
- expect(url.searchParams.has('audience')).toBeFalsy();
61
- expect(params).toEqual({});
62
- });
63
-
64
- test('w/ params', async () => {
65
- const extraParams = {
66
- prompt: 'login',
67
- display: 'page',
68
- loginHint: 'test@example.com',
69
- acrValues: ['urn:mace:incommon:iap:silver', 'urn:mace:incommon:iap:bronze'],
70
- uiLocales: ['en-US', 'hu-HU'],
71
- audiences: ['https://api.example.com', 'https://api2.example.com'],
72
- };
73
-
74
- await flow.login(extraParams);
75
-
76
- expect(flow.options.urlHandler).toHaveBeenCalledWith(expect.any(URL), extraParams);
77
-
78
- const stateData = getMockStorage(options.stateStorage).getLastState();
79
- const [url, params] = vi.mocked(options.urlHandler).mock.calls[0] as [URL, Record<string, unknown>];
80
-
81
- expect(`${url.origin}${url.pathname}`).toBe('https://brandtegrity.io/oauth2/auth');
82
- expect(url.searchParams.get('client_id')).toBe('client-id');
83
- expect(url.searchParams.get('redirect_uri')).toBe('https://brandtegrity.io/callback');
84
- expect(url.searchParams.get('response_type')).toBe('code');
85
- expect(url.searchParams.get('response_mode')).toBe('query');
86
- expect(url.searchParams.get('scope')).toBe('openid');
87
- expect(url.searchParams.get('code_challenge_method')).toBe('S256');
88
- expect(url.searchParams.get('state')).toBe(stateData?.id);
89
- expect(url.searchParams.get('code_challenge')).toBe(stateData?.codeChallenge);
90
- expect(url.searchParams.get('nonce')).toBe(stateData?.nonce);
91
- expect(url.searchParams.get('prompt')).toBe('login');
92
- expect(url.searchParams.get('display')).toBe('page');
93
- expect(url.searchParams.get('login_hint')).toBe('test@example.com');
94
- expect(url.searchParams.get('acr_values')).toBe('urn:mace:incommon:iap:silver urn:mace:incommon:iap:bronze');
95
- expect(url.searchParams.get('ui_locales')).toBe('en-US hu-HU');
96
- expect(url.searchParams.get('audience')).toBe('https://api.example.com https://api2.example.com');
97
- expect(params).toEqual(extraParams);
98
- });
99
- });
100
-
101
- describe('w/ serverSessionUri', () => {
102
- test('w/o params', async () => {
103
- options = createOptions({ urlHandler: vi.fn(), serverSessionUri: 'https://app.example.com/login' });
104
- flow = createRedirectFlow(options);
105
-
106
- await flow.login();
107
-
108
- expect(flow.options.urlHandler).toHaveBeenCalledWith(expect.any(URL), {});
109
-
110
- const [url, params] = vi.mocked(options.urlHandler).mock.calls[0] as [URL, Record<string, unknown>];
111
-
112
- expect(`${url.origin}${url.pathname}`).toBe('https://app.example.com/login');
113
- expect(url.searchParams.has('client_id')).toBeFalsy();
114
- expect(url.searchParams.has('redirect_uri')).toBeFalsy();
115
- expect(url.searchParams.has('response_type')).toBeFalsy();
116
- expect(url.searchParams.has('response_mode')).toBeFalsy();
117
- expect(url.searchParams.has('scope')).toBeFalsy();
118
- expect(url.searchParams.has('code_challenge_method')).toBeFalsy();
119
- expect(url.searchParams.has('state')).toBeFalsy();
120
- expect(url.searchParams.has('code_challenge')).toBeFalsy();
121
- expect(url.searchParams.has('nonce')).toBeFalsy();
122
- expect(url.searchParams.has('prompt')).toBeFalsy();
123
- expect(url.searchParams.has('display')).toBeFalsy();
124
- expect(url.searchParams.has('login_hint')).toBeFalsy();
125
- expect(url.searchParams.has('acr_values')).toBeFalsy();
126
- expect(url.searchParams.has('ui_locales')).toBeFalsy();
127
- expect(url.searchParams.has('audience')).toBeFalsy();
128
- expect(params).toEqual({});
129
- });
130
-
131
- test('w/ params', async () => {
132
- options = createOptions({ urlHandler: vi.fn(), serverSessionUri: 'https://app.example.com/login' });
133
- flow = createRedirectFlow(options);
134
-
135
- const extraParams = {
136
- prompt: 'login',
137
- display: 'page',
138
- loginHint: 'test@example.com',
139
- acrValues: ['urn:mace:incommon:iap:silver', 'urn:mace:incommon:iap:bronze'],
140
- uiLocales: ['en-US', 'hu-HU'],
141
- audiences: ['https://api.example.com', 'https://api2.example.com'],
142
- };
143
-
144
- await flow.login(extraParams);
145
-
146
- expect(flow.options.urlHandler).toHaveBeenCalledWith(expect.any(URL), extraParams);
147
-
148
- const [url, params] = vi.mocked(options.urlHandler).mock.calls[0] as [URL, Record<string, unknown>];
149
-
150
- expect(`${url.origin}${url.pathname}`).toBe('https://app.example.com/login');
151
- expect(url.searchParams.has('client_id')).toBeFalsy();
152
- expect(url.searchParams.has('redirect_uri')).toBeFalsy();
153
- expect(url.searchParams.has('response_type')).toBeFalsy();
154
- expect(url.searchParams.has('response_mode')).toBeFalsy();
155
- expect(url.searchParams.has('scope')).toBeFalsy();
156
- expect(url.searchParams.has('code_challenge_method')).toBeFalsy();
157
- expect(url.searchParams.has('state')).toBeFalsy();
158
- expect(url.searchParams.has('code_challenge')).toBeFalsy();
159
- expect(url.searchParams.has('nonce')).toBeFalsy();
160
- expect(url.searchParams.get('prompt')).toBe('login');
161
- expect(url.searchParams.get('display')).toBe('page');
162
- expect(url.searchParams.get('login_hint')).toBe('test@example.com');
163
- expect(url.searchParams.get('acr_values')).toBe('urn:mace:incommon:iap:silver urn:mace:incommon:iap:bronze');
164
- expect(url.searchParams.get('ui_locales')).toBe('en-US hu-HU');
165
- expect(url.searchParams.get('audience')).toBe('https://api.example.com https://api2.example.com');
166
- expect(params).toEqual(extraParams);
167
- });
168
- });
169
- });
170
-
171
- describe('register', () => {
172
- describe('w/o serverSessionUri', () => {
173
- test('w/o params', async () => {
174
- await flow.register();
175
-
176
- expect(flow.options.urlHandler).toHaveBeenCalledWith(expect.any(URL), { prompt: 'create' });
177
-
178
- const stateData = getMockStorage(options.stateStorage).getLastState();
179
- const [url, params] = vi.mocked(options.urlHandler).mock.calls[0] as [URL, Record<string, unknown>];
180
-
181
- expect(`${url.origin}${url.pathname}`).toBe('https://brandtegrity.io/oauth2/auth');
182
- expect(url.searchParams.get('client_id')).toBe('client-id');
183
- expect(url.searchParams.get('redirect_uri')).toBe('https://brandtegrity.io/callback');
184
- expect(url.searchParams.get('response_type')).toBe('code');
185
- expect(url.searchParams.get('response_mode')).toBe('query');
186
- expect(url.searchParams.get('scope')).toBe('openid');
187
- expect(url.searchParams.get('code_challenge_method')).toBe('S256');
188
- expect(url.searchParams.get('state')).toBe(stateData?.id);
189
- expect(url.searchParams.get('code_challenge')).toBe(stateData?.codeChallenge);
190
- expect(url.searchParams.get('nonce')).toBe(stateData?.nonce);
191
- expect(url.searchParams.get('prompt')).toBe('create');
192
- expect(url.searchParams.has('display')).toBeFalsy();
193
- expect(url.searchParams.has('login_hint')).toBeFalsy();
194
- expect(url.searchParams.has('acr_values')).toBeFalsy();
195
- expect(url.searchParams.has('ui_locales')).toBeFalsy();
196
- expect(url.searchParams.has('audience')).toBeFalsy();
197
- expect(params).toEqual({ prompt: 'create' });
198
- });
199
-
200
- test('w/ params', async () => {
201
- const extraParams = {
202
- prompt: 'create',
203
- display: 'page',
204
- loginHint: 'test@example.com',
205
- acrValues: ['urn:mace:incommon:iap:silver', 'urn:mace:incommon:iap:bronze'],
206
- uiLocales: ['en-US', 'hu-HU'],
207
- audiences: ['https://api.example.com', 'https://api2.example.com'],
208
- };
209
-
210
- await flow.register({ ...extraParams, prompt: undefined });
211
-
212
- expect(flow.options.urlHandler).toHaveBeenCalledWith(expect.any(URL), extraParams);
213
-
214
- const stateData = getMockStorage(options.stateStorage).getLastState();
215
- const [url, params] = vi.mocked(options.urlHandler).mock.calls[0] as [URL, Record<string, unknown>];
216
-
217
- expect(`${url.origin}${url.pathname}`).toBe('https://brandtegrity.io/oauth2/auth');
218
- expect(url.searchParams.get('client_id')).toBe('client-id');
219
- expect(url.searchParams.get('redirect_uri')).toBe('https://brandtegrity.io/callback');
220
- expect(url.searchParams.get('response_type')).toBe('code');
221
- expect(url.searchParams.get('response_mode')).toBe('query');
222
- expect(url.searchParams.get('scope')).toBe('openid');
223
- expect(url.searchParams.get('code_challenge_method')).toBe('S256');
224
- expect(url.searchParams.get('state')).toBe(stateData?.id);
225
- expect(url.searchParams.get('code_challenge')).toBe(stateData?.codeChallenge);
226
- expect(url.searchParams.get('nonce')).toBe(stateData?.nonce);
227
- expect(url.searchParams.get('prompt')).toBe('create');
228
- expect(url.searchParams.get('display')).toBe('page');
229
- expect(url.searchParams.get('login_hint')).toBe('test@example.com');
230
- expect(url.searchParams.get('acr_values')).toBe('urn:mace:incommon:iap:silver urn:mace:incommon:iap:bronze');
231
- expect(url.searchParams.get('ui_locales')).toBe('en-US hu-HU');
232
- expect(url.searchParams.get('audience')).toBe('https://api.example.com https://api2.example.com');
233
- expect(params).toEqual(extraParams);
234
- });
235
- });
236
-
237
- describe('w/ serverSessionUri', () => {
238
- test('w/o params', async () => {
239
- options = createOptions({ urlHandler: vi.fn(), serverSessionUri: 'https://app.example.com/login' });
240
- flow = createRedirectFlow(options);
241
-
242
- await flow.register();
243
-
244
- expect(flow.options.urlHandler).toHaveBeenCalledWith(expect.any(URL), { prompt: 'create' });
245
-
246
- const [url, params] = vi.mocked(options.urlHandler).mock.calls[0] as [URL, Record<string, unknown>];
247
-
248
- expect(`${url.origin}${url.pathname}`).toBe('https://app.example.com/login');
249
- expect(url.searchParams.has('client_id')).toBeFalsy();
250
- expect(url.searchParams.has('redirect_uri')).toBeFalsy();
251
- expect(url.searchParams.has('response_type')).toBeFalsy();
252
- expect(url.searchParams.has('response_mode')).toBeFalsy();
253
- expect(url.searchParams.has('scope')).toBeFalsy();
254
- expect(url.searchParams.has('code_challenge_method')).toBeFalsy();
255
- expect(url.searchParams.has('state')).toBeFalsy();
256
- expect(url.searchParams.has('code_challenge')).toBeFalsy();
257
- expect(url.searchParams.has('nonce')).toBeFalsy();
258
- expect(url.searchParams.get('prompt')).toBe('create');
259
- expect(url.searchParams.has('display')).toBeFalsy();
260
- expect(url.searchParams.has('login_hint')).toBeFalsy();
261
- expect(url.searchParams.has('acr_values')).toBeFalsy();
262
- expect(url.searchParams.has('ui_locales')).toBeFalsy();
263
- expect(url.searchParams.has('audience')).toBeFalsy();
264
- expect(params).toEqual({ prompt: 'create' });
265
- });
266
-
267
- test('w/ params', async () => {
268
- options = createOptions({ urlHandler: vi.fn(), serverSessionUri: 'https://app.example.com/login' });
269
- flow = createRedirectFlow(options);
270
-
271
- const extraParams = {
272
- prompt: 'create',
273
- display: 'page',
274
- loginHint: 'test@example.com',
275
- acrValues: ['urn:mace:incommon:iap:silver', 'urn:mace:incommon:iap:bronze'],
276
- uiLocales: ['en-US', 'hu-HU'],
277
- audiences: ['https://api.example.com', 'https://api2.example.com'],
278
- };
279
-
280
- await flow.register({ ...extraParams, prompt: undefined });
281
-
282
- expect(flow.options.urlHandler).toHaveBeenCalledWith(expect.any(URL), extraParams);
283
-
284
- const [url, params] = vi.mocked(options.urlHandler).mock.calls[0] as [URL, Record<string, unknown>];
285
-
286
- expect(`${url.origin}${url.pathname}`).toBe('https://app.example.com/login');
287
- expect(url.searchParams.has('client_id')).toBeFalsy();
288
- expect(url.searchParams.has('redirect_uri')).toBeFalsy();
289
- expect(url.searchParams.has('response_type')).toBeFalsy();
290
- expect(url.searchParams.has('response_mode')).toBeFalsy();
291
- expect(url.searchParams.has('scope')).toBeFalsy();
292
- expect(url.searchParams.has('code_challenge_method')).toBeFalsy();
293
- expect(url.searchParams.has('state')).toBeFalsy();
294
- expect(url.searchParams.has('code_challenge')).toBeFalsy();
295
- expect(url.searchParams.has('nonce')).toBeFalsy();
296
- expect(url.searchParams.get('prompt')).toBe('create');
297
- expect(url.searchParams.get('display')).toBe('page');
298
- expect(url.searchParams.get('login_hint')).toBe('test@example.com');
299
- expect(url.searchParams.get('acr_values')).toBe('urn:mace:incommon:iap:silver urn:mace:incommon:iap:bronze');
300
- expect(url.searchParams.get('ui_locales')).toBe('en-US hu-HU');
301
- expect(url.searchParams.get('audience')).toBe('https://api.example.com https://api2.example.com');
302
- expect(params).toEqual(extraParams);
303
- });
304
- });
305
- });
306
-
307
- describe('entry', () => {
308
- test('should redirect to the provider entry endpoint preserving query parameters', async () => {
309
- await flow.entry('https://brandtegrity.io/entry?challenge=abc123&foo=bar');
310
-
311
- const [url, params] = vi.mocked(options.urlHandler).mock.calls[0];
312
-
313
- expect((url as URL).toString()).toBe('https://brandtegrity.io/provider/entry?challenge=abc123&foo=bar');
314
- expect(params).toBeUndefined();
315
- });
316
-
317
- test('should default to the current window location when no url is provided', async () => {
318
- window.location.search = '?challenge=abc123&foo=bar';
319
-
320
- await flow.entry();
321
-
322
- const [url] = vi.mocked(options.urlHandler).mock.calls[0];
323
-
324
- expect((url as URL).toString()).toBe('https://brandtegrity.io/provider/entry?challenge=abc123&foo=bar');
325
- });
326
- });
327
-
328
- test('flow state accessors', async () => {
329
- options = createOptions({ lazyLoad: true, urlHandler: vi.fn() });
330
- flow = createRedirectFlow(options);
331
-
332
- expect(flow.options).toBe(options);
333
- expect(flow.initialized).toBeFalsy();
334
- expect(flow.storage).toBe(options.storage);
335
- expect(flow.httpClient).toBe(options.httpClient);
336
- expect(flow.logging).toBe(options.logging);
337
- expect(flow.sessionId).toBeNull();
338
- expect(flow.shortAppId).toBeNull();
339
- expect(flow.language).toBe('en-US');
340
- await expect(flow.isAuthenticated).resolves.toBeFalsy();
341
- expect(flow.isAuthenticatedSync).toBeFalsy();
342
- expect(flow.accessToken).toBeNull();
343
- expect(flow.accessTokenExpired).toBeTruthy();
344
- expect(flow.accessTokenExpirationDate).toBeNull();
345
- expect(flow.refreshToken).toBeNull();
346
- expect(flow.idToken).toBeNull();
347
- expect(flow.idTokenClaims).toBeNull();
348
-
349
- await flow.init();
350
-
351
- flow.sessionId = 'abc123';
352
- flow.shortAppId = 'app';
353
- flow.language = 'hu-HU';
354
- flow.session = getMockStorage(options.storage).generateSession();
355
-
356
- expect(flow.initialized).toBeTruthy();
357
- expect(flow.sessionId).toBe('abc123');
358
- expect(flow.shortAppId).toBe('app');
359
- expect(flow.language).toBe('hu-HU');
360
- await expect(flow.isAuthenticated).resolves.toBeTruthy();
361
- expect(flow.isAuthenticatedSync).toBeTruthy();
362
- expect(flow.accessToken).toBe(flow.session.access_token);
363
- expect(flow.accessTokenExpired).toBeFalsy();
364
- expect(flow.accessTokenExpirationDate).toBe(flow.session.expires_at);
365
- expect(flow.refreshToken).toBe(flow.session.refresh_token);
366
- expect(flow.idToken).toBe(flow.session.id_token);
367
- expect(flow.idTokenClaims).toBe(flow.session?.claims);
368
- });
369
- });
@@ -1,199 +0,0 @@
1
- import type { LoginComponent } from '../../../src/types';
2
- import { beforeEach, describe, test, expect } from 'vitest';
3
- import { createOptions, createFakeBaseFlow } from '@strivacity/testing/mocks/sdk';
4
- import { worker, http, HttpResponse } from '@strivacity/testing/mocks/msw';
5
- import { getDefaultFlowState, ProtocolError, OidcError, ServerError, NetworkError } from '../../../src/utils';
6
- import { startSessionHandler, finalizeSessionHandler } from '../../../src/handlers/embedded';
7
-
8
- describe('startSessionHandler', () => {
9
- let params: Parameters<typeof startSessionHandler>[0];
10
-
11
- beforeEach(() => {
12
- globalThis.location.href = 'https://brandtegrity.io';
13
- params = { base: createFakeBaseFlow(), options: createOptions(), flowState: getDefaultFlowState(), params: {} };
14
- });
15
-
16
- test('should start session correctly', async () => {
17
- worker.use(
18
- http.get('https://brandtegrity.io/oauth2/auth', () =>
19
- HttpResponse.text('https://brandtegrity.io/login?session_id=abc123&short_app_id=app&language=hu-HU'),
20
- ),
21
- );
22
-
23
- await startSessionHandler(params);
24
-
25
- expect(params.base.dispatchEvent).toHaveBeenCalledWith('flowInitiated', []);
26
- expect(params.flowState.sessionId).toBe('abc123');
27
- expect(params.flowState.shortAppId).toBe('app');
28
- expect(params.flowState.language).toBe('hu-HU');
29
- });
30
-
31
- describe('should exchange the code for tokens correctly', () => {
32
- test('w/o serverSessionUri', async () => {
33
- worker.use(http.get('https://brandtegrity.io/oauth2/auth', () => HttpResponse.text('https://brandtegrity.io/callback?code=abc123')));
34
-
35
- await startSessionHandler(params);
36
-
37
- expect(globalThis.location.href).not.toBe('https://brandtegrity.io/callback?code=abc123');
38
- expect(params.base.tokenExchange).toHaveBeenCalledWith({ code: 'abc123' });
39
- });
40
-
41
- test('w/ serverSessionUri', async () => {
42
- worker.use(http.get('https://brandtegrity.io/login', () => HttpResponse.text('https://brandtegrity.io/callback?code=abc123')));
43
- params.options = createOptions({ serverSessionUri: 'https://brandtegrity.io/login' });
44
-
45
- await startSessionHandler(params);
46
-
47
- expect(globalThis.location.href).toBe('https://brandtegrity.io/callback?code=abc123');
48
- expect(params.base.tokenExchange).not.toHaveBeenCalled();
49
- });
50
- });
51
-
52
- test('should reject with a ProtocolError when short_app_id is missing', async () => {
53
- worker.use(http.get('https://brandtegrity.io/oauth2/auth', () => HttpResponse.text('https://brandtegrity.io/login?session_id=abc')));
54
-
55
- await expect(startSessionHandler(params)).rejects.toThrow(new ProtocolError('short_app_id is missing in the response'));
56
- expect(params.options.logging?.error).toHaveBeenCalledWith('Start login session error', expect.any(ProtocolError));
57
- });
58
-
59
- test('should reject with a ProtocolError when neither code nor session_id are present', async () => {
60
- worker.use(http.get('https://brandtegrity.io/oauth2/auth', () => HttpResponse.text('https://brandtegrity.io/login?something=else')));
61
-
62
- await expect(startSessionHandler(params)).rejects.toThrow(new ProtocolError('Neither "code" nor "session_id" is present in the response'));
63
- expect(params.options.logging?.error).toHaveBeenCalledWith('Start login session error', expect.any(ProtocolError));
64
- });
65
-
66
- test('should reject with a ProtocolError when neither code nor session_id are present', async () => {
67
- worker.use(
68
- http.get('https://brandtegrity.io/oauth2/auth', () =>
69
- HttpResponse.text('https://brandtegrity.io/login?error=access_denied&error_description=nope&error_uri=https://example.com/error'),
70
- ),
71
- );
72
-
73
- await expect(startSessionHandler(params)).rejects.toThrow(new OidcError('access_denied', 'nope', 'https://example.com/error'));
74
- expect(params.options.logging?.error).toHaveBeenCalledWith('Start login session error', expect.any(OidcError));
75
- });
76
-
77
- test('should reject with a ProtocolError when the redirect URI does not match the configured redirectUri', async () => {
78
- worker.use(http.get('https://brandtegrity.io/oauth2/auth', () => HttpResponse.text('https://invalid.domain/callback?code=abc123')));
79
-
80
- await expect(startSessionHandler(params)).rejects.toThrow(new ProtocolError('Invalid redirect URI'));
81
- expect(params.options.logging?.error).toHaveBeenCalledWith('Start login session error', expect.any(ProtocolError));
82
- });
83
-
84
- describe('should reject with an error when the HTTP request fails', () => {
85
- test('HTTP 400', async () => {
86
- worker.use(http.get('https://brandtegrity.io/oauth2/auth', () => new HttpResponse(null, { status: 400 })));
87
-
88
- await expect(startSessionHandler(params)).rejects.toThrow(new ProtocolError('Failed to start login session'));
89
- expect(params.options.logging?.error).toHaveBeenCalledWith('Start login session error', expect.any(ProtocolError));
90
- });
91
-
92
- test('HTTP 429', async () => {
93
- worker.use(http.get('https://brandtegrity.io/oauth2/auth', () => new HttpResponse(null, { status: 429 })));
94
-
95
- await expect(startSessionHandler(params)).rejects.toThrow(new ServerError('Failed to start login session', 429));
96
- expect(params.options.logging?.error).toHaveBeenCalledWith('Start login session error', expect.any(ServerError));
97
- });
98
-
99
- test('HTTP 500', async () => {
100
- worker.use(http.get('https://brandtegrity.io/oauth2/auth', () => new HttpResponse(null, { status: 500 })));
101
-
102
- await expect(startSessionHandler(params)).rejects.toThrow(new ServerError('Failed to start login session', 500));
103
- expect(params.options.logging?.error).toHaveBeenCalledWith('Start login session error', expect.any(ServerError));
104
- });
105
-
106
- test('HTTP 503', async () => {
107
- worker.use(http.get('https://brandtegrity.io/oauth2/auth', () => HttpResponse.error()));
108
-
109
- await expect(startSessionHandler(params)).rejects.toThrow(new NetworkError('Network request failed: https://brandtegrity.io/oauth2/auth'));
110
- expect(params.options.logging?.error).toHaveBeenCalledWith('Start login session error', expect.any(NetworkError));
111
- });
112
- });
113
- });
114
-
115
- describe('finalizeSessionHandler', () => {
116
- let params: Parameters<typeof finalizeSessionHandler>[0];
117
-
118
- beforeEach(() => {
119
- globalThis.sty = {};
120
- globalThis.location.href = 'https://brandtegrity.io';
121
- params = {
122
- base: createFakeBaseFlow(),
123
- options: createOptions(),
124
- flowState: { ...getDefaultFlowState(), sessionId: 'abc123' },
125
- url: 'https://brandtegrity.io/finalize',
126
- };
127
- });
128
-
129
- describe('should finalize session correctly', () => {
130
- test('w/o serverSessionUri', async () => {
131
- globalThis.sty = { hostElement: { sessionId: 'abc123', shortAppId: 'app', lang: 'hu-HU' } as unknown as LoginComponent };
132
- params.flowState = getDefaultFlowState();
133
- worker.use(http.get('https://brandtegrity.io/finalize', () => HttpResponse.text('https://brandtegrity.io/callback?code=abc123')));
134
-
135
- await finalizeSessionHandler(params);
136
-
137
- expect(params.flowState.sessionId).toBe('abc123');
138
- expect(params.flowState.shortAppId).toBe('app');
139
- expect(params.flowState.language).toBe('hu-HU');
140
-
141
- expect(globalThis.location.href).not.toBe('https://brandtegrity.io/callback?code=abc123');
142
- expect(params.base.tokenExchange).toHaveBeenCalledWith({ code: 'abc123' });
143
- });
144
-
145
- test('w/ serverSessionUri', async () => {
146
- worker.use(http.get('https://brandtegrity.io/finalize', () => HttpResponse.text('https://brandtegrity.io/callback?code=abc123')));
147
- params.options = createOptions({ serverSessionUri: 'https://brandtegrity.io/login' });
148
-
149
- await finalizeSessionHandler(params);
150
-
151
- expect(globalThis.location.href).toBe('https://brandtegrity.io/callback?code=abc123');
152
- expect(params.base.tokenExchange).not.toHaveBeenCalled();
153
- });
154
- });
155
-
156
- test('should throw when the session ID is missing', async () => {
157
- params.flowState = getDefaultFlowState();
158
-
159
- await expect(finalizeSessionHandler(params)).rejects.toThrow(new Error('Session ID is missing. Cannot finalize login session.'));
160
- expect(params.options.logging?.error).toHaveBeenCalledWith('Failed to finalize login session', expect.any(Error));
161
- });
162
-
163
- test('should reject with a ProtocolError when the redirect URI does not match the configured redirectUri', async () => {
164
- worker.use(http.get('https://brandtegrity.io/finalize', () => HttpResponse.text('https://invalid.domain/callback?code=abc123')));
165
-
166
- await expect(finalizeSessionHandler(params)).rejects.toThrow(new ProtocolError('Invalid redirect URI'));
167
- expect(params.options.logging?.error).toHaveBeenCalledWith('Finalize login session error', expect.any(ProtocolError));
168
- });
169
-
170
- describe('should reject with an error when the HTTP request fails', () => {
171
- test('HTTP 400', async () => {
172
- worker.use(http.get('https://brandtegrity.io/finalize', () => new HttpResponse(null, { status: 400 })));
173
-
174
- await expect(finalizeSessionHandler(params)).rejects.toThrow(new ProtocolError('Failed to finalize login session'));
175
- expect(params.options.logging?.error).toHaveBeenCalledWith('Finalize login session error', expect.any(ProtocolError));
176
- });
177
-
178
- test('HTTP 429', async () => {
179
- worker.use(http.get('https://brandtegrity.io/finalize', () => new HttpResponse(null, { status: 429 })));
180
-
181
- await expect(finalizeSessionHandler(params)).rejects.toThrow(new ServerError('Failed to finalize login session', 429));
182
- expect(params.options.logging?.error).toHaveBeenCalledWith('Finalize login session error', expect.any(ServerError));
183
- });
184
-
185
- test('HTTP 500', async () => {
186
- worker.use(http.get('https://brandtegrity.io/finalize', () => new HttpResponse(null, { status: 500 })));
187
-
188
- await expect(finalizeSessionHandler(params)).rejects.toThrow(new ServerError('Failed to finalize login session', 500));
189
- expect(params.options.logging?.error).toHaveBeenCalledWith('Finalize login session error', expect.any(ServerError));
190
- });
191
-
192
- test('HTTP 503', async () => {
193
- worker.use(http.get('https://brandtegrity.io/finalize', () => HttpResponse.error()));
194
-
195
- await expect(finalizeSessionHandler(params)).rejects.toThrow(new NetworkError('Network request failed: https://brandtegrity.io/finalize'));
196
- expect(params.options.logging?.error).toHaveBeenCalledWith('Finalize login session error', expect.any(NetworkError));
197
- });
198
- });
199
- });
@@ -1,8 +0,0 @@
1
- import { test, expect } from 'vitest';
2
- import * as index from '../../../src/handlers';
3
-
4
- test('should export the correct things', () => {
5
- const expectedExports = ['popupUrlHandler', 'popupCallbackHandler', 'redirectUrlHandler', 'redirectCallbackHandler'];
6
-
7
- expect(Object.keys(index)).toEqual(expectedExports);
8
- });