account page test coverage improved

This commit is contained in:
Nima Shkouhfar 2024-10-19 19:10:32 -04:00
parent 0cf8caa53b
commit 3ff01d186d
7 changed files with 643 additions and 0 deletions

View File

@ -16,3 +16,105 @@ type Story = StoryObj<typeof meta>;
export const Default: Story = { export const Default: Story = {
render: () => <KcPageStory /> render: () => <KcPageStory />
}; };
/**
* UsernameNotEditable:
* - Purpose: Test the scenario where the username field is not editable.
* - Scenario: The component renders, but the username field is disabled.
* - Key Aspect: Ensures that the `editUsernameAllowed` condition is respected and the username field is read-only.
*/
export const UsernameNotEditable: Story = {
render: () => (
<KcPageStory
kcContext={{
account: {
username: "john_doe",
email: "john.doe@gmail.com",
firstName: "John",
lastName: "Doe"
},
realm: {
registrationEmailAsUsername: false,
editUsernameAllowed: false
},
referrer: {
url: "/home"
},
url: {
accountUrl: "/account"
},
messagesPerField: {
printIfExists: () => ""
},
stateChecker: "state-checker"
}}
/>
)
};
/**
* WithValidationErrors:
* - Purpose: Test the form when there are validation errors.
* - Scenario: The component renders with error messages for invalid input in the fields.
* - Key Aspect: Ensures that error messages are properly displayed and the user can correct their inputs.
*/
export const WithValidationErrors: Story = {
render: () => (
<KcPageStory
kcContext={{
account: {
username: "john_doe",
email: "",
firstName: "",
lastName: "Doe"
},
realm: {
registrationEmailAsUsername: false,
editUsernameAllowed: true
},
referrer: {
url: "/home"
},
url: {
accountUrl: "/account"
},
messagesPerField: {
printIfExists: field => (field === "email" || field === "firstName" ? "has-error" : "")
},
stateChecker: "state-checker"
}}
/>
)
};
/**
* EmailAsUsername:
* - Purpose: Test the form where email is used as the username.
* - Scenario: The component renders without a separate username field, and the email field is treated as the username.
* - Key Aspect: Ensures the form functions correctly when `registrationEmailAsUsername` is enabled.
*/
export const EmailAsUsername: Story = {
render: () => (
<KcPageStory
kcContext={{
account: {
email: "john.doe@gmail.com",
firstName: "John",
lastName: "Doe"
},
realm: {
registrationEmailAsUsername: true
},
referrer: {
url: "/home"
},
url: {
accountUrl: "/account"
},
messagesPerField: {
printIfExists: () => ""
},
stateChecker: "state-checker"
}}
/>
)
};

View File

@ -78,3 +78,151 @@ export const Default: Story = {
/> />
) )
}; };
// No Available Roles or Grants Scenario
export const NoAvailableRolesOrGrants: Story = {
render: () => (
<KcPageStory
kcContext={{
pageId: "applications.ftl",
applications: {
applications: [
{
realmRolesAvailable: [],
resourceRolesAvailable: {},
additionalGrants: [],
clientScopesGranted: [],
effectiveUrl: "#",
client: {
clientId: "application1",
name: "Application 1",
consentRequired: true
}
}
]
}
}}
/>
)
};
// Consent Not Required Scenario
export const ConsentNotRequired: Story = {
render: () => (
<KcPageStory
kcContext={{
pageId: "applications.ftl",
applications: {
applications: [
{
realmRolesAvailable: [],
resourceRolesAvailable: {},
additionalGrants: [],
clientScopesGranted: [],
effectiveUrl: "#",
client: {
clientId: "application1",
name: "Application 1",
consentRequired: false // No consent required
}
}
]
}
}}
/>
)
};
// No Roles Available but Consent Required Scenario
export const NoRolesButConsentRequired: Story = {
render: () => (
<KcPageStory
kcContext={{
pageId: "applications.ftl",
applications: {
applications: [
{
realmRolesAvailable: [],
resourceRolesAvailable: {},
additionalGrants: [],
clientScopesGranted: ["scope1", "scope2"], // Consent required but no roles
effectiveUrl: "#",
client: {
clientId: "application1",
name: "Application 1",
consentRequired: true
}
}
]
}
}}
/>
)
};
// Only Resource Roles Available Scenario
export const OnlyResourceRolesAvailable: Story = {
render: () => (
<KcPageStory
kcContext={{
pageId: "applications.ftl",
applications: {
applications: [
{
realmRolesAvailable: [], // No realm roles
resourceRolesAvailable: {
resource1: [
{
roleName: "Resource Role Name 1",
roleDescription: "Resource role 1 description",
clientName: "Client Name 1",
clientId: "client1"
}
]
},
additionalGrants: [],
clientScopesGranted: [],
effectiveUrl: "#",
client: {
clientId: "application1",
name: "Application 1",
consentRequired: true
}
}
]
}
}}
/>
)
};
// No Additional Grants Scenario
export const NoAdditionalGrants: Story = {
render: () => (
<KcPageStory
kcContext={{
pageId: "applications.ftl",
applications: {
applications: [
{
realmRolesAvailable: [
{
name: "Realm Role Name 1"
}
],
resourceRolesAvailable: {},
additionalGrants: [], // No additional grants
clientScopesGranted: [],
effectiveUrl: "#",
client: {
clientId: "application1",
name: "Application 1",
consentRequired: true
}
}
]
}
}}
/>
)
};

