chore: add data-testid's and some additional testing

This commit is contained in:
Stefan Benz
2024-10-30 18:50:32 +01:00
parent 9af39ac1bc
commit 9c041cc46f
22 changed files with 227 additions and 113 deletions

View File

@@ -2,18 +2,23 @@ import {Page} from "@playwright/test";
export async function loginWithPassword(page: Page, username: string, password: string) { export async function loginWithPassword(page: Page, username: string, password: string) {
await page.goto("/loginname"); await page.goto("/loginname");
const loginname = page.getByLabel("Loginname"); await loginnameScreen(page, username)
await loginname.pressSequentially(username); await page.getByTestId("submit-button").click()
await loginname.press("Enter"); await passwordScreen(page, password)
const pw = page.getByLabel("Password"); await page.getByTestId("submit-button").click()
await pw.pressSequentially(password);
await pw.press("Enter");
} }
export async function loginnameScreen(page: Page, username: string) {
await page.getByTestId("username-text-input").pressSequentially(username);
}
export async function passwordScreen(page: Page, password: string) {
await page.getByTestId("password-text-input").pressSequentially(password);
}
export async function loginWithPasskey(page: Page, username: string) { export async function loginWithPasskey(page: Page, username: string) {
await page.goto("/loginname"); await page.goto("/loginname");
const loginname = page.getByLabel("Loginname"); await loginnameScreen(page, username)
await loginname.pressSequentially(username); await page.getByTestId("submit-button").click()
await loginname.press("Enter"); await page.getByTestId("submit-button").click()
} }

View File

@@ -2,11 +2,11 @@ import {Page} from "@playwright/test";
export async function changePassword(page: Page, loginname: string, password: string) { export async function changePassword(page: Page, loginname: string, password: string) {
await page.goto('password/change?' + new URLSearchParams({loginName: loginname})); await page.goto('password/change?' + new URLSearchParams({loginName: loginname}));
await changePasswordScreen(page, loginname, password, password) await changePasswordScreen(page, password, password)
await page.getByRole('button', {name: 'Continue'}).click(); await page.getByTestId("submit-button").click();
} }
async function changePasswordScreen(page: Page, loginname: string, password1: string, password2: string) { async function changePasswordScreen(page: Page, password1: string, password2: string) {
await page.getByLabel('New Password *').pressSequentially(password1); await page.getByTestId('password-text-input').pressSequentially(password1);
await page.getByLabel('Confirm Password *').pressSequentially(password2); await page.getByTestId('password-confirm-text-input').pressSequentially(password2);
} }

View File

@@ -3,11 +3,8 @@ import {registerWithPassword} from './register';
import {loginWithPassword} from "./login"; import {loginWithPassword} from "./login";
test("register with password", async ({page}) => { test("register with password", async ({page}) => {
const firstname = "firstname"
const lastname = "lastname"
const username = "register@example.com" const username = "register@example.com"
const password = "Password1!" const password = "Password1!"
await registerWithPassword(page, firstname, lastname, username, password, password) await registerWithPassword(page, "firstname", "lastname", username, password, password)
await page.getByRole("heading", {name: "Welcome " + lastname + " " + lastname + "!"}).click();
await loginWithPassword(page, username, password) await loginWithPassword(page, username, password)
}); });

View File

