fix tests, add autofocus disable option for dropdown

This commit is contained in:
Gregor Vostrak
2025-04-15 15:18:02 +02:00
parent 48be348c4c
commit af374c9c4d
13 changed files with 37 additions and 32 deletions

View File

@@ -109,7 +109,7 @@ services:
- sail
- reverse-proxy
playwright:
image: mcr.microsoft.com/playwright:v1.50.0-jammy
image: mcr.microsoft.com/playwright:v1.51.1-jammy
command: ['npx', 'playwright', 'test', '--ui-port=8080', '--ui-host=0.0.0.0']
working_dir: /src
extra_hosts:

View File

@@ -36,7 +36,7 @@ test('can register and delete account', async ({ page }) => {
await page.goto(PLAYWRIGHT_BASE_URL + '/user/profile');
await page.getByRole('button', { name: 'Delete Account' }).click();
await page.getByPlaceholder('Password').fill(password);
await page.getByRole('button', { name: 'Delete Account' }).nth(1).click();
await page.getByRole('button', { name: 'Delete Account' }).click();
await page.waitForURL(PLAYWRIGHT_BASE_URL + '/login');
await page.goto(PLAYWRIGHT_BASE_URL + '/login');
await page.getByLabel('Email').fill(email);

View File

@@ -16,7 +16,7 @@ test('test that creating and deleting a new client via the modal works', async (
await page.getByRole('button', { name: 'Create Client' }).click();
await page.getByPlaceholder('Client Name').fill(newClientName);
await Promise.all([
page.getByRole('button', { name: 'Create Client' }).nth(1).click(),
page.getByRole('button', { name: 'Create Client' }).click(),
page.waitForResponse(
async (response) =>
response.url().includes('/clients') &&
@@ -56,12 +56,12 @@ test('test that archiving and unarchiving clients works', async ({ page }) => {
await page.getByRole('button', { name: 'Create Client' }).click();
await page.getByLabel('Client Name').fill(newClientName);
await page.getByRole('button', { name: 'Create Client' }).nth(1).click();
await page.getByRole('button', { name: 'Create Client' }).click();
await expect(page.getByText(newClientName)).toBeVisible();
await page.getByRole('row').first().getByRole('button').click();
await Promise.all([
page.getByRole('button').getByText('Archive').first().click(),
page.getByRole('menuitem').getByText('Archive').click(),
expect(page.getByText(newClientName)).not.toBeVisible(),
]);
await Promise.all([
@@ -71,7 +71,7 @@ test('test that archiving and unarchiving clients works', async ({ page }) => {
await page.getByRole('row').first().getByRole('button').click();
await Promise.all([
page.getByRole('button').getByText('Unarchive').first().click(),
page.getByRole('menuitem').getByText('Unarchive').click(),
expect(page.getByText(newClientName)).not.toBeVisible(),
]);
await Promise.all([

View File

@@ -82,7 +82,7 @@ test('test that organization billable rate can be updated with all existing time
await goToMembersPage(page);
const newBillableRate = Math.round(Math.random() * 10000);
await page.getByRole('row').first().getByRole('button').click();
await page.getByRole('button').getByText('Edit').first().click();
await page.getByRole('menuitem').getByText('Edit').click();
await page.getByText('Organization Default Rate').click();
await page.getByText('Custom Rate').click();
await page

View File

@@ -17,7 +17,7 @@ test('test that updating project member billable rate works for existing time en
await page.getByRole('button', { name: 'Create Project' }).click();
await page.getByLabel('Project Name').fill(newProjectName);
await page.getByRole('button', { name: 'Create Project' }).nth(1).click();
await page.getByRole('button', { name: 'Create Project' }).click();
await expect(page.getByText(newProjectName)).toBeVisible();
await page.getByText(newProjectName).click();
@@ -35,8 +35,7 @@ test('test that updating project member billable rate works for existing time en
.getByRole('button')
.click();
await page
.getByRole('button', { name: 'Edit Project Member' })
.first()
.getByRole('menuitem', { name: 'Edit Project Member' })
.click();
await page.getByLabel('Billable Rate').fill(newBillableRate.toString());
await page.getByRole('button', { name: 'Update Project Member' }).click();

View File

@@ -17,7 +17,7 @@ test('test that creating and deleting a new project via the modal works', async
await page.getByRole('button', { name: 'Create Project' }).click();
await page.getByLabel('Project Name').fill(newProjectName);
await Promise.all([
page.getByRole('button', { name: 'Create Project' }).nth(1).click(),
page.getByRole('button', { name: 'Create Project' }).click(),
page.waitForResponse(
async (response) =>
response.url().includes('/projects') &&
@@ -62,12 +62,12 @@ test('test that archiving and unarchiving projects works', async ({ page }) => {
await page.getByRole('button', { name: 'Create Project' }).click();
await page.getByLabel('Project Name').fill(newProjectName);
await page.getByRole('button', { name: 'Create Project' }).nth(1).click();
await page.getByRole('button', { name: 'Create Project' }).click();
await expect(page.getByText(newProjectName)).toBeVisible();
await page.getByRole('row').first().getByRole('button').click();
await Promise.all([
page.getByRole('button').getByText('Archive').first().click(),
page.getByRole('menuitem').getByText('Archive').first().click(),
expect(page.getByText(newProjectName)).not.toBeVisible(),
]);
await Promise.all([
@@ -77,7 +77,7 @@ test('test that archiving and unarchiving projects works', async ({ page }) => {
await page.getByRole('row').first().getByRole('button').click();
await Promise.all([
page.getByRole('button').getByText('Unarchive').first().click(),
page.getByRole('menuitem').getByText('Unarchive').first().click(),
expect(page.getByText(newProjectName)).not.toBeVisible(),
]);
await Promise.all([
@@ -96,11 +96,11 @@ test('test that updating billable rate works with existing time entries', async
await page.getByRole('button', { name: 'Create Project' }).click();
await page.getByLabel('Project Name').fill(newProjectName);
await page.getByRole('button', { name: 'Create Project' }).nth(1).click();
await page.getByRole('button', { name: 'Create Project' }).click();
await expect(page.getByText(newProjectName)).toBeVisible();
await page.getByRole('row').first().getByRole('button').click();
await page.getByRole('button').getByText('Edit').first().click(),
await page.getByRole('menuitem').getByText('Edit').first().click();
await page.getByText('Non-Billable').click();
await page.getByText('Custom Rate').click();
await page

View File

@@ -15,7 +15,7 @@ test('test that creating and deleting a new client via the modal works', async (
await page.getByRole('button', { name: 'Create Tag' }).click();
await page.getByPlaceholder('Tag Name').fill(newTagName);
await Promise.all([
page.getByRole('button', { name: 'Create Tag' }).nth(1).click(),
page.getByRole('button', { name: 'Create Tag' }).click(),
page.waitForResponse(
async (response) =>
response.url().includes('/tags') &&

View File

@@ -16,7 +16,7 @@ test('test that creating and deleting a new tag in a new project works', async (
await page.getByRole('button', { name: 'Create Project' }).click();
await page.getByLabel('Project Name').fill(newProjectName);
await Promise.all([
page.getByRole('button', { name: 'Create Project' }).nth(1).click(),
page.getByRole('button', { name: 'Create Project' }).click(),
page.waitForResponse(
async (response) =>
response.url().includes('/projects') &&
@@ -41,7 +41,7 @@ test('test that creating and deleting a new tag in a new project works', async (
await page.getByPlaceholder('Task Name').fill(newTaskName);
await Promise.all([
page.getByRole('button', { name: 'Create Task' }).nth(1).click(),
page.getByRole('button', { name: 'Create Task' }).click(),
page.waitForResponse(
async (response) =>
response.url().includes('/tasks') &&
@@ -107,20 +107,20 @@ test('test that archiving and unarchiving tasks works', async ({ page }) => {
await page.getByRole('button', { name: 'Create Project' }).click();
await page.getByLabel('Project Name').fill(newProjectName);
await page.getByRole('button', { name: 'Create Project' }).nth(1).click();
await page.getByRole('button', { name: 'Create Project' }).click();
await expect(page.getByText(newProjectName)).toBeVisible();
await page.getByText(newProjectName).click();
await page.getByRole('button', { name: 'Create Task' }).click();
await page.getByPlaceholder('Task Name').fill(newTaskName);
await page.getByRole('button', { name: 'Create Task' }).nth(1).click();
await page.getByRole('button', { name: 'Create Task' }).click();
await expect(page.getByRole('table')).toContainText(newTaskName);
await page.getByRole('row').first().getByRole('button').click();
await Promise.all([
page.getByRole('button').getByText('Mark as done').first().click(),
page.getByRole('menuitem').getByText('Mark as done').first().click(),
expect(page.getByText(newTaskName)).not.toBeVisible(),
]);
await Promise.all([
@@ -130,7 +130,7 @@ test('test that archiving and unarchiving tasks works', async ({ page }) => {
await page.getByRole('row').first().getByRole('button').click();
await Promise.all([
page.getByRole('button').getByText('Mark as active').first().click(),
page.getByRole('menuitem').getByText('Mark as active').first().click(),
expect(page.getByText(newTaskName)).not.toBeVisible(),
]);
await Promise.all([

View File

@@ -2,11 +2,11 @@
@tailwind components;
@tailwind utilities;
:root.dark {
--color-bg-primary: #0f1011;
--color-bg-secondary: #17181a;
--color-bg-primary: #101012;
--color-bg-secondary: #17181B;
--color-bg-tertiary: #2A2C32;
--color-bg-quaternary: #141518;
--color-bg-background: #0B0B0B;
--color-bg-background: #090909;
--color-text-primary: #ffffff;
--color-text-secondary: #e3e4e6;
--color-text-tertiary: #969799;
@@ -22,7 +22,7 @@
--theme-color-menu-active: var(--color-bg-secondary);
--theme-color-card-background: var(--color-bg-secondary);
--theme-shadow-card: 0 4px 7px 0px rgb(0 0 0 / 30%);
--theme-shadow-card: 0 4px 7px 0px rgb(0 0 0 / 15%);
--theme-shadow-dropdown: 0 4px 7px 0px rgb(0 0 0 / 40%);
--theme-color-card-background-active: var(--color-bg-tertiary);

View File

@@ -266,7 +266,7 @@ const page = usePage<{
<BillingBanner v-if="isBillingActivated()" />
<div
class="min-h-screen bg-default-background border-l border-default-background-separator">
class="min-h-screen flex flex-col bg-default-background border-l border-default-background-separator">
<!-- Page Heading -->
<header
v-if="$slots.header"
@@ -281,7 +281,7 @@ const page = usePage<{
</header>
<!-- Page Content -->
<main class="pb-28">
<main class="pb-28 flex-1">
<slot />
</main>

View File

@@ -10,7 +10,6 @@ withDefaults(
}
);
</script>
Modal.vue
<template>
<button
:type="type"

View File

@@ -5,18 +5,23 @@ const props = withDefaults(
defineProps<{
align?: 'center' | 'end' | 'start';
closeOnContentClick?: boolean;
autoFocus?: boolean;
}>(),
{
align: 'start',
closeOnContentClick: true,
autoFocus: true,
}
);
const emit = defineEmits(['open', 'submit']);
const open = defineModel({ default: false });
function handleAutofocus(event: Event) {
if (props.autoFocus === false) {
event.preventDefault();
}
}
function onContentClick() {
if (props.closeOnContentClick === true) {
@@ -42,6 +47,7 @@ function onOpenChange(value: boolean) {
<PopoverContent
:align="align"
class="rounded-lg overflow-hidden relative border border-card-border overflow-none shadow-dropdown bg-card-background"
@open-auto-focus="handleAutofocus"
@click="onContentClick">
<slot name="content" />
</PopoverContent>

View File

@@ -171,6 +171,7 @@ function closeAndFocusInput() {
<Dropdown
v-model="open"
align="center"
:auto-focus="false"
:close-on-content-click="false"
@submit="open = false">
<template #trigger>