Implemented filters for Service Requests and Actions
This commit is contained in:
@@ -4,12 +4,14 @@ const { loadApplication } = require("./support/application.cjs");
|
||||
const flush = () => new Promise(resolve => setImmediate(resolve));
|
||||
function setup(family, saved = {}, principal = "user@example.invalid") {
|
||||
const local = {
|
||||
get: async key => ({ [key]: saved[key] }),
|
||||
set: async values => Object.assign(saved, JSON.parse(JSON.stringify(values)))
|
||||
get: async key => key === null ? { ...saved } : ({ [key]: saved[key] }),
|
||||
set: async values => Object.assign(saved, JSON.parse(JSON.stringify(values))),
|
||||
remove: async keys => keys.forEach(key => delete saved[key])
|
||||
};
|
||||
const api = family === "firefox" ? { browser: { storage: { local } } } : {
|
||||
chrome: { runtime: {}, storage: { local: {
|
||||
get: (key, done) => local.get(key).then(done), set: (values, done) => local.set(values).then(done)
|
||||
get: (key, done) => local.get(key).then(done), set: (values, done) => local.set(values).then(done),
|
||||
remove: (keys, done) => local.remove(keys).then(done)
|
||||
} } }
|
||||
};
|
||||
const app = loadApplication("content", { ...api, document: { createElement: () => ({ setAttribute() {}, addEventListener() {} }) } });
|
||||
@@ -41,6 +43,34 @@ function setup(family, saved = {}, principal = "user@example.invalid") {
|
||||
return { app, calls, load, saved, local };
|
||||
}
|
||||
for (const family of ["chrome", "firefox"]) {
|
||||
test(`${family}: Current Quarter -> Next Quarter -> Current Quarter restores SR hours and filters without requests`, async () => {
|
||||
const h = setup(family);
|
||||
const currentStamp = Date.now() - 2000;
|
||||
const nextStamp = currentStamp + 1000;
|
||||
let hours = 2;
|
||||
h.app.fusionCrmServiceRequests.requestCrmServiceRequest = async () => {
|
||||
h.calls.push("sr");
|
||||
return [{ SrNumber: "SR1", ReportedHours_c: hours, OpportunityName_Id_c: { OptyNumber: "OP1" } }];
|
||||
};
|
||||
await h.load(currentStamp, false);
|
||||
hours = 8;
|
||||
await h.load(nextStamp, false);
|
||||
assert.equal(h.app.opportunityCrmServiceRequests.getSummary("OP1").reportedHours, 8);
|
||||
const count = h.calls.length;
|
||||
await h.load(currentStamp, true);
|
||||
assert.equal(h.calls.length, count);
|
||||
assert.equal(h.app.opportunityCrmServiceRequests.createBadge("OP1").textContent, "\u2705 SR (2h)");
|
||||
h.app.opportunitiesTable.renderOpportunitiesTable = () => {};
|
||||
h.app.activityFilters.toggle("sr", "under4");
|
||||
assert.equal(h.app.activityFilters.matches({ OptyNumber: "OP1" }), true);
|
||||
await h.load(nextStamp, true);
|
||||
assert.equal(h.calls.length, count);
|
||||
assert.equal(h.app.activityFilters.matches({ OptyNumber: "OP1" }), false);
|
||||
const reopened = setup(family, h.saved);
|
||||
await reopened.load(currentStamp, true);
|
||||
assert.deepEqual(reopened.calls, []);
|
||||
assert.equal(reopened.app.opportunityCrmServiceRequests.getSummary("OP1").reportedHours, 2);
|
||||
});
|
||||
test(`${family}: activities persist across instances with product timestamps and no credential storage`, async () => {
|
||||
const h = setup(family);
|
||||
const stamp = Date.now() - 1000;
|
||||
@@ -78,6 +108,26 @@ test("TTL follows product preferences, rejects stale/mismatched cache and stores
|
||||
await h.load(stamp + 1, true);
|
||||
assert.deepEqual(h.calls, []);
|
||||
});
|
||||
|
||||
test("versioned SR cache reads matching legacy entries and prunes expired snapshots only", async () => {
|
||||
const h = setup("firefox");
|
||||
const legacyKey = `opportunitiesExtension.activities.v1:${JSON.stringify(["user@example.invalid", "sr", "all"])}`;
|
||||
const stamp = Date.now() - 1000;
|
||||
h.saved[legacyKey] = { fetchedAt: stamp, items: [], hasNext: false };
|
||||
assert.ok(await h.app.activityCache.read("sr", "all", stamp));
|
||||
assert.equal(await h.app.activityCache.read("sr", "all", stamp + 1), null);
|
||||
const expiredStamp = Date.now() - 25 * 3600000;
|
||||
const expiredKey = `opportunitiesExtension.activities.v1:${JSON.stringify(["user@example.invalid", "sr", "all", expiredStamp])}`;
|
||||
h.saved[expiredKey] = { fetchedAt: expiredStamp, items: [], hasNext: false };
|
||||
h.saved.preferences = { keep: true };
|
||||
await h.app.activityCache.write("sr", "all", stamp + 1, []);
|
||||
assert.equal(h.saved[expiredKey], undefined);
|
||||
assert.ok(h.saved[legacyKey]);
|
||||
assert.equal(h.saved.preferences.keep, true);
|
||||
await h.app.activityCache.invalidate();
|
||||
assert.equal(await h.app.activityCache.read("sr", "all", stamp + 1), null);
|
||||
assert.equal(h.saved.preferences.keep, true);
|
||||
});
|
||||
test("storage failure does not lose live activity results and failures are never cached", async () => {
|
||||
const h = setup("firefox");
|
||||
h.local.get = async () => { throw new Error("Synthetic storage read failure"); };
|
||||
|
||||
Reference in New Issue
Block a user