@@ -2,30 +2,38 @@ import {Page} from "@playwright/test";
export async function registerWithPassword(page: Page, firstname: string, lastname: string, email: string, password1: string, password2: string) { export async function registerWithPassword(page: Page, firstname: string, lastname: string, email: string, password1: string, password2: string) {
await page.goto('/register'); await page.goto('/register');
await registerUserScreenPassword(page, firstname, lastname, email)
await page.getByTestId('submit-button').click();
await registerPasswordScreen(page, password1, password2)
await page.getByTestId('submit-button').click();
}
async function registerUserScreenPassword(page: Page, firstname: string, lastname: string, email: string) {
await registerUserScreen(page, firstname, lastname, email) await registerUserScreen(page, firstname, lastname, email)
await page.getByLabel('Password').click(); await page.getByLabel('Password').click();
await page.getByRole('button', {name: 'Continue'}).click(); }
await registerPasswordScreen(page, password1, password2)
await page.getByRole('button', {name: 'Continue'}).click(); async function registerPasswordScreen(page: Page, password1: string, password2: string) {
await page.getByTestId('password-text-input').fill(password1);
await page.getByTestId('password-confirm-text-input').fill(password2);
} }
export async function registerWithPasskey(page: Page, firstname: string, lastname: string, email: string) { export async function registerWithPasskey(page: Page, firstname: string, lastname: string, email: string) {
await page.goto('/register'); await page.goto('/register');
await registerUserScreenPasskey(page, firstname, lastname, email)
await page.getByTestId('submit-button').click();
await page.getByTestId('submit-button').click();
}
async function registerUserScreenPasskey(page: Page, firstname: string, lastname: string, email: string) {
await registerUserScreen(page, firstname, lastname, email) await registerUserScreen(page, firstname, lastname, email)
await page.getByLabel('Passkey').click(); await page.getByLabel('Passkey').click();
await page.getByRole('button', {name: 'Continue'}).click();
await page.getByRole('button', {name: 'Continue'}).click();
} }
async function registerUserScreen(page: Page, firstname: string, lastname: string, email: string) { async function registerUserScreen(page: Page, firstname: string, lastname: string, email: string) {
await page.getByLabel('First name *').pressSequentially(firstname); await page.getByTestId('firstname-text-input').pressSequentially(firstname);
await page.getByLabel('Last name *').pressSequentially(lastname); await page.getByTestId('lastname-text-input').pressSequentially(lastname);
await page.getByLabel('E-mail *').pressSequentially(email); await page.getByTestId('email-text-input').pressSequentially(email);
await page.getByRole('checkbox').first().check(); await page.getByTestId('privacy-policy-checkbox').check();
await page.getByRole('checkbox').nth(1).check(); await page.getByTestId('tos-checkbox').check();
}
async function registerPasswordScreen(page: Page, password1: string, password2: string) {
await page.getByLabel('Password *', {exact: true}).fill(password1);
await page.getByLabel('Confirm Password *').fill(password2);
} }

View File

