keycloakify 11.3.9-rc.0 → 11.3.9
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/login/lib/getUserProfileApi/getUserProfileApi.d.ts +0 -1
- package/login/lib/getUserProfileApi/getUserProfileApi.js +1 -1
- package/login/lib/getUserProfileApi/getUserProfileApi.js.map +1 -1
- package/package.json +1 -1
- package/src/login/lib/getUserProfileApi/getUserProfileApi.ts +1 -3
- package/stories/account/pages/Account.stories.tsx +102 -0
- package/stories/account/pages/Applications.stories.tsx +148 -0
- package/stories/account/pages/FederatedIdentity.stories.tsx +58 -0
- package/stories/account/pages/Log.stories.tsx +104 -0
- package/stories/account/pages/Password.stories.tsx +76 -0
- package/stories/account/pages/Sessions.stories.tsx +94 -0
- package/stories/account/pages/Totp.stories.tsx +61 -0
- package/stories/login/pages/LoginIdpLinkConfirm.stories.tsx +38 -1
- package/stories/login/pages/LoginIdpLinkEmail.stories.tsx +54 -11
- package/stories/login/pages/LoginOauth2DeviceVerifyUserCode.stories.tsx +44 -0
- package/stories/login/pages/LoginOauthGrant.stories.tsx +69 -1
- package/stories/login/pages/LoginOtp.stories.tsx +110 -0
- package/stories/login/pages/LoginPageExpired.stories.tsx +23 -0
- package/stories/login/pages/LoginPassword.stories.tsx +51 -0
- package/stories/login/pages/LoginRecoveryAuthnCodeConfig.stories.tsx +22 -0
- package/stories/login/pages/LoginResetOtp.stories.tsx +79 -0
- package/stories/login/pages/LoginResetPassword.stories.tsx +30 -0
- package/stories/login/pages/LoginUpdatePassword.stories.tsx +46 -0
- package/stories/login/pages/LoginUpdateProfile.stories.tsx +23 -0
- package/stories/login/pages/LoginVerifyEmail.stories.tsx +75 -0
- package/stories/login/pages/LoginX509Info.stories.tsx +25 -0
- package/stories/login/pages/LogoutConfirm.stories.tsx +29 -0
- package/stories/login/pages/SelectAuthenticator.stories.tsx +21 -0
- package/stories/login/pages/UpdateEmail.stories.tsx +22 -0
- package/stories/login/pages/WebauthnAuthenticate.stories.tsx +141 -0
- package/stories/login/pages/WebauthnError.stories.tsx +69 -0
- package/stories/login/pages/WebauthnRegister.stories.tsx +44 -0
@@ -26,3 +26,79 @@ export const WithMessage: Story = {
|
|
26
26
|
/>
|
27
27
|
)
|
28
28
|
};
|
29
|
+
/**
|
30
|
+
* FirstTimePasswordSetup:
|
31
|
+
* - Purpose: Tests the page when no password is set (e.g., first login).
|
32
|
+
* - Scenario: This renders the form without the current password field.
|
33
|
+
* - Key Aspect: Ensures the page only displays fields for setting a new password.
|
34
|
+
*/
|
35
|
+
export const FirstTimePasswordSetup: Story = {
|
36
|
+
render: () => (
|
37
|
+
<KcPageStory
|
38
|
+
kcContext={{
|
39
|
+
account: {
|
40
|
+
username: "john_doe"
|
41
|
+
},
|
42
|
+
password: {
|
43
|
+
passwordSet: false
|
44
|
+
},
|
45
|
+
url: {
|
46
|
+
passwordUrl: "/password"
|
47
|
+
},
|
48
|
+
stateChecker: "state-checker"
|
49
|
+
}}
|
50
|
+
/>
|
51
|
+
)
|
52
|
+
};
|
53
|
+
|
54
|
+
/**
|
55
|
+
* IncorrectCurrentPassword:
|
56
|
+
* - Purpose: Simulates validation error when the current password is incorrect.
|
57
|
+
* - Scenario: This renders the page with an error message indicating the current password is incorrect.
|
58
|
+
* - Key Aspect: Validates that an error message is correctly displayed for the current password input.
|
59
|
+
*/
|
60
|
+
export const IncorrectCurrentPassword: Story = {
|
61
|
+
render: () => (
|
62
|
+
<KcPageStory
|
63
|
+
kcContext={{
|
64
|
+
message: { type: "error", summary: "Incorrect current password." },
|
65
|
+
account: {
|
66
|
+
username: "john_doe"
|
67
|
+
},
|
68
|
+
password: {
|
69
|
+
passwordSet: true
|
70
|
+
},
|
71
|
+
url: {
|
72
|
+
passwordUrl: "/password"
|
73
|
+
},
|
74
|
+
stateChecker: "state-checker"
|
75
|
+
}}
|
76
|
+
/>
|
77
|
+
)
|
78
|
+
};
|
79
|
+
|
80
|
+
/**
|
81
|
+
* SubmissionSuccessWithRedirect:
|
82
|
+
* - Purpose: Simulates a successful form submission with a redirect or success message.
|
83
|
+
* - Scenario: After successfully changing the password, a success message and redirect behavior are triggered.
|
84
|
+
* - Key Aspect: Verifies the handling of successful submissions.
|
85
|
+
*/
|
86
|
+
export const SubmissionSuccessWithRedirect: Story = {
|
87
|
+
render: () => (
|
88
|
+
<KcPageStory
|
89
|
+
kcContext={{
|
90
|
+
message: { type: "success", summary: "Password successfully changed." },
|
91
|
+
account: {
|
92
|
+
username: "john_doe"
|
93
|
+
},
|
94
|
+
password: {
|
95
|
+
passwordSet: true
|
96
|
+
},
|
97
|
+
url: {
|
98
|
+
passwordUrl: "/password"
|
99
|
+
},
|
100
|
+
stateChecker: "state-checker"
|
101
|
+
}}
|
102
|
+
/>
|
103
|
+
)
|
104
|
+
};
|
@@ -57,3 +57,97 @@ export const WithError: Story = {
|
|
57
57
|
/>
|
58
58
|
)
|
59
59
|
};
|
60
|
+
/**
|
61
|
+
* No active sessions scenario:
|
62
|
+
* - Simulates the scenario where no sessions are active for the user.
|
63
|
+
*/
|
64
|
+
export const NoActiveSessions: Story = {
|
65
|
+
render: () => (
|
66
|
+
<KcPageStory
|
67
|
+
kcContext={{
|
68
|
+
sessions: {
|
69
|
+
sessions: []
|
70
|
+
},
|
71
|
+
stateChecker: "randomStateCheckerValue"
|
72
|
+
}}
|
73
|
+
/>
|
74
|
+
)
|
75
|
+
};
|
76
|
+
|
77
|
+
/**
|
78
|
+
* Single session scenario:
|
79
|
+
* - Displays only one active session with session details.
|
80
|
+
*/
|
81
|
+
export const SingleSession: Story = {
|
82
|
+
render: () => (
|
83
|
+
<KcPageStory
|
84
|
+
kcContext={{
|
85
|
+
sessions: {
|
86
|
+
sessions: [
|
87
|
+
{
|
88
|
+
expires: "2024-04-26T18:14:19Z",
|
89
|
+
clients: ["account"],
|
90
|
+
ipAddress: "172.20.0.1",
|
91
|
+
started: "2024-04-26T08:14:19Z",
|
92
|
+
lastAccess: "2024-04-26T08:30:54Z",
|
93
|
+
id: "single-session-id"
|
94
|
+
}
|
95
|
+
]
|
96
|
+
},
|
97
|
+
stateChecker: "anotherStateChecker"
|
98
|
+
}}
|
99
|
+
/>
|
100
|
+
)
|
101
|
+
};
|
102
|
+
|
103
|
+
/**
|
104
|
+
* Multiple clients per session scenario:
|
105
|
+
* - Displays sessions where each session has multiple associated clients.
|
106
|
+
*/
|
107
|
+
export const MultipleClientsSession: Story = {
|
108
|
+
render: () => (
|
109
|
+
<KcPageStory
|
110
|
+
kcContext={{
|
111
|
+
sessions: {
|
112
|
+
sessions: [
|
113
|
+
{
|
114
|
+
expires: "2024-04-26T18:14:19Z",
|
115
|
+
clients: ["account", "admin-console", "another-client"],
|
116
|
+
ipAddress: "172.20.0.1",
|
117
|
+
started: "2024-04-26T08:14:19Z",
|
118
|
+
lastAccess: "2024-04-26T08:30:54Z",
|
119
|
+
id: "multiple-clients-session"
|
120
|
+
}
|
121
|
+
]
|
122
|
+
},
|
123
|
+
stateChecker: "multiClientsStateChecker"
|
124
|
+
}}
|
125
|
+
/>
|
126
|
+
)
|
127
|
+
};
|
128
|
+
|
129
|
+
/**
|
130
|
+
* Session without client details scenario:
|
131
|
+
* - Simulates a session where no client information is provided.
|
132
|
+
*/
|
133
|
+
export const SessionWithoutClients: Story = {
|
134
|
+
render: () => (
|
135
|
+
<KcPageStory
|
136
|
+
kcContext={{
|
137
|
+
sessions: {
|
138
|
+
sessions: [
|
139
|
+
{
|
140
|
+
expires: "2024-04-26T18:14:19Z",
|
141
|
+
clients: [], // No clients information
|
142
|
+
ipAddress: "172.20.0.1",
|
143
|
+
started: "2024-04-26T08:14:19Z",
|
144
|
+
lastAccess: "2024-04-26T08:30:54Z",
|
145
|
+
id: "no-clients-session"
|
146
|
+
}
|
147
|
+
]
|
148
|
+
},
|
149
|
+
stateChecker: "noClientsStateChecker"
|
150
|
+
}}
|
151
|
+
/>
|
152
|
+
)
|
153
|
+
};
|
@@ -180,3 +180,64 @@ export const MoreThanOneTotpProviders: Story = {
|
|
180
180
|
/>
|
181
181
|
)
|
182
182
|
};
|
183
|
+
|
184
|
+
// TOTP Enabled but No Existing OTP Credentials
|
185
|
+
export const TotpEnabledNoOtpCredentials: Story = {
|
186
|
+
render: () => (
|
187
|
+
<KcPageStory
|
188
|
+
kcContext={{
|
189
|
+
totp: {
|
190
|
+
enabled: true,
|
191
|
+
totpSecretEncoded: "HE4W MSTC OBKU CY2M",
|
192
|
+
otpCredentials: [] // No OTP Credentials
|
193
|
+
},
|
194
|
+
stateChecker: "stateChecker123",
|
195
|
+
url: {
|
196
|
+
totpUrl: "http://localhost:8080/realms/myrealm/account/totp"
|
197
|
+
}
|
198
|
+
}}
|
199
|
+
/>
|
200
|
+
)
|
201
|
+
};
|
202
|
+
|
203
|
+
// Manual Mode TOTP without Scanning
|
204
|
+
export const ManualModeTotp: Story = {
|
205
|
+
render: () => (
|
206
|
+
<KcPageStory
|
207
|
+
kcContext={{
|
208
|
+
mode: "manual", // Manual mode
|
209
|
+
totp: {
|
210
|
+
enabled: false,
|
211
|
+
totpSecretEncoded: "HE4W MSTC OBKU CY2M",
|
212
|
+
otpCredentials: []
|
213
|
+
},
|
214
|
+
stateChecker: "stateChecker123",
|
215
|
+
url: {
|
216
|
+
totpUrl: "http://localhost:8080/realms/myrealm/account/totp"
|
217
|
+
}
|
218
|
+
}}
|
219
|
+
/>
|
220
|
+
)
|
221
|
+
};
|
222
|
+
|
223
|
+
// Multiple OTP Devices Scenario
|
224
|
+
export const MultipleOtpDevices: Story = {
|
225
|
+
render: () => (
|
226
|
+
<KcPageStory
|
227
|
+
kcContext={{
|
228
|
+
totp: {
|
229
|
+
enabled: true,
|
230
|
+
totpSecretEncoded: "G55E MZKC JFUD",
|
231
|
+
otpCredentials: [
|
232
|
+
{ id: "1", userLabel: "Phone 1" },
|
233
|
+
{ id: "2", userLabel: "Tablet" }
|
234
|
+
]
|
235
|
+
},
|
236
|
+
stateChecker: "stateChecker123",
|
237
|
+
url: {
|
238
|
+
totpUrl: "http://localhost:8080/realms/myrealm/account/totp"
|
239
|
+
}
|
240
|
+
}}
|
241
|
+
/>
|
242
|
+
)
|
243
|
+
};
|
@@ -2,6 +2,14 @@ import React from "react";
|
|
2
2
|
import type { Meta, StoryObj } from "@storybook/react";
|
3
3
|
import { createKcPageStory } from "../KcPageStory";
|
4
4
|
|
5
|
+
// Mock kcContext to avoid the TS2304 error
|
6
|
+
const mockKcContext = {
|
7
|
+
url: {
|
8
|
+
loginAction: "/login-action"
|
9
|
+
},
|
10
|
+
idpAlias: "mockIdpAlias"
|
11
|
+
};
|
12
|
+
|
5
13
|
const { KcPageStory } = createKcPageStory({ pageId: "login-idp-link-confirm.ftl" });
|
6
14
|
|
7
15
|
const meta = {
|
@@ -13,6 +21,35 @@ export default meta;
|
|
13
21
|
|
14
22
|
type Story = StoryObj<typeof meta>;
|
15
23
|
|
24
|
+
/**
|
25
|
+
* Default:
|
26
|
+
* - Purpose: Tests standard behavior with mock data.
|
27
|
+
* - Scenario: The component renders with a mocked identity provider alias (`mockIdpAlias`) and a login action URL (`/login-action`).
|
28
|
+
* - Key Aspect: Ensures the default behavior of the component with standard values for kcContext.
|
29
|
+
*/
|
16
30
|
export const Default: Story = {
|
17
|
-
render: () => <KcPageStory />
|
31
|
+
render: () => <KcPageStory kcContext={mockKcContext} />
|
32
|
+
};
|
33
|
+
|
34
|
+
/**
|
35
|
+
* WithFormSubmissionError:
|
36
|
+
* - Purpose: Tests how the component handles form submission errors.
|
37
|
+
* - Scenario: Simulates a form submission error by setting the login action URL to `/error` and displays an error message.
|
38
|
+
* - Key Aspect: Verifies that the component can display error messages during form submission failure, ensuring proper error handling.
|
39
|
+
*/
|
40
|
+
export const WithFormSubmissionError: Story = {
|
41
|
+
render: () => (
|
42
|
+
<KcPageStory
|
43
|
+
kcContext={{
|
44
|
+
...mockKcContext,
|
45
|
+
url: {
|
46
|
+
loginAction: "/error"
|
47
|
+
},
|
48
|
+
message: {
|
49
|
+
type: "error",
|
50
|
+
summary: "An error occurred during form submission."
|
51
|
+
}
|
52
|
+
}}
|
53
|
+
/>
|
54
|
+
)
|
18
55
|
};
|
@@ -2,6 +2,20 @@ import React from "react";
|
|
2
2
|
import type { Meta, StoryObj } from "@storybook/react";
|
3
3
|
import { createKcPageStory } from "../KcPageStory";
|
4
4
|
|
5
|
+
// Mock kcContext to avoid TS2304 error and to simulate the real environment
|
6
|
+
const mockKcContext = {
|
7
|
+
url: {
|
8
|
+
loginAction: "/login-action"
|
9
|
+
},
|
10
|
+
idpAlias: "mockIdpAlias",
|
11
|
+
brokerContext: {
|
12
|
+
username: "mockUser"
|
13
|
+
},
|
14
|
+
realm: {
|
15
|
+
displayName: "MockRealm"
|
16
|
+
}
|
17
|
+
};
|
18
|
+
|
5
19
|
const { KcPageStory } = createKcPageStory({ pageId: "login-idp-link-email.ftl" });
|
6
20
|
|
7
21
|
const meta = {
|
@@ -13,13 +27,27 @@ export default meta;
|
|
13
27
|
|
14
28
|
type Story = StoryObj<typeof meta>;
|
15
29
|
|
30
|
+
/**
|
31
|
+
* Default:
|
32
|
+
* - Purpose: Tests the default behavior with mock data.
|
33
|
+
* - Scenario: The component renders with a mocked identity provider alias (`mockIdpAlias`), a default broker username (`mockUser`), and a default realm name (`MockRealm`).
|
34
|
+
* - Key Aspect: Ensures the default behavior of the component with typical kcContext values.
|
35
|
+
*/
|
16
36
|
export const Default: Story = {
|
17
|
-
render: () => <KcPageStory />
|
37
|
+
render: () => <KcPageStory kcContext={mockKcContext} />
|
18
38
|
};
|
39
|
+
|
40
|
+
/**
|
41
|
+
* WithIdpAlias:
|
42
|
+
* - Purpose: Tests behavior when the idpAlias is set to "Google".
|
43
|
+
* - Scenario: Simulates the component being used with a Google identity provider, showing the username "john.doe" and realm "MyRealm".
|
44
|
+
* - Key Aspect: Ensures the correct identity provider alias ("Google") and broker context (user info) are displayed in the email linking instructions.
|
45
|
+
*/
|
19
46
|
export const WithIdpAlias: Story = {
|
20
47
|
render: () => (
|
21
48
|
<KcPageStory
|
22
49
|
kcContext={{
|
50
|
+
...mockKcContext,
|
23
51
|
idpAlias: "Google",
|
24
52
|
brokerContext: {
|
25
53
|
username: "john.doe"
|
@@ -31,32 +59,47 @@ export const WithIdpAlias: Story = {
|
|
31
59
|
/>
|
32
60
|
)
|
33
61
|
};
|
34
|
-
|
62
|
+
|
63
|
+
/**
|
64
|
+
* WithCustomRealmDisplayName:
|
65
|
+
* - Purpose: Tests behavior when the realm display name is customized.
|
66
|
+
* - Scenario: Simulates the component with a Facebook identity provider, a broker username "jane.doe", and a custom realm name "CustomRealm".
|
67
|
+
* - Key Aspect: Ensures that custom realm display names are rendered correctly alongside the idpAlias and broker context.
|
68
|
+
*/
|
69
|
+
export const WithCustomRealmDisplayName: Story = {
|
35
70
|
render: () => (
|
36
71
|
<KcPageStory
|
37
72
|
kcContext={{
|
38
|
-
|
73
|
+
...mockKcContext,
|
74
|
+
idpAlias: "Facebook",
|
39
75
|
brokerContext: {
|
40
|
-
username: "
|
76
|
+
username: "jane.doe"
|
41
77
|
},
|
42
78
|
realm: {
|
43
|
-
displayName: "
|
79
|
+
displayName: "CUSTOM REALM DISPLAY NAME"
|
44
80
|
}
|
45
81
|
}}
|
46
82
|
/>
|
47
83
|
)
|
48
84
|
};
|
49
85
|
|
50
|
-
|
86
|
+
/**
|
87
|
+
* WithFormSubmissionError:
|
88
|
+
* - Purpose: Tests how the component handles form submission errors.
|
89
|
+
* - Scenario: Simulates a form submission error by setting the login action URL to `/error` and displays an error message.
|
90
|
+
* - Key Aspect: Verifies that the component can display error messages during form submission failure, ensuring proper error handling.
|
91
|
+
*/
|
92
|
+
export const WithFormSubmissionError: Story = {
|
51
93
|
render: () => (
|
52
94
|
<KcPageStory
|
53
95
|
kcContext={{
|
54
|
-
|
55
|
-
|
56
|
-
|
96
|
+
...mockKcContext,
|
97
|
+
url: {
|
98
|
+
loginAction: "/error"
|
57
99
|
},
|
58
|
-
|
59
|
-
|
100
|
+
message: {
|
101
|
+
type: "error",
|
102
|
+
summary: "An error occurred during form submission."
|
60
103
|
}
|
61
104
|
}}
|
62
105
|
/>
|
@@ -16,3 +16,47 @@ type Story = StoryObj<typeof meta>;
|
|
16
16
|
export const Default: Story = {
|
17
17
|
render: () => <KcPageStory />
|
18
18
|
};
|
19
|
+
|
20
|
+
/**
|
21
|
+
* WithErrorMessage:
|
22
|
+
* - Purpose: Tests when there is an error with the OAuth2 device user code entry.
|
23
|
+
* - Scenario: The component renders with an error message displayed to the user.
|
24
|
+
* - Key Aspect: Ensures the error message is properly shown when the user enters an invalid code.
|
25
|
+
*/
|
26
|
+
export const WithErrorMessage: Story = {
|
27
|
+
render: () => (
|
28
|
+
<KcPageStory
|
29
|
+
kcContext={{
|
30
|
+
url: {
|
31
|
+
oauth2DeviceVerificationAction: "/mock-oauth2-device-verification"
|
32
|
+
},
|
33
|
+
message: {
|
34
|
+
summary: "The user code you entered is invalid. Please try again.",
|
35
|
+
type: "error"
|
36
|
+
}
|
37
|
+
}}
|
38
|
+
/>
|
39
|
+
)
|
40
|
+
};
|
41
|
+
|
42
|
+
/**
|
43
|
+
* WithEmptyInputField:
|
44
|
+
* - Purpose: Tests when the user code field is left empty.
|
45
|
+
* - Scenario: The component renders the form, and the user tries to submit without entering any code.
|
46
|
+
* - Key Aspect: Ensures the form displays validation errors when the field is left empty.
|
47
|
+
*/
|
48
|
+
export const WithEmptyInputField: Story = {
|
49
|
+
render: () => (
|
50
|
+
<KcPageStory
|
51
|
+
kcContext={{
|
52
|
+
url: {
|
53
|
+
oauth2DeviceVerificationAction: "/mock-oauth2-device-verification"
|
54
|
+
},
|
55
|
+
message: {
|
56
|
+
summary: "User code cannot be empty. Please enter a valid code.",
|
57
|
+
type: "error"
|
58
|
+
}
|
59
|
+
}}
|
60
|
+
/>
|
61
|
+
)
|
62
|
+
};
|
@@ -2,6 +2,25 @@ import React from "react";
|
|
2
2
|
import type { Meta, StoryObj } from "@storybook/react";
|
3
3
|
import { createKcPageStory } from "../KcPageStory";
|
4
4
|
|
5
|
+
// Mock kcContext to simulate real environment
|
6
|
+
const mockKcContext = {
|
7
|
+
url: {
|
8
|
+
oauthAction: "/oauth-action"
|
9
|
+
},
|
10
|
+
oauth: {
|
11
|
+
clientScopesRequested: [{ consentScreenText: "Scope1", dynamicScopeParameter: "dynamicScope1" }, { consentScreenText: "Scope2" }],
|
12
|
+
code: "mockCode"
|
13
|
+
},
|
14
|
+
client: {
|
15
|
+
attributes: {
|
16
|
+
policyUri: "https://twitter.com/en/tos",
|
17
|
+
tosUri: "https://twitter.com/en/privacy"
|
18
|
+
},
|
19
|
+
name: "Twitter",
|
20
|
+
clientId: "twitter-client-id"
|
21
|
+
}
|
22
|
+
};
|
23
|
+
|
5
24
|
const { KcPageStory } = createKcPageStory({ pageId: "login-oauth-grant.ftl" });
|
6
25
|
|
7
26
|
const meta = {
|
@@ -13,6 +32,55 @@ export default meta;
|
|
13
32
|
|
14
33
|
type Story = StoryObj<typeof meta>;
|
15
34
|
|
35
|
+
/**
|
36
|
+
* Default:
|
37
|
+
* - Purpose: Tests the default behavior with meaningful logo (Twitter).
|
38
|
+
* - Scenario: The component renders with Twitter as the client, displaying its logo, policy, and terms of service links.
|
39
|
+
* - Key Aspect: Ensures the component works with a realistic `logoUri` and client name.
|
40
|
+
*/
|
16
41
|
export const Default: Story = {
|
17
|
-
render: () => <KcPageStory />
|
42
|
+
render: () => <KcPageStory kcContext={mockKcContext} />
|
43
|
+
};
|
44
|
+
|
45
|
+
/**
|
46
|
+
* WithoutScopes:
|
47
|
+
* - Purpose: Tests the component when no OAuth scopes are requested.
|
48
|
+
* - Scenario: The component renders with no scopes listed under the consent screen.
|
49
|
+
* - Key Aspect: Ensures the component renders correctly when there are no requested scopes.
|
50
|
+
*/
|
51
|
+
export const WithoutScopes: Story = {
|
52
|
+
render: () => (
|
53
|
+
<KcPageStory
|
54
|
+
kcContext={{
|
55
|
+
...mockKcContext,
|
56
|
+
oauth: {
|
57
|
+
...mockKcContext.oauth,
|
58
|
+
clientScopesRequested: []
|
59
|
+
}
|
60
|
+
}}
|
61
|
+
/>
|
62
|
+
)
|
63
|
+
};
|
64
|
+
|
65
|
+
/**
|
66
|
+
* WithFormSubmissionError:
|
67
|
+
* - Purpose: Tests how the component handles form submission errors.
|
68
|
+
* - Scenario: The `oauthAction` URL is set to an error route and an error message is displayed.
|
69
|
+
* - Key Aspect: Ensures that the component can display error messages when form submission fails.
|
70
|
+
*/
|
71
|
+
export const WithFormSubmissionError: Story = {
|
72
|
+
render: () => (
|
73
|
+
<KcPageStory
|
74
|
+
kcContext={{
|
75
|
+
...mockKcContext,
|
76
|
+
url: {
|
77
|
+
oauthAction: "/error"
|
78
|
+
},
|
79
|
+
message: {
|
80
|
+
type: "error",
|
81
|
+
summary: "An error occurred during form submission."
|
82
|
+
}
|
83
|
+
}}
|
84
|
+
/>
|
85
|
+
)
|
18
86
|
};
|
@@ -16,3 +16,113 @@ type Story = StoryObj<typeof meta>;
|
|
16
16
|
export const Default: Story = {
|
17
17
|
render: () => <KcPageStory />
|
18
18
|
};
|
19
|
+
|
20
|
+
/**
|
21
|
+
* MultipleOtpCredentials:
|
22
|
+
* - Purpose: Tests the behavior when the user has multiple OTP credentials to choose from.
|
23
|
+
* - Scenario: Simulates the scenario where the user is presented with multiple OTP credentials and must select one to proceed.
|
24
|
+
* - Key Aspect: Ensures that multiple OTP credentials are listed and selectable, and the correct credential is selected by default.
|
25
|
+
*/
|
26
|
+
export const MultipleOtpCredentials: Story = {
|
27
|
+
render: () => (
|
28
|
+
<KcPageStory
|
29
|
+
kcContext={{
|
30
|
+
otpLogin: {
|
31
|
+
userOtpCredentials: [
|
32
|
+
{ id: "credential1", userLabel: "Device 1" },
|
33
|
+
{ id: "credential2", userLabel: "Device 2" },
|
34
|
+
{ id: "credential2", userLabel: "Device 3" },
|
35
|
+
{ id: "credential2", userLabel: "Device 4" },
|
36
|
+
{ id: "credential2", userLabel: "Device 5" },
|
37
|
+
{ id: "credential2", userLabel: "Device 6" }
|
38
|
+
],
|
39
|
+
selectedCredentialId: "credential1"
|
40
|
+
},
|
41
|
+
url: {
|
42
|
+
loginAction: "/login-action"
|
43
|
+
},
|
44
|
+
messagesPerField: {
|
45
|
+
existsError: () => false
|
46
|
+
}
|
47
|
+
}}
|
48
|
+
/>
|
49
|
+
)
|
50
|
+
};
|
51
|
+
|
52
|
+
/**
|
53
|
+
* WithOtpError:
|
54
|
+
* - Purpose: Tests the behavior when an error occurs with the OTP field (e.g., invalid OTP code).
|
55
|
+
* - Scenario: Simulates an invalid OTP code scenario where an error message is displayed.
|
56
|
+
* - Key Aspect: Ensures that the OTP input displays error messages correctly and the error is visible.
|
57
|
+
*/
|
58
|
+
export const WithOtpError: Story = {
|
59
|
+
render: () => (
|
60
|
+
<KcPageStory
|
61
|
+
kcContext={{
|
62
|
+
otpLogin: {
|
63
|
+
userOtpCredentials: []
|
64
|
+
},
|
65
|
+
url: {
|
66
|
+
loginAction: "/login-action"
|
67
|
+
},
|
68
|
+
messagesPerField: {
|
69
|
+
existsError: (field: string) => field === "totp",
|
70
|
+
get: () => "Invalid OTP code"
|
71
|
+
}
|
72
|
+
}}
|
73
|
+
/>
|
74
|
+
)
|
75
|
+
};
|
76
|
+
|
77
|
+
/**
|
78
|
+
* NoOtpCredentials:
|
79
|
+
* - Purpose: Tests the behavior when no OTP credentials are provided for the user.
|
80
|
+
* - Scenario: Simulates the scenario where the user is not presented with any OTP credentials, and only the OTP input is displayed.
|
81
|
+
* - Key Aspect: Ensures that the component handles cases where there are no user OTP credentials, and the user is only prompted for the OTP code.
|
82
|
+
*/
|
83
|
+
export const NoOtpCredentials: Story = {
|
84
|
+
render: () => (
|
85
|
+
<KcPageStory
|
86
|
+
kcContext={{
|
87
|
+
otpLogin: {
|
88
|
+
userOtpCredentials: []
|
89
|
+
},
|
90
|
+
url: {
|
91
|
+
loginAction: "/login-action"
|
92
|
+
},
|
93
|
+
messagesPerField: {
|
94
|
+
existsError: () => false
|
95
|
+
}
|
96
|
+
}}
|
97
|
+
/>
|
98
|
+
)
|
99
|
+
};
|
100
|
+
|
101
|
+
/**
|
102
|
+
* WithErrorAndMultipleOtpCredentials:
|
103
|
+
* - Purpose: Tests behavior when there is both an error in the OTP field and multiple OTP credentials.
|
104
|
+
* - Scenario: Simulates the case where the user has multiple OTP credentials and encounters an error with the OTP input.
|
105
|
+
* - Key Aspect: Ensures that the component can handle both multiple OTP credentials and display an error message simultaneously.
|
106
|
+
*/
|
107
|
+
export const WithErrorAndMultipleOtpCredentials: Story = {
|
108
|
+
render: () => (
|
109
|
+
<KcPageStory
|
110
|
+
kcContext={{
|
111
|
+
otpLogin: {
|
112
|
+
userOtpCredentials: [
|
113
|
+
{ id: "credential1", userLabel: "Device 1" },
|
114
|
+
{ id: "credential2", userLabel: "Device 2" }
|
115
|
+
],
|
116
|
+
selectedCredentialId: "credential1"
|
117
|
+
},
|
118
|
+
url: {
|
119
|
+
loginAction: "/login-action"
|
120
|
+
},
|
121
|
+
messagesPerField: {
|
122
|
+
existsError: (field: string) => field === "totp",
|
123
|
+
get: () => "Invalid OTP code"
|
124
|
+
}
|
125
|
+
}}
|
126
|
+
/>
|
127
|
+
)
|
128
|
+
};
|
@@ -16,3 +16,26 @@ type Story = StoryObj<typeof meta>;
|
|
16
16
|
export const Default: Story = {
|
17
17
|
render: () => <KcPageStory />
|
18
18
|
};
|
19
|
+
|
20
|
+
/**
|
21
|
+
* WithErrorMessage:
|
22
|
+
* - Purpose: Tests behavior when an error message is displayed along with the page expiration message.
|
23
|
+
* - Scenario: Simulates a case where the session expired due to an error, and an error message is displayed alongside the expiration message.
|
24
|
+
* - Key Aspect: Ensures that error messages are displayed correctly in addition to the page expiration notice.
|
25
|
+
*/
|
26
|
+
export const WithErrorMessage: Story = {
|
27
|
+
render: () => (
|
28
|
+
<KcPageStory
|
29
|
+
kcContext={{
|
30
|
+
url: {
|
31
|
+
loginRestartFlowUrl: "/mock-restart-flow",
|
32
|
+
loginAction: "/mock-continue-login"
|
33
|
+
},
|
34
|
+
message: {
|
35
|
+
type: "error",
|
36
|
+
summary: "An error occurred while processing your session."
|
37
|
+
}
|
38
|
+
}}
|
39
|
+
/>
|
40
|
+
)
|
41
|
+
};
|