Fixed the date ranges for the Reference options
This commit is contained in:
@@ -48,7 +48,7 @@ test("Redwood cascade is byte-identical to the characterized original", () => {
|
||||
test("fiscal module can run alone without DOM, browser APIs or network", () => {
|
||||
const factory = new vm.Script(`${read("src/features/opportunities/fiscal-periods.js")}\ncreateOpportunitiesFiscalPeriods;`).runInNewContext();
|
||||
assert.deepEqual(json(factory().getFiscalPeriodRange("Current Fiscal Year", new Date(2027, 0, 15))), {
|
||||
startCloseDate: "2026-06-01T00:00:00.000Z", endCloseDate: "2027-05-31T00:00:00.000Z"
|
||||
startCloseDate: "2026-06-01T00:00:00.000Z", endCloseDate: "2027-06-01T00:00:00.000Z"
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ const FILTER_KEY = "opportunities-extension-filter-preferences";
|
||||
const TYPE_KEY = "opportunities-extension-opportunity-type-preferences";
|
||||
const CACHE_KEY = "opportunitiesExtension.opptyProductsCache.v1";
|
||||
const DAY = 86400000;
|
||||
const range = { startCloseDate: "2026-06-01T00:00:00.000Z", endCloseDate: "2026-08-31T00:00:00.000Z" };
|
||||
const range = { startCloseDate: "2026-06-01T00:00:00.000Z", endCloseDate: "2026-09-01T00:00:00.000Z" };
|
||||
const drain = () => new Promise(resolve => setImmediate(resolve));
|
||||
const productRequest = (requestId, optyNumbers = ["SYNTH-1"]) => ({
|
||||
type: PREFIX + "requestOpptyProducts", requestId, optyNumbers, accessToken: "synthetic-products-token"
|
||||
@@ -63,21 +63,47 @@ test("distribution contracts: manifests, execution boundaries and deterministic
|
||||
test("fiscal dates preserve quarter/year boundaries, leap year and unsupported renewals", () => {
|
||||
const h = loadContent();
|
||||
const cases = [
|
||||
["Current Quarter", [2026, 5, 1], "2026-06-01", "2026-08-31"],
|
||||
["Current Quarter", [2026, 7, 31], "2026-06-01", "2026-08-31"],
|
||||
["Current Quarter", [2026, 8, 1], "2026-09-01", "2026-11-30"],
|
||||
["Current Quarter", [2028, 1, 29], "2027-12-01", "2028-02-29"],
|
||||
["Next Quarter", [2026, 10, 30], "2026-12-01", "2027-02-28"],
|
||||
["Previous Quarter", [2026, 7, 24], "2026-03-01", "2026-05-31"],
|
||||
["Current Fiscal Year", [2026, 4, 31], "2025-06-01", "2026-05-31"],
|
||||
["Current Fiscal Year", [2026, 5, 1], "2026-06-01", "2027-05-31"],
|
||||
["Current Fiscal Year", [2027, 0, 1], "2026-06-01", "2027-05-31"],
|
||||
["4 Rolling Quarters (CQ + 3)", [2026, 8, 16], "2026-09-01", "2027-08-31"]
|
||||
["Current Quarter", [2026, 0, 1], "2025-12-01", "2026-03-01"],
|
||||
["Current Quarter", [2026, 1, 28], "2025-12-01", "2026-03-01"],
|
||||
["Current Quarter", [2026, 2, 1], "2026-03-01", "2026-06-01"],
|
||||
["Current Quarter", [2026, 4, 31], "2026-03-01", "2026-06-01"],
|
||||
["Current Quarter", [2026, 5, 1], "2026-06-01", "2026-09-01"],
|
||||
["Current Quarter", [2026, 7, 31], "2026-06-01", "2026-09-01"],
|
||||
["Current Quarter", [2026, 8, 1], "2026-09-01", "2026-12-01"],
|
||||
["Current Quarter", [2026, 9, 19], "2026-09-01", "2026-12-01"],
|
||||
["Current Quarter", [2026, 10, 30], "2026-09-01", "2026-12-01"],
|
||||
["Current Quarter", [2026, 11, 1], "2026-12-01", "2027-03-01"],
|
||||
["Current Quarter", [2026, 11, 31], "2026-12-01", "2027-03-01"],
|
||||
["Current Quarter", [2028, 1, 29], "2027-12-01", "2028-03-01"],
|
||||
["Next Quarter", [2026, 0, 1], "2026-03-01", "2026-06-01"],
|
||||
["Next Quarter", [2026, 4, 31], "2026-06-01", "2026-09-01"],
|
||||
["Next Quarter", [2026, 5, 1], "2026-09-01", "2026-12-01"],
|
||||
["Next Quarter", [2026, 10, 30], "2026-12-01", "2027-03-01"],
|
||||
["Next Quarter", [2026, 11, 1], "2027-03-01", "2027-06-01"],
|
||||
["Previous Quarter", [2026, 0, 1], "2025-09-01", "2025-12-01"],
|
||||
["Previous Quarter", [2026, 2, 1], "2025-12-01", "2026-03-01"],
|
||||
["Previous Quarter", [2026, 5, 1], "2026-03-01", "2026-06-01"],
|
||||
["Previous Quarter", [2026, 8, 1], "2026-06-01", "2026-09-01"],
|
||||
["Previous Quarter", [2026, 11, 1], "2026-09-01", "2026-12-01"],
|
||||
["Current Fiscal Year", [2026, 0, 1], "2025-06-01", "2026-06-01"],
|
||||
["Current Fiscal Year", [2026, 4, 31], "2025-06-01", "2026-06-01"],
|
||||
["Current Fiscal Year", [2026, 5, 1], "2026-06-01", "2027-06-01"],
|
||||
["Current Fiscal Year", [2027, 0, 1], "2026-06-01", "2027-06-01"],
|
||||
["4 Rolling Quarters (CQ + 3)", [2026, 0, 1], "2025-12-01", "2026-12-01"],
|
||||
["4 Rolling Quarters (CQ + 3)", [2026, 2, 1], "2026-03-01", "2027-03-01"],
|
||||
["4 Rolling Quarters (CQ + 3)", [2026, 5, 1], "2026-06-01", "2027-06-01"],
|
||||
["4 Rolling Quarters (CQ + 3)", [2026, 8, 16], "2026-09-01", "2027-09-01"],
|
||||
["4 Rolling Quarters (CQ + 3)", [2026, 11, 1], "2026-12-01", "2027-12-01"]
|
||||
];
|
||||
for (const [period, date, start, end] of cases) {
|
||||
assert.deepEqual(plain(h.getFiscalPeriodRange(period, new Date(...date))), {
|
||||
startCloseDate: start + "T00:00:00.000Z", endCloseDate: end + "T00:00:00.000Z"
|
||||
});
|
||||
const dateRange = h.getFiscalPeriodRange(period, new Date(...date));
|
||||
const criterion = h.createOpportunitiesQueryPayload(dateRange, 0).q.criteria[1];
|
||||
assert.equal(criterion.value1, start + "T00:00:00.000+0000");
|
||||
assert.equal(criterion.value2, end + "T00:00:00.000+0000");
|
||||
assert.equal(dateRange.endCloseDate, end + "T00:00:00.000Z", "payload must not mutate the shared date range");
|
||||
}
|
||||
assert.equal(h.getFiscalPeriodRange("RENEWALS (Current + Past Due)", new Date()), null);
|
||||
});
|
||||
@@ -90,11 +116,11 @@ test("opportunity query preserves fields, record-set OR, date AND, and paginatio
|
||||
assert.deepEqual(plain(h.createOpportunitiesQueryPayload(range, 15)), {
|
||||
aggregationResults: false, applications: ["ORACLE-ISS-APP"], onlyData: true, entity: "Opportunity",
|
||||
q: { op: "$and", criteria: [
|
||||
{ op: "$or", criteria: types.map(value => ({ op: "$eq", attribute: "RecordSet", value })) },
|
||||
{ op: "$wi", attribute: "EffectiveDate", value1: range.startCloseDate, value2: range.endCloseDate, dynamicDate: false }
|
||||
{ op: "$and", criteria: [{ op: "$or", criteria: types.map(value => ({ op: "$eq", attribute: "RecordSet", value })) }] },
|
||||
{ op: "$wi", attribute: "EffectiveDate", value1: "2026-06-01T00:00:00.000+0000", value2: "2026-09-01T00:00:00.000+0000" }
|
||||
] }, keywords: null, keywordsFields: fields,
|
||||
fields: [...fields, "CustomerAccount.PartyUniqueName", "CustomerAccount.PartyId", "CustomerAccount.PartyNumber", "CustomerAccount.Region_c", "CustomerAccount.PrimaryAddress.CountryCode"],
|
||||
sort: [], language: "en", skipInValidFields: true, skipHiddenFromUIFields: true,
|
||||
sort: null, language: "en", skipInValidFields: true, skipHiddenFromUIFields: true,
|
||||
copiedFrom: "queries/d5dbcd01-9ff3-40be-9b5b-64744cbf7162", limit: 15, offset: 15
|
||||
});
|
||||
});
|
||||
@@ -163,6 +189,15 @@ test("filter storage round-trip, WON_PENDING membership, search, sorting and ref
|
||||
assert.equal(reopened.filters().ownerSearch, "");
|
||||
});
|
||||
|
||||
test("removed renewals reference falls back to Current Quarter without losing other filters", () => {
|
||||
const storage = new Map([[FILTER_KEY, JSON.stringify({ period: "RENEWALS (Current + Past Due)", tableSearch: "cloud" })]]);
|
||||
const h = loadContent({ storage });
|
||||
const select = { value: "Current Quarter" };
|
||||
h.restoreFilterPreferences(select);
|
||||
assert.equal(select.value, "Current Quarter");
|
||||
assert.equal(h.filters().tableSearch, "cloud");
|
||||
});
|
||||
|
||||
test("malformed preferences fall back, while theme/type/cache keys retain their schema", () => {
|
||||
const storage = new Map([[FILTER_KEY, "not JSON"], ["opportunities-extension-theme", "dark"],
|
||||
[TYPE_KEY, JSON.stringify({ opportunityTypeValues: ["ORA_MYOPTIES", "UNKNOWN"], opptyProductsCacheHours: 24 })]]);
|
||||
|
||||
@@ -174,70 +174,28 @@ test("SR Save validates form, maps dynamic values, locks duplicate clicks and pr
|
||||
assert.equal(posts[0].message.phase, "prepare");
|
||||
const preparedPayload = { ...payload, ReportedByPartyId: 303, SvcQuestionsCollection_c: [],
|
||||
SourceCd: "SVC_OPPORTUNITY_SCREEN", SeverityCd: "ORA_SVC_SEV2", ChannelTypeCd: "ORA_SVC_WEB" };
|
||||
const preparedHeaders = {
|
||||
requestSrTokenCatalog: { Authorization: "Session", "Content-Type": "application/vnd.oracle.adf.action+json", Origin: "https://example.invalid" },
|
||||
requestPostServiceRequest: { Authorization: "Session", "Content-Type": "application/vnd.oracle.adf.action+json", Origin: "https://example.invalid", "vb-proxy-header-x-oracle-ectoken": "(generated after confirmation)" }
|
||||
};
|
||||
posts[0].resolve({ ok: true, payload: preparedPayload, headers: preparedHeaders });
|
||||
posts[0].resolve({ ok: true, payload: preparedPayload });
|
||||
await flush();
|
||||
const confirmation = () => h.nodes().find(node => node.className?.includes("opportunities-extension-sr-confirmation"));
|
||||
const confirm = () => h.nodes().find(node => node.textContent === "Confirm Save");
|
||||
assert.ok(confirmation());
|
||||
const preview = h.nodes().find(node => node.tag === "pre");
|
||||
assert.equal(preview.textContent, JSON.stringify(preparedPayload, null, 2));
|
||||
const previews = h.nodes().filter(node => node.tag === "pre");
|
||||
assert.equal(previews.length, 3);
|
||||
assert.equal(previews[1].textContent, JSON.stringify(preparedHeaders.requestSrTokenCatalog, null, 2));
|
||||
assert.equal(previews[2].textContent, JSON.stringify(preparedHeaders.requestPostServiceRequest, null, 2));
|
||||
assert.ok(h.nodes().some(node => node.textContent === "x-appbuilder-client-id: not yet observed in SeaaS requests."));
|
||||
assert.equal(h.form().parent.inert, true);
|
||||
assert.equal(h.document.activeElement.textContent, "Cancel");
|
||||
assert.equal(h.nodes().some(node => node.className?.includes("opportunities-extension-sr-confirmation")), false);
|
||||
assert.equal(h.nodes().some(node => node.textContent === "Confirm Save"), false);
|
||||
assert.equal(posts.length, 2, "Save proceeds directly from preparation to creation");
|
||||
assert.equal(posts[1].message.phase, "confirm");
|
||||
assert.deepEqual(posts[1].message.payload, preparedPayload);
|
||||
assert.equal(save().textContent, "Saving...");
|
||||
await submit();
|
||||
assert.equal(posts.length, 1, "awaiting confirmation must never send a creation request");
|
||||
confirm().focus();
|
||||
confirmation().listeners.keydown({ key: "Tab", preventDefault() {}, stopPropagation() {} });
|
||||
assert.equal(h.document.activeElement, preview);
|
||||
h.nodes().filter(node => node.tag === "button" && node.textContent === "Cancel").at(-1).click();
|
||||
assert.equal(posts.length, 2, "duplicate clicks cannot create another SR");
|
||||
posts[1].resolve({ ok: false, error: "Synthetic failure" });
|
||||
await saving;
|
||||
assert.equal(posts.length, 1, "Cancel never creates SR");
|
||||
assert.equal(confirmation(), undefined);
|
||||
assert.equal(h.form().parent.inert, false);
|
||||
assert.equal(notices.at(-1)[1], true);
|
||||
assert.equal(save().disabled, false);
|
||||
assert.equal(h.nodes().find(node => node.name === "description").value, "Dynamic description");
|
||||
assert.equal(h.document.activeElement, save());
|
||||
assert.equal(notices.length, 0);
|
||||
|
||||
const escaped = submit();
|
||||
posts[1].resolve({ ok: true, payload: preparedPayload });
|
||||
await flush();
|
||||
confirmation().listeners.keydown({ key: "Escape", preventDefault() {}, stopPropagation() {} });
|
||||
await escaped;
|
||||
assert.equal(posts.length, 2);
|
||||
assert.ok(h.form(), "Escape closes only the confirmation");
|
||||
|
||||
const failed = submit();
|
||||
posts[2].resolve({ ok: true, payload: preparedPayload });
|
||||
await flush();
|
||||
const confirmButton = confirm();
|
||||
confirmButton.click();
|
||||
confirmButton.click();
|
||||
await flush();
|
||||
assert.equal(posts.length, 4, "double confirm sends only one creation request");
|
||||
assert.equal(posts[3].message.phase, "confirm");
|
||||
assert.deepEqual(posts[3].message.payload, preparedPayload);
|
||||
assert.equal(posts[3].message.payload.AccountPartyId, 100000000000101);
|
||||
assert.equal(save().textContent, "Saving...");
|
||||
posts[3].resolve({ ok: false, error: "Synthetic failure" });
|
||||
await failed;
|
||||
assert.equal(notices.at(-1)[1], true);
|
||||
delete h.app.opportunitiesTableState.opportunitiesTableState.items[1].CustomerAccount.CountryCode;
|
||||
const retry = submit();
|
||||
assert.equal(posts[4].message.payload.CountryText_c, "BR", "uses PrimaryAddress.CountryCode even without CustomerAccount.CountryCode");
|
||||
posts[4].resolve({ ok: true, payload: preparedPayload });
|
||||
assert.equal(posts[2].message.payload.CountryText_c, "BR", "uses PrimaryAddress.CountryCode even without CustomerAccount.CountryCode");
|
||||
posts[2].resolve({ ok: true, payload: preparedPayload });
|
||||
await flush();
|
||||
confirm().click();
|
||||
await flush();
|
||||
posts[5].resolve({ ok: true, result: { SrId: 505, SrNumber: "SR505" } });
|
||||
assert.equal(posts.length, 4);
|
||||
posts[3].resolve({ ok: true, result: { SrId: 505, SrNumber: "SR505" } });
|
||||
await retry;
|
||||
assert.equal(h.form(), undefined);
|
||||
assert.equal(notices.at(-1)[0], "Service Request saved successfully.");
|
||||
|
||||
Reference in New Issue
Block a user