View File

@ -36,3 +36,61 @@ export const NotConnected: Story = {
/> />
) )
}; };
/**
* RemoveLinkNotPossible:
* - Federated identities are connected, but the user cannot remove them due to restrictions.
*/
export const RemoveLinkNotPossible: Story = {
render: () => (
<KcPageStory
kcContext={{
pageId: "federatedIdentity.ftl",
federatedIdentity: {
identities: [
{
providerId: "google",
displayName: "Google",
userName: "john.doe@gmail.com",
connected: true
}
],
removeLinkPossible: false
},
stateChecker: "1234",
url: {
socialUrl: "/social"
}
}}
/>
)
};
/**
* AddLinkForUnconnectedIdentity:
* - The user has an identity that is not connected and can add it.
*/
export const AddLinkForUnconnectedIdentity: Story = {
render: () => (
<KcPageStory
kcContext={{
pageId: "federatedIdentity.ftl",
federatedIdentity: {
identities: [
{
providerId: "github",
displayName: "GitHub",
userName: "",
connected: false
}
],
removeLinkPossible: true
},
stateChecker: "1234",
url: {
socialUrl: "/social"
}
}}
/>
)
};

View File

@ -355,3 +355,107 @@ export const Default: Story = {
/> />
) )
}; };
export const LogsMissingDetails: Story = {
render: () => (
<KcPageStory
kcContext={{
pageId: "log.ftl",
log: {
events: [
{
date: "2024-04-26T12:29:08Z",
ipAddress: "127.0.0.1",
client: "",
details: [],
event: "login"
}
]
}
}}
/>
)
};
export const SingleLogEntry: Story = {
render: () => (
<KcPageStory
kcContext={{
pageId: "log.ftl",
log: {
events: [
{
date: "2024-04-26T12:29:08Z",
ipAddress: "127.0.0.1",
client: "keycloakify-frontend",
details: [
{ key: "auth_method", value: "openid-connect" },
{ key: "username", value: "john.doe" }
],
event: "login"
}
]
}
}}
/>
)
};
export const LogsWithLongDetails: Story = {
render: () => (
<KcPageStory
kcContext={{
pageId: "log.ftl",
log: {
events: [
{
date: "2024-04-26T12:29:08Z",
ipAddress: "127.0.0.1",
client: "keycloakify-frontend",
details: [
{ key: "auth_method", value: "openid-connect" },
{ key: "username", value: "john.doe" },
{ key: "session_duration", value: "2 hours 30 minutes 45 seconds" },
{ key: "location", value: "Windsor, Ontario, Canada" },
{ key: "user_agent", value: "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" }
],
event: "login"
}
]
}
}}
/>
)
};
export const EmptyClientField: Story = {
render: () => (
<KcPageStory
kcContext={{
pageId: "log.ftl",
log: {
events: [
{
date: "2024-04-26T12:29:08Z",
ipAddress: "127.0.0.1",
client: "", // Empty client field
details: [
{ key: "auth_method", value: "openid-connect" },
{ key: "username", value: "john.doe" }
],
event: "login"
}
]
}
}}
/>
)
};
export const NoLogsAvailable: Story = {
render: () => (
<KcPageStory
kcContext={{
pageId: "log.ftl",
log: {
events: [] // No log events
}
}}
/>
)
};

View File

