Skip to content
Merged

Dev #1992

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
172d54b
AB#31676 start with tenant map lookup
AndreGAot Feb 6, 2026
6e2b494
AB#30398 - Add Creation Date to Applicant list default view
plavoie-BC Feb 9, 2026
3a13bbb
AB#31363 - Improve styling of date controls on Grant Applications
plavoie-BC Feb 9, 2026
6c0a04d
AB#31676 make the oidc sub submission scrape dynamic
AndreGAot Feb 9, 2026
4c2f0a3
AB#31676 SQ cleanup
AndreGAot Feb 9, 2026
22f32ea
AB#31676 more SQ
AndreGAot Feb 9, 2026
a397ad7
AB#31843 - Docker - Use ADD instruction to retrieve remote resources
plavoie-BC Feb 9, 2026
8f84455
AB#31843 - SQ - Remove old TODO comments
plavoie-BC Feb 9, 2026
f964900
AB#31676 codeQL suggestions
AndreGAot Feb 9, 2026
1815eaa
AB#31676 remove using
AndreGAot Feb 9, 2026
efb912a
AB#31676 optimize recon worker
AndreGAot Feb 10, 2026
8db04bd
AB#31676 appsetting file cleanup
AndreGAot Feb 10, 2026
cdd3faa
AB#31824: Dont delete supplier
aurelio-aot Feb 6, 2026
9cd2a30
AB#31824: Deassociate Applicant from Supplier
aurelio-aot Feb 9, 2026
61b29a0
Potential fix for pull request finding 'Constant condition'
aurelio-aot Feb 9, 2026
bdd1555
AB#31676 more CodeQL
AndreGAot Feb 10, 2026
549b105
Merge pull request #1978 from bcgov/feature/AB#31676-portal-tenant-lo…
JamesPasta Feb 10, 2026
efd372d
Merge pull request #1982 from bcgov/bugfix/AB#31824-deassociate-supplier
JamesPasta Feb 10, 2026
4e4b2b0
AB#31676 update key compare for better security
AndreGAot Feb 10, 2026
010dc99
Merge pull request #1977 from bcgov/feature/AB#31363-submission-date-…
JamesPasta Feb 10, 2026
91159d0
Merge branch 'dev' into feature/AB#31843-sonarqube-cleanup
plavoie-BC Feb 10, 2026
a33e6b6
Apply suggestion from @Copilot
AndreGAot Feb 10, 2026
71d8727
Merge pull request #1983 from bcgov/feature/AB#31676-portal-tenant-lo…
AndreGAot Feb 10, 2026
d4c5fd7
Added The ApplicationsActionBar spec
Stephan-McColm Feb 10, 2026
a5240a9
AB#31843 - Update HtmlSanitizer from 9.0.889 to 9.0.892 to resolve vu…
plavoie-BC Feb 10, 2026
1bdcb52
Merge branch 'feature/AB#31843-sonarqube-cleanup' of https://github.c…
plavoie-BC Feb 10, 2026
94055e1
Merge branch 'dev' into feature/AB#31843-sonarqube-cleanup
plavoie-BC Feb 10, 2026
3d88040
feature/AB#31004
DavidBrightBcGov Feb 10, 2026
7124829
Improved ApplicationsActionBar spec
Stephan-McColm Feb 11, 2026
fabe4e6
Improved ApplicationsActionBar Spec - asserts visibility of the colum…
Stephan-McColm Feb 11, 2026
704896b
Includes menu selection
Stephan-McColm Feb 11, 2026
afaa394
Fixed the payment test
Stephan-McColm Feb 11, 2026
7288407
Refinements to flow.
Stephan-McColm Feb 11, 2026
52485e6
feature/AB#31826 Fixed basicEmail.cy.ts to be able to login irrespect…
Stephan-McColm Feb 11, 2026
547701c
Merge pull request #1985 from bcgov/feature/AB#31826-Applications-Act…
DarylTodosichuk Feb 11, 2026
f781b2b
Merge pull request #1980 from bcgov/feature/AB#31843-sonarqube-cleanup
JamesPasta Feb 11, 2026
f52826a
Updated the sorting method call based on copilots recommendations
DavidBrightBcGov Feb 11, 2026
6889e0d
AB#31867: Validate empty SupplierNumber in PaymentRequest frontend
aurelio-aot Feb 11, 2026
21c6bf7
AB#31867: Dont save empty suppliernumber from CAS
aurelio-aot Feb 11, 2026
db681be
AB#31867: Fix sonarqube issue
aurelio-aot Feb 11, 2026
3e51bc8
AB#31867: Improve validation message wording
aurelio-aot Feb 11, 2026
67648e6
Merge pull request #1984 from bcgov/feature/AB#31004-links-column-app…
JamesPasta Feb 11, 2026
42437d5
Merge pull request #1988 from bcgov/feature/AB#31867-check-empty-supp…
JamesPasta Feb 11, 2026
82c1d3b
Centralize authentication with cy.session() caching, reducing login t…
Feb 12, 2026
85b3301
Update applications/Unity.AutoUI/cypress/e2e/ApplicationsActionBar.cy.ts
Stephan-McColm Feb 12, 2026
2d6ac6d
addressing code review comments
Feb 12, 2026
1436bbb
Merge pull request #1991 from bcgov/feature/AB#31895-Cypress-Central-…
DarylTodosichuk Feb 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
514 changes: 514 additions & 0 deletions applications/Unity.AutoUI/cypress/e2e/ApplicationsActionBar.cy.ts

Large diffs are not rendered by default.

669 changes: 376 additions & 293 deletions applications/Unity.AutoUI/cypress/e2e/basicEmail.cy.ts

Large diffs are not rendered by default.

