Skip to content

Commit 7f145cf

Browse files
committed
make sure cost column shows in shared report view, #1019
1 parent b579ed1 commit 7f145cf

File tree

3 files changed

+67
-8
lines changed

3 files changed

+67
-8
lines changed

e2e/shared-reports.spec.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
createTimeEntryViaApi,
99
createTimeEntryWithTagViaApi,
1010
createBareTimeEntryViaApi,
11+
createBillableProjectViaApi,
1112
} from './utils/api';
1213
import {
1314
goToReporting,
@@ -577,3 +578,58 @@ test('test that updating expiration date on already-public report works', async
577578
const now = new Date();
578579
expect(returnedDate.getTime()).toBeGreaterThan(now.getTime());
579580
});
581+
582+
// ──────────────────────────────────────────────────
583+
// Shared Report Cost Column Tests
584+
// ──────────────────────────────────────────────────
585+
586+
test('test that shared report displays cost column correctly aligned with data rows', async ({
587+
page,
588+
ctx,
589+
}) => {
590+
const projectName = 'BillableProj ' + Math.floor(Math.random() * 10000);
591+
const reportName = 'BillableReport ' + Math.floor(Math.random() * 10000);
592+
593+
const project = await createBillableProjectViaApi(ctx, {
594+
name: projectName,
595+
billable_rate: 10000, // 100.00 per hour
596+
});
597+
await createTimeEntryViaApi(ctx, {
598+
description: `Entry for ${projectName}`,
599+
duration: '1h',
600+
projectId: project.id,
601+
billable: true,
602+
});
603+
604+
await goToReporting(page);
605+
await expect(page.getByTestId('reporting_view').getByText(projectName)).toBeVisible();
606+
607+
const { shareableLink } = await saveAsSharedReport(page, reportName);
608+
609+
// Navigate to the shared report
610+
await page.goto(shareableLink);
611+
await expect(page.getByText('Reporting')).toBeVisible();
612+
await expect(page.getByText(projectName)).toBeVisible();
613+
614+
// Verify the table header has all three columns
615+
await expect(page.getByText('Name', { exact: true })).toBeVisible();
616+
await expect(page.getByText('Duration', { exact: true })).toBeVisible();
617+
await expect(page.getByText('Cost', { exact: true })).toBeVisible();
618+
619+
// Verify the Total row displays both duration and cost
620+
await expect(page.getByText('Total')).toBeVisible();
621+
622+
// The data rows should render cost values (not just header + duration)
623+
// With 1h at 100/h the cost should be displayed somewhere in the table
624+
// If showCost is not passed to ReportingRow, only the header "Cost" and
625+
// the Total row cost will render, but individual row costs will be missing
626+
const table = page.locator('[style*="grid-template-columns"]');
627+
// Count elements containing the cost value - header "Cost" + project row cost + total row cost = 3
628+
// If broken (showCost not passed), the project row won't render its cost cell
629+
await expect(table.getByText(/100/).first()).toBeVisible();
630+
631+
// Verify the cost value appears at least twice in the table
632+
// (once for the data row, once for the total) beyond just the header
633+
const costValues = table.getByText(/100/);
634+
await expect(costValues).toHaveCount(2);
635+
});

resources/js/Components/Common/Reporting/ReportingOverview.vue

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -427,8 +427,7 @@ const tableData = computed(() => {
427427
v-if="showBillableRate"
428428
class="justify-end pr-6 flex items-center font-medium">
429429
{{
430-
aggregatedTableTimeEntries.cost !== null &&
431-
aggregatedTableTimeEntries.cost !== undefined
430+
aggregatedTableTimeEntries.cost
432431
? formatCents(
433432
aggregatedTableTimeEntries.cost,
434433
getOrganizationCurrencyString(),

resources/js/Pages/SharedReport.vue

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ onMounted(async () => {
222222
:key="entry.description ?? 'none'"
223223
:currency="reportCurrency"
224224
:currency-format="reportCurrencyFormat"
225+
:show-cost="true"
225226
:entry="entry"></ReportingRow>
226227
<div
227228
class="contents [&>*]:transition text-text-tertiary [&>*]:h-[50px]">
@@ -239,12 +240,15 @@ onMounted(async () => {
239240
</div>
240241
<div class="justify-end pr-6 flex items-center font-medium">
241242
{{
242-
formatCents(
243-
aggregatedTableTimeEntries.cost,
244-
reportCurrency,
245-
reportCurrencyFormat,
246-
reportCurrencySymbol
247-
)
243+
aggregatedTableTimeEntries.cost
244+
? formatCents(
245+
aggregatedTableTimeEntries.cost,
246+
reportCurrency,
247+
reportCurrencyFormat,
248+
reportCurrencySymbol,
249+
reportNumberFormat
250+
)
251+
: '--'
248252
}}
249253
</div>
250254
</div>

0 commit comments

Comments
 (0)