Added a badge to display the monthly ramp

This commit is contained in:
2026-09-23 23:24:31 -03:00
parent 3ef0d2aafd
commit b92d75f558
11 changed files with 229 additions and 21 deletions

View File

@@ -68,6 +68,29 @@ test("ten columns retain their links and put product/customer controls below the
assert.equal(findClass(h.cell("customer"), "opportunities-extension-products-count"), undefined);
});
test("ramp months preserve zero and flag missing values beside the product count", () => {
const h = setup();
const badge = () => findClass(h.cell("name"), "opportunities-extension-products-ramp");
assert.equal(badge(), undefined);
for (const [values, expected] of [
[[], null], [[null], "RM N/D"], [[null, undefined, "", " "], "RM N/D"], [[6], "RM 6"],
[[0], "RM 0"], [[0, "3", null, " 6 ", 3], "RM 0,3,N/D,6,3"]
]) {
h.app.productsContentState.opptyProductsByNumber.set("TEST-1", {
fromCache: true, items: values.map(RampMonths_c => ({ RampMonths_c }))
});
h.app.opportunitiesTable.renderOpportunitiesTable();
if (expected === null) assert.equal(badge(), undefined);
else {
assert.equal(badge().textContent, expected);
assert.equal(badge().attributes["data-missing"], String(expected.includes("N/D")));
assert.match(badge().title, /^Ramp Months:/);
assert.equal(h.cell("name").children[0].children[1].children[1], badge());
}
assert.equal(findClass(h.cell("name"), "opportunities-extension-products-count").textContent, String(values.length));
}
});
test("products remain expandable with AI summary and a ten-column detail row after sorting", () => {
const h = setup([synthetic("B", "Zulu"), synthetic("A", "Alpha")]);
h.app.productsContentState.opptyProductsByNumber.set("B", { items: [{ ProdGroupName: "Cloud", RevnAmount: "10" }] });
@@ -86,6 +109,18 @@ test("products remain expandable with AI summary and a ten-column detail row aft
assert.deepEqual(h.summaries, ["B"], "collapsing does not generate another summary");
});
test("product table distinguishes unavailable ramp months from numeric zero", () => {
const h = setup();
h.app.productsContentState.opptyProductsByNumber.set("TEST-1", {
items: [null, undefined, "", " ", 0, "0", 6].map(RampMonths_c => ({ RampMonths_c }))
});
h.app.opportunitiesTable.renderOpportunitiesTable();
findClass(h.cell("name"), "opportunities-extension-products-count").click();
const table = findClass(h.rows()[1], "opportunities-extension-products-table");
const rows = table.children.find(child => child.tag === "tbody").children;
assert.deepEqual(rows.map(row => row.children[9].textContent), ["N/D", "N/D", "N/D", "N/D", "0", "0", "6"]);
});
test("customer consumption still opens immediately, uses the right customer and preserves loading state", async () => {
const h = setup();
const opens = [];
@@ -151,7 +186,10 @@ test("table styles reserve compact widths, prioritize Name/Customer and keep nes
assert.match(css, /flex: 0 0 24px/);
assert.match(css, /td\[data-column="customer"\] \{\s*position: relative;/);
assert.match(css, /grid-template-columns: minmax\(0, 1fr\) 12px/);
assert.doesNotMatch(css, /text-overflow: ellipsis|overflow: hidden|th:nth-child|td:nth-child/);
const tableRules = css.replace(/[^{}]*\.opportunities-extension-products-ramp\s*\{[^}]*\}/g, "");
assert.doesNotMatch(tableRules, /text-overflow: ellipsis|overflow: hidden|th:nth-child|td:nth-child/);
assert.match(css, /\.opportunities-extension-products-ramp\s*\{[^}]*background: #f0e8f7/);
assert.match(css, /\[data-theme="dark"\] \.opportunities-extension-products-ramp\s*\{[^}]*color: #ead5fc/);
for (const width of [1120, 1280, 1440, 1840]) {
const remaining = width - fixed;
assert.equal(fixed + remaining / 2 + remaining / 2, width);