@@ -1,4 +1,4 @@
import fetch from 'node-fetch'; import fetch from "node-fetch";
import {Page} from "@playwright/test"; import {Page} from "@playwright/test";
import {registerWithPasskey} from "./register"; import {registerWithPasskey} from "./register";
import {loginWithPasskey, loginWithPassword} from "./login"; import {loginWithPasskey, loginWithPassword} from "./login";
@@ -20,7 +20,7 @@ class User {
this.props = userProps; this.props = userProps;
} }
async ensure() { async ensure(page: Page) {
await this.remove() await this.remove()
const body = { const body = {
@@ -72,6 +72,10 @@ class User {
return return
} }
public setUserId(userId: string) {
this.user = userId
}
public userId() { public userId() {
return this.user; return this.user;
} }
@@ -84,6 +88,14 @@ class User {
return this.props.password; return this.props.password;
} }
public firstname() {
return this.props.firstName
}
public lastname() {
return this.props.lastName
}
public fullName() { public fullName() {
return this.props.firstName + " " + this.props.lastName return this.props.firstName + " " + this.props.lastName
} }
@@ -102,6 +114,73 @@ class User {
export class PasswordUser extends User { export class PasswordUser extends User {
} }
enum OtpType {
time = "time-based",
sms = "sms",
email = "email",
}
export interface otpUserProps {
email: string;
firstName: string;
lastName: string;
organization: string;
type: OtpType,
}
export class PasswordUserWithOTP extends User {
private type: OtpType
private code: string
constructor(props: otpUserProps) {
super({
email: props.email,
firstName: props.firstName,
lastName: props.lastName,
organization: props.organization,
password: ""
})
this.type = props.type
}
async ensure(page: Page) {
await super.ensure(page)
const body = {
username: this.props.email,
organization: {
orgId: this.props.organization
},
profile: {
givenName: this.props.firstName,
familyName: this.props.lastName,
},
email: {
email: this.props.email,
isVerified: true,
},
password: {
password: this.props.password!,
}
}
const response = await fetch(process.env.ZITADEL_API_URL! + "/v2/users/human", {
method: 'POST',
body: JSON.stringify(body),
headers: {
'Content-Type': 'application/json',
'Authorization': "Bearer " + process.env.ZITADEL_SERVICE_USER_TOKEN!
}
});
if (response.statusCode >= 400 && response.statusCode != 409) {
const error = 'HTTP Error: ' + response.statusCode + ' - ' + response.statusMessage;
console.error(error);
throw new Error(error);
}
return
}
}
export interface passkeyUserProps { export interface passkeyUserProps {
email: string; email: string;
firstName: string; firstName: string;
@@ -109,40 +188,54 @@ export interface passkeyUserProps {
organization: string; organization: string;
} }
export class PasskeyUser { export class PasskeyUser extends User {
private props: passkeyUserProps
constructor(props: passkeyUserProps) { constructor(props: passkeyUserProps) {
this.props = props super({
email: props.email,
firstName: props.firstName,
lastName: props.lastName,
organization: props.organization,
password: ""
})
} }
async ensurePasskey(page: Page) { public async ensure(page: Page) {
await registerWithPasskey(page, this.props.firstName, this.props.lastName, this.props.email) await this.remove()
await registerWithPasskey(page, this.firstname(), this.lastname(), this.username())
} }
public async login(page: Page) { public async login(page: Page) {
await loginWithPasskey(page, this.props.email) await loginWithPasskey(page, this.username())
} }
public fullName() { public async remove() {
return this.props.firstName + " " + this.props.lastName const resp = await getUserByUsername(this.username())
if (!resp || !resp.result || !resp.result[0]) {
return
}
this.setUserId(resp.result[0].userId)
await super.remove()
}
} }
async ensurePasskeyRegister() { async function getUserByUsername(username: string) {
const url = new URL(process.env.ZITADEL_API_URL!) const listUsersBody = {
const registerBody = { queries: [{
domain: url.hostname, userNameQuery: {
userName: username,
} }
const userId = "" }]
const registerResponse = await fetch(process.env.ZITADEL_API_URL! + "/v2/users/" + userId + "/passkeys", { }
const jsonBody = JSON.stringify(listUsersBody)
const registerResponse = await fetch(process.env.ZITADEL_API_URL! + "/v2/users", {
method: 'POST', method: 'POST',
body: JSON.stringify(registerBody), body: jsonBody,
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Authorization': "Bearer " + process.env.ZITADEL_SERVICE_USER_TOKEN! 'Authorization': "Bearer " + process.env.ZITADEL_SERVICE_USER_TOKEN!
} }
}); });
if (registerResponse.statusCode >= 400 && registerResponse.statusCode != 409) { if (registerResponse.statusCode >= 400) {
const error = 'HTTP Error: ' + registerResponse.statusCode + ' - ' + registerResponse.statusMessage; const error = 'HTTP Error: ' + registerResponse.statusCode + ' - ' + registerResponse.statusMessage;
console.error(error); console.error(error);
throw new Error(error); throw new Error(error);
@@ -150,26 +243,3 @@ export class PasskeyUser {
const respJson = await registerResponse.json() const respJson = await registerResponse.json()
return respJson return respJson
} }
async ensurePasskeyVerify(passkeyId: string, credential: Credential) {
const verifyBody = {
publicKeyCredential: credential,
passkeyName: "passkey",
}
const userId = ""
const verifyResponse = await fetch(process.env.ZITADEL_API_URL! + "/v2/users/" + userId + "/passkeys/" + passkeyId, {
method: 'POST',
body: JSON.stringify(verifyBody),
headers: {
'Content-Type': 'application/json',
'Authorization': "Bearer " + process.env.ZITADEL_SERVICE_USER_TOKEN!
}
});
if (verifyResponse.statusCode >= 400 && verifyResponse.statusCode != 409) {
const error = 'HTTP Error: ' + verifyResponse.statusCode + ' - ' + verifyResponse.statusMessage;
console.error(error);
throw new Error(error);
}
return
}
}

View File

@@ -1,5 +1,7 @@
import {test as base} from "@playwright/test";
import path from 'path'; import path from 'path';
import dotenv from 'dotenv'; import dotenv from 'dotenv';
import {PasskeyUser} from "./user";
// Read from ".env" file. // Read from ".env" file.
dotenv.config({path: path.resolve(__dirname, '.env.local')}); dotenv.config({path: path.resolve(__dirname, '.env.local')});
@@ -86,7 +88,7 @@ const test = base.extend<{ user: PasskeyUser }>({
enabled: false, enabled: false,
}); });
}, },
}); });*/
const test = base.extend<{ user: PasskeyUser }>({ const test = base.extend<{ user: PasskeyUser }>({
user: async ({page}, use) => { user: async ({page}, use) => {
@@ -96,7 +98,7 @@ const test = base.extend<{ user: PasskeyUser }>({
lastName: "last", lastName: "last",
organization: "", organization: "",
}); });
await user.ensurePasskey(page); await user.ensure(page);
await use(user) await use(user)
}, },
}); });
@@ -105,4 +107,3 @@ test("username and passkey login", async ({user, page}) => {
await user.login(page) await user.login(page)
await page.getByRole("heading", {name: "Welcome " + user.fullName() + "!"}).click(); await page.getByRole("heading", {name: "Welcome " + user.fullName() + "!"}).click();
}); });
*/

