Implementation of the customer consumption display
This commit is contained in:
71
dist/chromium/background.js
vendored
71
dist/chromium/background.js
vendored
@@ -20,6 +20,13 @@
|
|||||||
const CUSTOMER_TOKEN_SERVICE_URL = "https://spa.oracle.com/oalcrm/web/api/g2m-consumer-application/consumerTokenService";
|
const CUSTOMER_TOKEN_SERVICE_URL = "https://spa.oracle.com/oalcrm/web/api/g2m-consumer-application/consumerTokenService";
|
||||||
const ACCOUNT_SUMMARY_URL = "https://spa.oracle.com/oalcrm/web/api/provider-proxy/g2m-account/service/accountsummary";
|
const ACCOUNT_SUMMARY_URL = "https://spa.oracle.com/oalcrm/web/api/provider-proxy/g2m-account/service/accountsummary";
|
||||||
const ACCOUNT_PLANS_URL = "https://spa.oracle.com/oalcrm/web/api/provider-proxy/g2m-consumption/service/v1/account/accountPlans";
|
const ACCOUNT_PLANS_URL = "https://spa.oracle.com/oalcrm/web/api/provider-proxy/g2m-consumption/service/v1/account/accountPlans";
|
||||||
|
const CONSUMPTION_TREND_URL = "https://spa.oracle.com/oalcrm/web/api/provider-proxy/g2m-consumption/service/v1/plan/trend";
|
||||||
|
const CONSUMPTION_TREND_REQUESTS = {
|
||||||
|
quarterly: "requestConsumptionServiceQuarterly",
|
||||||
|
monthly: "requestConsumptionServiceMonthly",
|
||||||
|
weekly: "requestConsumptionServiceWeekly",
|
||||||
|
daily: "requestConsumptionServiceDaily"
|
||||||
|
};
|
||||||
const ACCOUNT_PLANS_PAYLOAD = {
|
const ACCOUNT_PLANS_PAYLOAD = {
|
||||||
hierarchy: "single",
|
hierarchy: "single",
|
||||||
products: "all",
|
products: "all",
|
||||||
@@ -149,6 +156,20 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (message.type === "opportunitiesExtension.requestConsumptionTrend") {
|
||||||
|
requestConsumptionTrend(message)
|
||||||
|
.then(sendResponse)
|
||||||
|
.catch((error) => {
|
||||||
|
sendResponse({
|
||||||
|
ok: false,
|
||||||
|
error: error.message || "Unable to load consumption trend.",
|
||||||
|
debugRequests: Array.isArray(error.debugRequests) ? error.debugRequests : []
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -282,6 +303,56 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function requestConsumptionTrend(message) {
|
||||||
|
const subPlanNum = typeof message.subPlanNum === "string" ? message.subPlanNum.trim() : "";
|
||||||
|
const period = typeof message.period === "string" ? message.period.toLowerCase() : "";
|
||||||
|
const requestName = CONSUMPTION_TREND_REQUESTS[period];
|
||||||
|
const authorization = normalizeMessageAuthorization(message.authorization, "g2m-authorization");
|
||||||
|
const debugRequests = [];
|
||||||
|
|
||||||
|
if (!subPlanNum) {
|
||||||
|
throw new Error("Sub plan number is required for the consumption trend.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!requestName) {
|
||||||
|
throw new Error(`Unsupported consumption trend period: ${period || "(missing)"}.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!authorization.value) {
|
||||||
|
throw new Error("OCICONS-TS authorization is unavailable for the consumption trend.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = `${CONSUMPTION_TREND_URL}/${encodeURIComponent(subPlanNum)}?quarter=All&timePeriod=${period}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetchJson(url, {
|
||||||
|
method: "GET",
|
||||||
|
credentials: "include",
|
||||||
|
cache: "no-store",
|
||||||
|
headers: {
|
||||||
|
Accept: "application/json",
|
||||||
|
"G2m-Authorization": authorization.value
|
||||||
|
}
|
||||||
|
}, requestName, debugRequests);
|
||||||
|
const items = Array.isArray(response)
|
||||||
|
? response
|
||||||
|
: Array.isArray(response && response.items)
|
||||||
|
? response.items
|
||||||
|
: [];
|
||||||
|
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
subPlanNum,
|
||||||
|
period,
|
||||||
|
items,
|
||||||
|
debugRequests
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
error.debugRequests = debugRequests;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeMessageAuthorization(authorization, fallbackHeaderName) {
|
function normalizeMessageAuthorization(authorization, fallbackHeaderName) {
|
||||||
const headerName = authorization && typeof authorization.name === "string"
|
const headerName = authorization && typeof authorization.name === "string"
|
||||||
? authorization.name.trim()
|
? authorization.name.trim()
|
||||||
|
|||||||
1308
dist/chromium/content.js
vendored
1308
dist/chromium/content.js
vendored
File diff suppressed because it is too large
Load Diff
71
dist/firefox/background.js
vendored
71
dist/firefox/background.js
vendored
@@ -20,6 +20,13 @@
|
|||||||
const CUSTOMER_TOKEN_SERVICE_URL = "https://spa.oracle.com/oalcrm/web/api/g2m-consumer-application/consumerTokenService";
|
const CUSTOMER_TOKEN_SERVICE_URL = "https://spa.oracle.com/oalcrm/web/api/g2m-consumer-application/consumerTokenService";
|
||||||
const ACCOUNT_SUMMARY_URL = "https://spa.oracle.com/oalcrm/web/api/provider-proxy/g2m-account/service/accountsummary";
|
const ACCOUNT_SUMMARY_URL = "https://spa.oracle.com/oalcrm/web/api/provider-proxy/g2m-account/service/accountsummary";
|
||||||
const ACCOUNT_PLANS_URL = "https://spa.oracle.com/oalcrm/web/api/provider-proxy/g2m-consumption/service/v1/account/accountPlans";
|
const ACCOUNT_PLANS_URL = "https://spa.oracle.com/oalcrm/web/api/provider-proxy/g2m-consumption/service/v1/account/accountPlans";
|
||||||
|
const CONSUMPTION_TREND_URL = "https://spa.oracle.com/oalcrm/web/api/provider-proxy/g2m-consumption/service/v1/plan/trend";
|
||||||
|
const CONSUMPTION_TREND_REQUESTS = {
|
||||||
|
quarterly: "requestConsumptionServiceQuarterly",
|
||||||
|
monthly: "requestConsumptionServiceMonthly",
|
||||||
|
weekly: "requestConsumptionServiceWeekly",
|
||||||
|
daily: "requestConsumptionServiceDaily"
|
||||||
|
};
|
||||||
const ACCOUNT_PLANS_PAYLOAD = {
|
const ACCOUNT_PLANS_PAYLOAD = {
|
||||||
hierarchy: "single",
|
hierarchy: "single",
|
||||||
products: "all",
|
products: "all",
|
||||||
@@ -149,6 +156,20 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (message.type === "opportunitiesExtension.requestConsumptionTrend") {
|
||||||
|
requestConsumptionTrend(message)
|
||||||
|
.then(sendResponse)
|
||||||
|
.catch((error) => {
|
||||||
|
sendResponse({
|
||||||
|
ok: false,
|
||||||
|
error: error.message || "Unable to load consumption trend.",
|
||||||
|
debugRequests: Array.isArray(error.debugRequests) ? error.debugRequests : []
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -282,6 +303,56 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function requestConsumptionTrend(message) {
|
||||||
|
const subPlanNum = typeof message.subPlanNum === "string" ? message.subPlanNum.trim() : "";
|
||||||
|
const period = typeof message.period === "string" ? message.period.toLowerCase() : "";
|
||||||
|
const requestName = CONSUMPTION_TREND_REQUESTS[period];
|
||||||
|
const authorization = normalizeMessageAuthorization(message.authorization, "g2m-authorization");
|
||||||
|
const debugRequests = [];
|
||||||
|
|
||||||
|
if (!subPlanNum) {
|
||||||
|
throw new Error("Sub plan number is required for the consumption trend.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!requestName) {
|
||||||
|
throw new Error(`Unsupported consumption trend period: ${period || "(missing)"}.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!authorization.value) {
|
||||||
|
throw new Error("OCICONS-TS authorization is unavailable for the consumption trend.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = `${CONSUMPTION_TREND_URL}/${encodeURIComponent(subPlanNum)}?quarter=All&timePeriod=${period}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetchJson(url, {
|
||||||
|
method: "GET",
|
||||||
|
credentials: "include",
|
||||||
|
cache: "no-store",
|
||||||
|
headers: {
|
||||||
|
Accept: "application/json",
|
||||||
|
"G2m-Authorization": authorization.value
|
||||||
|
}
|
||||||
|
}, requestName, debugRequests);
|
||||||
|
const items = Array.isArray(response)
|
||||||
|
? response
|
||||||
|
: Array.isArray(response && response.items)
|
||||||
|
? response.items
|
||||||
|
: [];
|
||||||
|
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
subPlanNum,
|
||||||
|
period,
|
||||||
|
items,
|
||||||
|
debugRequests
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
error.debugRequests = debugRequests;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeMessageAuthorization(authorization, fallbackHeaderName) {
|
function normalizeMessageAuthorization(authorization, fallbackHeaderName) {
|
||||||
const headerName = authorization && typeof authorization.name === "string"
|
const headerName = authorization && typeof authorization.name === "string"
|
||||||
? authorization.name.trim()
|
? authorization.name.trim()
|
||||||
|
|||||||
1308
dist/firefox/content.js
vendored
1308
dist/firefox/content.js
vendored
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,7 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "node scripts/build.mjs",
|
"build": "node scripts/build.mjs",
|
||||||
"check": "node --check src/content.js && node scripts/build.mjs --check"
|
"check": "node --check src/content.js && node --check src/background.js && node tests/consumptionTrend.test.cjs && node scripts/build.mjs --check",
|
||||||
|
"test": "node tests/consumptionTrend.test.cjs"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,13 @@
|
|||||||
const CUSTOMER_TOKEN_SERVICE_URL = "https://spa.oracle.com/oalcrm/web/api/g2m-consumer-application/consumerTokenService";
|
const CUSTOMER_TOKEN_SERVICE_URL = "https://spa.oracle.com/oalcrm/web/api/g2m-consumer-application/consumerTokenService";
|
||||||
const ACCOUNT_SUMMARY_URL = "https://spa.oracle.com/oalcrm/web/api/provider-proxy/g2m-account/service/accountsummary";
|
const ACCOUNT_SUMMARY_URL = "https://spa.oracle.com/oalcrm/web/api/provider-proxy/g2m-account/service/accountsummary";
|
||||||
const ACCOUNT_PLANS_URL = "https://spa.oracle.com/oalcrm/web/api/provider-proxy/g2m-consumption/service/v1/account/accountPlans";
|
const ACCOUNT_PLANS_URL = "https://spa.oracle.com/oalcrm/web/api/provider-proxy/g2m-consumption/service/v1/account/accountPlans";
|
||||||
|
const CONSUMPTION_TREND_URL = "https://spa.oracle.com/oalcrm/web/api/provider-proxy/g2m-consumption/service/v1/plan/trend";
|
||||||
|
const CONSUMPTION_TREND_REQUESTS = {
|
||||||
|
quarterly: "requestConsumptionServiceQuarterly",
|
||||||
|
monthly: "requestConsumptionServiceMonthly",
|
||||||
|
weekly: "requestConsumptionServiceWeekly",
|
||||||
|
daily: "requestConsumptionServiceDaily"
|
||||||
|
};
|
||||||
const ACCOUNT_PLANS_PAYLOAD = {
|
const ACCOUNT_PLANS_PAYLOAD = {
|
||||||
hierarchy: "single",
|
hierarchy: "single",
|
||||||
products: "all",
|
products: "all",
|
||||||
@@ -149,6 +156,20 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (message.type === "opportunitiesExtension.requestConsumptionTrend") {
|
||||||
|
requestConsumptionTrend(message)
|
||||||
|
.then(sendResponse)
|
||||||
|
.catch((error) => {
|
||||||
|
sendResponse({
|
||||||
|
ok: false,
|
||||||
|
error: error.message || "Unable to load consumption trend.",
|
||||||
|
debugRequests: Array.isArray(error.debugRequests) ? error.debugRequests : []
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -282,6 +303,56 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function requestConsumptionTrend(message) {
|
||||||
|
const subPlanNum = typeof message.subPlanNum === "string" ? message.subPlanNum.trim() : "";
|
||||||
|
const period = typeof message.period === "string" ? message.period.toLowerCase() : "";
|
||||||
|
const requestName = CONSUMPTION_TREND_REQUESTS[period];
|
||||||
|
const authorization = normalizeMessageAuthorization(message.authorization, "g2m-authorization");
|
||||||
|
const debugRequests = [];
|
||||||
|
|
||||||
|
if (!subPlanNum) {
|
||||||
|
throw new Error("Sub plan number is required for the consumption trend.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!requestName) {
|
||||||
|
throw new Error(`Unsupported consumption trend period: ${period || "(missing)"}.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!authorization.value) {
|
||||||
|
throw new Error("OCICONS-TS authorization is unavailable for the consumption trend.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = `${CONSUMPTION_TREND_URL}/${encodeURIComponent(subPlanNum)}?quarter=All&timePeriod=${period}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetchJson(url, {
|
||||||
|
method: "GET",
|
||||||
|
credentials: "include",
|
||||||
|
cache: "no-store",
|
||||||
|
headers: {
|
||||||
|
Accept: "application/json",
|
||||||
|
"G2m-Authorization": authorization.value
|
||||||
|
}
|
||||||
|
}, requestName, debugRequests);
|
||||||
|
const items = Array.isArray(response)
|
||||||
|
? response
|
||||||
|
: Array.isArray(response && response.items)
|
||||||
|
? response.items
|
||||||
|
: [];
|
||||||
|
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
subPlanNum,
|
||||||
|
period,
|
||||||
|
items,
|
||||||
|
debugRequests
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
error.debugRequests = debugRequests;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeMessageAuthorization(authorization, fallbackHeaderName) {
|
function normalizeMessageAuthorization(authorization, fallbackHeaderName) {
|
||||||
const headerName = authorization && typeof authorization.name === "string"
|
const headerName = authorization && typeof authorization.name === "string"
|
||||||
? authorization.name.trim()
|
? authorization.name.trim()
|
||||||
|
|||||||
1308
src/content.js
1308
src/content.js
File diff suppressed because it is too large
Load Diff
174
tests/consumptionTrend.test.cjs
Normal file
174
tests/consumptionTrend.test.cjs
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
const assert = require("node:assert/strict");
|
||||||
|
const fs = require("node:fs");
|
||||||
|
const path = require("node:path");
|
||||||
|
const vm = require("node:vm");
|
||||||
|
|
||||||
|
const root = path.resolve(__dirname, "..");
|
||||||
|
|
||||||
|
function loadContentHelpers() {
|
||||||
|
const source = fs.readFileSync(path.join(root, "src", "content.js"), "utf8");
|
||||||
|
const marker = "\n if (insertTile()) {";
|
||||||
|
const instrumented = source.replace(marker, `
|
||||||
|
globalThis.__consumptionTrendTest = {
|
||||||
|
normalizeConsumptionTrendItems,
|
||||||
|
formatConsumptionPointLabel,
|
||||||
|
createNiceConsumptionMaximum,
|
||||||
|
calculateAverageConsumption
|
||||||
|
};
|
||||||
|
${marker}`);
|
||||||
|
const context = {
|
||||||
|
chrome: { runtime: { onMessage: { addListener() {} } } },
|
||||||
|
document: { getElementById: () => ({}) },
|
||||||
|
window: {
|
||||||
|
location: {
|
||||||
|
hostname: "eeho.fa.us2.oraclecloud.com",
|
||||||
|
pathname: "/fscmUI/faces/FuseWelcome"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Intl,
|
||||||
|
Date,
|
||||||
|
Map,
|
||||||
|
Set,
|
||||||
|
Number,
|
||||||
|
String,
|
||||||
|
Array,
|
||||||
|
Object,
|
||||||
|
Math
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.runInNewContext(instrumented, context);
|
||||||
|
return context.__consumptionTrendTest;
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadBackground(fetchCalls) {
|
||||||
|
let listener;
|
||||||
|
const source = fs.readFileSync(path.join(root, "src", "background.js"), "utf8");
|
||||||
|
const headers = {
|
||||||
|
get(name) {
|
||||||
|
return name.toLowerCase() === "content-type" ? "application/json" : null;
|
||||||
|
},
|
||||||
|
forEach(callback) {
|
||||||
|
callback("application/json", "content-type");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const context = {
|
||||||
|
chrome: {
|
||||||
|
runtime: {
|
||||||
|
onMessage: {
|
||||||
|
addListener(callback) {
|
||||||
|
listener = callback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fetch: async (url, options) => {
|
||||||
|
fetchCalls.push({ url, options });
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
status: 200,
|
||||||
|
statusText: "OK",
|
||||||
|
headers,
|
||||||
|
text: async () => JSON.stringify([{ fyDate: "2026-09-01", usedAmount: 25 }])
|
||||||
|
};
|
||||||
|
},
|
||||||
|
URL,
|
||||||
|
Date,
|
||||||
|
JSON,
|
||||||
|
Map,
|
||||||
|
Set,
|
||||||
|
Promise,
|
||||||
|
String,
|
||||||
|
Array,
|
||||||
|
Object,
|
||||||
|
Number,
|
||||||
|
Math,
|
||||||
|
setTimeout,
|
||||||
|
clearTimeout
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.runInNewContext(source, context);
|
||||||
|
return listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
function dispatch(listener, message) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const asynchronous = listener(message, {}, resolve);
|
||||||
|
assert.equal(asynchronous, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
const helpers = loadContentHelpers();
|
||||||
|
const points = helpers.normalizeConsumptionTrendItems([
|
||||||
|
{
|
||||||
|
fyDate: "2026-08-22",
|
||||||
|
fiscalTime: ["22-Aug-26"],
|
||||||
|
fiscalQtr: "FY27-Q1",
|
||||||
|
usageCategory: "Funded Allocation",
|
||||||
|
usedAmount: 31000,
|
||||||
|
arrCd: 120000,
|
||||||
|
currencyCode: "BRL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fyDate: "2026-08-22",
|
||||||
|
fiscalTime: ["22-Aug-26"],
|
||||||
|
usageCategory: "OVERAGE",
|
||||||
|
usedAmount: 4200,
|
||||||
|
currencyCode: "BRL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fyDate: "2026-08-15",
|
||||||
|
fiscalTime: ["15-Aug-26"],
|
||||||
|
usageCategory: null,
|
||||||
|
usedAmount: 29000,
|
||||||
|
currencyCode: "BRL"
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert.equal(points.length, 2);
|
||||||
|
assert.equal(points[0].dateKey, "2026-08-15");
|
||||||
|
assert.equal(points[0].funded, 29000);
|
||||||
|
assert.equal(points[1].funded, 31000);
|
||||||
|
assert.equal(points[1].overage, 4200);
|
||||||
|
assert.equal(points[1].total, 35200);
|
||||||
|
assert.equal(points[1].arr, 120000);
|
||||||
|
assert.equal(helpers.formatConsumptionPointLabel(points[1], "weekly"), "22-Aug-26");
|
||||||
|
assert.equal(helpers.createNiceConsumptionMaximum(35200), 50000);
|
||||||
|
assert.equal(helpers.calculateAverageConsumption(points, true), 29000);
|
||||||
|
assert.equal(helpers.calculateAverageConsumption(points, false), 32100);
|
||||||
|
assert.equal(helpers.calculateAverageConsumption(points, true, new Set(["funded"])), 29000);
|
||||||
|
assert.equal(helpers.calculateAverageConsumption(points, false, new Set(["overage"])), 2100);
|
||||||
|
|
||||||
|
const fetchCalls = [];
|
||||||
|
const listener = loadBackground(fetchCalls);
|
||||||
|
const periods = ["quarterly", "monthly", "weekly", "daily"];
|
||||||
|
|
||||||
|
for (const period of periods) {
|
||||||
|
const response = await dispatch(listener, {
|
||||||
|
type: "opportunitiesExtension.requestConsumptionTrend",
|
||||||
|
subPlanNum: "11276098",
|
||||||
|
period,
|
||||||
|
authorization: { name: "g2m-authorization", value: "ocicons-secret" }
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(response.ok, true);
|
||||||
|
assert.equal(response.period, period);
|
||||||
|
assert.equal(response.items.length, 1);
|
||||||
|
assert.equal(response.debugRequests[0].name, `requestConsumptionService${period[0].toUpperCase()}${period.slice(1)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.equal(fetchCalls.length, 4);
|
||||||
|
fetchCalls.forEach((call, index) => {
|
||||||
|
assert.equal(call.options.method, "GET");
|
||||||
|
assert.equal(call.options.headers["G2m-Authorization"], "ocicons-secret");
|
||||||
|
assert.match(call.url, /\/11276098\?quarter=All&timePeriod=/);
|
||||||
|
assert.ok(call.url.endsWith(periods[index]));
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("Consumption trend tests passed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
run().catch((error) => {
|
||||||
|
console.error(error);
|
||||||
|
process.exitCode = 1;
|
||||||
|
});
|
||||||
103
tests/fixtures/consumption-trend.html
vendored
Normal file
103
tests/fixtures/consumption-trend.html
vendored
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Consumption Trend Visual Test</title>
|
||||||
|
<style>
|
||||||
|
html, body { width: 100%; min-height: 100%; margin: 0; }
|
||||||
|
body { font-family: Arial, sans-serif; }
|
||||||
|
#opportunities-extension-modal { position: fixed; inset: 0; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="opportunities-extension-modal" class="opportunities-extension-modal" data-theme="light"></div>
|
||||||
|
<script>
|
||||||
|
window.chrome = { runtime: { onMessage: { addListener() {} } } };
|
||||||
|
|
||||||
|
async function initialize() {
|
||||||
|
const source = await fetch("/src/content.js").then((response) => response.text());
|
||||||
|
const marker = /\r?\n if \(insertTile\(\)\) \{/;
|
||||||
|
const exposure = `
|
||||||
|
window.__trendHarness = {
|
||||||
|
ensureStyles: ensureExtensionStyles,
|
||||||
|
createAccountPlanDetails,
|
||||||
|
createConsumptionTrendSection,
|
||||||
|
renderConsumptionTrendChart
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
`;
|
||||||
|
const testableSource = source
|
||||||
|
.replace(" if (!isAllowedPage()) {", " if (false) {")
|
||||||
|
.replace(marker, `${exposure}\n if (insertTile()) {`);
|
||||||
|
window.eval(testableSource);
|
||||||
|
|
||||||
|
const plan = {
|
||||||
|
subPlanNum: "11276098",
|
||||||
|
planType: "Universal Credits",
|
||||||
|
bookingCustomer: "Example Customer",
|
||||||
|
soldToPartyName: "Example Sold To",
|
||||||
|
contractId: "12345678",
|
||||||
|
hdrStatusCode: "ACTIVE",
|
||||||
|
startDate: "2026-06-01",
|
||||||
|
endDate: "2027-05-31"
|
||||||
|
};
|
||||||
|
const items = [
|
||||||
|
["20-Jun-26", 29000, 0], ["27-Jun-26", 30000, 0], ["04-Jul-26", 33000, 0],
|
||||||
|
["11-Jul-26", 28500, 0], ["18-Jul-26", 29500, 0], ["25-Jul-26", 23000, 10000],
|
||||||
|
["01-Aug-26", 0, 29000], ["08-Aug-26", 0, 32000], ["15-Aug-26", 0, 30000],
|
||||||
|
["22-Aug-26", 31000, 4500], ["29-Aug-26", 37000, 0], ["05-Sep-26", 35000, 0],
|
||||||
|
["12-Sep-26", 2000, 0]
|
||||||
|
].flatMap(([label, funded, overage]) => {
|
||||||
|
const [day, month, year] = label.split("-");
|
||||||
|
const monthNumber = { Jun: "06", Jul: "07", Aug: "08", Sep: "09" }[month];
|
||||||
|
const base = {
|
||||||
|
fyDate: `20${year}-${monthNumber}-${day}`,
|
||||||
|
fiscalTime: [label],
|
||||||
|
fiscalQtr: "FY27-Q1",
|
||||||
|
currencyCode: "USD",
|
||||||
|
arrCd: 0
|
||||||
|
};
|
||||||
|
const rows = [{ ...base, usageCategory: "Funded Allocation", usedAmount: funded }];
|
||||||
|
if (overage) rows.push({ ...base, usageCategory: "OVERAGE", usedAmount: overage });
|
||||||
|
return rows;
|
||||||
|
});
|
||||||
|
|
||||||
|
window.__trendHarness.ensureStyles();
|
||||||
|
const overlay = document.getElementById("opportunities-extension-modal");
|
||||||
|
overlay.dataset.theme = new URLSearchParams(window.location.search).get("theme") === "dark"
|
||||||
|
? "dark"
|
||||||
|
: "light";
|
||||||
|
const modal = document.createElement("section");
|
||||||
|
modal.className = "opportunities-extension-account-plans-modal";
|
||||||
|
const dialog = document.createElement("div");
|
||||||
|
dialog.className = "opportunities-extension-account-plans-dialog";
|
||||||
|
const header = document.createElement("header");
|
||||||
|
header.className = "opportunities-extension-account-plans-header";
|
||||||
|
header.innerHTML = "<div><h2>Cloud Consumption</h2><p>Example customer</p></div>";
|
||||||
|
const content = document.createElement("div");
|
||||||
|
content.className = "opportunities-extension-account-plans-content";
|
||||||
|
const tabs = document.createElement("div");
|
||||||
|
tabs.className = "opportunities-extension-account-plans-tabs";
|
||||||
|
tabs.innerHTML = '<button class="opportunities-extension-account-plan-tab" aria-selected="true"><span class="opportunities-extension-account-plan-status-indicator" data-active="true"></span>Universal Credits 11276098</button>';
|
||||||
|
const panel = document.createElement("section");
|
||||||
|
panel.className = "opportunities-extension-account-plan-panel";
|
||||||
|
const trend = window.__trendHarness.createConsumptionTrendSection(plan);
|
||||||
|
panel.append(window.__trendHarness.createAccountPlanDetails(plan), trend);
|
||||||
|
content.append(tabs, panel);
|
||||||
|
dialog.append(header, content);
|
||||||
|
modal.append(dialog);
|
||||||
|
overlay.append(modal);
|
||||||
|
window.__trendHarness.renderConsumptionTrendChart(
|
||||||
|
trend,
|
||||||
|
trend.querySelector(".opportunities-extension-consumption-chart"),
|
||||||
|
items,
|
||||||
|
"weekly",
|
||||||
|
plan.subPlanNum
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user