Add Field component system and migrate UI

This commit is contained in:
Gregor Vostrak
2026-02-10 12:22:53 +01:00
parent 1ecb332458
commit fd012e7c69
71 changed files with 1023 additions and 741 deletions

View File

@@ -192,9 +192,7 @@ test('shows error for invalid login credentials', async ({ page }) => {
await page.getByLabel('Password').fill('wrongpassword123');
await page.getByRole('button', { name: 'Log in' }).click();
await expect(
page.getByText('These credentials do not match our records.')
).toBeVisible();
await expect(page.getByText('These credentials do not match our records.')).toBeVisible();
});
test('shows error when registering with existing email', async ({ page }) => {

View File

@@ -44,6 +44,28 @@ test('test that user can create an API key', async ({ page }) => {
await createNewApiToken(page);
});
test('test that creating an API key with empty name shows validation error', async ({ page }) => {
await page.goto(PLAYWRIGHT_BASE_URL + '/user/profile');
// Wait for the API Key Name input to be visible before interacting
const nameInput = page.getByLabel('API Key Name');
await expect(nameInput).toBeVisible();
// Ensure the API Key Name input is empty
await nameInput.fill('');
// Click the create button and wait for the 422 response
const [response] = await Promise.all([
page.waitForResponse('**/users/me/api-tokens'),
page.getByRole('button', { name: 'Create API Key' }).click(),
]);
expect(response.status()).toBe(422);
// Verify that an error notification is shown with validation message about the name field
await expect(page.getByText('name field is required')).toBeVisible({ timeout: 5000 });
});
test('test that user can delete an API key', async ({ page }) => {
await page.goto(PLAYWRIGHT_BASE_URL + '/user/profile');
await createNewApiToken(page);

View File

@@ -158,12 +158,9 @@ test('test that deselecting a project removes the filter', async ({ page, ctx })
page.getByRole('button', { name: 'Projects' }).first().getByText('1')
).toBeVisible();
// Deselect project
// Deselect project (no network request expected — TanStack Query serves cached unfiltered data)
await page.getByRole('button', { name: 'Projects' }).first().click();
await Promise.all([
page.getByRole('option').filter({ hasText: project1Name }).click(),
waitForReportingUpdate(page),
]);
await page.getByRole('option').filter({ hasText: project1Name }).click();
await page.keyboard.press('Escape');
// Verify badge count is gone (no count displayed when 0)
@@ -281,12 +278,9 @@ test('test that deselecting a client removes the filter', async ({ page, ctx })
page.getByRole('button', { name: 'Clients' }).first().getByText('1')
).toBeVisible();
// Deselect client
// Deselect client (no network request expected — TanStack Query serves cached unfiltered data)
await page.getByRole('button', { name: 'Clients' }).first().click();
await Promise.all([
page.getByRole('option').filter({ hasText: client1Name }).click(),
waitForReportingUpdate(page),
]);
await page.getByRole('option').filter({ hasText: client1Name }).click();
await page.keyboard.press('Escape');
await expect(
@@ -445,12 +439,9 @@ test('test that deselecting a member removes the filter', async ({ page, ctx })
page.getByRole('button', { name: 'Members' }).first().getByText('1')
).toBeVisible();
// Deselect member
// Deselect member (no network request expected — TanStack Query serves cached unfiltered data)
await page.getByRole('button', { name: 'Members' }).first().click();
await Promise.all([
page.getByRole('option').filter({ hasText: 'John Doe' }).click(),
waitForReportingUpdate(page),
]);
await page.getByRole('option').filter({ hasText: 'John Doe' }).click();
await page.keyboard.press('Escape');
// Verify badge count is gone
@@ -544,12 +535,9 @@ test('test that deselecting a tag removes the filter', async ({ page, ctx }) =>
await expect(page.getByRole('button', { name: 'Tags' }).getByText('1')).toBeVisible();
// Deselect tag
// Deselect tag (no network request expected — TanStack Query serves cached unfiltered data)
await page.getByRole('button', { name: 'Tags' }).click();
await Promise.all([
page.getByRole('option').filter({ hasText: tag1Name }).click(),
waitForReportingUpdate(page),
]);
await page.getByRole('option').filter({ hasText: tag1Name }).click();
await page.keyboard.press('Escape');
await expect(page.getByRole('button', { name: 'Tags' }).getByText(/^\d+$/)).not.toBeVisible();

View File

@@ -417,10 +417,9 @@ export async function updateOrganizationCurrencyViaWeb(
currency: string,
name: string = 'Test Organization'
) {
const response = await ctx.request.put(
`${PLAYWRIGHT_BASE_URL}/teams/${ctx.orgId}`,
{ data: { name, currency } }
);
const response = await ctx.request.put(`${PLAYWRIGHT_BASE_URL}/teams/${ctx.orgId}`, {
data: { name, currency },
});
expect(response.status()).toBe(200);
}

View File

@@ -78,4 +78,4 @@ export async function getPasswordResetUrl(
expect(resetUrlMatch).toBeTruthy();
return resetUrlMatch![1].replace(/&/g, '&');
}
}