View File

@@ -15,7 +15,7 @@ const test = base.extend<{ user: PasswordUser }>({
password: "Password1!", password: "Password1!",
organization: "", organization: "",
}); });
await user.ensure(); await user.ensure(page);
await use(user); await use(user);
}, },
}); });

View File

@@ -15,7 +15,7 @@ const test = base.extend<{ user: PasswordUser }>({
password: "Password1!", password: "Password1!",
organization: "", organization: "",
}); });
await user.ensure(); await user.ensure(page);
await use(user); await use(user);
}, },
}); });

View File

@@ -140,6 +140,7 @@ export function ChangePasswordForm({
})} })}
label="New Password" label="New Password"
error={errors.password?.message as string} error={errors.password?.message as string}
data-testid="password-text-input"
/> />
</div> </div>
<div className=""> <div className="">
@@ -152,6 +153,7 @@ export function ChangePasswordForm({
})} })}
label="Confirm Password" label="Confirm Password"
error={errors.confirmPassword?.message as string} error={errors.confirmPassword?.message as string}
data-testid="password-confirm-text-input"
/> />
</div> </div>
</div> </div>
@@ -167,7 +169,7 @@ export function ChangePasswordForm({
{error && <Alert>{error}</Alert>} {error && <Alert>{error}</Alert>}
<div className="mt-8 flex w-full flex-row items-center justify-between"> <div className="mt-8 flex w-full flex-row items-center justify-between">
<BackButton /> <BackButton data-testid="back-button" />
<Button <Button
type="submit" type="submit"
variant={ButtonVariants.Primary} variant={ButtonVariants.Primary}
@@ -178,6 +180,7 @@ export function ChangePasswordForm({
watchPassword !== watchConfirmPassword watchPassword !== watchConfirmPassword
} }
onClick={handleSubmit(submitChange)} onClick={handleSubmit(submitChange)}
data-testid="submit-button"
> >
{loading && <Spinner className="h-5 w-5 mr-2" />} {loading && <Spinner className="h-5 w-5 mr-2" />}
{t("change.submit")} {t("change.submit")}

View File

@@ -235,7 +235,7 @@ export function LoginOTP({
)} )}
<div className="mt-8 flex w-full flex-row items-center"> <div className="mt-8 flex w-full flex-row items-center">
<BackButton /> <BackButton data-testid="back-button" />
<span className="flex-grow"></span> <span className="flex-grow"></span>
<Button <Button
type="submit" type="submit"
@@ -245,6 +245,7 @@ export function LoginOTP({
onClick={handleSubmit((e) => { onClick={handleSubmit((e) => {
setCodeAndContinue(e, organization); setCodeAndContinue(e, organization);
})} })}
data-testid="submit-button"
> >
{loading && <Spinner className="h-5 w-5 mr-2" />} {loading && <Spinner className="h-5 w-5 mr-2" />}
{t("verify.submit")} {t("verify.submit")}

View File

@@ -229,6 +229,7 @@ export function LoginPasskey({
"/password?" + new URLSearchParams(params), // alt is set because password is requested as alternative auth method, so passwordless prompt can be escaped "/password?" + new URLSearchParams(params), // alt is set because password is requested as alternative auth method, so passwordless prompt can be escaped
); );
}} }}
data-testid="password-button"
> >
{t("verify.usePassword")} {t("verify.usePassword")}
</Button> </Button>
@@ -263,6 +264,7 @@ export function LoginPasskey({
setLoading(false); setLoading(false);
}); });
}} }}
data-testid="submit-button"
> >
{loading && <Spinner className="h-5 w-5 mr-2" />} {loading && <Spinner className="h-5 w-5 mr-2" />}
{t("verify.submit")} {t("verify.submit")}

