Files
pleno-vue/tests/unit/superuser-invoice-distribution-view.spec.js
T
Jeppe Bundgaard b39b458f4f Add .prettierrc.json and refactor test files for improved formatting consistency:
- Introduced `.prettierrc.json` to enforce consistent code formatting across the project.
- Updated unit and e2e test files to address formatting issues, improve readability, and ensure alignment with the new Prettier configuration.
2026-04-13 09:13:27 +02:00

208 lines
12 KiB
JavaScript

import { readFileSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
const root = process.cwd();
const routerSource = readFileSync(join(root, "src/router.js"), "utf8");
const invoicesViewSource = readFileSync(
join(root, "src/views/dashboards/superUserDashboard/CollectedOrderInvoices.vue"),
"utf8"
);
const distributionOverviewSource = readFileSync(
join(root, "src/views/dashboards/superUserDashboard/invoiceDistribution/InvoiceDistributionOverview.vue"),
"utf8"
);
const distributionMonthSource = readFileSync(
join(root, "src/views/dashboards/superUserDashboard/invoiceDistribution/InvoiceDistributionMonthView.vue"),
"utf8"
);
const distributionApiSource = readFileSync(
join(root, "src/views/dashboards/superUserDashboard/invoiceDistribution/imports/invoiceDistributionApi.js"),
"utf8"
);
const distributionChartSource = readFileSync(
join(
root,
"src/views/dashboards/superUserDashboard/invoiceDistribution/components/InvoiceDistributionTrendChart.vue"
),
"utf8"
);
const distributionSkeletonSource = readFileSync(
join(root, "src/views/dashboards/superUserDashboard/invoiceDistribution/components/InvoiceDistributionSkeleton.vue"),
"utf8"
);
describe("superuser invoice distribution routing", () => {
it("keeps monthly distribution routes and route contract unchanged", () => {
expect(routerSource).toContain("name: 'collectedorderinvoicesdistribution'");
expect(routerSource).toContain("path: '/superuser/invoices/distribution/:year/:month'");
expect(routerSource).toContain("name: 'collectedorderinvoicesdistributiontab'");
expect(routerSource).toContain("path: '/superuser/invoices/distribution/:year/:month/:tab'");
expect(routerSource).toContain("component: InvoiceDistributionMonthView");
});
});
describe("CollectedOrderInvoices distribution tab contract", () => {
it("keeps Distribution tab wired to overview component", () => {
expect(invoicesViewSource).toContain("slot: 'distribution'");
expect(invoicesViewSource).toContain("name: t('superuser_invoice_distribution.tab_label')");
expect(invoicesViewSource).toContain("case 'distribution':");
expect(invoicesViewSource).toContain("return InvoiceDistributionOverview;");
});
});
describe("Distribution overview contract", () => {
it("renders decision-first shell sections and executive scanning order", () => {
expect(distributionOverviewSource).toContain('class="overview-header hero-surface"');
expect(distributionOverviewSource).toContain('class="control-toolbar');
expect(distributionOverviewSource).toContain('class="kpi-strip"');
expect(distributionOverviewSource).toContain('class="chart-section"');
expect(distributionOverviewSource).toContain("distribution-table");
expect(distributionOverviewSource).toContain('class="insights-grid"');
});
it("supports month/total sorting and source composition cues", () => {
expect(distributionOverviewSource).toContain("const sortKey = ref('month')");
expect(distributionOverviewSource).toContain("const sortDirection = ref('desc')");
expect(distributionOverviewSource).toContain("setSort('month')");
expect(distributionOverviewSource).toContain("setSort('total')");
expect(distributionOverviewSource).toContain("sortMonthSummaries(filteredMonthSummaries.value");
expect(distributionOverviewSource).toContain("source-composition__segment--fixed");
expect(distributionOverviewSource).toContain("source-composition__segment--subscription");
expect(distributionOverviewSource).toContain("source-composition__segment--customer-prices");
expect(distributionOverviewSource).toContain("metrics.customer_prices");
});
it("keeps loading, error, and empty states with recovery actions", () => {
expect(distributionOverviewSource).toContain("InvoiceDistributionSkeleton");
expect(distributionOverviewSource).toContain("superuser_invoice_distribution.errors.overview_load_failed");
expect(distributionOverviewSource).toContain("superuser_invoice_distribution.actions.try_again");
expect(distributionOverviewSource).toContain("superuser_invoice_distribution.empty.no_months");
});
});
describe("Distribution monthly view contract", () => {
it("uses route params for tab selection and month navigation", () => {
expect(distributionMonthSource).toContain("const TABS = ['overview', 'departments', 'customers', 'compare']");
expect(distributionMonthSource).toContain("/superuser/invoices/distribution/${year}/${month}/${tab}");
expect(distributionMonthSource).toContain("() => route.params.tab");
expect(distributionMonthSource).toContain("watch(activeTab, async (tab) => {");
});
it("hydrates and syncs high-value controls through URL query state", () => {
expect(distributionMonthSource).toContain("const QUERY_KEYS = [");
expect(distributionMonthSource).toContain("'compareMonth'");
expect(distributionMonthSource).toContain("'compareMode'");
expect(distributionMonthSource).toContain("'compareVisibility'");
expect(distributionMonthSource).toContain("'customerSearch'");
expect(distributionMonthSource).toContain("'customerSource'");
expect(distributionMonthSource).toContain("'customerDepartment'");
expect(distributionMonthSource).toContain("'departmentSearch'");
expect(distributionMonthSource).toContain("normalizeDistributionQueryState(route.query)");
expect(distributionMonthSource).toContain("buildDistributionQueryState({");
expect(distributionMonthSource).toContain("router.replace({");
});
it("keeps workflow toolbar priority and summary ribbon", () => {
expect(distributionMonthSource).toContain('class="v3-toolbar-card');
expect(distributionMonthSource).toContain('class="v3-hero-card');
expect(distributionMonthSource).toContain("distribution-month-prev");
expect(distributionMonthSource).toContain("distribution-month-next");
expect(distributionMonthSource).toContain("distribution-compare-month-picker");
expect(distributionMonthSource).toContain("distribution-run-compare");
expect(distributionMonthSource).toContain('class="summary-ribbon');
});
it("renders upgraded tab content for overview/departments/customers/compare", () => {
expect(distributionMonthSource).toContain('value="overview"');
expect(distributionMonthSource).toContain('value="departments"');
expect(distributionMonthSource).toContain('value="customers"');
expect(distributionMonthSource).toContain('value="compare"');
expect(distributionMonthSource).toContain('class="v3-overview-grid');
expect(distributionMonthSource).toContain('class="v3-surface');
expect(distributionMonthSource).toContain("allocation-chips");
expect(distributionMonthSource).toContain("sortCompareRows(compareRows.value)");
expect(distributionMonthSource).toContain("selectedWarningInvoiceId");
expect(distributionMonthSource).toContain("warning-panel__header");
expect(distributionMonthSource).toContain('value="customer_prices"');
expect(distributionMonthSource).toContain("distribution-compare-visibility-picker");
expect(distributionMonthSource).toContain("monthFallback.usedLegacyDistribution");
expect(distributionMonthSource).toContain("monthFallback.usedSplitV2Distribution");
expect(distributionMonthSource).toContain("compareFallback.usedLegacyCompare");
expect(distributionMonthSource).toContain("compareFallback.usedSingleCompareFallback");
});
it("keeps department footer totals excluding customer prices from the total column", () => {
expect(distributionMonthSource).toContain("buildDepartmentAllocationFooterTotals");
expect(distributionMonthSource).toContain('class="department-table__footer"');
expect(distributionMonthSource).toContain("departmentFooterTotals.totalAmount");
expect(distributionMonthSource).toContain('has-text-grey">-</td>');
});
it("keeps compare mode values and progress visibility", () => {
expect(distributionMonthSource).toContain("const compareMode = ref('invoice_total')");
expect(distributionMonthSource).toContain("DISTRIBUTION_COMPARE_MODES");
expect(distributionMonthSource).toContain("line_by_line");
expect(distributionMonthSource).toContain("compareProgress");
expect(distributionMonthSource).toContain("compareCompletionPercent");
expect(distributionMonthSource).toContain("onRows:");
expect(distributionMonthSource).toContain("aggregateCompareRows(streamedRows)");
});
});
describe("Distribution accessibility contract", () => {
it("adds aria labels, table captions, and focus-visible styles", () => {
expect(distributionOverviewSource).toContain("aria-label");
expect(distributionOverviewSource).toContain("<caption>");
expect(distributionOverviewSource).toContain("focus-visible");
expect(distributionMonthSource).toContain("aria-label");
expect(distributionMonthSource).toContain("<caption>");
expect(distributionMonthSource).toContain("focus-visible");
});
});
describe("Distribution API adapter contract", () => {
it("uses period endpoint and supports v2 all/split distribution with legacy fallback", () => {
expect(distributionApiSource).toContain("'/superuser/invoicing/period'");
expect(distributionApiSource).toContain("'/superuser/invoicing/period/distribution/v2/all'");
expect(distributionApiSource).toContain("'/superuser/invoicing/period/distribution/v2/fixed-pricing'");
expect(distributionApiSource).toContain("'/superuser/invoicing/period/distribution/v2/wash-subscriptions'");
expect(distributionApiSource).toContain("'/superuser/invoicing/period/distribution/v2/customer-prices'");
expect(distributionApiSource).toContain("'/superuser/invoicing/period/distribution/fixed-pricing'");
expect(distributionApiSource).toContain("'/superuser/invoicing/period/distribution/wash-subscriptions'");
expect(distributionApiSource).toContain("usedLegacyDistribution");
expect(distributionApiSource).toContain("usedSplitV2Distribution");
expect(distributionApiSource).toContain("dateFrom");
expect(distributionApiSource).toContain("dateTo");
});
it("runs month compare against v2 bulk endpoint with single-v2 and legacy fallback paths", () => {
expect(distributionApiSource).toContain("compareCollectedInvoicesForMonth");
expect(distributionApiSource).toContain("'/collected-invoices/economic/v2/compare/bulk'");
expect(distributionApiSource).toContain("'/collected-invoices/economic/v2/compare'");
expect(distributionApiSource).toContain("'/collected-invoices/economic/compare'");
expect(distributionApiSource).toContain("usedLegacyCompare");
expect(distributionApiSource).toContain("usedSingleCompareFallback");
expect(distributionApiSource).toContain("normalizeCompareResult");
expect(distributionApiSource).toContain("aggregateCompareRows");
});
});
describe("Distribution visual components contract", () => {
it("uses chart.js line chart with four datasets and aria label support", () => {
expect(distributionChartSource).toContain("import { Line } from 'vue-chartjs'");
expect(distributionChartSource).toContain("label: props.labels.total");
expect(distributionChartSource).toContain("label: props.labels.booked");
expect(distributionChartSource).toContain("label: props.labels.distribution");
expect(distributionChartSource).toContain("label: props.labels.customerPrices");
expect(distributionChartSource).toContain("ariaLabel");
});
it("provides reusable skeleton shimmer component", () => {
expect(distributionSkeletonSource).toContain("loading-shimmer");
expect(distributionSkeletonSource).toContain('v-for="index in rows"');
expect(distributionSkeletonSource).toContain("skeleton-block");
});
});