mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-14 11:12:16 +01:00
@@ -19,6 +19,10 @@ import {
|
||||
// Each test registers a new user and creates test data, which needs more time
|
||||
test.describe.configure({ timeout: 60000 });
|
||||
|
||||
// Date picker button name patterns for different date formats
|
||||
const DATE_PICKER_BUTTON_PATTERN =
|
||||
/^Pick a date$|^\d{4}-\d{2}-\d{2}$|^\d{2}\/\d{2}\/\d{4}$|^\d{2}\.\d{2}\.\d{4}$/;
|
||||
|
||||
// ──────────────────────────────────────────────────
|
||||
// Shared Report Lifecycle Tests
|
||||
// ──────────────────────────────────────────────────
|
||||
@@ -203,6 +207,128 @@ test('test that shared report with No Task filter shows entries without a task',
|
||||
await expect(page.getByText('Total')).toBeVisible();
|
||||
});
|
||||
|
||||
// ──────────────────────────────────────────────────
|
||||
// Report Date Picker Tests
|
||||
// ──────────────────────────────────────────────────
|
||||
|
||||
test('test that creating a report with an expiration date works', async ({ page }) => {
|
||||
const projectName = 'DatePickerProj ' + Math.floor(Math.random() * 10000);
|
||||
const reportName = 'DatePickerReport ' + Math.floor(Math.random() * 10000);
|
||||
|
||||
await createProject(page, projectName);
|
||||
await createTimeEntryWithProject(page, projectName, '1h');
|
||||
|
||||
await goToReporting(page);
|
||||
await expect(page.getByTestId('reporting_view').getByText(projectName)).toBeVisible();
|
||||
|
||||
// Open the save report modal
|
||||
await page.getByRole('button', { name: 'Save Report' }).click();
|
||||
await page.getByLabel('Name').fill(reportName);
|
||||
|
||||
// The "Public" checkbox should be checked by default, showing the date picker
|
||||
const datePicker = page
|
||||
.getByRole('dialog')
|
||||
.getByRole('button', { name: DATE_PICKER_BUTTON_PATTERN });
|
||||
await expect(datePicker).toBeVisible();
|
||||
await datePicker.click();
|
||||
|
||||
// Select a date in the next month
|
||||
const calendarGrid = page.getByRole('grid');
|
||||
await expect(calendarGrid).toBeVisible({ timeout: 5000 });
|
||||
await page.getByRole('button', { name: /Next/i }).click();
|
||||
await page.getByRole('gridcell').filter({ hasText: /^15$/ }).first().click();
|
||||
|
||||
// Wait for the calendar to close
|
||||
await expect(calendarGrid).not.toBeVisible();
|
||||
|
||||
// Create the report and verify it includes the public_until date
|
||||
const [response] = await Promise.all([
|
||||
page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().includes('/reports') &&
|
||||
response.request().method() === 'POST' &&
|
||||
response.status() === 201
|
||||
),
|
||||
page.getByRole('dialog').getByRole('button', { name: 'Create Report' }).click(),
|
||||
]);
|
||||
const responseBody = await response.json();
|
||||
expect(responseBody.data.public_until).toBeTruthy();
|
||||
});
|
||||
|
||||
test('test that editing a report to make it public with expiration date works', async ({
|
||||
page,
|
||||
}) => {
|
||||
const projectName = 'EditDateProj ' + Math.floor(Math.random() * 10000);
|
||||
const reportName = 'EditDateReport ' + Math.floor(Math.random() * 10000);
|
||||
|
||||
await createProject(page, projectName);
|
||||
await createTimeEntryWithProject(page, projectName, '1h');
|
||||
|
||||
await goToReporting(page);
|
||||
await expect(page.getByTestId('reporting_view').getByText(projectName)).toBeVisible();
|
||||
|
||||
// Open the save report modal and create a private report
|
||||
await page.getByRole('button', { name: 'Save Report' }).click();
|
||||
await page.getByLabel('Name').fill(reportName);
|
||||
|
||||
// Uncheck "Public" to create a private report
|
||||
await page.getByLabel('Public').click();
|
||||
|
||||
await Promise.all([
|
||||
page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().includes('/reports') &&
|
||||
response.request().method() === 'POST' &&
|
||||
response.status() === 201
|
||||
),
|
||||
page.getByRole('dialog').getByRole('button', { name: 'Create Report' }).click(),
|
||||
]);
|
||||
|
||||
// Go to shared reports and edit
|
||||
await goToReportingShared(page);
|
||||
await expect(page.getByText(reportName)).toBeVisible();
|
||||
await expect(page.getByText('Private')).toBeVisible();
|
||||
|
||||
// Click more options and edit
|
||||
await page
|
||||
.getByRole('button', { name: new RegExp('Actions for Project ' + reportName) })
|
||||
.click();
|
||||
await page.getByRole('menuitem', { name: /^Edit Report/ }).click();
|
||||
|
||||
// Check "Public" to make it public - this should show the date picker
|
||||
await page.getByLabel('Public').click();
|
||||
|
||||
// The date picker should now be visible
|
||||
const datePicker = page
|
||||
.getByRole('dialog')
|
||||
.getByRole('button', { name: DATE_PICKER_BUTTON_PATTERN });
|
||||
await expect(datePicker).toBeVisible();
|
||||
await datePicker.click();
|
||||
|
||||
// Select a date in the next month
|
||||
const calendarGrid = page.getByRole('grid');
|
||||
await expect(calendarGrid).toBeVisible({ timeout: 5000 });
|
||||
await page.getByRole('button', { name: /Next/i }).click();
|
||||
await page.getByRole('gridcell').filter({ hasText: /^20$/ }).first().click();
|
||||
|
||||
// Wait for the calendar to close
|
||||
await expect(calendarGrid).not.toBeVisible();
|
||||
|
||||
// Update the report and verify it includes the public_until date
|
||||
const [response] = await Promise.all([
|
||||
page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().includes('/reports/') &&
|
||||
response.request().method() === 'PUT' &&
|
||||
response.status() === 200
|
||||
),
|
||||
page.getByRole('button', { name: 'Update Report' }).click(),
|
||||
]);
|
||||
const responseBody = await response.json();
|
||||
expect(responseBody.data.public_until).toBeTruthy();
|
||||
expect(responseBody.data.is_public).toBe(true);
|
||||
});
|
||||
|
||||
test('test that shared report with No Client filter shows entries without a client', async ({
|
||||
page,
|
||||
}) => {
|
||||
|
||||
284
e2e/time.spec.ts
284
e2e/time.spec.ts
@@ -11,10 +11,37 @@ import {
|
||||
} from './utils/currentTimeEntry';
|
||||
import { createProject, createBillableProject, createBareTimeEntry } from './utils/reporting';
|
||||
|
||||
// Date picker button name patterns for different date formats
|
||||
// Matches: "Pick a date", "YYYY-MM-DD", "DD/MM/YYYY", "DD.MM.YYYY", "MM/DD/YYYY", "DD-MM-YYYY", "MM-DD-YYYY"
|
||||
const DATE_PICKER_BUTTON_PATTERN =
|
||||
/^Pick a date$|^\d{4}-\d{2}-\d{2}$|^\d{2}\/\d{2}\/\d{4}$|^\d{2}\.\d{2}\.\d{4}$/;
|
||||
// Same pattern but without "Pick a date" - for when we expect an actual date to be displayed
|
||||
const DATE_DISPLAY_PATTERN = /^\d{4}-\d{2}-\d{2}$|^\d{2}\/\d{2}\/\d{4}$|^\d{2}\.\d{2}\.\d{4}$/;
|
||||
|
||||
/**
|
||||
* Extracts day of month from an ISO timestamp string
|
||||
*/
|
||||
function getDayFromTimestamp(timestamp: string): number {
|
||||
return new Date(timestamp).getUTCDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts month (1-indexed) from an ISO timestamp string
|
||||
*/
|
||||
function getMonthFromTimestamp(timestamp: string): number {
|
||||
return new Date(timestamp).getUTCMonth() + 1;
|
||||
}
|
||||
|
||||
async function goToTimeOverview(page: Page) {
|
||||
await page.goto(PLAYWRIGHT_BASE_URL + '/time');
|
||||
}
|
||||
|
||||
async function goToOrganizationSettings(page: Page) {
|
||||
await page.goto(PLAYWRIGHT_BASE_URL + '/dashboard');
|
||||
await page.locator('[data-testid="organization_switcher"]:visible').click();
|
||||
await page.getByText('Organization Settings').click();
|
||||
}
|
||||
|
||||
async function createEmptyTimeEntry(page: Page) {
|
||||
await Promise.all([
|
||||
newTimeEntryResponse(page),
|
||||
@@ -310,7 +337,262 @@ test.skip('test that load more works when the end of page is reached', async ({
|
||||
|
||||
// TODO: Test Grouped time entries by description/project
|
||||
|
||||
// TODO: Add Test for Date Update
|
||||
// Date Update Tests
|
||||
|
||||
test('test that updating the start date of a time entry via the edit modal works', async ({
|
||||
page,
|
||||
}) => {
|
||||
await createBareTimeEntry(page, 'Date edit test', '1h');
|
||||
await goToTimeOverview(page);
|
||||
|
||||
const timeEntryRows = page.locator('[data-testid="time_entry_row"]');
|
||||
const newTimeEntry = timeEntryRows.first();
|
||||
|
||||
// Open edit modal via the actions dropdown
|
||||
const actionsDropdown = newTimeEntry
|
||||
.getByRole('button', { name: 'Actions for the time entry' })
|
||||
.first();
|
||||
await actionsDropdown.click();
|
||||
await page.getByTestId('time_entry_edit').click();
|
||||
await expect(page.getByRole('dialog')).toBeVisible();
|
||||
|
||||
// Click the start date picker (first date picker button in the Start section)
|
||||
const startDatePicker = page
|
||||
.getByRole('dialog')
|
||||
.getByRole('button', { name: DATE_PICKER_BUTTON_PATTERN })
|
||||
.first();
|
||||
await startDatePicker.click();
|
||||
|
||||
// Navigate to the previous month and select the 15th
|
||||
await page.getByRole('button', { name: /Previous/i }).click();
|
||||
await page.getByRole('gridcell').filter({ hasText: /^15$/ }).first().click();
|
||||
|
||||
// Get current month to calculate expected month after going to previous
|
||||
const now = new Date();
|
||||
const expectedMonth = now.getMonth() === 0 ? 12 : now.getMonth(); // Previous month (1-indexed)
|
||||
|
||||
// Submit the update and verify the response has correct date
|
||||
const [updateResponse] = await Promise.all([
|
||||
page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().includes('/time-entries') &&
|
||||
response.request().method() === 'PUT' &&
|
||||
response.status() === 200
|
||||
),
|
||||
page.getByRole('button', { name: 'Update Time Entry' }).click(),
|
||||
]);
|
||||
const updateBody = await updateResponse.json();
|
||||
expect(updateBody.data.start).toBeTruthy();
|
||||
expect(updateBody.data.end).toBeTruthy();
|
||||
// Verify the day was changed to 15th
|
||||
expect(getDayFromTimestamp(updateBody.data.start)).toBe(15);
|
||||
// Verify the month is the previous month
|
||||
expect(getMonthFromTimestamp(updateBody.data.start)).toBe(expectedMonth);
|
||||
});
|
||||
|
||||
test('test that setting a date in the create modal works', async ({ page }) => {
|
||||
await goToTimeOverview(page);
|
||||
|
||||
// Get today's date to compare later
|
||||
const today = new Date();
|
||||
|
||||
// Open create modal
|
||||
await page.getByRole('button', { name: 'Time entry actions' }).click();
|
||||
await page.getByRole('menuitem', { name: 'Manual time entry' }).click();
|
||||
await expect(page.getByRole('dialog')).toBeVisible();
|
||||
|
||||
// Set description
|
||||
await page
|
||||
.getByRole('dialog')
|
||||
.getByRole('textbox', { name: 'Description' })
|
||||
.fill('Date picker test entry');
|
||||
|
||||
// Set duration first (to ensure the form is valid)
|
||||
await page.locator('[role="dialog"] input[name="Duration"]').fill('1h');
|
||||
await page.locator('[role="dialog"] input[name="Duration"]').press('Tab');
|
||||
|
||||
// Click the start date picker
|
||||
const startDatePicker = page
|
||||
.getByRole('dialog')
|
||||
.getByRole('button', { name: DATE_PICKER_BUTTON_PATTERN })
|
||||
.first();
|
||||
await startDatePicker.click();
|
||||
|
||||
// Wait for calendar to appear
|
||||
const calendarGrid = page.getByRole('grid');
|
||||
await expect(calendarGrid).toBeVisible({ timeout: 5000 });
|
||||
|
||||
// Navigate to previous month and select the 15th (a day that's always in the middle of the month)
|
||||
await page.getByRole('button', { name: /Previous/i }).click();
|
||||
await page.getByRole('gridcell', { name: '15' }).getByRole('button').click();
|
||||
|
||||
// Wait for calendar to close
|
||||
await expect(calendarGrid).not.toBeVisible();
|
||||
|
||||
// Get current month to calculate expected month after going to previous
|
||||
const expectedMonth = today.getMonth() === 0 ? 12 : today.getMonth(); // Previous month (1-indexed)
|
||||
|
||||
// Submit and verify creation succeeds with correct date
|
||||
const [createResponse] = await Promise.all([
|
||||
page.waitForResponse(
|
||||
(response) => response.url().includes('/time-entries') && response.status() === 201
|
||||
),
|
||||
page.getByRole('button', { name: 'Create Time Entry' }).click(),
|
||||
]);
|
||||
const createBody = await createResponse.json();
|
||||
expect(createBody.data.start).toBeTruthy();
|
||||
// Verify the day was set to 15th
|
||||
expect(getDayFromTimestamp(createBody.data.start)).toBe(15);
|
||||
// Verify the month is the previous month
|
||||
expect(getMonthFromTimestamp(createBody.data.start)).toBe(expectedMonth);
|
||||
});
|
||||
|
||||
test('test that updating the date via the time entry row range selector works', async ({
|
||||
page,
|
||||
}) => {
|
||||
await createBareTimeEntry(page, 'Date range test', '1h');
|
||||
await goToTimeOverview(page);
|
||||
|
||||
const timeEntryRows = page.locator('[data-testid="time_entry_row"]');
|
||||
const newTimeEntry = timeEntryRows.first();
|
||||
await expect(newTimeEntry).toBeVisible();
|
||||
|
||||
// Open the time range popover
|
||||
const timeEntryRangeElement = newTimeEntry.getByTestId('time_entry_range_selector');
|
||||
await timeEntryRangeElement.click();
|
||||
|
||||
// Verify the range selector dropdown is open
|
||||
const rangeStart = page.getByTestId('time_entry_range_start');
|
||||
await expect(rangeStart).toBeVisible();
|
||||
|
||||
// Click the start date picker button within the range selector
|
||||
const startDatePicker = page.getByRole('button', { name: DATE_DISPLAY_PATTERN }).first();
|
||||
await expect(startDatePicker).toBeVisible();
|
||||
await startDatePicker.click();
|
||||
|
||||
// Wait for the calendar to appear and select a day
|
||||
const calendarGrid = page.getByRole('grid');
|
||||
await expect(calendarGrid).toBeVisible({ timeout: 5000 });
|
||||
|
||||
// Navigate to previous month and select the 5th
|
||||
await page.getByRole('button', { name: /Previous/i }).click();
|
||||
await page.getByRole('gridcell').filter({ hasText: /^5$/ }).first().click();
|
||||
|
||||
// Get current month to calculate expected month after going to previous
|
||||
const now = new Date();
|
||||
const expectedMonth = now.getMonth() === 0 ? 12 : now.getMonth(); // Previous month (1-indexed)
|
||||
|
||||
// Verify the time entry update API call succeeds with correct date
|
||||
const updateResponse = await page.waitForResponse(async (response) => {
|
||||
return (
|
||||
response.status() === 200 &&
|
||||
response.request().method() === 'PUT' &&
|
||||
(await response.headerValue('Content-Type')) === 'application/json'
|
||||
);
|
||||
});
|
||||
const updateBody = await updateResponse.json();
|
||||
expect(updateBody.data.start).toBeTruthy();
|
||||
// Verify the day was changed to 5th
|
||||
expect(getDayFromTimestamp(updateBody.data.start)).toBe(5);
|
||||
// Verify the month is the previous month
|
||||
expect(getMonthFromTimestamp(updateBody.data.start)).toBe(expectedMonth);
|
||||
});
|
||||
|
||||
test('test that updating the end date via the time entry row range selector works', async ({
|
||||
page,
|
||||
}) => {
|
||||
await createBareTimeEntry(page, 'End date range test', '1h');
|
||||
await goToTimeOverview(page);
|
||||
|
||||
const timeEntryRows = page.locator('[data-testid="time_entry_row"]');
|
||||
const newTimeEntry = timeEntryRows.first();
|
||||
await expect(newTimeEntry).toBeVisible();
|
||||
|
||||
// Open the time range popover
|
||||
const timeEntryRangeElement = newTimeEntry.getByTestId('time_entry_range_selector');
|
||||
await timeEntryRangeElement.click();
|
||||
|
||||
// Verify the range selector dropdown is open
|
||||
const rangeEnd = page.getByTestId('time_entry_range_end');
|
||||
await expect(rangeEnd).toBeVisible();
|
||||
|
||||
// Click the end date picker button (second date picker)
|
||||
const datePickers = page.getByRole('button', { name: DATE_DISPLAY_PATTERN });
|
||||
const endDatePicker = datePickers.nth(1);
|
||||
await expect(endDatePicker).toBeVisible();
|
||||
await endDatePicker.click();
|
||||
|
||||
// Wait for the calendar to appear
|
||||
const calendarGrid = page.getByRole('grid');
|
||||
await expect(calendarGrid).toBeVisible({ timeout: 5000 });
|
||||
|
||||
// Navigate to next month and select the 20th (to ensure end > start)
|
||||
await page.getByRole('button', { name: /Next/i }).click();
|
||||
await page.getByRole('gridcell').filter({ hasText: /^20$/ }).first().click();
|
||||
|
||||
// Get current month to calculate expected month after going to next
|
||||
const now = new Date();
|
||||
const expectedMonth = now.getMonth() === 11 ? 1 : now.getMonth() + 2; // Next month (1-indexed)
|
||||
|
||||
// Verify the time entry update API call succeeds with correct date
|
||||
const updateResponse = await page.waitForResponse(async (response) => {
|
||||
return (
|
||||
response.status() === 200 &&
|
||||
response.request().method() === 'PUT' &&
|
||||
(await response.headerValue('Content-Type')) === 'application/json'
|
||||
);
|
||||
});
|
||||
const updateBody = await updateResponse.json();
|
||||
expect(updateBody.data.end).toBeTruthy();
|
||||
// Verify the day was changed to 20th
|
||||
expect(getDayFromTimestamp(updateBody.data.end)).toBe(20);
|
||||
// Verify the month is the next month
|
||||
expect(getMonthFromTimestamp(updateBody.data.end)).toBe(expectedMonth);
|
||||
});
|
||||
|
||||
test('test that date picker displays date in organization date format', async ({ page }) => {
|
||||
// First change the organization date format to DD/MM/YYYY
|
||||
await goToOrganizationSettings(page);
|
||||
await page.getByLabel('Date Format').click();
|
||||
await page.getByRole('option', { name: 'DD/MM/YYYY' }).click();
|
||||
await Promise.all([
|
||||
page
|
||||
.locator('form')
|
||||
.filter({ hasText: 'Date Format' })
|
||||
.getByRole('button', { name: 'Save' })
|
||||
.click(),
|
||||
page.waitForResponse(
|
||||
async (response) =>
|
||||
response.url().includes('/organizations/') &&
|
||||
response.request().method() === 'PUT' &&
|
||||
response.status() === 200 &&
|
||||
(await response.json()).data.date_format === 'slash-separated-dd-mm-yyyy'
|
||||
),
|
||||
]);
|
||||
|
||||
// Create a time entry and open the edit modal
|
||||
await createBareTimeEntry(page, 'Date format test', '1h');
|
||||
await goToTimeOverview(page);
|
||||
|
||||
const timeEntryRows = page.locator('[data-testid="time_entry_row"]');
|
||||
const newTimeEntry = timeEntryRows.first();
|
||||
await expect(newTimeEntry).toBeVisible();
|
||||
|
||||
// Open edit modal
|
||||
const actionsDropdown = newTimeEntry
|
||||
.getByRole('button', { name: 'Actions for the time entry' })
|
||||
.first();
|
||||
await actionsDropdown.click();
|
||||
await page.getByTestId('time_entry_edit').click();
|
||||
await expect(page.getByRole('dialog')).toBeVisible();
|
||||
|
||||
// Verify the date picker shows the date in DD/MM/YYYY format
|
||||
const datePicker = page
|
||||
.getByRole('dialog')
|
||||
.getByRole('button', { name: /^\d{2}\/\d{2}\/\d{4}$/ })
|
||||
.first();
|
||||
await expect(datePicker).toBeVisible();
|
||||
});
|
||||
|
||||
// TODO: Test that project can be created in the time entry row
|
||||
|
||||
|
||||
@@ -10,6 +10,9 @@ import {
|
||||
import type { Page } from '@playwright/test';
|
||||
import { newTagResponse } from './utils/tags';
|
||||
|
||||
// Date picker button name patterns for different date formats
|
||||
const DATE_DISPLAY_PATTERN = /^\d{4}-\d{2}-\d{2}$|^\d{2}\/\d{2}\/\d{4}$|^\d{2}\.\d{2}\.\d{4}$/;
|
||||
|
||||
async function goToDashboard(page: Page) {
|
||||
await page.goto(PLAYWRIGHT_BASE_URL + '/dashboard');
|
||||
}
|
||||
@@ -254,6 +257,63 @@ test('test that adding a new tag when the timer is running', async ({ page }) =>
|
||||
await assertThatTimerIsStopped(page);
|
||||
});
|
||||
|
||||
test('test that setting an end time with a different date via the timetracker range selector works', async ({
|
||||
page,
|
||||
}) => {
|
||||
await goToDashboard(page);
|
||||
|
||||
// Start a timer
|
||||
await Promise.all([newTimeEntryResponse(page), startOrStopTimerWithButton(page)]);
|
||||
await assertThatTimerHasStarted(page);
|
||||
|
||||
// Open the time range dropdown by clicking on the time display
|
||||
await page.getByTestId('time_entry_time').click();
|
||||
const rangeStart = page.getByTestId('time_entry_range_start');
|
||||
await expect(rangeStart).toBeVisible();
|
||||
|
||||
// Click "Set End Time" button
|
||||
await page.getByRole('button', { name: 'Set End Time' }).click();
|
||||
|
||||
// The end time picker should now be visible with a Confirm button
|
||||
const rangeEnd = page.getByTestId('time_entry_range_end');
|
||||
await expect(rangeEnd).toBeVisible();
|
||||
const confirmButton = page.getByRole('button', { name: 'Confirm' });
|
||||
await expect(confirmButton).toBeVisible();
|
||||
|
||||
// Click the end date picker to change the date
|
||||
const endDatePickers = page.getByRole('button', { name: DATE_DISPLAY_PATTERN });
|
||||
// The second date picker is the end date (first is the start date)
|
||||
const endDatePicker = endDatePickers.nth(1);
|
||||
await expect(endDatePicker).toBeVisible();
|
||||
await endDatePicker.click();
|
||||
|
||||
// Calendar should appear
|
||||
const calendarGrid = page.getByRole('grid');
|
||||
await expect(calendarGrid).toBeVisible({ timeout: 5000 });
|
||||
|
||||
// Navigate to the next month and select a day to ensure end > start
|
||||
await page.getByRole('button', { name: /Next/i }).click();
|
||||
await page.getByRole('gridcell').filter({ hasText: /^15$/ }).first().click();
|
||||
|
||||
// The dropdown should still be open after selecting a date (not auto-closed)
|
||||
await expect(rangeEnd).toBeVisible();
|
||||
await expect(confirmButton).toBeVisible();
|
||||
|
||||
// Click Confirm to finalize and verify the API call
|
||||
const [updateResponse] = await Promise.all([
|
||||
page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().includes('/time-entries') &&
|
||||
response.request().method() === 'PUT' &&
|
||||
response.status() === 200
|
||||
),
|
||||
confirmButton.click(),
|
||||
]);
|
||||
const updateBody = await updateResponse.json();
|
||||
expect(updateBody.data.start).toBeTruthy();
|
||||
expect(updateBody.data.end).toBeTruthy();
|
||||
});
|
||||
|
||||
// test that search is working
|
||||
|
||||
// test that adding a tag and project and starting the timer afterwards works and sets the project and tag correctly
|
||||
|
||||
@@ -314,5 +314,7 @@ export async function saveAsSharedReport(
|
||||
page.getByRole('dialog').getByRole('button', { name: 'Create Report' }).click(),
|
||||
]);
|
||||
const responseBody = await response.json();
|
||||
// Wait for navigation to shared reports page
|
||||
await page.waitForURL('**/reporting/shared');
|
||||
return { shareableLink: responseBody.data.shareable_link };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user