View File

@@ -120,6 +120,7 @@ export function PasswordForm({
autoComplete="password" autoComplete="password"
{...register("password", { required: "This field is required" })} {...register("password", { required: "This field is required" })}
label="Password" label="Password"
data-testid="password-text-input"
/> />
{!loginSettings?.hidePasswordReset && ( {!loginSettings?.hidePasswordReset && (
<button <button
@@ -155,7 +156,7 @@ export function PasswordForm({
)} )}
<div className="mt-8 flex w-full flex-row items-center"> <div className="mt-8 flex w-full flex-row items-center">
<BackButton /> <BackButton data-testid="back-button" />
<span className="flex-grow"></span> <span className="flex-grow"></span>
<Button <Button
type="submit" type="submit"
@@ -163,6 +164,7 @@ export function PasswordForm({
variant={ButtonVariants.Primary} variant={ButtonVariants.Primary}
disabled={loading || !formState.isValid} disabled={loading || !formState.isValid}
onClick={handleSubmit(submitPassword)} onClick={handleSubmit(submitPassword)}
data-testid="submit-button"
> >
{loading && <Spinner className="h-5 w-5 mr-2" />} {loading && <Spinner className="h-5 w-5 mr-2" />}
{t("verify.submit")} {t("verify.submit")}

View File

@@ -60,6 +60,7 @@ export function PrivacyPolicyCheckboxes({ legal, onChange }: Props) {
}); });
onChange(checked && acceptanceState.privacyPolicyAccepted); onChange(checked && acceptanceState.privacyPolicyAccepted);
}} }}
data-testid="privacy-policy-checkbox"
/> />
<div className="mr-4 w-[28rem]"> <div className="mr-4 w-[28rem]">
@@ -84,6 +85,7 @@ export function PrivacyPolicyCheckboxes({ legal, onChange }: Props) {
}); });
onChange(checked && acceptanceState.tosAccepted); onChange(checked && acceptanceState.tosAccepted);
}} }}
data-testid="tos-checkbox"
/> />
<div className="mr-4 w-[28rem]"> <div className="mr-4 w-[28rem]">

View File

