mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-12 10:04:25 +00:00
chore: add data-testid's and some additional testing
This commit is contained in:
@@ -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()
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -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)
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
@@ -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,67 +188,58 @@ 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
|
||||||
async ensurePasskeyRegister() {
|
|
||||||
const url = new URL(process.env.ZITADEL_API_URL!)
|
|
||||||
const registerBody = {
|
|
||||||
domain: url.hostname,
|
|
||||||
}
|
}
|
||||||
const userId = ""
|
this.setUserId(resp.result[0].userId)
|
||||||
const registerResponse = await fetch(process.env.ZITADEL_API_URL! + "/v2/users/" + userId + "/passkeys", {
|
await super.remove()
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify(registerBody),
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Authorization': "Bearer " + process.env.ZITADEL_SERVICE_USER_TOKEN!
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (registerResponse.statusCode >= 400 && registerResponse.statusCode != 409) {
|
|
||||||
const error = 'HTTP Error: ' + registerResponse.statusCode + ' - ' + registerResponse.statusMessage;
|
|
||||||
console.error(error);
|
|
||||||
throw new Error(error);
|
|
||||||
}
|
|
||||||
const respJson = await registerResponse.json()
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getUserByUsername(username: string) {
|
||||||
|
const listUsersBody = {
|
||||||
|
queries: [{
|
||||||
|
userNameQuery: {
|
||||||
|
userName: username,
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
const jsonBody = JSON.stringify(listUsersBody)
|
||||||
|
const registerResponse = await fetch(process.env.ZITADEL_API_URL! + "/v2/users", {
|
||||||
|
method: 'POST',
|
||||||
|
body: jsonBody,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': "Bearer " + process.env.ZITADEL_SERVICE_USER_TOKEN!
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (registerResponse.statusCode >= 400) {
|
||||||
|
const error = 'HTTP Error: ' + registerResponse.statusCode + ' - ' + registerResponse.statusMessage;
|
||||||
|
console.error(error);
|
||||||
|
throw new Error(error);
|
||||||
|
}
|
||||||
|
const respJson = await registerResponse.json()
|
||||||
|
return respJson
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
@@ -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);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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")}
|
||||||
|
|||||||
@@ -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")}
|
||||||
|
|||||||
@@ -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")}
|
||||||
|
|||||||
@@ -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")}
|
||||||
|
|||||||
@@ -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]">
|
||||||
|
|||||||
@@ -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")}
|
||||||
|
|||||||
@@ -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")}
|
||||||
|
|||||||
@@ -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")}
|
||||||
|
|||||||
@@ -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")}
|
||||||
|
|||||||
@@ -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")}
|
||||||
|
|||||||
@@ -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")}
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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")}
|
||||||
|
|||||||
@@ -34,20 +34,25 @@ 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, {
|
||||||
return createSessionAndUpdateCookie(
|
user: {search: {case: "userId", value: human.userId}},
|
||||||
checks,
|
password: {password: command.password}
|
||||||
undefined,
|
});
|
||||||
command.authRequestId,
|
}
|
||||||
).then((session) => {
|
console.log(checks)
|
||||||
return {
|
return createSessionAndUpdateCookie(
|
||||||
userId: human.userId,
|
checks,
|
||||||
sessionId: session.id,
|
undefined,
|
||||||
factors: session.factors,
|
command.authRequestId,
|
||||||
};
|
).then((session) => {
|
||||||
});
|
return {
|
||||||
|
userId: human.userId,
|
||||||
|
sessionId: session.id,
|
||||||
|
factors: session.factors,
|
||||||
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user