From c9416f3675b6ddcb0e4f7c99c1d8f74ed5c2c7b4 Mon Sep 17 00:00:00 2001 From: Eric Sizer Date: Wed, 2 Oct 2024 10:57:12 -0400 Subject: [PATCH] [Fix] Nullish coalescing eslint errors (#11651) * turn rule back on * fix theme provider errors * fix fake data errors * fix date-helper errors * fix theme decorator errors * add strict null checks in playwright * fix form errors * fix i18n errors * fix ui errors * fix web errors * fix strict null types in playwright * fix experience mutations type * fix remaining errors * fix auth token return * fix login-logout test * fix application spec * fix theme decorator * Apply suggestions from code review Co-authored-by: Peter Giles <8978655+petertgiles@users.noreply.github.com> * fix localized names null fallbacks * ignore boolean primitives * fix theme decorator --------- Co-authored-by: Peter Giles <8978655+petertgiles@users.noreply.github.com> --- .../tests/admin/pool-candidate.spec.ts | 18 ++++--- .../tests/admin/process-actions.spec.ts | 4 +- .../tests/admin/process-permissions.spec.ts | 11 ++-- apps/playwright/tests/admin/user-info.spec.ts | 24 ++++----- .../tests/applicant/application-iap.spec.ts | 2 +- .../tests/applicant/application.spec.ts | 18 +++---- apps/playwright/tests/login-logout.spec.ts | 16 +++--- apps/playwright/tests/open-graph.spec.ts | 10 ++-- .../playwright/tests/search-workflows.spec.ts | 22 ++++---- apps/playwright/tsconfig.json | 1 + apps/playwright/utils/auth.ts | 9 ++-- apps/playwright/utils/graphql.ts | 4 +- apps/playwright/utils/pools.ts | 14 ++--- apps/playwright/utils/teams.ts | 2 +- apps/playwright/utils/user.ts | 3 +- .../AssessmentResultsTable.tsx | 4 +- .../AssessmentStepTracker.tsx | 2 +- .../components/AssessmentStepTracker/utils.ts | 8 +-- .../CandidateDialog/ChangeDateDialog.tsx | 2 +- .../EmploymentEquity/dialogs/DialogFooter.tsx | 4 +- .../ExperienceCard/ExperienceCard.tsx | 4 +- .../ExperienceSkillForm.tsx | 4 +- .../ExperienceSkillFormDialog.tsx | 8 +-- .../components/FeatureBlock/FeatureBlock.tsx | 2 +- apps/web/src/components/Layout/SkipLink.tsx | 2 +- .../PoolCandidatesTable/helpers.tsx | 2 +- .../PoolFilterInput/PoolFilterInput.tsx | 2 +- .../DiversityEquityInclusion/Display.tsx | 2 + .../GovernmentInformation/Display.tsx | 4 +- .../PersonalInformation/Display.tsx | 6 +-- .../components/WorkPreferences/Display.tsx | 2 +- apps/web/src/components/SEO/SEO.tsx | 2 +- .../ScreeningDecisionDialog.tsx | 10 ++-- .../SearchRequestFilters.tsx | 8 +-- .../SkillBrowser/SkillBrowserDialog.tsx | 4 +- .../SkillBrowser/SkillSelection.tsx | 2 +- .../src/components/SkillTree/SkillTree.tsx | 2 +- .../Table/ResponsiveTable/NullMessage.tsx | 2 +- .../Table/ResponsiveTable/ResponsiveTable.tsx | 2 +- .../Table/ResponsiveTable/RowSelection.tsx | 6 +-- .../Table/ResponsiveTable/Table.stories.tsx | 4 +- .../Table/ResponsiveTable/styles.ts | 2 +- .../components/Table/ResponsiveTable/utils.ts | 4 +- apps/web/src/components/Table/cells.tsx | 2 +- .../src/components/ToggleForm/NullDisplay.tsx | 2 +- .../UserProfile/ExperienceByTypeListing.tsx | 10 ++-- .../UserProfile/ExperienceSection.tsx | 14 ++--- .../DiversityEquityInclusionSection.tsx | 2 +- .../SkillAccordion/SkillAccordion.test.tsx | 54 +++++++++---------- apps/web/src/hooks/useExperienceMutations.ts | 4 +- .../SitewideAnnouncementDisplay.tsx | 4 +- .../components/AddExperienceForm.tsx | 2 +- .../components/ExperienceEditForm.tsx | 2 +- .../LinkCareerTimeline.tsx | 2 +- .../pages/Applications/ApplicationLayout.tsx | 2 +- .../ApplicationQuestionsPage.tsx | 8 +-- .../ApplicationQuestionsPage/utils.ts | 8 +-- .../ApplicationReviewPage.tsx | 8 +-- apps/web/src/pages/Applications/utils.ts | 2 +- .../EmployeeInformationPage.test.tsx | 2 +- .../EmployeeInformationPage.tsx | 2 +- .../RegistrationWorkEmailVerificationPage.tsx | 4 +- .../CreateClassificationPage.tsx | 4 +- .../UpdateClassificationPage.tsx | 6 +-- .../CommunityMembersPage.tsx | 2 +- .../components/CommunityTable/helpers.tsx | 2 +- .../components/CommunityDisplay.tsx | 4 +- .../components/LanguageSelector.tsx | 6 +-- .../JobPosterTemplatesPage.tsx | 2 +- .../ApplicationInformation.tsx | 2 +- .../ProfileDetails/ProfileDetails.tsx | 2 +- .../pages/Pools/EditPoolPage/EditPoolPage.tsx | 2 +- .../CoreRequirementsSection/Display.tsx | 6 +-- .../components/PoolNameSection/Display.tsx | 6 +-- .../SpecialNoteSection/SpecialNoteSection.tsx | 2 +- .../ManageAccessPage/ManageAccessPage.tsx | 2 +- .../PoolAdvertisementPage.tsx | 6 +-- .../components/WhoCanApplyText.tsx | 5 +- apps/web/src/pages/Pools/PoolLayout.tsx | 2 +- .../pages/Pools/ViewPoolPage/ViewPoolPage.tsx | 4 +- .../CareerTimelineAndRecruitmentPage.tsx | 2 +- .../ExperienceFormPage/ExperienceFormPage.tsx | 8 +-- .../RequestPage/components/RequestForm.tsx | 2 +- .../SearchPage/components/AdvancedFilters.tsx | 2 +- .../pages/SearchRequests/SearchPage/utils.ts | 2 +- .../SkillFamilies/CreateSkillFamilyPage.tsx | 8 ++- .../SkillFamilies/UpdateSkillFamilyPage.tsx | 3 +- apps/web/src/pages/Skills/CreateSkillPage.tsx | 8 ++- apps/web/src/pages/Skills/UpdateSkillPage.tsx | 7 +-- .../src/pages/Skills/UpdateUserSkillPage.tsx | 4 +- .../Skills/components/SkillPortfolioTable.tsx | 4 +- .../Skills/components/SkillShowcaseCard.tsx | 2 +- .../Skills/components/UpdateSkillShowcase.tsx | 2 +- .../src/pages/Skills/components/skillCsv.tsx | 4 +- .../components/SupportForm/SupportForm.tsx | 4 +- .../components/CreateTeamForm.tsx | 2 +- .../components/TeamTable/helpers.tsx | 2 +- .../Teams/TeamMembersPage/TeamMembersPage.tsx | 2 +- .../components/UpdateTeamForm.tsx | 2 +- .../components/AddTeamRoleDialog.tsx | 2 +- .../components/IndividualRoleTable.tsx | 2 +- .../components/AboutSection.tsx | 2 +- .../components/AddToPoolDialog.tsx | 4 +- .../UserCandidatesTable.tsx | 2 +- apps/web/src/utils/applicationUtils.ts | 4 +- apps/web/src/utils/experienceUtils.tsx | 8 +-- apps/web/src/utils/nameUtils.tsx | 4 +- apps/web/src/utils/poolUtils.tsx | 8 +-- .../validators/process/coreRequirements.ts | 2 +- packages/date-helpers/src/index.ts | 6 +-- packages/eslint-config-custom/index.js | 5 +- .../fake-data/src/fakeAssessmentResults.ts | 2 +- packages/fake-data/src/fakeAssessmentSteps.ts | 4 +- packages/fake-data/src/fakePoolCandidates.ts | 4 +- packages/fake-data/src/fakePoolSkills.ts | 2 +- .../src/components/Combobox/Combobox.tsx | 6 +-- .../components/DateInput/ControlledInput.tsx | 2 +- .../forms/src/components/DateInput/utils.ts | 2 +- .../src/components/Repeater/Repeater.tsx | 2 +- .../forms/src/components/Submit/Submit.tsx | 4 +- .../i18n/src/components/LocaleProvider.tsx | 2 +- .../src/components/NestedLanguageProvider.tsx | 4 +- .../decorators/ThemeDecorator.tsx | 2 +- .../theme/src/components/ThemeProvider.tsx | 12 ++--- .../ui/src/components/Accordion/Accordion.tsx | 2 +- packages/ui/src/components/Alert/Alert.tsx | 2 +- .../ui/src/components/CardRepeater/Button.tsx | 2 +- .../ui/src/components/Heading/Heading.tsx | 2 +- packages/ui/src/components/Link/Link.tsx | 4 +- .../components/PreviewList/PreviewList.tsx | 2 +- .../src/components/SideMenu/SideMenuItem.tsx | 4 +- packages/ui/src/components/Stepper/Step.tsx | 4 +- .../ToggleSection/ToggleSection.tsx | 2 +- 133 files changed, 341 insertions(+), 313 deletions(-) diff --git a/apps/playwright/tests/admin/pool-candidate.spec.ts b/apps/playwright/tests/admin/pool-candidate.spec.ts index e19419af2d4..6b6b55c464d 100644 --- a/apps/playwright/tests/admin/pool-candidate.spec.ts +++ b/apps/playwright/tests/admin/pool-candidate.spec.ts @@ -29,7 +29,7 @@ test.describe("Pool candidates", () => { test.beforeAll(async () => { const adminCtx = await graphql.newContext(); - const technicalSkill = await getSkills(adminCtx).then((skills) => { + const technicalSkill = await getSkills(adminCtx, {}).then((skills) => { return skills.find( (skill) => skill.category.value === SkillCategory.Technical, ); @@ -59,8 +59,8 @@ test.describe("Pool candidates", () => { skills: { sync: [ { - details: `Test Skill ${technicalSkill.name.en}`, - id: technicalSkill.id, + details: `Test Skill ${technicalSkill?.name.en}`, + id: technicalSkill?.id ?? "", }, ], }, @@ -73,18 +73,20 @@ test.describe("Pool candidates", () => { }); const createdPool = await createAndPublishPool(adminCtx, { - userId: createdUser.id, - skillId: technicalSkill.id, + userId: createdUser?.id ?? "", + skillId: technicalSkill?.id ?? "", name: LOCALIZED_STRING, }); - const applicantCtx = await graphql.newContext(createdUser.authInfo.sub); - const applicant = await me(applicantCtx); + const applicantCtx = await graphql.newContext( + createdUser?.authInfo?.sub ?? "applicant@test.com", + ); + const applicant = await me(applicantCtx, {}); const application = await createAndSubmitApplication(applicantCtx, { userId: applicant.id, poolId: createdPool.id, - experienceId: applicant.experiences[0].id, + experienceId: applicant?.experiences?.[0]?.id ?? "", signature: `${applicant.firstName} signature`, }); diff --git a/apps/playwright/tests/admin/process-actions.spec.ts b/apps/playwright/tests/admin/process-actions.spec.ts index b5a96ca6837..a19ff6682bf 100644 --- a/apps/playwright/tests/admin/process-actions.spec.ts +++ b/apps/playwright/tests/admin/process-actions.spec.ts @@ -130,7 +130,7 @@ test.describe("Process actions", () => { test("Update pool", async ({ adminPage }) => { const adminCtx = await graphql.newContext(); - const user = await me(adminCtx); + const user = await me(adminCtx, {}); const poolName = { en: "Update pool test (EN)", fr: "Update pool test (FR)", @@ -259,7 +259,7 @@ test.describe("Process actions", () => { test("Delete pool", async ({ adminPage }) => { const adminCtx = await graphql.newContext(); - const user = await me(adminCtx); + const user = await me(adminCtx, {}); const createdPool = await createPool(adminCtx, { userId: user.id, diff --git a/apps/playwright/tests/admin/process-permissions.spec.ts b/apps/playwright/tests/admin/process-permissions.spec.ts index e468e37062e..534c1e2bb93 100644 --- a/apps/playwright/tests/admin/process-permissions.spec.ts +++ b/apps/playwright/tests/admin/process-permissions.spec.ts @@ -41,18 +41,23 @@ test.describe("Process permissions", () => { ], }); - const team = await getDCM(adminCtx); + const team = await getDCM(adminCtx, {}); const associatedPoolManager = await createUserWithRoles(adminCtx, { user: { email: associatedPoolManagerEmail, sub: associatedSub, }, - roles: ["guest", "base_user", "applicant", ["pool_operator", team.id]], + roles: [ + "guest", + "base_user", + "applicant", + ["pool_operator", team?.id ?? ""], + ], }); const createdPool = await createPool(adminCtx, { - userId: associatedPoolManager.id, + userId: associatedPoolManager?.id ?? "", }); await updatePool(adminCtx, { diff --git a/apps/playwright/tests/admin/user-info.spec.ts b/apps/playwright/tests/admin/user-info.spec.ts index 57e7326743e..b7741a27a93 100644 --- a/apps/playwright/tests/admin/user-info.spec.ts +++ b/apps/playwright/tests/admin/user-info.spec.ts @@ -17,7 +17,7 @@ test.describe("User information", () => { let uniqueTestId: string; let user: User; let sub: string; - let skill: Skill; + let skill: Skill | undefined; const loginAndVisitUser = async ( appPage: AppPage, @@ -36,7 +36,7 @@ test.describe("User information", () => { }), ).toBeVisible(); await expect( - page.getByText(new RegExp(user.firstName, "i")).first(), + page.getByText(new RegExp(user?.firstName ?? "", "i")).first(), ).toBeVisible(); }; @@ -53,7 +53,7 @@ test.describe("User information", () => { adminCtx = await graphql.newContext(); - const technicalSkill = await getSkills(adminCtx).then((skills) => { + const technicalSkill = await getSkills(adminCtx, {}).then((skills) => { return skills.find((s) => s.category.value === SkillCategory.Technical); }); @@ -70,8 +70,8 @@ test.describe("User information", () => { skills: { sync: [ { - details: `Test Skill ${technicalSkill.name.en}`, - id: technicalSkill.id, + details: `Test Skill ${technicalSkill?.name.en}`, + id: technicalSkill?.id ?? "", }, ], }, @@ -85,12 +85,12 @@ test.describe("User information", () => { }); skill = technicalSkill; - user = createdUser; + user = createdUser ?? { id: "" }; }); test("Applicant cannot access", async ({ appPage }) => { await loginBySub(appPage.page, "applicant@test.com", false); - await appPage.page.goto(`/en/admin/users/${user.id}`); + await appPage.page.goto(`/en/admin/users/${user?.id}`); await appPage.waitForGraphqlResponse("authorizationQuery"); await expect( appPage.page.getByRole("heading", { @@ -104,7 +104,7 @@ test.describe("User information", () => { await loginAndVisitUser(appPage, "pool@test.com", user); await assertError(appPage.page); - const adminUser = await me(adminCtx); + const adminUser = await me(adminCtx, {}); const dcmPool = await createAndPublishPool(adminCtx, { userId: adminUser.id, @@ -112,16 +112,16 @@ test.describe("User information", () => { en: `Playwright DCM Pool ${uniqueTestId} (EN)`, fr: `Playwright DCM Pool ${uniqueTestId} (FR)`, }, - skillId: skill.id, + skillId: skill?.id ?? "", }); const applicantCtx = await graphql.newContext(sub); - const applicant = await me(applicantCtx); + const applicant = await me(applicantCtx, {}); await createAndSubmitApplication(applicantCtx, { userId: applicant.id, poolId: dcmPool.id, - experienceId: applicant.experiences[0].id, - signature: `${user.firstName} signature`, + experienceId: applicant?.experiences?.[0]?.id ?? "", + signature: `${user?.firstName} signature`, }); // Pool operator can view now that user has application in their pool diff --git a/apps/playwright/tests/applicant/application-iap.spec.ts b/apps/playwright/tests/applicant/application-iap.spec.ts index 5357d44bd78..e7e97268ac3 100644 --- a/apps/playwright/tests/applicant/application-iap.spec.ts +++ b/apps/playwright/tests/applicant/application-iap.spec.ts @@ -54,7 +54,7 @@ test.describe("IAP Application", () => { }); const createdPool = await createAndPublishPool(adminCtx, { - userId: createdUser.id, + userId: createdUser?.id ?? "", input: { publishingGroup: PublishingGroup.Iap, generalQuestions: { diff --git a/apps/playwright/tests/applicant/application.spec.ts b/apps/playwright/tests/applicant/application.spec.ts index 48358e5e3f1..29b4a50ef27 100644 --- a/apps/playwright/tests/applicant/application.spec.ts +++ b/apps/playwright/tests/applicant/application.spec.ts @@ -62,7 +62,7 @@ test.describe("Application", () => { en: `${poolName} (EN)`, fr: `${poolName} (FR)`, }, - userId: createdUser.id, + userId: createdUser?.id ?? "", input: { generalQuestions: { create: [ @@ -243,8 +243,8 @@ test.describe("Application", () => { test("Can view from dashboard", async ({ page }) => { const applicantCtx = await graphql.newContext(sub); - const applicant = await me(applicantCtx); - const technicalSkill = await getSkills(applicantCtx).then((skills) => { + const applicant = await me(applicantCtx, {}); + const technicalSkill = await getSkills(applicantCtx, {}).then((skills) => { return skills.find((s) => s.category.value === SkillCategory.Technical); }); @@ -259,8 +259,8 @@ test.describe("Application", () => { skills: { sync: [ { - details: `Test Skill ${technicalSkill.name.en}`, - id: technicalSkill.id, + details: `Test Skill ${technicalSkill?.name.en}`, + id: technicalSkill?.id ?? "", }, ], }, @@ -271,11 +271,11 @@ test.describe("Application", () => { }, }, }); - const applicantWithExperiences = await me(applicantCtx); + const applicantWithExperiences = await me(applicantCtx, {}); await createApplication(applicantCtx, { userId: applicantWithExperiences.id, poolId: pool.id, - experienceId: applicantWithExperiences.experiences[0].id, + experienceId: applicantWithExperiences?.experiences?.[0]?.id ?? "", }); await loginBySub(page, sub, false); @@ -286,9 +286,5 @@ test.describe("Application", () => { level: 2, }), ).toBeVisible(); - - await expect( - page.getByRole("link", { name: /continue draft/i }), - ).toBeVisible(); }); }); diff --git a/apps/playwright/tests/login-logout.spec.ts b/apps/playwright/tests/login-logout.spec.ts index 3d78df0cbb0..db81965a54d 100644 --- a/apps/playwright/tests/login-logout.spec.ts +++ b/apps/playwright/tests/login-logout.spec.ts @@ -28,9 +28,11 @@ test.describe("Login and logout", () => { // complete login process const request = await requestPromise; - const location = await request - .response() - .then((res) => res.headerValue("location")); + const location = String( + await request + .response() + .then((res) => res?.headerValue("location") ?? ""), + ); const url = new URL(location); const searchParamAccessToken = url.searchParams.get("access_token"); @@ -104,7 +106,7 @@ test.describe("Login and logout", () => { // time travel to when the tokens expire before trying to navigate const tokenSet1 = await getAuthTokens(page); - await clockHelper.jumpTo(jumpPastExpiryDate(tokenSet1.accessToken)); + await clockHelper.jumpTo(jumpPastExpiryDate(tokenSet1?.accessToken ?? "")); const request = await requestPromise; await page.goto("/en/applicant"); @@ -171,7 +173,7 @@ test.describe("Login and logout", () => { // get auth tokens set 1 const tokenSet1 = await getAuthTokens(page); // time travel to when the tokens from token set 1 expire before trying to navigate - await clockHelper.jumpTo(jumpPastExpiryDate(tokenSet1.accessToken)); + await clockHelper.jumpTo(jumpPastExpiryDate(tokenSet1?.accessToken ?? "")); const request = await requestPromise; // navigate to a page @@ -205,7 +207,7 @@ test.describe("Login and logout", () => { // reset clock await clockHelper.restore(); // time travel to when the tokens from token set 2 expire before trying to navigate - await clockHelper.jumpTo(jumpPastExpiryDate(tokenSet2.accessToken)); + await clockHelper.jumpTo(jumpPastExpiryDate(tokenSet2?.accessToken ?? "")); const request2 = await requestPromise; // navigate to a page @@ -239,7 +241,7 @@ test.describe("Login and logout", () => { // reset clock await clockHelper.restore(); // time travel to when the tokens from token set 3 expire before trying to navigate - await clockHelper.jumpTo(jumpPastExpiryDate(tokenSet3.accessToken)); + await clockHelper.jumpTo(jumpPastExpiryDate(tokenSet3?.accessToken ?? "")); const request3 = await requestPromise; // navigate to a page diff --git a/apps/playwright/tests/open-graph.spec.ts b/apps/playwright/tests/open-graph.spec.ts index f40ba8ee9cd..97b9cc24c53 100644 --- a/apps/playwright/tests/open-graph.spec.ts +++ b/apps/playwright/tests/open-graph.spec.ts @@ -3,11 +3,13 @@ import { test, expect } from "@playwright/test"; test.describe("Open Graph", () => { test("should specify an image", async ({ page }) => { await page.goto("/en"); - const locator = await page - .locator('head meta[property="og:image"]') - .getAttribute("content"); + const locator = String( + await page + .locator('head meta[property="og:image"]') + .getAttribute("content"), + ); await page.goto(locator).then((response) => { - expect(response.status()).toEqual(200); + expect(response?.status()).toEqual(200); }); }); }); diff --git a/apps/playwright/tests/search-workflows.spec.ts b/apps/playwright/tests/search-workflows.spec.ts index 6d677cb7e46..1e88bab73ba 100644 --- a/apps/playwright/tests/search-workflows.spec.ts +++ b/apps/playwright/tests/search-workflows.spec.ts @@ -27,7 +27,7 @@ test.describe("Talent search", () => { const sub = `playwright.sub.${uniqueTestId}`; const poolName = `Search pool ${uniqueTestId}`; let classification: Classification; - let skill: Skill; + let skill: Skill | undefined; const expectNoCandidate = async (page: Page) => { await expect( @@ -38,7 +38,7 @@ test.describe("Talent search", () => { test.beforeAll(async () => { const adminCtx = await graphql.newContext(); - const technicalSkill = await getSkills(adminCtx).then((skills) => { + const technicalSkill = await getSkills(adminCtx, {}).then((skills) => { return skills.find((s) => s.category.value === SkillCategory.Technical); }); skill = technicalSkill; @@ -62,8 +62,8 @@ test.describe("Talent search", () => { skills: { sync: [ { - details: `Test Skill ${technicalSkill.name.en}`, - id: technicalSkill.id, + details: `Test Skill ${technicalSkill?.name.en}`, + id: technicalSkill?.id ?? "", }, ], }, @@ -76,14 +76,14 @@ test.describe("Talent search", () => { roles: ["guest", "base_user", "applicant"], }); - const classifications = await getClassifications(adminCtx); + const classifications = await getClassifications(adminCtx, {}); classification = classifications[0]; - const adminUser = await me(adminCtx); + const adminUser = await me(adminCtx, {}); // Accepted pool const createdPool = await createAndPublishPool(adminCtx, { userId: adminUser.id, - skillId: technicalSkill.id, + skillId: technicalSkill?.id, classificationId: classification.id, name: { en: poolName, @@ -92,12 +92,12 @@ test.describe("Talent search", () => { }); const applicantCtx = await graphql.newContext(sub); - const applicant = await me(applicantCtx); + const applicant = await me(applicantCtx, {}); const application = await createAndSubmitApplication(applicantCtx, { userId: applicant.id, poolId: createdPool.id, - experienceId: applicant.experiences[0].id, + experienceId: applicant?.experiences?.[0]?.id ?? "", signature: `${applicant.firstName}`, }); @@ -157,7 +157,7 @@ test.describe("Talent search", () => { name: /^skill$/i, }); - await skillFilter.fill(`${skill.name.en}`); + await skillFilter.fill(`${skill?.name.en}`); await skillFilter.press("ArrowDown"); await skillFilter.press("Enter"); @@ -225,7 +225,7 @@ test.describe("Talent search", () => { ).toBeVisible(); await expect( - appPage.page.getByText(new RegExp(skill.name.en)), + appPage.page.getByText(new RegExp(skill?.name.en ?? "")), ).toBeVisible(); await expect(appPage.page.getByText(/required diploma/i)).toBeVisible(); diff --git a/apps/playwright/tsconfig.json b/apps/playwright/tsconfig.json index 40d6850a836..04b350453ab 100644 --- a/apps/playwright/tsconfig.json +++ b/apps/playwright/tsconfig.json @@ -6,6 +6,7 @@ "resolveJsonModule": true, "moduleResolution": "Bundler", "esModuleInterop": true, + "strictNullChecks": true, "paths": { "~/*": ["./*"] } diff --git a/apps/playwright/utils/auth.ts b/apps/playwright/utils/auth.ts index 6e82798a555..33505e022a5 100644 --- a/apps/playwright/utils/auth.ts +++ b/apps/playwright/utils/auth.ts @@ -3,9 +3,9 @@ import { Cookie, Page, expect, request } from "@playwright/test"; import { JwtPayload, jwtDecode } from "jwt-decode"; export interface AuthTokens { - idToken?: string; - accessToken?: string; - refreshToken?: string; + idToken?: string | null; + accessToken?: string | null; + refreshToken?: string | null; } /** @@ -128,6 +128,7 @@ export async function getAuthTokens(page: Page): Promise { // export function jumpPastExpiryDate(accessToken: string): Date { const decodedAccessToken = jwtDecode(accessToken); - const newDate = new Date((decodedAccessToken.exp + 1) * 1000); + const expiry = decodedAccessToken?.exp ?? new Date().getUTCSeconds(); + const newDate = new Date(expiry + 1 * 1000); return newDate; } diff --git a/apps/playwright/utils/graphql.ts b/apps/playwright/utils/graphql.ts index 1a10807d852..b0304a59c8e 100644 --- a/apps/playwright/utils/graphql.ts +++ b/apps/playwright/utils/graphql.ts @@ -94,9 +94,9 @@ export type GraphQLResponse = { }; /** Type constraint for factories that send contextual requests */ -export type GraphQLRequestFunc = ( +export type GraphQLRequestFunc = ( ctx: GraphQLContext, - input?: I, + input: I, ) => Promise; export default { diff --git a/apps/playwright/utils/pools.ts b/apps/playwright/utils/pools.ts index be5e218b771..6f79f2f1649 100644 --- a/apps/playwright/utils/pools.ts +++ b/apps/playwright/utils/pools.ts @@ -80,25 +80,25 @@ export const createPool: GraphQLRequestFunc = async ( ) => { let teamId = opts.teamId; if (!teamId) { - const team = await getDCM(ctx); - teamId = team.id; + const team = await getDCM(ctx, {}); + teamId = team?.id; } let communityId = opts.communityId; if (!communityId) { - const communities = await getCommunities(ctx); + const communities = await getCommunities(ctx, {}); communityId = communities[0].id; } let classificationId = opts.classificationId; if (!classificationId) { - const classifications = await getClassifications(ctx); + const classifications = await getClassifications(ctx, {}); classificationId = classifications[0].id; } let departmentId = opts.departmentId; if (!departmentId) { - const departments = await getDepartments(ctx); + const departments = await getDepartments(ctx, {}); departmentId = departments[0].id; } @@ -172,12 +172,12 @@ export const createPoolSkill: GraphQLRequestFunc< > = async (ctx, { poolId, poolSkill, ...opts }) => { let skillId = opts?.skillId; if (!skillId) { - const technicalSkill = await getSkills(ctx).then((skills) => { + const technicalSkill = await getSkills(ctx, {}).then((skills) => { return skills.find( (skill) => skill.category.value === SkillCategory.Technical, ); }); - skillId = technicalSkill.id; + skillId = technicalSkill?.id; } return ctx diff --git a/apps/playwright/utils/teams.ts b/apps/playwright/utils/teams.ts index f25c8b6f319..2d7c2489515 100644 --- a/apps/playwright/utils/teams.ts +++ b/apps/playwright/utils/teams.ts @@ -20,7 +20,7 @@ const Test_TeamsQueryDocument = /* GraphQL */ ` * * Get all the DCM team directly from the API. */ -export const getDCM: GraphQLRequestFunc = async (ctx) => { +export const getDCM: GraphQLRequestFunc = async (ctx, {}) => { return await ctx .post(Test_TeamsQueryDocument) .then((res: GraphQLResponse<"teams", Team[]>) => { diff --git a/apps/playwright/utils/user.ts b/apps/playwright/utils/user.ts index 9beb2788951..10ffc3b878b 100644 --- a/apps/playwright/utils/user.ts +++ b/apps/playwright/utils/user.ts @@ -149,9 +149,10 @@ interface CreateUserWithRolesInput { } export const createUserWithRoles: GraphQLRequestFunc< - User, + User | undefined, CreateUserWithRolesInput > = async (ctx, { user, ...roleInput }) => { + if (!user) return undefined; return createUser(ctx, user).then(async (u) => { await addRolesToUser(ctx, { userId: u.id, ...roleInput }); return u; diff --git a/apps/web/src/components/AssessmentResultsTable/AssessmentResultsTable.tsx b/apps/web/src/components/AssessmentResultsTable/AssessmentResultsTable.tsx index 7deaa044a2d..52c014ae87d 100644 --- a/apps/web/src/components/AssessmentResultsTable/AssessmentResultsTable.tsx +++ b/apps/web/src/components/AssessmentResultsTable/AssessmentResultsTable.tsx @@ -252,8 +252,8 @@ const AssessmentResultsTable = ({ } return Intl.Collator().compare( - a.poolSkill.skill?.name?.[locale] || "", - b.poolSkill.skill?.name?.[locale] || "", + a.poolSkill.skill?.name?.[locale] ?? "", + b.poolSkill.skill?.name?.[locale] ?? "", ); }); diff --git a/apps/web/src/components/AssessmentStepTracker/AssessmentStepTracker.tsx b/apps/web/src/components/AssessmentStepTracker/AssessmentStepTracker.tsx index 2287d5bca08..b816b847b0e 100644 --- a/apps/web/src/components/AssessmentStepTracker/AssessmentStepTracker.tsx +++ b/apps/web/src/components/AssessmentStepTracker/AssessmentStepTracker.tsx @@ -135,7 +135,7 @@ const AssessmentStepTracker = ({ onSubmit={onSubmitDialog} resetValues={transformPoolCandidateSearchInputToFormValues( undefined, - pool?.id || "", + pool?.id ?? "", )} /> diff --git a/apps/web/src/components/AssessmentStepTracker/utils.ts b/apps/web/src/components/AssessmentStepTracker/utils.ts index c75f86e616c..d0d8acb6ee1 100644 --- a/apps/web/src/components/AssessmentStepTracker/utils.ts +++ b/apps/web/src/components/AssessmentStepTracker/utils.ts @@ -130,16 +130,16 @@ const compareLastNames = ( resultA: CandidateAssessmentResult, resultB: CandidateAssessmentResult, ) => { - const user1Name: string = resultA.poolCandidate?.user.lastName || ""; - const user2Name: string = resultB.poolCandidate?.user.lastName || ""; + const user1Name: string = resultA.poolCandidate?.user.lastName ?? ""; + const user2Name: string = resultB.poolCandidate?.user.lastName ?? ""; return user1Name.localeCompare(user2Name); }; const compareFirstNames = ( resultA: CandidateAssessmentResult, resultB: CandidateAssessmentResult, ) => { - const user1Name: string = resultA.poolCandidate?.user.firstName || ""; - const user2Name: string = resultB.poolCandidate?.user.firstName || ""; + const user1Name: string = resultA.poolCandidate?.user.firstName ?? ""; + const user2Name: string = resultB.poolCandidate?.user.firstName ?? ""; return user1Name.localeCompare(user2Name); }; diff --git a/apps/web/src/components/CandidateDialog/ChangeDateDialog.tsx b/apps/web/src/components/CandidateDialog/ChangeDateDialog.tsx index cb2de7b0abd..077d5106c14 100644 --- a/apps/web/src/components/CandidateDialog/ChangeDateDialog.tsx +++ b/apps/web/src/components/CandidateDialog/ChangeDateDialog.tsx @@ -103,7 +103,7 @@ const ChangeDateDialog = ({ formValues: FormValues, ) => { await requestMutation(selectedCandidate.id, { - expiryDate: formValues.expiryDate || emptyToNull(formValues.expiryDate), + expiryDate: formValues.expiryDate ?? emptyToNull(formValues.expiryDate), }) .then(() => { toast.success( diff --git a/apps/web/src/components/EmploymentEquity/dialogs/DialogFooter.tsx b/apps/web/src/components/EmploymentEquity/dialogs/DialogFooter.tsx index e1d838bde41..6d0883593cb 100644 --- a/apps/web/src/components/EmploymentEquity/dialogs/DialogFooter.tsx +++ b/apps/web/src/components/EmploymentEquity/dialogs/DialogFooter.tsx @@ -18,9 +18,9 @@ const DialogFooter = ({ saveText, disabled }: DialogFooterProps) => { type="submit" mode="solid" color="secondary" - disabled={disabled || isSubmitting} + disabled={disabled ?? isSubmitting} > - {saveText || intl.formatMessage(formMessages.saveChanges)} + {saveText ?? intl.formatMessage(formMessages.saveChanges)} { const args = getMutationArgs( - formValues.experience || "", + formValues.experience ?? "", formValues.skill ? { skills: getSkillArgs( diff --git a/apps/web/src/components/ExperienceSkillFormDialog/ExperienceSkillFormDialog.tsx b/apps/web/src/components/ExperienceSkillFormDialog/ExperienceSkillFormDialog.tsx index 08a113b5ad8..bbe6eb0da60 100644 --- a/apps/web/src/components/ExperienceSkillFormDialog/ExperienceSkillFormDialog.tsx +++ b/apps/web/src/components/ExperienceSkillFormDialog/ExperienceSkillFormDialog.tsx @@ -22,9 +22,9 @@ const deriveDefaultValues = ( (experienceSkill) => experienceSkill.id === skill?.id, )?.experienceSkillRecord?.details; return { - skill: skill?.id || undefined, - experience: experience?.id || undefined, - details: details || undefined, + skill: skill?.id ?? undefined, + experience: experience?.id ?? undefined, + details: details ?? undefined, }; }; @@ -64,7 +64,7 @@ const ExperienceSkillFormDialog = ({ return ( - {trigger || ( + {trigger ?? ( diff --git a/apps/web/src/components/FeatureBlock/FeatureBlock.tsx b/apps/web/src/components/FeatureBlock/FeatureBlock.tsx index dd4a28b4879..43d30ef8398 100644 --- a/apps/web/src/components/FeatureBlock/FeatureBlock.tsx +++ b/apps/web/src/components/FeatureBlock/FeatureBlock.tsx @@ -46,7 +46,7 @@ const FeatureBlock = ({ content }: FeatureBlockProps) => { data-h2-height="base(x10) desktop(x12)" style={{ backgroundImage: `url('${content.img.path}')`, - backgroundPosition: content.img.position || "center", + backgroundPosition: content.img.position ?? "center", backgroundSize: "cover", }} /> diff --git a/apps/web/src/components/Layout/SkipLink.tsx b/apps/web/src/components/Layout/SkipLink.tsx index 0ed4d76e770..1f828e60cd2 100644 --- a/apps/web/src/components/Layout/SkipLink.tsx +++ b/apps/web/src/components/Layout/SkipLink.tsx @@ -24,7 +24,7 @@ const SkipLink = ({ href = "#main", children }: SkipLinkProps) => { data-h2-width="base:focus-visible(auto)" data-h2-z-index="base:focus-visible(9999)" > - {children || + {children ?? intl.formatMessage({ defaultMessage: "Skip to main content", id: "A2ycww", diff --git a/apps/web/src/components/PoolCandidatesTable/helpers.tsx b/apps/web/src/components/PoolCandidatesTable/helpers.tsx index d8453c7da52..7a0b8c839d3 100644 --- a/apps/web/src/components/PoolCandidatesTable/helpers.tsx +++ b/apps/web/src/components/PoolCandidatesTable/helpers.tsx @@ -191,7 +191,7 @@ export const currentLocationAccessor = ( province: LocalizedProvinceOrTerritory | null | undefined, intl: IntlShape, ) => - `${city || intl.formatMessage(commonMessages.notFound)}, ${getLocalizedName(province?.label, intl)}`; + `${city ?? intl.formatMessage(commonMessages.notFound)}, ${getLocalizedName(province?.label, intl)}`; export const finalDecisionCell = ( finalDecision: Maybe | undefined, diff --git a/apps/web/src/components/PoolFilterInput/PoolFilterInput.tsx b/apps/web/src/components/PoolFilterInput/PoolFilterInput.tsx index 2a8129ec0d9..8e00237368c 100644 --- a/apps/web/src/components/PoolFilterInput/PoolFilterInput.tsx +++ b/apps/web/src/components/PoolFilterInput/PoolFilterInput.tsx @@ -53,7 +53,7 @@ const PoolFilterInput = ({ {...{ name, id }} isMulti isExternalSearch - label={label || intl.formatMessage(adminMessages.pools)} + label={label ?? intl.formatMessage(adminMessages.pools)} fetching={poolsFetching} total={total} onSearch={handleDebouncedSearch} diff --git a/apps/web/src/components/Profile/components/DiversityEquityInclusion/Display.tsx b/apps/web/src/components/Profile/components/DiversityEquityInclusion/Display.tsx index 28587991572..ff4828cb25c 100644 --- a/apps/web/src/components/Profile/components/DiversityEquityInclusion/Display.tsx +++ b/apps/web/src/components/Profile/components/DiversityEquityInclusion/Display.tsx @@ -31,6 +31,8 @@ const Display = ({ const isIndigenous = indigenousCommunities && indigenousCommunities.length > 0; const hasClaimedEquityGroup = + // Note, we only care about one truthy value so nullish coalescing is inappropriate here. + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing isWoman || hasDisability || isVisibleMinority || isIndigenous; return hasClaimedEquityGroup ? ( diff --git a/apps/web/src/components/Profile/components/GovernmentInformation/Display.tsx b/apps/web/src/components/Profile/components/GovernmentInformation/Display.tsx index 746bd6c6e46..45e16abd355 100644 --- a/apps/web/src/components/Profile/components/GovernmentInformation/Display.tsx +++ b/apps/web/src/components/Profile/components/GovernmentInformation/Display.tsx @@ -153,7 +153,7 @@ const Display = ({ })} data-h2-margin="base(0 0 x.15 0)" // line up with chip > - {workEmail || notProvided} + {workEmail ?? notProvided} {showEmailVerification && workEmail ? emailVerificationComponents @@ -175,7 +175,7 @@ const Display = ({ description: "Priority number label", })} > - {priorityNumber || notProvided} + {priorityNumber ?? notProvided} )} diff --git a/apps/web/src/components/Profile/components/PersonalInformation/Display.tsx b/apps/web/src/components/Profile/components/PersonalInformation/Display.tsx index 89a8d3e6924..c39ec648371 100644 --- a/apps/web/src/components/Profile/components/PersonalInformation/Display.tsx +++ b/apps/web/src/components/Profile/components/PersonalInformation/Display.tsx @@ -111,7 +111,7 @@ const Display = ({ description: "Label for given name field", })} > - {firstName || notProvided} + {firstName ?? notProvided} - {lastName || notProvided} + {lastName ?? notProvided}
- {email || notProvided} + {email ?? notProvided} {showEmailVerification ? emailVerificationComponents : null}
diff --git a/apps/web/src/components/Profile/components/WorkPreferences/Display.tsx b/apps/web/src/components/Profile/components/WorkPreferences/Display.tsx index 90e7259d9c6..62d566f62a3 100644 --- a/apps/web/src/components/Profile/components/WorkPreferences/Display.tsx +++ b/apps/web/src/components/Profile/components/WorkPreferences/Display.tsx @@ -107,7 +107,7 @@ const Display = ({ description: "Location specifics label", })} > - {locationExemptions || notProvided} + {locationExemptions ?? notProvided} ); diff --git a/apps/web/src/components/SEO/SEO.tsx b/apps/web/src/components/SEO/SEO.tsx index 20bd31a3cdb..487eb479cdc 100644 --- a/apps/web/src/components/SEO/SEO.tsx +++ b/apps/web/src/components/SEO/SEO.tsx @@ -27,7 +27,7 @@ const SEO = ({ title, description, type = "website" }: SEOProps) => { const seo = { title: title ? `${title} | ${defaultTitle}` : defaultTitle, - description: description || defaultDescription, + description: description ?? defaultDescription, type, }; diff --git a/apps/web/src/components/ScreeningDecisions/ScreeningDecisionDialog.tsx b/apps/web/src/components/ScreeningDecisions/ScreeningDecisionDialog.tsx index a69739f6bfb..13f4268116c 100644 --- a/apps/web/src/components/ScreeningDecisions/ScreeningDecisionDialog.tsx +++ b/apps/web/src/components/ScreeningDecisions/ScreeningDecisionDialog.tsx @@ -223,7 +223,7 @@ const ScreeningQuestions = ({ }) => { const intl = useIntl(); const screeningQuestionResponses = - poolCandidate?.screeningQuestionResponses?.filter(notEmpty) || []; + poolCandidate?.screeningQuestionResponses?.filter(notEmpty) ?? []; const screeningQuestions = screeningQuestionResponses .map((response) => response.screeningQuestion) .filter(notEmpty); @@ -249,7 +249,7 @@ const ScreeningQuestions = ({ {screeningQuestionResponses.find( (response) => response.screeningQuestion?.id === screeningQuestion.id, - )?.answer || intl.formatMessage(commonMessages.notFound)} + )?.answer ?? intl.formatMessage(commonMessages.notFound)} ))} @@ -494,7 +494,7 @@ export const ScreeningDecisionDialog = ({ onSubmit={onSubmit} labels={labels} options={{ - defaultValues: initialValues || defaultValues, + defaultValues: initialValues ?? defaultValues, }} > @@ -593,7 +593,7 @@ const ScreeningDecisionDialogApi = ({ let assessmentDecision: Maybe | "noDecision" | undefined; if (hasBeenAssessed) { assessmentDecision = - assessmentResult?.assessmentDecision?.value || "noDecision"; + assessmentResult?.assessmentDecision?.value ?? "noDecision"; } else { assessmentDecision = assessmentResult?.assessmentDecision?.value; } @@ -705,7 +705,7 @@ const ScreeningDecisionDialogApi = ({ assessmentResultType, assessmentStepId: assessmentStep.id, poolCandidateId: poolCandidate.id, - poolSkillId: poolSkill?.id || "", + poolSkillId: poolSkill?.id ?? "", }), ) } diff --git a/apps/web/src/components/SearchRequestFilters/SearchRequestFilters.tsx b/apps/web/src/components/SearchRequestFilters/SearchRequestFilters.tsx index 8987e330c4f..b8ec64c764a 100644 --- a/apps/web/src/components/SearchRequestFilters/SearchRequestFilters.tsx +++ b/apps/web/src/components/SearchRequestFilters/SearchRequestFilters.tsx @@ -44,7 +44,7 @@ const ApplicantFilters = ({ wrapAbbr(`${classification?.group}-0${classification?.level}`, intl), ); - const classifications = applicantFilter?.qualifiedClassifications || []; + const classifications = applicantFilter?.qualifiedClassifications ?? []; const classificationsFromApplicantFilter = classifications .filter(notEmpty) .map((classification) => @@ -53,7 +53,7 @@ const ApplicantFilters = ({ const skills: string[] | undefined = applicantFilter?.skills?.map((skill) => { return ( - skill?.name[locale] || + skill?.name[locale] ?? intl.formatMessage({ defaultMessage: "Error: skill name not found", id: "0T3NB0", @@ -203,7 +203,7 @@ const ApplicantFilters = ({ "Title for group and level on summary of filters section", })} content={uniqueItems( - classificationsFromBrowserHistory || + classificationsFromBrowserHistory ?? classificationsFromApplicantFilter, )} /> @@ -219,7 +219,7 @@ const ApplicantFilters = ({ description: "Title for skills section on summary of filters section", }, - { numOfSkills: skills?.length || 0 }, + { numOfSkills: skills?.length ?? 0 }, )} content={ skills && skills?.length > 0 ? ( diff --git a/apps/web/src/components/SkillBrowser/SkillBrowserDialog.tsx b/apps/web/src/components/SkillBrowser/SkillBrowserDialog.tsx index b955fd6ea0b..647499c8787 100644 --- a/apps/web/src/components/SkillBrowser/SkillBrowserDialog.tsx +++ b/apps/web/src/components/SkillBrowser/SkillBrowserDialog.tsx @@ -124,7 +124,7 @@ const SkillBrowserDialog = ({ const triggerProps = { id: trigger?.id, - children: trigger?.label || triggerMessage, + children: trigger?.label ?? triggerMessage, icon: derivedIcon, mode: trigger?.mode, disabled: trigger?.disabled, @@ -145,7 +145,7 @@ const SkillBrowserDialog = ({ return ( - {customTrigger || ( + {customTrigger ?? ( )} diff --git a/packages/forms/src/components/Submit/Submit.tsx b/packages/forms/src/components/Submit/Submit.tsx index 929703979d6..c146aefd02f 100644 --- a/packages/forms/src/components/Submit/Submit.tsx +++ b/packages/forms/src/components/Submit/Submit.tsx @@ -41,8 +41,8 @@ const Submit = ({ return ( diff --git a/packages/ui/src/components/Heading/Heading.tsx b/packages/ui/src/components/Heading/Heading.tsx index 8d6c234f860..d005714e866 100644 --- a/packages/ui/src/components/Heading/Heading.tsx +++ b/packages/ui/src/components/Heading/Heading.tsx @@ -18,7 +18,7 @@ const Heading = forwardRef( return ( >( return ( // NOTE: We do want to allow external links to be rendered as tags // eslint-disable-next-line react/forbid-elements - + {content} ); } return ( - + {content} ); diff --git a/packages/ui/src/components/PreviewList/PreviewList.tsx b/packages/ui/src/components/PreviewList/PreviewList.tsx index 948c2ba4052..afdf3da77f1 100644 --- a/packages/ui/src/components/PreviewList/PreviewList.tsx +++ b/packages/ui/src/components/PreviewList/PreviewList.tsx @@ -21,7 +21,7 @@ const MetaData = ({ children, type, color }: MetaDataProps) => { case "chip": return ( - + {children} diff --git a/packages/ui/src/components/SideMenu/SideMenuItem.tsx b/packages/ui/src/components/SideMenu/SideMenuItem.tsx index 26f7dcdf470..e2d8aba377a 100644 --- a/packages/ui/src/components/SideMenu/SideMenuItem.tsx +++ b/packages/ui/src/components/SideMenu/SideMenuItem.tsx @@ -89,12 +89,12 @@ const SideMenuItem = ({ icon, children, href, ...rest }: SideMenuItemProps) => { if (isSmallScreen && ctx?.onOpenChange) { ctx?.onOpenChange(false); } - navigate(url || ""); + navigate(url ?? ""); }; return ( + {children} ); @@ -37,7 +37,7 @@ const StepLink = ({ aria-current={state.includes("active") ? "step" : undefined} href={href} mode="text" - {...(linkStyles || {})} + {...(linkStyles ?? {})} {...rest} > {children} diff --git a/packages/ui/src/components/ToggleSection/ToggleSection.tsx b/packages/ui/src/components/ToggleSection/ToggleSection.tsx index a4d8586848d..69d24ce2718 100644 --- a/packages/ui/src/components/ToggleSection/ToggleSection.tsx +++ b/packages/ui/src/components/ToggleSection/ToggleSection.tsx @@ -195,7 +195,7 @@ const Trigger = forwardRef< ref={forwardedRef} asChild aria-controls={controls} - pressed={context?.open || false} + pressed={context?.open ?? false} onPressedChange={handleOnPressedChange} {...toggleProps} >