mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-11 21:42:11 +00:00
chore: add basic acceptance tests
This commit is contained in:
7
acceptance/tests/admin.spec.ts
Normal file
7
acceptance/tests/admin.spec.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import {test} from "@playwright/test";
|
||||||
|
import {loginWithPassword} from "./login";
|
||||||
|
|
||||||
|
test("admin login", async ({page}) => {
|
||||||
|
await loginWithPassword(page, "zitadel-admin@zitadel.localhost", "Password1.")
|
||||||
|
await page.getByRole("heading", {name: "Welcome ZITADEL Admin!"}).click();
|
||||||
|
});
|
||||||
19
acceptance/tests/login.ts
Normal file
19
acceptance/tests/login.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import {Page} from "@playwright/test";
|
||||||
|
|
||||||
|
export async function loginWithPassword(page: Page, username: string, password: string) {
|
||||||
|
await page.goto("/loginname");
|
||||||
|
const loginname = page.getByLabel("Loginname");
|
||||||
|
await loginname.pressSequentially(username);
|
||||||
|
await loginname.press("Enter");
|
||||||
|
const pw = page.getByLabel("Password");
|
||||||
|
await pw.pressSequentially(password);
|
||||||
|
await pw.press("Enter");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function loginWithPasskey(page: Page, username: string) {
|
||||||
|
await page.goto("/loginname");
|
||||||
|
const loginname = page.getByLabel("Loginname");
|
||||||
|
await loginname.pressSequentially(username);
|
||||||
|
await loginname.press("Enter");
|
||||||
|
}
|
||||||
12
acceptance/tests/password.ts
Normal file
12
acceptance/tests/password.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import {Page} from "@playwright/test";
|
||||||
|
|
||||||
|
export async function changePassword(page: Page, loginname: string, password: string) {
|
||||||
|
await page.goto('password/change?' + new URLSearchParams({loginName: loginname}));
|
||||||
|
await changePasswordScreen(page, loginname, password, password)
|
||||||
|
await page.getByRole('button', {name: 'Continue'}).click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function changePasswordScreen(page: Page, loginname: string, password1: string, password2: string) {
|
||||||
|
await page.getByLabel('New Password *').pressSequentially(password1);
|
||||||
|
await page.getByLabel('Confirm Password *').pressSequentially(password2);
|
||||||
|
}
|
||||||
13
acceptance/tests/register.spec.ts
Normal file
13
acceptance/tests/register.spec.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import {test} from "@playwright/test";
|
||||||
|
import {registerWithPassword} from './register';
|
||||||
|
import {loginWithPassword} from "./login";
|
||||||
|
|
||||||
|
test("register with password", async ({page}) => {
|
||||||
|
const firstname = "firstname"
|
||||||
|
const lastname = "lastname"
|
||||||
|
const username = "register@example.com"
|
||||||
|
const password = "Password1!"
|
||||||
|
await registerWithPassword(page, firstname, lastname, username, password, password)
|
||||||
|
await page.getByRole("heading", {name: "Welcome " + lastname + " " + lastname + "!"}).click();
|
||||||
|
await loginWithPassword(page, username, password)
|
||||||
|
});
|
||||||
31
acceptance/tests/register.ts
Normal file
31
acceptance/tests/register.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import {Page} from "@playwright/test";
|
||||||
|
|
||||||
|
export async function registerWithPassword(page: Page, firstname: string, lastname: string, email: string, password1: string, password2: string) {
|
||||||
|
await page.goto('/register');
|
||||||
|
await registerUserScreen(page, firstname, lastname, email)
|
||||||
|
await page.getByLabel('Password').click();
|
||||||
|
await page.getByRole('button', {name: 'Continue'}).click();
|
||||||
|
await registerPasswordScreen(page, password1, password2)
|
||||||
|
await page.getByRole('button', {name: 'Continue'}).click();
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function registerWithPasskey(page: Page, firstname: string, lastname: string, email: string) {
|
||||||
|
await page.goto('/register');
|
||||||
|
await registerUserScreen(page, firstname, lastname, email)
|
||||||
|
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) {
|
||||||
|
await page.getByLabel('First name *').pressSequentially(firstname);
|
||||||
|
await page.getByLabel('Last name *').pressSequentially(lastname);
|
||||||
|
await page.getByLabel('E-mail *').pressSequentially(email);
|
||||||
|
await page.getByRole('checkbox').first().check();
|
||||||
|
await page.getByRole('checkbox').nth(1).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);
|
||||||
|
}
|
||||||
175
acceptance/tests/user.ts
Normal file
175
acceptance/tests/user.ts
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
import fetch from 'node-fetch';
|
||||||
|
import {Page} from "@playwright/test";
|
||||||
|
import {registerWithPasskey} from "./register";
|
||||||
|
import {loginWithPasskey, loginWithPassword} from "./login";
|
||||||
|
import {changePassword} from "./password";
|
||||||
|
|
||||||
|
export interface userProps {
|
||||||
|
email: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
organization: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
class User {
|
||||||
|
private readonly props: userProps;
|
||||||
|
private user: string;
|
||||||
|
|
||||||
|
constructor(userProps: userProps) {
|
||||||
|
this.props = userProps;
|
||||||
|
}
|
||||||
|
|
||||||
|
async ensure() {
|
||||||
|
await this.remove()
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
async remove() {
|
||||||
|
const response = await fetch(process.env.ZITADEL_API_URL! + "/v2/users/" + this.userId(), {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: {
|
||||||
|
'Authorization': "Bearer " + process.env.ZITADEL_SERVICE_USER_TOKEN!
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (response.statusCode >= 400 && response.statusCode != 404) {
|
||||||
|
const error = 'HTTP Error: ' + response.statusCode + ' - ' + response.statusMessage;
|
||||||
|
console.error(error);
|
||||||
|
throw new Error(error);
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
public userId() {
|
||||||
|
return this.user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public username() {
|
||||||
|
return this.props.email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public password() {
|
||||||
|
return this.props.password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public fullName() {
|
||||||
|
return this.props.firstName + " " + this.props.lastName
|
||||||
|
}
|
||||||
|
|
||||||
|
public async login(page: Page) {
|
||||||
|
await loginWithPassword(page, this.username(), this.password())
|
||||||
|
}
|
||||||
|
|
||||||
|
public async changePassword(page: Page, password: string) {
|
||||||
|
await loginWithPassword(page, this.username(), this.password())
|
||||||
|
await changePassword(page, this.username(), password)
|
||||||
|
this.props.password = password
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PasswordUser extends User {
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface passkeyUserProps {
|
||||||
|
email: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
organization: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PasskeyUser {
|
||||||
|
private props: passkeyUserProps
|
||||||
|
|
||||||
|
constructor(props: passkeyUserProps) {
|
||||||
|
this.props = props
|
||||||
|
}
|
||||||
|
|
||||||
|
async ensurePasskey(page: Page) {
|
||||||
|
await registerWithPasskey(page, this.props.firstName, this.props.lastName, this.props.email)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async login(page: Page) {
|
||||||
|
await loginWithPasskey(page, this.props.email)
|
||||||
|
}
|
||||||
|
|
||||||
|
public fullName() {
|
||||||
|
return this.props.firstName + " " + this.props.lastName
|
||||||
|
}
|
||||||
|
|
||||||
|
async ensurePasskeyRegister() {
|
||||||
|
const url = new URL(process.env.ZITADEL_API_URL!)
|
||||||
|
const registerBody = {
|
||||||
|
domain: url.hostname,
|
||||||
|
}
|
||||||
|
const userId = ""
|
||||||
|
const registerResponse = await fetch(process.env.ZITADEL_API_URL! + "/v2/users/" + userId + "/passkeys", {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
108
acceptance/tests/username-passkey.spec.ts
Normal file
108
acceptance/tests/username-passkey.spec.ts
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
import path from 'path';
|
||||||
|
import dotenv from 'dotenv';
|
||||||
|
|
||||||
|
// Read from ".env" file.
|
||||||
|
dotenv.config({path: path.resolve(__dirname, '.env.local')});
|
||||||
|
|
||||||
|
/*
|
||||||
|
const BASE64_ENCODED_PK =
|
||||||
|
"MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" +
|
||||||
|
"MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV" +
|
||||||
|
"oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ" +
|
||||||
|
"FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq" +
|
||||||
|
"GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0" +
|
||||||
|
"+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM" +
|
||||||
|
"8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD" +
|
||||||
|
"/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ" +
|
||||||
|
"5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe" +
|
||||||
|
"pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol" +
|
||||||
|
"L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d" +
|
||||||
|
"xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi" +
|
||||||
|
"uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8" +
|
||||||
|
"K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct" +
|
||||||
|
"lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa" +
|
||||||
|
"9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH" +
|
||||||
|
"zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H" +
|
||||||
|
"BYGpI8g==";
|
||||||
|
|
||||||
|
const test = base.extend<{ user: PasskeyUser }>({
|
||||||
|
user: async ({page}, use) => {
|
||||||
|
|
||||||
|
// Initialize a CDP session for the current page
|
||||||
|
const client = await page.context().newCDPSession(page);
|
||||||
|
// Enable WebAuthn environment in this session
|
||||||
|
await client.send('WebAuthn.enable', {enableUI: true});
|
||||||
|
|
||||||
|
// Attach a virtual authenticator with specific options
|
||||||
|
const result = await client.send('WebAuthn.addVirtualAuthenticator', {
|
||||||
|
options: {
|
||||||
|
protocol: 'ctap2',
|
||||||
|
transport: 'usb',
|
||||||
|
hasResidentKey: true,
|
||||||
|
hasUserVerification: true,
|
||||||
|
isUserVerified: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const authenticatorId = result.authenticatorId;
|
||||||
|
|
||||||
|
const url = new URL(process.env.ZITADEL_API_URL!)
|
||||||
|
await client.send('WebAuthn.addCredential', {
|
||||||
|
credential: {
|
||||||
|
credentialId: "",
|
||||||
|
rpId: url.hostname,
|
||||||
|
privateKey: BASE64_ENCODED_PK,
|
||||||
|
isResidentCredential: false,
|
||||||
|
signCount: 0,
|
||||||
|
},
|
||||||
|
authenticatorId: authenticatorId
|
||||||
|
});
|
||||||
|
|
||||||
|
await client.send('WebAuthn.setUserVerified', {
|
||||||
|
authenticatorId: authenticatorId,
|
||||||
|
isUserVerified: true,
|
||||||
|
});
|
||||||
|
await client.send('WebAuthn.setAutomaticPresenceSimulation', {
|
||||||
|
authenticatorId: authenticatorId,
|
||||||
|
enabled: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const user = new PasskeyUser({
|
||||||
|
email: "password@example.com",
|
||||||
|
firstName: "first",
|
||||||
|
lastName: "last",
|
||||||
|
organization: "",
|
||||||
|
});
|
||||||
|
await user.ensure();
|
||||||
|
const respJson = await user.ensurePasskeyRegister();
|
||||||
|
|
||||||
|
const credential = await navigator.credentials.create({
|
||||||
|
publicKey: respJson.publicKeyCredentialCreationOptions
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.ensurePasskeyVerify(respJson.passkeyId, respJson.publicKeyCredentialCreationOptions)
|
||||||
|
use(user);
|
||||||
|
await client.send('WebAuthn.setAutomaticPresenceSimulation', {
|
||||||
|
authenticatorId,
|
||||||
|
enabled: false,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const test = base.extend<{ user: PasskeyUser }>({
|
||||||
|
user: async ({page}, use) => {
|
||||||
|
const user = new PasskeyUser({
|
||||||
|
email: "passkey@example.com",
|
||||||
|
firstName: "first",
|
||||||
|
lastName: "last",
|
||||||
|
organization: "",
|
||||||
|
});
|
||||||
|
await user.ensurePasskey(page);
|
||||||
|
await use(user)
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
test("username and passkey login", async ({user, page}) => {
|
||||||
|
await user.login(page)
|
||||||
|
await page.getByRole("heading", {name: "Welcome " + user.fullName() + "!"}).click();
|
||||||
|
});
|
||||||
|
*/
|
||||||
26
acceptance/tests/username-password-changed.spec.ts
Normal file
26
acceptance/tests/username-password-changed.spec.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import {test as base} from "@playwright/test";
|
||||||
|
import {PasswordUser} from './user';
|
||||||
|
import path from 'path';
|
||||||
|
import dotenv from 'dotenv';
|
||||||
|
|
||||||
|
// Read from ".env" file.
|
||||||
|
dotenv.config({path: path.resolve(__dirname, '.env.local')});
|
||||||
|
|
||||||
|
const test = base.extend<{ user: PasswordUser }>({
|
||||||
|
user: async ({page}, use) => {
|
||||||
|
const user = new PasswordUser({
|
||||||
|
email: "password-changed@example.com",
|
||||||
|
firstName: "first",
|
||||||
|
lastName: "last",
|
||||||
|
password: "Password1!",
|
||||||
|
organization: "",
|
||||||
|
});
|
||||||
|
await user.ensure();
|
||||||
|
await use(user);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
test("username and password changed login", async ({user, page}) => {
|
||||||
|
await user.changePassword(page, "ChangedPw1!")
|
||||||
|
await user.login(page)
|
||||||
|
});
|
||||||
@@ -1,12 +1,28 @@
|
|||||||
import { test } from "@playwright/test";
|
import {test as base} from "@playwright/test";
|
||||||
|
import {PasswordUser} from './user';
|
||||||
|
import path from 'path';
|
||||||
|
import dotenv from 'dotenv';
|
||||||
|
|
||||||
test("username and password", async ({ page }) => {
|
// Read from ".env" file.
|
||||||
await page.goto("/");
|
dotenv.config({path: path.resolve(__dirname, '.env.local')});
|
||||||
const loginname = page.getByLabel("Loginname");
|
|
||||||
await loginname.pressSequentially("zitadel-admin@zitadel.localhost");
|
const test = base.extend<{ user: PasswordUser }>({
|
||||||
await loginname.press("Enter");
|
user: async ({page}, use) => {
|
||||||
const password = page.getByLabel("Password");
|
const user = new PasswordUser({
|
||||||
await password.pressSequentially("Password1!");
|
email: "password@example.com",
|
||||||
await password.press("Enter");
|
firstName: "first",
|
||||||
await page.getByRole("heading", { name: "Welcome ZITADEL Admin!" }).click();
|
lastName: "last",
|
||||||
|
password: "Password1!",
|
||||||
|
organization: "",
|
||||||
|
});
|
||||||
|
await user.ensure();
|
||||||
|
await use(user);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("username and password login", async ({user, page}) => {
|
||||||
|
await user.login(page)
|
||||||
|
await page.getByRole("heading", {name: "Welcome " + user.fullName() + "!"}).click();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ export async function registerPasskeyLink(
|
|||||||
sessionToken: sessionCookie.token,
|
sessionToken: sessionCookie.token,
|
||||||
});
|
});
|
||||||
|
|
||||||
const domain = headers().get("host");
|
// TODO remove ports from host header for URL with port
|
||||||
|
const domain = "localhost";
|
||||||
|
|
||||||
if (!domain) {
|
if (!domain) {
|
||||||
throw new Error("Could not get domain");
|
throw new Error("Could not get domain");
|
||||||
|
|||||||
@@ -85,7 +85,8 @@ export async function updateSession(options: UpdateSessionCommand) {
|
|||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
});
|
});
|
||||||
|
|
||||||
const host = headers().get("host");
|
// TODO remove ports from host header for URL with port
|
||||||
|
const host = "localhost"
|
||||||
|
|
||||||
if (
|
if (
|
||||||
host &&
|
host &&
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { defineConfig, devices } from "@playwright/test";
|
import {defineConfig, devices} from "@playwright/test";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read environment variables from file.
|
* Read environment variables from file.
|
||||||
@@ -12,70 +12,70 @@ import { defineConfig, devices } from "@playwright/test";
|
|||||||
* See https://playwright.dev/docs/test-configuration.
|
* See https://playwright.dev/docs/test-configuration.
|
||||||
*/
|
*/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
testDir: "./acceptance/tests",
|
testDir: "./acceptance/tests",
|
||||||
/* Run tests in files in parallel */
|
/* Run tests in files in parallel */
|
||||||
fullyParallel: true,
|
fullyParallel: true,
|
||||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||||
forbidOnly: !!process.env.CI,
|
forbidOnly: !!process.env.CI,
|
||||||
/* Retry on CI only */
|
/* Retry on CI only */
|
||||||
retries: process.env.CI ? 2 : 0,
|
retries: process.env.CI ? 2 : 0,
|
||||||
/* Opt out of parallel tests on CI. */
|
/* Opt out of parallel tests on CI. */
|
||||||
workers: process.env.CI ? 1 : undefined,
|
workers: process.env.CI ? 1 : undefined,
|
||||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||||
reporter: "html",
|
reporter: "html",
|
||||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||||
use: {
|
use: {
|
||||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||||
baseURL: "http://127.0.0.1:3000",
|
baseURL: "http://127.0.0.1:3000",
|
||||||
|
|
||||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||||
trace: "on-first-retry",
|
trace: "on-first-retry",
|
||||||
},
|
|
||||||
|
|
||||||
/* Configure projects for major browsers */
|
|
||||||
projects: [
|
|
||||||
{
|
|
||||||
name: "chromium",
|
|
||||||
use: { ...devices["Desktop Chrome"] },
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
/* Configure projects for major browsers */
|
||||||
name: "firefox",
|
projects: [
|
||||||
use: { ...devices["Desktop Firefox"] },
|
{
|
||||||
|
name: "chromium",
|
||||||
|
use: {...devices["Desktop Chrome"]},
|
||||||
|
},
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
name: "firefox",
|
||||||
|
use: { ...devices["Desktop Firefox"] },
|
||||||
|
},
|
||||||
|
TODO: webkit fails. Is this a bug?
|
||||||
|
{
|
||||||
|
name: 'webkit',
|
||||||
|
use: { ...devices['Desktop Safari'] },
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Test against mobile viewports. */
|
||||||
|
// {
|
||||||
|
// name: 'Mobile Chrome',
|
||||||
|
// use: { ...devices['Pixel 5'] },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: 'Mobile Safari',
|
||||||
|
// use: { ...devices['iPhone 12'] },
|
||||||
|
// },
|
||||||
|
|
||||||
|
/* Test against branded browsers. */
|
||||||
|
// {
|
||||||
|
// name: 'Microsoft Edge',
|
||||||
|
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: 'Google Chrome',
|
||||||
|
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
|
||||||
|
// },
|
||||||
|
],
|
||||||
|
|
||||||
|
/* Run local dev server before starting the tests */
|
||||||
|
webServer: {
|
||||||
|
command: "pnpm start:built",
|
||||||
|
url: "http://127.0.0.1:3000",
|
||||||
|
reuseExistingServer: !process.env.CI,
|
||||||
|
timeout: 5 * 60_000,
|
||||||
},
|
},
|
||||||
/* TODO: webkit fails. Is this a bug?
|
|
||||||
{
|
|
||||||
name: 'webkit',
|
|
||||||
use: { ...devices['Desktop Safari'] },
|
|
||||||
},
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Test against mobile viewports. */
|
|
||||||
// {
|
|
||||||
// name: 'Mobile Chrome',
|
|
||||||
// use: { ...devices['Pixel 5'] },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'Mobile Safari',
|
|
||||||
// use: { ...devices['iPhone 12'] },
|
|
||||||
// },
|
|
||||||
|
|
||||||
/* Test against branded browsers. */
|
|
||||||
// {
|
|
||||||
// name: 'Microsoft Edge',
|
|
||||||
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'Google Chrome',
|
|
||||||
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
|
|
||||||
// },
|
|
||||||
],
|
|
||||||
|
|
||||||
/* Run local dev server before starting the tests */
|
|
||||||
webServer: {
|
|
||||||
command: "pnpm start:built",
|
|
||||||
url: "http://127.0.0.1:3000",
|
|
||||||
reuseExistingServer: !process.env.CI,
|
|
||||||
timeout: 5 * 60_000,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user