@strivacity/sdk-react 3.0.3 → 4.0.0-beta.0
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/CHANGELOG.md +1 -1
- package/README.md +1562 -406
- package/dist/assets/rolldown-runtime.cjs +1 -0
- package/dist/assets/rolldown-runtime.mjs +1 -0
- package/dist/components.cjs +2 -0
- package/dist/components.cjs.map +1 -0
- package/dist/components.d.ts +11 -0
- package/dist/components.mjs +2 -0
- package/dist/components.mjs.map +1 -0
- package/dist/errors.cjs +2 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.ts +1 -0
- package/dist/errors.mjs +2 -0
- package/dist/errors.mjs.map +1 -0
- package/dist/hooks.cjs +2 -0
- package/dist/hooks.cjs.map +1 -0
- package/dist/hooks.d.ts +33 -0
- package/dist/hooks.mjs +2 -0
- package/dist/hooks.mjs.map +1 -0
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +9 -13
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/dist/storages.cjs +1 -0
- package/dist/storages.d.ts +1 -0
- package/dist/storages.mjs +1 -0
- package/dist/types.cjs +1 -2
- package/dist/types.d.ts +147 -110
- package/dist/types.mjs +1 -2
- package/dist/utils.cjs +1 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.mjs +1 -0
- package/package.json +51 -7
- package/testing/tests/components.spec.tsx +146 -0
- package/testing/tests/errors.spec.ts +10 -0
- package/testing/tests/guard.spec.tsx +119 -0
- package/testing/tests/hooks.spec.tsx +418 -0
- package/testing/tests/index.spec.ts +105 -0
- package/testing/tests/storages.spec.ts +10 -0
- package/testing/tests/utils.spec.ts +10 -0
- package/testing/utils/common.tsx +63 -0
- package/dist/AuthProvider.cjs +0 -2
- package/dist/AuthProvider.cjs.map +0 -1
- package/dist/AuthProvider.d.ts +0 -7
- package/dist/AuthProvider.mjs +0 -2
- package/dist/AuthProvider.mjs.map +0 -1
- package/dist/LoginRenderer.cjs +0 -2
- package/dist/LoginRenderer.cjs.map +0 -1
- package/dist/LoginRenderer.d.ts +0 -20
- package/dist/LoginRenderer.mjs +0 -2
- package/dist/LoginRenderer.mjs.map +0 -1
- package/dist/composables.cjs +0 -2
- package/dist/composables.cjs.map +0 -1
- package/dist/composables.d.ts +0 -12
- package/dist/composables.mjs +0 -2
- package/dist/composables.mjs.map +0 -1
- package/dist/types.cjs.map +0 -1
- package/dist/types.mjs.map +0 -1
package/dist/types.d.ts
CHANGED
|
@@ -1,176 +1,213 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { PopupFlow } from '@strivacity/sdk-core
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import { ReactNode, DetailedHTMLProps, HTMLAttributes } from 'react';
|
|
2
|
+
import { LoginComponent, NotificationComponent, LandingComponent, LanguageSelectorComponent, SDKInitConfig, SessionData, IdTokenClaims, RedirectFlow, PopupFlow, NativeFlow, EmbeddedFlow, initFlow, NativeFlowState, NativeFlowMessage, NativeParams } from '@strivacity/sdk-core';
|
|
3
|
+
import { FallbackError } from '@strivacity/sdk-core/utils';
|
|
4
|
+
export * from '@strivacity/sdk-core/types';
|
|
5
|
+
declare module 'react' {
|
|
6
|
+
namespace JSX {
|
|
7
|
+
interface IntrinsicElements {
|
|
8
|
+
'sty-login': ElementProps<LoginComponent, {
|
|
9
|
+
onLogin?: () => void;
|
|
10
|
+
onClose?: () => void;
|
|
11
|
+
onError?: (e: CustomEvent<string>) => void;
|
|
12
|
+
}>;
|
|
13
|
+
'sty-notifications': ElementProps<NotificationComponent>;
|
|
14
|
+
'sty-language-selector': ElementProps<LanguageSelectorComponent>;
|
|
15
|
+
'sty-landing': ElementProps<LandingComponent>;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export type ElementProps<T extends HTMLElement, Extra = object> = DetailedHTMLProps<Omit<HTMLAttributes<T>, keyof Extra> & Partial<Omit<T, keyof HTMLElement>> & Extra, T>;
|
|
20
|
+
export type SDKContext<Flow extends RedirectFlow | PopupFlow | NativeFlow | EmbeddedFlow> = {
|
|
21
|
+
/**
|
|
22
|
+
* The underlying Strivacity SDK flow instance.
|
|
12
23
|
*/
|
|
13
|
-
|
|
24
|
+
readonly sdk: Flow;
|
|
14
25
|
/**
|
|
15
|
-
*
|
|
26
|
+
* A boolean indicating whether the SDK is still loading. This can be used to show a loading spinner or similar UI while the SDK is initializing.
|
|
16
27
|
*/
|
|
17
|
-
|
|
28
|
+
readonly loading: boolean;
|
|
18
29
|
/**
|
|
19
|
-
*
|
|
30
|
+
* BCP 47 language code representing the current language of the SDK.
|
|
20
31
|
*/
|
|
21
|
-
|
|
32
|
+
readonly language: string;
|
|
22
33
|
/**
|
|
23
|
-
*
|
|
34
|
+
* A boolean indicating whether the user is authenticated. This can be used to conditionally render UI based on the user's authentication state.
|
|
24
35
|
*/
|
|
25
|
-
|
|
36
|
+
readonly isAuthenticated: boolean;
|
|
26
37
|
/**
|
|
27
|
-
* The
|
|
38
|
+
* The claims from the ID token, if available. This can be used to access user information and other claims provided by the authentication server.
|
|
28
39
|
*/
|
|
29
|
-
|
|
40
|
+
readonly idTokenClaims: IdTokenClaims | null;
|
|
30
41
|
/**
|
|
31
|
-
* The
|
|
42
|
+
* The access token, if available. This can be used to authenticate API requests or other interactions with the backend.
|
|
32
43
|
*/
|
|
33
|
-
|
|
44
|
+
readonly accessToken: string | null;
|
|
34
45
|
/**
|
|
35
|
-
*
|
|
46
|
+
* The refresh token, if available. This can be used to obtain new access tokens when the current one expires.
|
|
36
47
|
*/
|
|
37
|
-
|
|
48
|
+
readonly refreshToken: string | null;
|
|
38
49
|
/**
|
|
39
|
-
*
|
|
50
|
+
* A boolean indicating whether the access token has expired. This can be used to trigger a refresh of the access token or to log the user out.
|
|
40
51
|
*/
|
|
41
|
-
|
|
42
|
-
};
|
|
43
|
-
/**
|
|
44
|
-
* Represents the available authentication flows and operations for Popup-based interactions.
|
|
45
|
-
*/
|
|
46
|
-
export type PopupSDK = {
|
|
52
|
+
readonly accessTokenExpired: boolean;
|
|
47
53
|
/**
|
|
48
|
-
*
|
|
54
|
+
* The expiration date of the access token, if available. This can be used to determine when to refresh the access token or to log the user out.
|
|
49
55
|
*/
|
|
50
|
-
|
|
56
|
+
readonly accessTokenExpirationDate: number | null;
|
|
51
57
|
/**
|
|
52
|
-
*
|
|
58
|
+
* Subscribes to a specific SDK event.
|
|
53
59
|
*/
|
|
54
|
-
|
|
60
|
+
subscribeToEvent: Flow['subscribeToEvent'];
|
|
55
61
|
/**
|
|
56
|
-
*
|
|
62
|
+
* Subscribes to all SDK events.
|
|
57
63
|
*/
|
|
58
|
-
|
|
64
|
+
subscribeToAllEvents: Flow['subscribeToAllEvents'];
|
|
59
65
|
/**
|
|
60
|
-
*
|
|
66
|
+
* Checks whether the user is currently authenticated, optionally triggering a token refresh.
|
|
61
67
|
*/
|
|
62
|
-
|
|
68
|
+
checkAuthentication: Flow['checkAuthentication'];
|
|
63
69
|
/**
|
|
64
|
-
*
|
|
70
|
+
* Initializes the SDK, loading metadata and restoring any persisted session.
|
|
65
71
|
*/
|
|
66
|
-
|
|
72
|
+
init: Flow['init'];
|
|
67
73
|
/**
|
|
68
|
-
*
|
|
74
|
+
* Performs a token exchange using the provided parameters.
|
|
69
75
|
*/
|
|
70
|
-
|
|
76
|
+
tokenExchange: Flow['tokenExchange'];
|
|
71
77
|
/**
|
|
72
|
-
*
|
|
78
|
+
* Handles the authentication callback by parsing the response from the given URL.
|
|
73
79
|
*/
|
|
74
|
-
|
|
80
|
+
handleCallback: Flow['handleCallback'];
|
|
75
81
|
/**
|
|
76
|
-
*
|
|
82
|
+
* Refreshes the current access token using the refresh token.
|
|
77
83
|
*/
|
|
78
|
-
|
|
79
|
-
};
|
|
80
|
-
/**
|
|
81
|
-
* Represents the available authentication flows and operations for Redirect-based interactions.
|
|
82
|
-
*/
|
|
83
|
-
export type RedirectSDK = {
|
|
84
|
+
refresh: Flow['refresh'];
|
|
84
85
|
/**
|
|
85
|
-
*
|
|
86
|
+
* Revokes the current tokens.
|
|
86
87
|
*/
|
|
87
|
-
|
|
88
|
+
revoke: Flow['revoke'];
|
|
88
89
|
/**
|
|
89
|
-
*
|
|
90
|
+
* Logs the user out and optionally redirects to a post-logout URI.
|
|
90
91
|
*/
|
|
91
|
-
|
|
92
|
+
logout: Flow['logout'];
|
|
92
93
|
/**
|
|
93
|
-
*
|
|
94
|
+
* Initiates the login flow.
|
|
94
95
|
*/
|
|
95
|
-
|
|
96
|
+
login: Flow['login'];
|
|
96
97
|
/**
|
|
97
|
-
* Initiates the
|
|
98
|
+
* Initiates the registration flow.
|
|
98
99
|
*/
|
|
99
|
-
|
|
100
|
+
register: Flow['register'];
|
|
100
101
|
/**
|
|
101
|
-
*
|
|
102
|
+
* Handles the entry point URL of the authentication flow, typically used for embedded or native modes.
|
|
102
103
|
*/
|
|
103
|
-
|
|
104
|
+
entry: Flow['entry'];
|
|
105
|
+
};
|
|
106
|
+
export type SDKInstance = ReturnType<typeof initFlow>;
|
|
107
|
+
export type StyAuthProviderProps = {
|
|
104
108
|
/**
|
|
105
|
-
*
|
|
109
|
+
* The options to be used by the AuthProvider. These options are passed to the SDK during initialization.
|
|
106
110
|
*/
|
|
107
|
-
|
|
111
|
+
options: SDKInitConfig;
|
|
108
112
|
/**
|
|
109
|
-
*
|
|
113
|
+
* The session data to be used by the AuthProvider.
|
|
114
|
+
*
|
|
115
|
+
* If not provided, the AuthProvider will attempt to retrieve the session data from the SDK.
|
|
110
116
|
*/
|
|
111
|
-
|
|
117
|
+
session?: SessionData | null;
|
|
112
118
|
/**
|
|
113
|
-
*
|
|
119
|
+
* The children to be rendered by the AuthProvider. This is typically the rest of your application.
|
|
114
120
|
*/
|
|
115
|
-
|
|
121
|
+
children: ReactNode;
|
|
116
122
|
};
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
123
|
+
export type LoginContext = {
|
|
124
|
+
/**
|
|
125
|
+
* Whether a form submission or session initialization is in progress.
|
|
126
|
+
*/
|
|
127
|
+
loading: boolean;
|
|
121
128
|
/**
|
|
122
|
-
*
|
|
129
|
+
* Current form field values, keyed by form ID then widget ID.
|
|
123
130
|
*/
|
|
124
|
-
|
|
131
|
+
forms: Record<string, Record<string, unknown>>;
|
|
125
132
|
/**
|
|
126
|
-
*
|
|
133
|
+
* Current validation and info messages, keyed by form ID then widget ID.
|
|
127
134
|
*/
|
|
128
|
-
|
|
135
|
+
messages: Record<string, Record<string, NativeFlowMessage>>;
|
|
129
136
|
/**
|
|
130
|
-
*
|
|
137
|
+
* The current login flow state returned by the backend.
|
|
131
138
|
*/
|
|
132
|
-
|
|
139
|
+
state: Partial<NativeFlowState>;
|
|
133
140
|
/**
|
|
134
|
-
*
|
|
141
|
+
* Submits the form with the given ID and advances the login flow.
|
|
142
|
+
*
|
|
143
|
+
* @param formId - The ID of the form to submit.
|
|
144
|
+
* @param customBody - Optional custom body to send with the form submission. If not provided, the current form values will be used.
|
|
145
|
+
* @returns A promise that resolves when the form submission is complete.
|
|
135
146
|
*/
|
|
136
|
-
|
|
147
|
+
submitForm: (formId: string, customBody?: Record<string, unknown>) => Promise<void>;
|
|
137
148
|
/**
|
|
138
|
-
*
|
|
149
|
+
* Redirects to the hosted login UI.
|
|
150
|
+
*
|
|
151
|
+
* @param message - Optional message to log before redirecting.
|
|
152
|
+
* @returns A promise that resolves when the redirect is initiated.
|
|
139
153
|
*/
|
|
140
|
-
|
|
154
|
+
triggerFallback: (message?: string) => void;
|
|
141
155
|
/**
|
|
142
|
-
*
|
|
156
|
+
* Signals that the login flow was closed by the user.
|
|
143
157
|
*/
|
|
144
|
-
|
|
158
|
+
triggerClose: () => void;
|
|
145
159
|
/**
|
|
146
|
-
*
|
|
160
|
+
* Updates a single field value within a form before submission.
|
|
161
|
+
*
|
|
162
|
+
* @param formId - The ID of the form containing the field.
|
|
163
|
+
* @param widgetId - The ID of the widget (field) to update.
|
|
164
|
+
* @param value - The new value to set for the field.
|
|
147
165
|
*/
|
|
148
|
-
|
|
166
|
+
setFormValue: (formId: string, widgetId: string, value: unknown) => void;
|
|
149
167
|
/**
|
|
150
|
-
*
|
|
168
|
+
* Sets a validation or info message on a specific widget.
|
|
169
|
+
*
|
|
170
|
+
* @param formId - The ID of the form containing the widget.
|
|
171
|
+
* @param widgetId - The ID of the widget to set the message for.
|
|
172
|
+
* @param value - The message to set, which can be a string or a structured NativeFlowMessage.
|
|
151
173
|
*/
|
|
152
|
-
|
|
174
|
+
setMessage: (formId: string, widgetId: string, value: NativeFlowMessage) => void;
|
|
153
175
|
};
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
+
export type UseNativeLoginOptions = {
|
|
177
|
+
/**
|
|
178
|
+
* Optional parameters to be passed to the login session request.
|
|
179
|
+
*/
|
|
180
|
+
params?: NativeParams;
|
|
181
|
+
/**
|
|
182
|
+
* Called when the user successfully completes the login flow.
|
|
183
|
+
*/
|
|
184
|
+
onLogin?: (session: SessionData) => void | Promise<void>;
|
|
185
|
+
/**
|
|
186
|
+
* Called when the fallback flow is triggered.
|
|
187
|
+
*/
|
|
188
|
+
onFallback?: (error: FallbackError) => void | Promise<void>;
|
|
189
|
+
/**
|
|
190
|
+
* Called when the login flow is closed by the user.
|
|
191
|
+
*/
|
|
192
|
+
onClose?: () => void | Promise<void>;
|
|
193
|
+
/**
|
|
194
|
+
* Called when an error occurs during login flow initialization or submission.
|
|
195
|
+
*/
|
|
196
|
+
onError?: (error: Error) => void | Promise<void>;
|
|
197
|
+
/**
|
|
198
|
+
* Called when a global message is received during the login flow.
|
|
199
|
+
*/
|
|
200
|
+
onGlobalMessage?: (message: NativeFlowMessage) => void | Promise<void>;
|
|
201
|
+
};
|
|
202
|
+
export type WithAuthGuardOptions = {
|
|
203
|
+
/**
|
|
204
|
+
* The URL to redirect the user to if they are not authenticated.
|
|
205
|
+
*
|
|
206
|
+
* @default '/login'
|
|
207
|
+
*/
|
|
208
|
+
loginUri?: string;
|
|
209
|
+
/**
|
|
210
|
+
* A component to render while the authentication state is being determined. Defaults to `null`.
|
|
211
|
+
*/
|
|
212
|
+
onLoading?: () => React.ReactNode;
|
|
176
213
|
};
|
package/dist/types.mjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
//# sourceMappingURL=types.mjs.map
|
|
1
|
+
import"./assets/rolldown-runtime.mjs";export*from"@strivacity/sdk-core/types";
|
package/dist/utils.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require("./assets/rolldown-runtime.cjs");var e=require("@strivacity/sdk-core/utils");Object.keys(e).forEach(function(t){t!=="default"&&!Object.prototype.hasOwnProperty.call(exports,t)&&Object.defineProperty(exports,t,{enumerable:!0,get:function(){return e[t]}})});
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@strivacity/sdk-core/utils';
|
package/dist/utils.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./assets/rolldown-runtime.mjs";export*from"@strivacity/sdk-core/utils";
|
package/package.json
CHANGED
|
@@ -1,20 +1,64 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strivacity/sdk-react",
|
|
3
|
-
"version": "
|
|
4
|
-
"license": "MIT",
|
|
3
|
+
"version": "4.0.0-beta.0",
|
|
5
4
|
"description": "Strivacity React SDK client",
|
|
5
|
+
"license": "MIT",
|
|
6
6
|
"author": "strivacity <opensource@strivacity.com>",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "https://github.com/Strivacity/sdk-js"
|
|
10
10
|
},
|
|
11
|
+
"sideEffects": false,
|
|
12
|
+
"main": "./dist/index.cjs",
|
|
13
|
+
"types": "./dist/types.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"import": "./dist/index.mjs",
|
|
18
|
+
"require": "./dist/index.cjs",
|
|
19
|
+
"default": "./dist/index.mjs"
|
|
20
|
+
},
|
|
21
|
+
"./components": {
|
|
22
|
+
"types": "./dist/components.d.ts",
|
|
23
|
+
"import": "./dist/components.mjs",
|
|
24
|
+
"require": "./dist/components.cjs",
|
|
25
|
+
"default": "./dist/components.mjs"
|
|
26
|
+
},
|
|
27
|
+
"./errors": {
|
|
28
|
+
"types": "./dist/errors.d.ts",
|
|
29
|
+
"import": "./dist/errors.mjs",
|
|
30
|
+
"require": "./dist/errors.cjs",
|
|
31
|
+
"default": "./dist/errors.mjs"
|
|
32
|
+
},
|
|
33
|
+
"./hooks": {
|
|
34
|
+
"types": "./dist/hooks.d.ts",
|
|
35
|
+
"import": "./dist/hooks.mjs",
|
|
36
|
+
"require": "./dist/hooks.cjs",
|
|
37
|
+
"default": "./dist/hooks.mjs"
|
|
38
|
+
},
|
|
39
|
+
"./storages": {
|
|
40
|
+
"types": "./dist/storages.d.ts",
|
|
41
|
+
"import": "./dist/storages.mjs",
|
|
42
|
+
"require": "./dist/storages.cjs",
|
|
43
|
+
"default": "./dist/storages.mjs"
|
|
44
|
+
},
|
|
45
|
+
"./types": {
|
|
46
|
+
"types": "./dist/types.d.ts",
|
|
47
|
+
"import": "./dist/types.mjs",
|
|
48
|
+
"require": "./dist/types.cjs",
|
|
49
|
+
"default": "./dist/types.mjs"
|
|
50
|
+
},
|
|
51
|
+
"./utils": {
|
|
52
|
+
"types": "./dist/utils.d.ts",
|
|
53
|
+
"import": "./dist/utils.mjs",
|
|
54
|
+
"require": "./dist/utils.cjs",
|
|
55
|
+
"default": "./dist/utils.mjs"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
11
58
|
"dependencies": {
|
|
12
|
-
"@strivacity/sdk-core": "
|
|
59
|
+
"@strivacity/sdk-core": "4.0.0-beta.0"
|
|
13
60
|
},
|
|
14
61
|
"peerDependencies": {
|
|
15
62
|
"react": ">=18"
|
|
16
|
-
}
|
|
17
|
-
"main": "./dist/index.cjs",
|
|
18
|
-
"module": "./dist/index.mjs",
|
|
19
|
-
"types": "./dist/index.d.ts"
|
|
63
|
+
}
|
|
20
64
|
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import type { SDKContext, RedirectFlow, SessionData } from '../../src/types';
|
|
2
|
+
import { describe, test, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
3
|
+
import { initFlow } from '@strivacity/sdk-core';
|
|
4
|
+
import { StyAuthProvider } from '../../src/components';
|
|
5
|
+
import { useStrivacity } from '../../src/hooks';
|
|
6
|
+
import { createMockFlow } from '@strivacity/testing/mocks/sdk';
|
|
7
|
+
import { mount, cleanupMounts, flush, act } from '../utils/common';
|
|
8
|
+
|
|
9
|
+
vi.mock('@strivacity/sdk-core', async (importOriginal) => ({
|
|
10
|
+
...(await importOriginal<typeof import('@strivacity/sdk-core')>()),
|
|
11
|
+
initFlow: vi.fn(),
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
afterEach(() => {
|
|
15
|
+
cleanupMounts();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
function install(flow: RedirectFlow, session: SessionData | null = null) {
|
|
19
|
+
vi.mocked(initFlow).mockReturnValue(flow as never);
|
|
20
|
+
|
|
21
|
+
let context: SDKContext<RedirectFlow> | undefined;
|
|
22
|
+
|
|
23
|
+
function Consumer() {
|
|
24
|
+
context = useStrivacity<RedirectFlow>();
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const options = { mode: 'redirect' as const, issuer: 'https://brandtegrity.io', clientId: 'client-id', redirectUri: 'https://brandtegrity.io/callback' };
|
|
29
|
+
|
|
30
|
+
mount(
|
|
31
|
+
<StyAuthProvider options={options} session={session ?? undefined}>
|
|
32
|
+
<Consumer />
|
|
33
|
+
</StyAuthProvider>,
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
return { context: () => context!, options };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe('StyAuthProvider', () => {
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
vi.mocked(initFlow).mockReset();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('initializes the flow through core sdk initFlow with the given options', async () => {
|
|
45
|
+
const flow = createMockFlow<RedirectFlow>();
|
|
46
|
+
const { options } = install(flow);
|
|
47
|
+
await flush();
|
|
48
|
+
|
|
49
|
+
expect(initFlow).toHaveBeenCalledTimes(1);
|
|
50
|
+
expect(initFlow).toHaveBeenCalledWith(options);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('subscribes to all sdk events on mount and disposes on unmount', async () => {
|
|
54
|
+
const dispose = vi.fn();
|
|
55
|
+
const flow = createMockFlow<RedirectFlow>({ subscribeToAllEvents: vi.fn().mockReturnValue({ dispose }) });
|
|
56
|
+
install(flow);
|
|
57
|
+
await flush();
|
|
58
|
+
|
|
59
|
+
expect(flow.subscribeToAllEvents).toHaveBeenCalledTimes(1);
|
|
60
|
+
expect(flow.subscribeToAllEvents).toHaveBeenCalledWith(expect.any(Function));
|
|
61
|
+
|
|
62
|
+
cleanupMounts();
|
|
63
|
+
|
|
64
|
+
expect(dispose).toHaveBeenCalledTimes(1);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('seeds the flow session when a session prop is given', async () => {
|
|
68
|
+
const flow = createMockFlow<RedirectFlow>();
|
|
69
|
+
const session = { access_token: 'access-token' } as unknown as SessionData;
|
|
70
|
+
|
|
71
|
+
install(flow, session);
|
|
72
|
+
await flush();
|
|
73
|
+
|
|
74
|
+
expect(flow.session).toBe(session);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test.each([
|
|
78
|
+
['init', [], undefined],
|
|
79
|
+
['checkAuthentication', [{ autoRefresh: false }], true],
|
|
80
|
+
['tokenExchange', [{ code: 'abc' }], undefined],
|
|
81
|
+
['handleCallback', ['https://brandtegrity.io/callback?code=abc'], undefined],
|
|
82
|
+
['refresh', [], undefined],
|
|
83
|
+
['revoke', [], undefined],
|
|
84
|
+
['logout', [{ postLogoutRedirectUri: 'https://brandtegrity.io' }], undefined],
|
|
85
|
+
['login', [{ scopes: ['openid'] }], undefined],
|
|
86
|
+
['register', [{ scopes: ['openid'] }], undefined],
|
|
87
|
+
['entry', ['https://brandtegrity.io/entry'], undefined],
|
|
88
|
+
] as const)('%s calls through to the flow instance returned by core sdk', async (method, args, resolvedValue) => {
|
|
89
|
+
const flow = createMockFlow<RedirectFlow>({ [method]: vi.fn().mockReturnValue(resolvedValue) });
|
|
90
|
+
const { context } = install(flow);
|
|
91
|
+
await flush();
|
|
92
|
+
|
|
93
|
+
const result = await (context()[method] as (...a: Array<unknown>) => unknown)(...args);
|
|
94
|
+
|
|
95
|
+
expect(flow[method as keyof RedirectFlow]).toHaveBeenCalledWith(...args);
|
|
96
|
+
expect(result).toEqual(resolvedValue);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test('exposes reactive state seeded from the flow instance after the initial session update settles', async () => {
|
|
100
|
+
const flow = createMockFlow<RedirectFlow>({
|
|
101
|
+
isAuthenticated: Promise.resolve(true),
|
|
102
|
+
language: 'hu-HU',
|
|
103
|
+
idTokenClaims: { sub: 'user-1' },
|
|
104
|
+
accessToken: 'access-token',
|
|
105
|
+
refreshToken: 'refresh-token',
|
|
106
|
+
accessTokenExpired: false,
|
|
107
|
+
accessTokenExpirationDate: 1234,
|
|
108
|
+
});
|
|
109
|
+
const { context } = install(flow);
|
|
110
|
+
|
|
111
|
+
expect(context().loading).toBe(true);
|
|
112
|
+
|
|
113
|
+
await flush();
|
|
114
|
+
|
|
115
|
+
expect(context().loading).toBe(false);
|
|
116
|
+
expect(context().isAuthenticated).toBe(true);
|
|
117
|
+
expect(context().language).toBe('hu-HU');
|
|
118
|
+
expect(context().idTokenClaims).toEqual({ sub: 'user-1' });
|
|
119
|
+
expect(context().accessToken).toBe('access-token');
|
|
120
|
+
expect(context().refreshToken).toBe('refresh-token');
|
|
121
|
+
expect(context().accessTokenExpired).toBe(false);
|
|
122
|
+
expect(context().accessTokenExpirationDate).toBe(1234);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('reactive state updates when the flow emits an event', async () => {
|
|
126
|
+
const subscribeToAllEvents = vi.fn().mockReturnValue({ dispose: vi.fn() });
|
|
127
|
+
const flow = createMockFlow<RedirectFlow>({ subscribeToAllEvents });
|
|
128
|
+
const { context } = install(flow);
|
|
129
|
+
await flush();
|
|
130
|
+
|
|
131
|
+
const onEvent = subscribeToAllEvents.mock.calls[0][0];
|
|
132
|
+
const mutableFlow = flow as unknown as { language: string; accessToken: string | null; isAuthenticated: Promise<boolean> };
|
|
133
|
+
|
|
134
|
+
mutableFlow.language = 'de-DE';
|
|
135
|
+
mutableFlow.accessToken = 'new-token';
|
|
136
|
+
mutableFlow.isAuthenticated = Promise.resolve(true);
|
|
137
|
+
|
|
138
|
+
await act(async () => {
|
|
139
|
+
await onEvent();
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
expect(context().language).toBe('de-DE');
|
|
143
|
+
expect(context().accessToken).toBe('new-token');
|
|
144
|
+
expect(context().isAuthenticated).toBe(true);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { test, expect } from 'vitest';
|
|
2
|
+
import * as reactErrors from '../../src/errors';
|
|
3
|
+
import * as coreErrors from '@strivacity/sdk-core/utils/errors';
|
|
4
|
+
|
|
5
|
+
test('re-exports error classes from the core sdk', () => {
|
|
6
|
+
const coreKeys = Object.keys(coreErrors);
|
|
7
|
+
|
|
8
|
+
expect(coreKeys.length).toBeGreaterThan(0);
|
|
9
|
+
expect(Object.keys(reactErrors).sort()).toEqual(coreKeys.sort());
|
|
10
|
+
});
|