diff --git a/src/Frontend/src/components/configuration/PlatformLicense.vue b/src/Frontend/src/components/configuration/PlatformLicense.vue
index c238f4dba2..9efc81c08d 100644
--- a/src/Frontend/src/components/configuration/PlatformLicense.vue
+++ b/src/Frontend/src/components/configuration/PlatformLicense.vue
@@ -40,16 +40,16 @@ const loading = computed(() => {
License expiry date:
{{ license.formattedExpirationDate }}
- {{ licenseStatus.subscriptionDaysLeft }}
+ {{ licenseStatus.subscriptionDaysLeft }}
-
Your license expired. Please update the license to continue using the Particular Service Platform.
+ Your license expired. Please update the license to continue using the Particular Service Platform.
diff --git a/src/Frontend/src/resources/LicenseInfo.ts b/src/Frontend/src/resources/LicenseInfo.ts
index 9644cf5b84..1d46aa61f3 100644
--- a/src/Frontend/src/resources/LicenseInfo.ts
+++ b/src/Frontend/src/resources/LicenseInfo.ts
@@ -22,3 +22,8 @@ export enum LicenseStatus {
ValidWithExpiringUpgradeProtection = "ValidWithExpiringUpgradeProtection",
ValidWithExpiringSubscription = "ValidWithExpiringSubscription",
}
+export enum LicenseType {
+ Subscription,
+ Trial,
+ UpgradeProtection,
+}
diff --git a/src/Frontend/test/preconditions/hasLicense.ts b/src/Frontend/test/preconditions/hasLicense.ts
index 8d20621ff5..9195861f01 100644
--- a/src/Frontend/test/preconditions/hasLicense.ts
+++ b/src/Frontend/test/preconditions/hasLicense.ts
@@ -1,6 +1,6 @@
import { activeLicenseResponse } from "../mocks/license-response-template";
import { SetupFactoryOptions } from "../driver";
-import LicenseInfo, { LicenseStatus } from "@/resources/LicenseInfo";
+import LicenseInfo, { LicenseStatus, LicenseType } from "@/resources/LicenseInfo";
import { useLicense } from "@/composables/serviceLicense";
const { license } = useLicense();
@@ -13,22 +13,16 @@ export const hasActiveLicense = ({ driver }: SetupFactoryOptions) => {
return activeLicenseResponse;
};
-export enum LicenseType {
- Subscription,
- Trial,
- UpgradeProtection,
-}
-
export const hasExpiredLicense = (licenseType: LicenseType, licenseExtensionUrl: string = "https://particular.net/extend-your-trial?p=servicepulse") => createLicenseMockedResponse(licenseType, false, licenseExtensionUrl);
export const hasExpiringLicense = (licenseType: LicenseType, licenseExtensionUrl: string = "https://particular.net/extend-your-trial?p=servicepulse") => createLicenseMockedResponse(licenseType, true, licenseExtensionUrl);
const createLicenseMockedResponse =
- (liceseType: LicenseType, expiring = false, licenseExtensionUrl: string) =>
+ (licenseType: LicenseType, expiring = false, licenseExtensionUrl: string) =>
({ driver }: SetupFactoryOptions) => {
const serviceControlInstanceUrl = window.defaultConfig.service_control_url;
let status: LicenseStatus;
- switch (liceseType) {
+ switch (licenseType) {
case LicenseType.Subscription:
status = expiring ? LicenseStatus.ValidWithExpiringSubscription : LicenseStatus.InvalidDueToExpiredSubscription;
break;
diff --git a/src/Frontend/test/preconditions/index.ts b/src/Frontend/test/preconditions/index.ts
index 0c20e7a9fe..40cb425704 100644
--- a/src/Frontend/test/preconditions/index.ts
+++ b/src/Frontend/test/preconditions/index.ts
@@ -15,6 +15,7 @@ export * from "./hasMonitoredEndpointDetails";
export { hasNoHeartbeatsEndpoints, hasHeartbeatsEndpoints } from "../preconditions/hasHeartbeatEndpoints";
export { serviceControlWithMonitoring } from "./serviceControlWithMonitoring";
export * from "./recoverability";
+export * from "./licensing";
export { hasLicensingReportAvailable } from "../preconditions/hasLicensingReportAvailable";
export { hasLicensingSettingTest } from "../preconditions/hasLicensingSettingTest";
export { hasLicensingEndpoints } from "../preconditions/hasLicensingEndpoints";
diff --git a/src/Frontend/test/preconditions/licensing.ts b/src/Frontend/test/preconditions/licensing.ts
new file mode 100644
index 0000000000..2471a374c7
--- /dev/null
+++ b/src/Frontend/test/preconditions/licensing.ts
@@ -0,0 +1,56 @@
+import { SetupFactoryOptions } from "../driver";
+import LicenseInfo, { LicenseStatus, LicenseType } from "@/resources/LicenseInfo";
+
+const licenseResponseTemplate = {
+ registered_to: "ACME Software",
+ edition: "Enterprise",
+ expiration_date: "2026-01-23T00:00:00.0000000Z",
+ upgrade_protection_expiration: "",
+ license_type: "Commercial",
+ instance_name: "Particular.ServiceControl",
+ trial_license: false,
+ license_status: LicenseStatus.Valid,
+ status: "valid",
+};
+
+export const withExpiredLicense = (licenseType: LicenseType, expiredDays: number) => getLicenseMockedResponse(licenseType, expiredDays, true);
+export const withExpiringLicense = (licenseType: LicenseType, expiringInDays: number) => getLicenseMockedResponse(licenseType, expiringInDays, false);
+
+const getLicenseMockedResponse =
+ (licenseType: LicenseType, expiringInDays: number, isExpired: boolean) =>
+ ({ driver }: SetupFactoryOptions) => {
+ const serviceControlInstanceUrl = window.defaultConfig.service_control_url;
+ const customISOString = getCustomDateISOString(expiringInDays, isExpired);
+
+ let status: LicenseStatus;
+ switch (licenseType) {
+ case LicenseType.Subscription:
+ status = isExpired ? LicenseStatus.InvalidDueToExpiredSubscription : LicenseStatus.ValidWithExpiringSubscription;
+ break;
+ case LicenseType.Trial:
+ status = isExpired ? LicenseStatus.InvalidDueToExpiredTrial : LicenseStatus.ValidWithExpiringTrial;
+ break;
+ case LicenseType.UpgradeProtection:
+ status = isExpired ? LicenseStatus.InvalidDueToExpiredUpgradeProtection : LicenseStatus.ValidWithExpiringUpgradeProtection;
+ break;
+ }
+ const response = { ...licenseResponseTemplate, license_type: licenseType, expiration_date: customISOString, license_status: status };
+ driver.mockEndpoint(`${serviceControlInstanceUrl}license`, {
+ body: response,
+ });
+ return response;
+ };
+function getCustomDateISOString(daysCount: number, isExpired: boolean) {
+ const today = new Date();
+ const customDate = new Date(today);
+
+ if (isExpired) {
+ customDate.setDate(today.getDate() - daysCount);
+ } else {
+ customDate.setDate(today.getDate() + daysCount);
+ }
+
+ const nativeISOString = customDate.toISOString(); // e.g., "2026-02-02T14:23:45.123Z"
+ const customISOString = nativeISOString.replace(/\.\d+Z$/, (match) => match.slice(0, -1).padEnd(8, "0") + "Z");
+ return customISOString;
+}
diff --git a/src/Frontend/test/specs/configuration/questions/licenseExpired.ts b/src/Frontend/test/specs/configuration/questions/licenseExpired.ts
new file mode 100644
index 0000000000..55afaafaf3
--- /dev/null
+++ b/src/Frontend/test/specs/configuration/questions/licenseExpired.ts
@@ -0,0 +1,6 @@
+import { screen } from "@testing-library/vue";
+
+export async function licenseExpired() {
+ const licenseExpiredText = await screen.findByRole("note", { name: "license-expired" });
+ return licenseExpiredText.textContent?.trim();
+}
diff --git a/src/Frontend/test/specs/configuration/questions/licenseExpiryDate.ts b/src/Frontend/test/specs/configuration/questions/licenseExpiryDate.ts
index e139850c60..453209945c 100644
--- a/src/Frontend/test/specs/configuration/questions/licenseExpiryDate.ts
+++ b/src/Frontend/test/specs/configuration/questions/licenseExpiryDate.ts
@@ -1,7 +1,6 @@
import { screen } from "@testing-library/vue";
export async function licenseExpiryDate() {
- const licenseExpiryDate = await screen.findByRole("note", { name: "licenseExpiryDate" });
- console.log(licenseExpiryDate.textContent);
- return licenseExpiryDate.textContent;
+ const licenseExpiryDate = await screen.findByRole("note", { name: "license-expiry-date" });
+ return licenseExpiryDate.textContent?.trim;
}
diff --git a/src/Frontend/test/specs/configuration/questions/licenseExpiryDaysLeft.ts b/src/Frontend/test/specs/configuration/questions/licenseExpiryDaysLeft.ts
index ff1e671e54..023715dde2 100644
--- a/src/Frontend/test/specs/configuration/questions/licenseExpiryDaysLeft.ts
+++ b/src/Frontend/test/specs/configuration/questions/licenseExpiryDaysLeft.ts
@@ -1,7 +1,6 @@
import { screen } from "@testing-library/vue";
export async function licenseExpiryDaysLeft() {
- const licenseExpiryDaysLeft = await screen.findByRole("note", { name: "licenseExpiryDaysLeft" });
- console.log(licenseExpiryDaysLeft.textContent);
- return licenseExpiryDaysLeft.textContent;
+ const licenseExpiryDaysLeft = await screen.findByRole("note", { name: "license-days-left" });
+ return licenseExpiryDaysLeft.textContent?.trim;
}
diff --git a/src/Frontend/test/specs/configuration/viewing-license.spec.ts b/src/Frontend/test/specs/configuration/viewing-license.spec.ts
index 82e2de5ba5..a84a7fec6b 100644
--- a/src/Frontend/test/specs/configuration/viewing-license.spec.ts
+++ b/src/Frontend/test/specs/configuration/viewing-license.spec.ts
@@ -1,95 +1,93 @@
-import { expect, vi } from "vitest";
+import { expect } from "vitest";
import { test, describe } from "../../drivers/vitest/driver";
import * as precondition from "../../preconditions";
import { licenseTypeDetails } from "./questions/licenseTypeDetails";
import { licenseExpiryDate } from "./questions/licenseExpiryDate";
import { licenseExpiryDaysLeft } from "./questions/licenseExpiryDaysLeft";
+import { licenseExpired } from "./questions/licenseExpired";
import { waitFor } from "@testing-library/vue";
+import { LicenseType } from "@/resources/LicenseInfo";
describe("FEATURE: License", () => {
describe("RULE: Platform license type should be shown shown", () => {
test("EXAMPLE: Valid platform license type should be shown", async ({ driver }) => {
- vi.useFakeTimers();
await driver.setUp(precondition.serviceControlWithMonitoring);
await driver.setUp(precondition.hasActiveLicense);
await driver.goTo("/configuration/license");
- vi.advanceTimersByTime(5000);
- waitFor(async () => {
+ await waitFor(async () => {
expect(await licenseTypeDetails()).toBe("Commercial, Enterprise");
});
});
});
+
describe("RULE: License expiry date should be shown", () => {
test("EXAMPLE: Valid license expiry date should be shown", async ({ driver }) => {
await driver.setUp(precondition.serviceControlWithMonitoring);
await driver.setUp(precondition.hasActiveLicense);
await driver.goTo("/configuration/license");
- waitFor(async () => {
+ await waitFor(async () => {
expect(await licenseExpiryDate()).toBeVisible();
});
});
});
- describe("RULE: Remaining license period should be displayed", () => {
- test.todo("EXAMPLE: An expired license should show 'expired'");
- /* SCENARIO
- Expired license
-
- Given an expired platform license
- Then "expired" is shown
- */
+
+ describe("RULE: License expired", () => {
+ test("EXAMPLE: An expired license should show 'expired'", async ({ driver }) => {
+ await driver.setUp(precondition.serviceControlWithMonitoring);
+ await driver.setUp(precondition.withExpiredLicense(LicenseType.Subscription, 5)); //license expired 6 days before
+ await driver.goTo("/configuration/license");
+ await waitFor(async () => {
+ expect(await licenseExpired()).toBe("Your license expired. Please update the license to continue using the Particular Service Platform.");
+ });
+ });
});
+
describe("RULE: License expiring soon must be displayed", () => {
- test("EXAMPLE: License expiring with 10 days should show 'expiring in X days'", async ({ driver }) => {
- /* SCENARIO
- License expiring soon
-
- Given a platform license with an expiry date within 10 days
- Then "expiring in X days" is shown
- */
+ test("EXAMPLE: License expiring with x days should show 'expiring in X days'", async ({ driver }) => {
+ await driver.setUp(precondition.serviceControlWithMonitoring);
+ await driver.setUp(precondition.withExpiringLicense(LicenseType.Subscription, 10));
+ await driver.goTo("/configuration/license");
+ await waitFor(async () => {
+ expect(await licenseExpiryDaysLeft()).toBeVisible(); //License expiry date: 2/5/2025 - expiring in 11 days
+ expect(await licenseExpiryDaysLeft()).toContain("expiring in"); //License expiry date: 2/5/2025 - expiring in 11 days
+ });
+ });
+ test("EXAMPLE: License expiring tomorrow should show 'expiring tomorrow'", async ({ driver }) => {
await driver.setUp(precondition.serviceControlWithMonitoring);
- const x = precondition.hasExpiringLicense(precondition.LicenseType.Subscription);
- console.log(x);
- await driver.setUp(precondition.hasExpiringLicense(precondition.LicenseType.Subscription));
+ await driver.setUp(precondition.withExpiringLicense(LicenseType.Subscription, 0));
await driver.goTo("/configuration/license");
- waitFor(async () => {
+ await waitFor(async () => {
expect(await licenseExpiryDaysLeft()).toBeVisible();
+ expect(await licenseExpiryDaysLeft()).toContain("expiring tomorrow");
});
});
- });
- describe("RULE: ABC", () => {
- test.todo("EXAMPLE: License expiring tomorrow should show 'expiring tomorrow'");
- /* SCENARIO
- License expiring tomorrow
-
- Given a platform license which expires tomorrow
- Then "expiring tomorrow" is shown
- */
- });
- describe("RULE: EFG", () => {
- test.todo("EXAMPLE: License expiring today should show 'expiring today'");
- /* SCENARIO
- License expiring today
-
- Given a platform license which expires today
- Then "expiring today" is shown
- */
- });
- describe("RULE: Remaining license period should be displayed", () => {
- test("EXAMPLE: License expiring in more than 10 days should show 'X days left", async ({ driver }) => {
- /* SCENARIO
- License expiring in the future
-
- Given a platform license which expires more than 10 days from now
- Then "X days left" is shown
- */
+ test("EXAMPLE: License expiring today should show 'expiring today'", async ({ driver }) => {
await driver.setUp(precondition.serviceControlWithMonitoring);
- await driver.setUp(precondition.hasActiveLicense);
+ await driver.setUp(precondition.withExpiringLicense(LicenseType.Subscription, -1));
await driver.goTo("/configuration/license");
- waitFor(async () => {
- expect(await licenseExpiryDaysLeft()).toContain("days left");
+ await waitFor(async () => {
+ expect(await licenseExpiryDaysLeft()).toBeVisible();
+ expect(await licenseExpiryDaysLeft()).toContain("expiring today");
});
});
});
+
+ // describe("RULE: Remaining license period should be displayed", () => {
+ // test("EXAMPLE: License expiring in more than 10 days should show 'X days left", async ({ driver }) => {
+ // /* SCENARIO
+ // License expiring in the future
+
+ // Given a platform license which expires more than 10 days from now
+ // Then "X days left" is shown
+ // */
+ // await driver.setUp(precondition.serviceControlWithMonitoring);
+ // await driver.setUp(precondition.hasActiveLicense);
+ // await driver.goTo("/configuration/license");
+ // waitFor(async () => {
+ // expect(await licenseExpiryDaysLeft()).toContain("days left");
+ // });
+ // });
+ // });
describe("RULE: Non-license options should be hidden if license has expired", () => {
test.todo("EXAMPLE: Only 'LICENSE' tab is visible when license has expired");
diff --git a/src/Frontend/test/specs/licensing/license-enforcement.spec.ts b/src/Frontend/test/specs/licensing/license-enforcement.spec.ts
index ac4e5427d1..32d8b5d6b2 100644
--- a/src/Frontend/test/specs/licensing/license-enforcement.spec.ts
+++ b/src/Frontend/test/specs/licensing/license-enforcement.spec.ts
@@ -5,6 +5,7 @@ import { expiredLicenseMessageWithValue } from "./questions/expiredLicenseMessag
import { viewYourLicenseButton } from "./questions/viewYourLicenseButton";
import { extendYourLicenseButton } from "./questions/extendYourLicenseButton";
import { getAlertNotifications } from "./questions/alertNotifications";
+import { LicenseType } from "@/resources/LicenseInfo";
describe("FEATURE: EXPIRING license detection", () => {
describe("RULE: The user should be alerted while using the monitoring endpoint list functionality about an EXPIRING license", () => {
@@ -12,7 +13,7 @@ describe("FEATURE: EXPIRING license detection", () => {
test(`EXAMPLE: Expiring trial with ${licenseExtensionUrl} as license extension url `, async ({ driver }) => {
//Arrange
await driver.setUp(precondition.serviceControlWithMonitoring);
- await driver.setUp(precondition.hasExpiringLicense(precondition.LicenseType.Trial, licenseExtensionUrl));
+ await driver.setUp(precondition.hasExpiringLicense(LicenseType.Trial, licenseExtensionUrl));
await driver.goTo("monitoring");
@@ -25,8 +26,8 @@ describe("FEATURE: EXPIRING license detection", () => {
});
[
- { description: "Expiring upgrade protection", licenseType: precondition.LicenseType.UpgradeProtection, textMatch: /once upgrade protection expires, you'll no longer have access to support or new product versions/i },
- { description: "Expiring platform subscription", licenseType: precondition.LicenseType.Subscription, textMatch: /Once the license expires you'll no longer be able to continue using the Particular Service Platform/i },
+ { description: "Expiring upgrade protection", licenseType: LicenseType.UpgradeProtection, textMatch: /once upgrade protection expires, you'll no longer have access to support or new product versions/i },
+ { description: "Expiring platform subscription", licenseType: LicenseType.Subscription, textMatch: /Once the license expires you'll no longer be able to continue using the Particular Service Platform/i },
].forEach(({ description, licenseType, textMatch }) => {
test(`EXAMPLE: ${description}`, async ({ driver }) => {
//Arrange
@@ -50,7 +51,7 @@ describe("FEATURE: EXPIRED license detection", () => {
test("EXAMPLE: Expired trial", async ({ driver }) => {
//Arrange
await driver.setUp(precondition.serviceControlWithMonitoring);
- await driver.setUp(precondition.hasExpiredLicense(precondition.LicenseType.Trial));
+ await driver.setUp(precondition.hasExpiredLicense(LicenseType.Trial));
//Act
await driver.goTo("monitoring");
@@ -69,7 +70,7 @@ describe("FEATURE: EXPIRED license detection", () => {
test("EXAMPLE: Expired platform subscription", async ({ driver }) => {
//Arrange
await driver.setUp(precondition.serviceControlWithMonitoring);
- await driver.setUp(precondition.hasExpiredLicense(precondition.LicenseType.Subscription));
+ await driver.setUp(precondition.hasExpiredLicense(LicenseType.Subscription));
//Act
await driver.goTo("monitoring");
@@ -88,7 +89,7 @@ describe("FEATURE: EXPIRED license detection", () => {
test("EXAMPLE: Expired upgrade protection", async ({ driver }) => {
//Arrange
await driver.setUp(precondition.serviceControlWithMonitoring);
- await driver.setUp(precondition.hasExpiredLicense(precondition.LicenseType.UpgradeProtection));
+ await driver.setUp(precondition.hasExpiredLicense(LicenseType.UpgradeProtection));
//Act
await driver.goTo("monitoring");
diff --git a/src/Frontend/test/specs/licensing/trial-license-notifications.spec.ts b/src/Frontend/test/specs/licensing/trial-license-notifications.spec.ts
index 2e5df8cd9d..96d7365db1 100644
--- a/src/Frontend/test/specs/licensing/trial-license-notifications.spec.ts
+++ b/src/Frontend/test/specs/licensing/trial-license-notifications.spec.ts
@@ -3,6 +3,7 @@ import { expect } from "vitest";
import { test, describe } from "../../drivers/vitest/driver";
import * as precondition from "../../preconditions";
import { getTrialBar } from "./questions/trialLicenseBar";
+import { LicenseType } from "@/resources/LicenseInfo";
describe("FEATURE: Trial license notifications", () => {
describe("RULE: The user should know they are using a trial license at all times", () => {
@@ -10,7 +11,7 @@ describe("FEATURE: Trial license notifications", () => {
test(`EXAMPLE: ${viewname}`, async ({ driver }) => {
//Arrange
await driver.setUp(precondition.serviceControlWithMonitoring);
- await driver.setUp(precondition.hasExpiringLicense(precondition.LicenseType.Trial));
+ await driver.setUp(precondition.hasExpiringLicense(LicenseType.Trial));
await driver.goTo(viewname);
@@ -25,7 +26,7 @@ describe("FEATURE: Trial license notifications", () => {
test(`EXAMPLE: ${viewname}`, async ({ driver }) => {
//Arrange
await driver.setUp(precondition.serviceControlWithMonitoring);
- await driver.setUp(precondition.hasExpiringLicense(precondition.LicenseType.Subscription));
+ await driver.setUp(precondition.hasExpiringLicense(LicenseType.Subscription));
await driver.goTo(viewname);