206 changes: 206 additions & 0 deletions applications/Unity.AutoUI/cypress/support/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
/**
* Authentication helper for Unity webapp
* Handles multiple authentication states and provides robust login flow
*/

interface LoginOptions {
baseUrl?: string;
useMfa?: boolean;
timeout?: number;
username?: string;
password?: string;
}

/**
* Detects if we're on the Keycloak login provider selection page
*/
function isKeycloakPage($body: JQuery<HTMLElement>): boolean {
return (
$body.find(".login-pf-page").length > 0 ||
$body.find("#social-idir").length > 0 ||
$body.find("#social-azureidir").length > 0
);
}

/**
* Detects if we're already logged in
*/
function isLoggedIn($body: JQuery<HTMLElement>): boolean {
return (
$body.find('button:contains("VIEW APPLICATIONS")').length > 0 ||
$body.find("#GrantApplicationsTable").length > 0
);
}

/**
* Detects if we're on the login landing page
*/
function isLoginPage($body: JQuery<HTMLElement>): boolean {
return $body.find('button:contains("LOGIN")').length > 0;
}

/**
* Handles the Keycloak IDIR selection and login form
*/
function handleKeycloakLogin(
options: LoginOptions,
useMfa: boolean,
timeout: number,
): void {
cy.log("🔑 Handling Keycloak login flow");

cy.get("body", { timeout }).then(($body) => {
// Click appropriate IDIR provider
if (useMfa && $body.find("#social-azureidir").length > 0) {
cy.log("Selecting IDIR - MFA");
cy.get("#social-azureidir", { timeout }).should("be.visible").click();
} else if ($body.find("#social-idir").length > 0) {
cy.log("Selecting IDIR");
cy.get("#social-idir", { timeout }).should("be.visible").click();
} else {
throw new Error(
"Expected Keycloak IDIR provider buttons but none found. Available: " +
$body
.find("a[id^='social-']")
.map((_, el) => el.id)
.get()
.join(", "),
);
}
});

// Handle username/password form if it appears
cy.get("body", { timeout }).then(($loginBody) => {
if ($loginBody.find("#user").length > 0) {
cy.log("Entering IDIR credentials");

const username = options.username || Cypress.env("test1username");
const password = options.password || Cypress.env("test1password");

cy.get("#user", { timeout })
.should("be.visible")
.type(username, { log: false });

cy.get("#password", { timeout })
.should("be.visible")
.type(password, { log: false });

// Look for Continue button or submit the form
cy.get("body").then(($formBody) => {
if ($formBody.find('button:contains("Continue")').length > 0) {
cy.contains("button", "Continue", { timeout }).click();
} else if ($formBody.find("input[type='submit']").length > 0) {
cy.get("input[type='submit']", { timeout }).click();
} else {
cy.log("⚠️ No submit button found, attempting form submission");
cy.get("#user").parents("form").submit();
}
});
} else {
cy.log("✓ Already authenticated, skipping credentials");
}
});
}

/**
* Ensures we end up at the GrantApplications page
*/
function ensureGrantApplicationsPage(timeout: number): void {
cy.location("pathname", { timeout }).then((pathname) => {
if (pathname.includes("/GrantApplications")) {
cy.log("✓ Already at GrantApplications page");
return;
}

// Check if VIEW APPLICATIONS button exists
cy.get("body", { timeout }).then(($body) => {
if ($body.find('button:contains("VIEW APPLICATIONS")').length > 0) {
cy.log("Clicking VIEW APPLICATIONS button");
cy.contains("button", "VIEW APPLICATIONS", { timeout })
.should("be.visible")
.click();
}
});
});

// Final assertion - we should be at GrantApplications
cy.location("pathname", { timeout }).should("include", "/GrantApplications");
cy.log("✓ Successfully navigated to GrantApplications");
}

/**
* Performs the actual login flow
*/
function performLogin(options: LoginOptions = {}): void {
const baseUrl = options.baseUrl || (Cypress.env("webapp.url") as string);
const useMfa = options.useMfa || false;
const timeout = options.timeout || 20000;

cy.visit(baseUrl);

cy.get("body", { timeout }).then(($body) => {
// Check if already logged in
if (isLoggedIn($body)) {
cy.log("✓ Already logged in");
return;
}

// Click LOGIN button if on landing page
if (isLoginPage($body)) {
cy.log("Clicking LOGIN button");
cy.contains("button", "LOGIN", { timeout }).click();
}
});

// Handle Keycloak login if needed
cy.get("body", { timeout }).then(($body) => {
if (isKeycloakPage($body)) {
handleKeycloakLogin(options, useMfa, timeout);
}
});

// Wait for login to complete - verify we're at GrantApplications or can navigate there
ensureGrantApplicationsPage(timeout);
}

/**
* Robust login helper that handles multiple Unity webapp states
*
* @example
* // In your test
* import { loginIfNeeded } from "../support/auth";
*
* beforeEach(() => {
* loginIfNeeded();
* });
*/
export function loginIfNeeded(
options: LoginOptions = {},
): Cypress.Chainable<void> {
const username = options.username || (Cypress.env("test1username") as string);
const baseUrl = options.baseUrl || (Cypress.env("webapp.url") as string);
const sessionId = `unity-${baseUrl}-${username}`;

return cy
.session(
sessionId,
() => {
performLogin(options);
},
{
validate() {
// Lightweight validation: check auth cookies exist without visiting
return cy.getCookie(".AspNetCore.Cookies").then((cookie) => {
if (!cookie) {
throw new Error("Session expired - auth cookie missing");
}
});
},
cacheAcrossSpecs: true,
},
)
.then(() => {
cy.visit(baseUrl);
ensureGrantApplicationsPage(options.timeout || 20000);
});
}
Loading