@@ -131,6 +131,7 @@ export function RegisterFormWithoutPassword({
{...register("firstname", { required: "This field is required" })} {...register("firstname", { required: "This field is required" })}
label="First name" label="First name"
error={errors.firstname?.message as string} error={errors.firstname?.message as string}
data-testid="firstname-text-input"
/> />
</div> </div>
<div className=""> <div className="">
@@ -141,6 +142,7 @@ export function RegisterFormWithoutPassword({
{...register("lastname", { required: "This field is required" })} {...register("lastname", { required: "This field is required" })}
label="Last name" label="Last name"
error={errors.lastname?.message as string} error={errors.lastname?.message as string}
data-testid="lastname-text-input"
/> />
</div> </div>
<div className="col-span-2"> <div className="col-span-2">
@@ -151,6 +153,7 @@ export function RegisterFormWithoutPassword({
{...register("email", { required: "This field is required" })} {...register("email", { required: "This field is required" })}
label="E-mail" label="E-mail"
error={errors.email?.message as string} error={errors.email?.message as string}
data-testid="email-text-input"
/> />
</div> </div>
</div> </div>
@@ -180,7 +183,7 @@ export function RegisterFormWithoutPassword({
)} )}
<div className="mt-8 flex w-full flex-row items-center justify-between"> <div className="mt-8 flex w-full flex-row items-center justify-between">
<BackButton /> <BackButton data-testid="back-button" />
<Button <Button
type="submit" type="submit"
variant={ButtonVariants.Primary} variant={ButtonVariants.Primary}
@@ -188,6 +191,7 @@ export function RegisterFormWithoutPassword({
onClick={handleSubmit((values) => onClick={handleSubmit((values) =>
submitAndContinue(values, selected === methods[0] ? false : true), submitAndContinue(values, selected === methods[0] ? false : true),
)} )}
data-testid="submit-button"
> >
{loading && <Spinner className="h-5 w-5 mr-2" />} {loading && <Spinner className="h-5 w-5 mr-2" />}
{t("submit")} {t("submit")}

View File

@@ -189,6 +189,7 @@ export function RegisterPasskey({
variant={ButtonVariants.Primary} variant={ButtonVariants.Primary}
disabled={loading || !formState.isValid} disabled={loading || !formState.isValid}
onClick={handleSubmit(submitRegisterAndContinue)} onClick={handleSubmit(submitRegisterAndContinue)}
data-testid="submit-button"
> >
{loading && <Spinner className="h-5 w-5 mr-2" />} {loading && <Spinner className="h-5 w-5 mr-2" />}
{t("set.submit")} {t("set.submit")}

View File

@@ -190,7 +190,7 @@ export function RegisterU2f({
)} )}
<div className="mt-8 flex w-full flex-row items-center"> <div className="mt-8 flex w-full flex-row items-center">
<BackButton /> <BackButton data-testid="back-button" />
<span className="flex-grow"></span> <span className="flex-grow"></span>
<Button <Button
@@ -199,6 +199,7 @@ export function RegisterU2f({
variant={ButtonVariants.Primary} variant={ButtonVariants.Primary}
disabled={loading} disabled={loading}
onClick={submitRegisterAndContinue} onClick={submitRegisterAndContinue}
data-testid="submit-button"
> >
{loading && <Spinner className="h-5 w-5 mr-2" />} {loading && <Spinner className="h-5 w-5 mr-2" />}
{t("set.submit")} {t("set.submit")}

View File

@@ -207,7 +207,7 @@ export function SetPasswordForm({
{error && <Alert>{error}</Alert>} {error && <Alert>{error}</Alert>}
<div className="mt-8 flex w-full flex-row items-center justify-between"> <div className="mt-8 flex w-full flex-row items-center justify-between">
<BackButton /> <BackButton data-testid="back-button" />
<Button <Button
type="submit" type="submit"
variant={ButtonVariants.Primary} variant={ButtonVariants.Primary}
@@ -218,6 +218,7 @@ export function SetPasswordForm({
watchPassword !== watchConfirmPassword watchPassword !== watchConfirmPassword
} }
onClick={handleSubmit(submitRegister)} onClick={handleSubmit(submitRegister)}
data-testid="submit-button"
> >
{loading && <Spinner className="h-5 w-5 mr-2" />} {loading && <Spinner className="h-5 w-5 mr-2" />}
{t("set.submit")} {t("set.submit")}

View File

@@ -149,6 +149,7 @@ export function SetRegisterPasswordForm({
})} })}
label="Password" label="Password"
error={errors.password?.message as string} error={errors.password?.message as string}
data-testid="password-text-input"
/> />
</div> </div>
<div className=""> <div className="">
@@ -161,6 +162,7 @@ export function SetRegisterPasswordForm({
})} })}
label="Confirm Password" label="Confirm Password"
error={errors.confirmPassword?.message as string} error={errors.confirmPassword?.message as string}
data-testid="password-confirm-text-input"
/> />
</div> </div>
</div> </div>
@@ -187,6 +189,7 @@ export function SetRegisterPasswordForm({
watchPassword !== watchConfirmPassword watchPassword !== watchConfirmPassword
} }
onClick={handleSubmit(submitRegister)} onClick={handleSubmit(submitRegister)}
data-testid="submit-button"
> >
{loading && <Spinner className="h-5 w-5 mr-2" />} {loading && <Spinner className="h-5 w-5 mr-2" />}
{t("password.submit")} {t("password.submit")}

View File

@@ -122,6 +122,7 @@ export function TotpRegister({
type="text" type="text"
{...register("code", { required: "This field is required" })} {...register("code", { required: "This field is required" })}
label="Code" label="Code"
data-testid="code-text-input"
/> />
</div> </div>
@@ -139,6 +140,7 @@ export function TotpRegister({
variant={ButtonVariants.Primary} variant={ButtonVariants.Primary}
disabled={loading || !formState.isValid} disabled={loading || !formState.isValid}
onClick={handleSubmit(continueWithCode)} onClick={handleSubmit(continueWithCode)}
data-testid="submit-button"
> >
{loading && <Spinner className="h-5 w-5 mr-2" />} {loading && <Spinner className="h-5 w-5 mr-2" />}
{t("set.submit")} {t("set.submit")}

View File

@@ -80,6 +80,7 @@ export function UsernameForm({
autoComplete="username" autoComplete="username"
{...register("loginName", { required: "This field is required" })} {...register("loginName", { required: "This field is required" })}
label="Loginname" label="Loginname"
data-testid="username-text-input"
/> />
{allowRegister && ( {allowRegister && (
<button <button
@@ -97,6 +98,7 @@ export function UsernameForm({
}} }}
type="button" type="button"
disabled={loading} disabled={loading}
data-testid="register-button"
> >
{t("register")} {t("register")}
</button> </button>
@@ -112,9 +114,10 @@ export function UsernameForm({
<div className="pt-6 pb-4">{children}</div> <div className="pt-6 pb-4">{children}</div>
<div className="mt-4 flex w-full flex-row items-center"> <div className="mt-4 flex w-full flex-row items-center">
<BackButton /> <BackButton data-testid="back-button" />
<span className="flex-grow"></span> <span className="flex-grow"></span>
<Button <Button
data-testid="submit-button"
type="submit" type="submit"
className="self-end" className="self-end"
variant={ButtonVariants.Primary} variant={ButtonVariants.Primary}

View File

@@ -110,6 +110,7 @@ export function VerifyEmailForm({
autoComplete="one-time-code" autoComplete="one-time-code"
{...register("code", { required: "This field is required" })} {...register("code", { required: "This field is required" })}
label="Code" label="Code"
data-testid="code-text-input"
// error={errors.username?.message as string} // error={errors.username?.message as string}
/> />
</div> </div>
@@ -125,6 +126,7 @@ export function VerifyEmailForm({
type="button" type="button"
onClick={() => resendCode()} onClick={() => resendCode()}
variant={ButtonVariants.Secondary} variant={ButtonVariants.Secondary}
data-testid="resend-button"
> >
{t("resendCode")} {t("resendCode")}
</Button> </Button>
@@ -135,6 +137,7 @@ export function VerifyEmailForm({
variant={ButtonVariants.Primary} variant={ButtonVariants.Primary}
disabled={loading || !formState.isValid} disabled={loading || !formState.isValid}
onClick={handleSubmit(submitCodeAndContinue)} onClick={handleSubmit(submitCodeAndContinue)}
data-testid="submit-button"
> >
{loading && <Spinner className="h-5 w-5 mr-2" />} {loading && <Spinner className="h-5 w-5 mr-2" />}
{t("submit")} {t("submit")}

View File

@@ -34,11 +34,16 @@ export async function registerUser(command: RegisterUserCommand) {
return { error: "Could not create user" }; return { error: "Could not create user" };
} }
const checks = create(ChecksSchema, { let checks = create(ChecksSchema, {
user: {search: {case: "userId", value: human.userId}}, user: {search: {case: "userId", value: human.userId}},
password: { password: command.password },
}); });
if (command.password) {
checks = create(ChecksSchema, {
user: {search: {case: "userId", value: human.userId}},
password: {password: command.password}
});
}
console.log(checks)
return createSessionAndUpdateCookie( return createSessionAndUpdateCookie(
checks, checks,
undefined, undefined,