@ -26,3 +26,79 @@ export const WithMessage: Story = {
/> />
) )
}; };
/**
* FirstTimePasswordSetup:
* - Purpose: Tests the page when no password is set (e.g., first login).
* - Scenario: This renders the form without the current password field.
* - Key Aspect: Ensures the page only displays fields for setting a new password.
*/
export const FirstTimePasswordSetup: Story = {
render: () => (
<KcPageStory
kcContext={{
account: {
username: "john_doe"
},
password: {
passwordSet: false
},
url: {
passwordUrl: "/password"
},
stateChecker: "state-checker"
}}
/>
)
};
/**
* IncorrectCurrentPassword:
* - Purpose: Simulates validation error when the current password is incorrect.
* - Scenario: This renders the page with an error message indicating the current password is incorrect.
* - Key Aspect: Validates that an error message is correctly displayed for the current password input.
*/
export const IncorrectCurrentPassword: Story = {
render: () => (
<KcPageStory
kcContext={{
message: { type: "error", summary: "Incorrect current password." },
account: {
username: "john_doe"
},
password: {
passwordSet: true
},
url: {
passwordUrl: "/password"
},
stateChecker: "state-checker"
}}
/>
)
};
/**
* SubmissionSuccessWithRedirect:
* - Purpose: Simulates a successful form submission with a redirect or success message.
* - Scenario: After successfully changing the password, a success message and redirect behavior are triggered.
* - Key Aspect: Verifies the handling of successful submissions.
*/
export const SubmissionSuccessWithRedirect: Story = {
render: () => (
<KcPageStory
kcContext={{
message: { type: "success", summary: "Password successfully changed." },
account: {
username: "john_doe"
},
password: {
passwordSet: true
},
url: {
passwordUrl: "/password"
},
stateChecker: "state-checker"
}}
/>
)
};

View File

@ -57,3 +57,97 @@ export const WithError: Story = {
/> />
) )
}; };
/**
* No active sessions scenario:
* - Simulates the scenario where no sessions are active for the user.
*/
export const NoActiveSessions: Story = {
render: () => (
<KcPageStory
kcContext={{
sessions: {
sessions: []
},
stateChecker: "randomStateCheckerValue"
}}
/>
)
};
/**
* Single session scenario:
* - Displays only one active session with session details.
*/
export const SingleSession: Story = {
render: () => (
<KcPageStory
kcContext={{
sessions: {
sessions: [
{
expires: "2024-04-26T18:14:19Z",
clients: ["account"],
ipAddress: "172.20.0.1",
started: "2024-04-26T08:14:19Z",
lastAccess: "2024-04-26T08:30:54Z",
id: "single-session-id"
}
]
},
stateChecker: "anotherStateChecker"
}}
/>
)
};
/**
* Multiple clients per session scenario:
* - Displays sessions where each session has multiple associated clients.
*/
export const MultipleClientsSession: Story = {
render: () => (
<KcPageStory
kcContext={{
sessions: {
sessions: [
{
expires: "2024-04-26T18:14:19Z",
clients: ["account", "admin-console", "another-client"],
ipAddress: "172.20.0.1",
started: "2024-04-26T08:14:19Z",
lastAccess: "2024-04-26T08:30:54Z",
id: "multiple-clients-session"
}
]
},
stateChecker: "multiClientsStateChecker"
}}
/>
)
};
/**
* Session without client details scenario:
* - Simulates a session where no client information is provided.
*/
export const SessionWithoutClients: Story = {
render: () => (
<KcPageStory
kcContext={{
sessions: {
sessions: [
{
expires: "2024-04-26T18:14:19Z",
clients: [], // No clients information
ipAddress: "172.20.0.1",
started: "2024-04-26T08:14:19Z",
lastAccess: "2024-04-26T08:30:54Z",
id: "no-clients-session"
}
]
},
stateChecker: "noClientsStateChecker"
}}
/>
)
};

View File

@ -180,3 +180,64 @@ export const MoreThanOneTotpProviders: Story = {
/> />
) )
}; };
// TOTP Enabled but No Existing OTP Credentials
export const TotpEnabledNoOtpCredentials: Story = {
render: () => (
<KcPageStory
kcContext={{
totp: {
enabled: true,
totpSecretEncoded: "HE4W MSTC OBKU CY2M",
otpCredentials: [] // No OTP Credentials
},
stateChecker: "stateChecker123",
url: {
totpUrl: "http://localhost:8080/realms/myrealm/account/totp"
}
}}
/>
)
};
// Manual Mode TOTP without Scanning
export const ManualModeTotp: Story = {
render: () => (
<KcPageStory
kcContext={{
mode: "manual", // Manual mode
totp: {
enabled: false,
totpSecretEncoded: "HE4W MSTC OBKU CY2M",
otpCredentials: []
},
stateChecker: "stateChecker123",
url: {
totpUrl: "http://localhost:8080/realms/myrealm/account/totp"
}
}}
/>
)
};
// Multiple OTP Devices Scenario
export const MultipleOtpDevices: Story = {
render: () => (
<KcPageStory
kcContext={{
totp: {
enabled: true,
totpSecretEncoded: "G55E MZKC JFUD",
otpCredentials: [
{ id: "1", userLabel: "Phone 1" },
{ id: "2", userLabel: "Tablet" }
]
},
stateChecker: "stateChecker123",
url: {
totpUrl: "http://localhost:8080/realms/myrealm/account/totp"
}
}}
/>
)
};