make sure empty duration input updates v-model to null, fixes #816

This commit is contained in:
Gregor Vostrak
2025-06-24 18:10:39 +02:00
parent a45c8a89f6
commit f79d995fdd
4 changed files with 55 additions and 2 deletions

View File

@@ -102,7 +102,7 @@ test('test that updating billable rate works with existing time entries', async
await page.getByRole('row').first().getByRole('button').click();
await page.getByRole('menuitem').getByText('Edit').first().click();
await page.getByText('Non-Billable').click();
await page.getByText('Non-Billable').click();
await page.getByText('Custom Rate').click();
await page
.getByPlaceholder('Billable Rate')
@@ -136,6 +136,49 @@ test('test that updating billable rate works with existing time entries', async
).toBeVisible();
});
test('test that creating and updating project time estimate works', async ({ page }) => {
const newProjectName = 'New Project ' + Math.floor(1 + Math.random() * 10000);
const timeEstimate = '10';
await goToProjectsOverview(page);
await page.getByRole('button', { name: 'Create Project' }).click();
await page.getByLabel('Project Name').fill(newProjectName);
await page.getByLabel('Time Estimated').fill(timeEstimate);
await Promise.all([
page.getByRole('button', { name: 'Create Project' }).click(),
page.waitForResponse(
async (response) =>
response.url().includes('/projects') &&
response.request().method() === 'POST' &&
response.status() === 201 &&
(await response.json()).data.estimated_time === parseInt(timeEstimate) * 60 * 60
),
]);
// Check that time estimate is displayed in the projects table
await expect(page.getByTestId('project_table')).toContainText(timeEstimate + 'h');
// Edit project to remove time estimate
await page.getByRole('row').first().getByRole('button').click();
await page.getByRole('menuitem').getByText('Edit').first().click();
await page.getByLabel('Time Estimated').fill('');
await Promise.all([
page.getByRole('button', { name: 'Update Project' }).click(),
page.waitForResponse(
async (response) =>
response.url().includes('/projects') &&
response.request().method() === 'PUT' &&
response.status() === 200 &&
(await response.json()).data.estimated_time === null
),
]);
// Check that time estimate is no longer displayed
await expect(page.getByTestId('project_table')).not.toContainText(timeEstimate + 'h');
});
// Create new project with new Client
// Create new project with existing Client

View File

@@ -11,9 +11,10 @@ const emit = defineEmits(['submit']);
<div class="pt-6">
<div class="flex items-center space-x-1 mb-2">
<ClockIcon class="text-text-quaternary w-4"></ClockIcon>
<InputLabel for="billable" value="Time Estimated" />
<InputLabel for="time-estimated" value="Time Estimated" />
</div>
<DurationInput
id="time-estimated"
v-model="model"
class="max-w-[150px]"
@submit="emit('submit')"></DurationInput>

View File

@@ -2,6 +2,10 @@
import { computed, ref } from 'vue';
import { TextInput } from '@/packages/ui/src';
defineProps<{
id?: string;
}>();
const model = defineModel<number | null>({
default: null,
});
@@ -16,6 +20,8 @@ function updateDuration() {
const hours = parseInt(temporaryCustomTimerEntry.value);
if (!isNaN(hours)) {
model.value = hours * 60 * 60;
} else {
model.value = null;
}
temporaryCustomTimerEntry.value = '';
}
@@ -54,6 +60,7 @@ function updateAndSubmit() {
<template>
<div class="relative">
<TextInput
:id="id"
v-model="currentTime"
class="w-full overflow-hidden pr-14"
placeholder="0"

View File

@@ -5,6 +5,7 @@ import { twMerge } from 'tailwind-merge';
const props = defineProps<{
name?: string;
class?: string;
id?: string;
}>();
const input = ref<HTMLInputElement | null>(null);
@@ -21,6 +22,7 @@ const model = defineModel();
<template>
<input
:id="id"
ref="input"
v-model="model"
:class="