From 786b9e1407ed24f94a72274068629d3e7e39f4bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Jun 2026 13:42:02 +0000 Subject: [PATCH 1/2] chore(deps): bump typescript from 5.9.3 to 6.0.3 in /quality Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.9.3 to 6.0.3. - [Release notes](https://github.com/microsoft/TypeScript/releases) - [Commits](https://github.com/microsoft/TypeScript/compare/v5.9.3...v6.0.3) --- updated-dependencies: - dependency-name: typescript dependency-version: 6.0.3 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- quality/package.json | 2 +- quality/yarn.lock | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/quality/package.json b/quality/package.json index ecaf989985..6e849ebc5a 100644 --- a/quality/package.json +++ b/quality/package.json @@ -48,7 +48,7 @@ "otplib": "^13.4.1", "prettier": "^3.8.4", "tsx": "^4.22.4", - "typescript": "5.9.3" + "typescript": "6.0.3" }, "devDependencies": { "prettier-plugin-organize-imports": "^4.3.0" diff --git a/quality/yarn.lock b/quality/yarn.lock index 3000903508..874a2de5de 100644 --- a/quality/yarn.lock +++ b/quality/yarn.lock @@ -3896,7 +3896,12 @@ type-fest@^5.2.0, type-fest@^5.4.4: dependencies: tagged-tag "^1.0.0" -typescript@5.9.3, typescript@^5.7.3, typescript@^5.9.3: +typescript@6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-6.0.3.tgz#90251dc007916e972786cb94d74d15b185577d21" + integrity sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw== + +typescript@^5.7.3, typescript@^5.9.3: version "5.9.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f" integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw== From 5097f214f29ca0e866a999d0c9c1580627473341 Mon Sep 17 00:00:00 2001 From: Douglas DUTEIL Date: Tue, 30 Jun 2026 17:35:32 +0200 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=8F=B7=EF=B8=8F=20quality:=20fix=20st?= =?UTF-8?q?rict-mode=20errors=20for=20TypeScript=206?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Problem** TypeScript 6.0.3 defaults strict to true, causing ~140 type errors across the quality test suite (uninitialized DTO properties, unknown catch bindings, implicit any indexing, null/undefined propagation through find/attr/match calls). **Proposal** Add definite assignment assertions to class-validator DTOs, cast unknown error bindings, suppress untyped third-party modules with @ts-expect-error, and apply targeted ! / as casts at the narrow sites where null/undefined is already guarded by test assertions. --- quality/cypress/plugins/log-plugin.ts | 6 +- .../support/api/dto/get-discovery.dto.ts | 80 +++++++++---------- .../api/dto/post-token-introspection.dto.ts | 22 ++--- .../support/api/steps/api-jwt-steps.ts | 16 ++-- .../support/api/steps/api-request-steps.ts | 16 ++-- .../common/helpers/accessibility-helper.ts | 2 +- .../support/common/helpers/cookie-helper.ts | 2 +- .../support/common/helpers/fixtures-helper.ts | 9 ++- .../common/helpers/sp-claims-helper.ts | 78 ++++++++++-------- .../common/steps/accessibility-steps.ts | 2 +- .../common/steps/image-snapshot-steps.ts | 4 +- .../support/common/steps/local-log-steps.ts | 4 +- .../common/types/service-provider-config.d.ts | 4 +- .../helpers/operator-user-provider.ts | 3 +- .../exploitation/pages/exploit-form-page.ts | 9 ++- .../pages/exploit-idp-list-page.ts | 6 +- .../pages/exploit-sp-list-page.ts | 5 +- .../steps/exploit-common-steps.ts | 5 +- .../steps/exploit-idp-form-steps.ts | 3 +- .../steps/exploit-idp-list-steps.ts | 5 +- .../steps/exploit-sp-form-steps.ts | 3 +- .../steps/exploit-sp-list-steps.ts | 8 +- .../usager/steps/contact-support-steps.ts | 18 +++-- .../support/usager/steps/interaction-steps.ts | 4 +- .../steps/service-provider-error-steps.ts | 4 +- .../usager/steps/service-provider-steps.ts | 2 +- .../multiple-cucumber-html-reporter.ts | 1 + quality/scripts/parse-business-log.ts | 4 +- 28 files changed, 178 insertions(+), 147 deletions(-) diff --git a/quality/cypress/plugins/log-plugin.ts b/quality/cypress/plugins/log-plugin.ts index a5d9bc745a..f5e6264cdc 100644 --- a/quality/cypress/plugins/log-plugin.ts +++ b/quality/cypress/plugins/log-plugin.ts @@ -27,16 +27,16 @@ interface hasBusinessLogArgs { export const hasBusinessLog = async ( args: hasBusinessLogArgs, -): Promise => { +): Promise => { const { event, containerName } = args; const stringifiedEvent = JSON.stringify(event); const command = `${dockerLogsCommand(containerName)} | tsx ${EXEC_TOOL_PATH} /dev/stdin '${stringifiedEvent}'`; - let exitCode = 0; + let exitCode: string | undefined = "UNKNOWN"; try { await asyncExec(command); } catch (err) { - exitCode = err.code; + exitCode = (err as NodeJS.ErrnoException).code ?? "UNKNOWN"; } return exitCode; }; diff --git a/quality/cypress/support/api/dto/get-discovery.dto.ts b/quality/cypress/support/api/dto/get-discovery.dto.ts index b18610298a..1b7a133d1b 100644 --- a/quality/cypress/support/api/dto/get-discovery.dto.ts +++ b/quality/cypress/support/api/dto/get-discovery.dto.ts @@ -3,156 +3,156 @@ import { IsArray, IsBoolean, IsString, MinLength } from "class-validator"; export class GetDiscoveryDto { @IsString({ each: true }) @IsArray() - readonly acr_values_supported: string[]; + readonly acr_values_supported!: string[]; @IsString() @MinLength(1) - readonly authorization_endpoint: string; + readonly authorization_endpoint!: string; @IsBoolean() - readonly claims_parameter_supported: boolean; + readonly claims_parameter_supported!: boolean; @IsString({ each: true }) @IsArray() - readonly claims_supported: string[]; + readonly claims_supported!: string[]; @IsString({ each: true }) @IsArray() - readonly code_challenge_methods_supported: string[]; + readonly code_challenge_methods_supported!: string[]; @IsString() @MinLength(1) - readonly end_session_endpoint: string; + readonly end_session_endpoint!: string; @IsString({ each: true }) @IsArray() - readonly grant_types_supported: string[]; + readonly grant_types_supported!: string[]; @IsString({ each: true }) @IsArray() - readonly id_token_signing_alg_values_supported: string[]; + readonly id_token_signing_alg_values_supported!: string[]; @IsString() @MinLength(1) - readonly introspection_endpoint: string; + readonly introspection_endpoint!: string; @IsString({ each: true }) @IsArray() - readonly introspection_endpoint_auth_methods_supported: string[]; + readonly introspection_endpoint_auth_methods_supported!: string[]; @IsString({ each: true }) @IsArray() - readonly introspection_endpoint_auth_signing_alg_values_supported: string[]; + readonly introspection_endpoint_auth_signing_alg_values_supported!: string[]; @IsString({ each: true }) @IsArray() - readonly introspection_signing_alg_values_supported: string[]; + readonly introspection_signing_alg_values_supported!: string[]; @IsString({ each: true }) @IsArray() - readonly introspection_encryption_alg_values_supported: string[]; + readonly introspection_encryption_alg_values_supported!: string[]; @IsString({ each: true }) @IsArray() - readonly introspection_encryption_enc_values_supported: string[]; + readonly introspection_encryption_enc_values_supported!: string[]; @IsString() @MinLength(1) - readonly issuer: string; + readonly issuer!: string; @IsString() @MinLength(1) - readonly jwks_uri: string; + readonly jwks_uri!: string; @IsBoolean() - readonly authorization_response_iss_parameter_supported: boolean; + readonly authorization_response_iss_parameter_supported!: boolean; @IsString({ each: true }) @IsArray() - readonly response_modes_supported: string[]; + readonly response_modes_supported!: string[]; @IsString({ each: true }) @IsArray() - readonly response_types_supported: string[]; + readonly response_types_supported!: string[]; @IsString({ each: true }) @IsArray() - readonly scopes_supported: string[]; + readonly scopes_supported!: string[]; @IsString({ each: true }) @IsArray() - readonly subject_types_supported: string[]; + readonly subject_types_supported!: string[]; @IsString({ each: true }) @IsArray() - readonly token_endpoint_auth_methods_supported: string[]; + readonly token_endpoint_auth_methods_supported!: string[]; @IsString({ each: true }) @IsArray() - readonly token_endpoint_auth_signing_alg_values_supported: string[]; + readonly token_endpoint_auth_signing_alg_values_supported!: string[]; @IsString() @MinLength(1) - readonly token_endpoint: string; + readonly token_endpoint!: string; @IsString({ each: true }) @IsArray() - readonly request_object_signing_alg_values_supported: string[]; + readonly request_object_signing_alg_values_supported!: string[]; @IsBoolean() - readonly request_parameter_supported: boolean; + readonly request_parameter_supported!: boolean; @IsBoolean() - readonly request_uri_parameter_supported: boolean; + readonly request_uri_parameter_supported!: boolean; @IsBoolean() - readonly require_request_uri_registration: boolean; + readonly require_request_uri_registration!: boolean; @IsString() @MinLength(1) - readonly userinfo_endpoint: string; + readonly userinfo_endpoint!: string; @IsString({ each: true }) @IsArray() - readonly userinfo_signing_alg_values_supported: string[]; + readonly userinfo_signing_alg_values_supported!: string[]; @IsString() @MinLength(1) - readonly revocation_endpoint: string; + readonly revocation_endpoint!: string; @IsString({ each: true }) @IsArray() - readonly revocation_endpoint_auth_methods_supported: string[]; + readonly revocation_endpoint_auth_methods_supported!: string[]; @IsString({ each: true }) @IsArray() - readonly revocation_endpoint_auth_signing_alg_values_supported: string[]; + readonly revocation_endpoint_auth_signing_alg_values_supported!: string[]; @IsString({ each: true }) @IsArray() - readonly claim_types_supported: string[]; + readonly claim_types_supported!: string[]; @IsString({ each: true }) @IsArray() - readonly id_token_encryption_alg_values_supported: string[]; + readonly id_token_encryption_alg_values_supported!: string[]; @IsString({ each: true }) @IsArray() - readonly id_token_encryption_enc_values_supported: string[]; + readonly id_token_encryption_enc_values_supported!: string[]; @IsString({ each: true }) @IsArray() - readonly userinfo_encryption_alg_values_supported: string[]; + readonly userinfo_encryption_alg_values_supported!: string[]; @IsString({ each: true }) @IsArray() - readonly userinfo_encryption_enc_values_supported: string[]; + readonly userinfo_encryption_enc_values_supported!: string[]; @IsString({ each: true }) @IsArray() - readonly request_object_encryption_alg_values_supported: string[]; + readonly request_object_encryption_alg_values_supported!: string[]; @IsString({ each: true }) @IsArray() - readonly request_object_encryption_enc_values_supported: string[]; + readonly request_object_encryption_enc_values_supported!: string[]; } diff --git a/quality/cypress/support/api/dto/post-token-introspection.dto.ts b/quality/cypress/support/api/dto/post-token-introspection.dto.ts index d91ec2ae9d..715581f352 100644 --- a/quality/cypress/support/api/dto/post-token-introspection.dto.ts +++ b/quality/cypress/support/api/dto/post-token-introspection.dto.ts @@ -11,52 +11,52 @@ import { export class ValidTokenIntrospection { @IsBoolean() - readonly active: boolean; + readonly active!: boolean; @IsString() @MinLength(1) - readonly sub: string; + readonly sub!: string; @IsString() @MinLength(1) - readonly client_id: string; + readonly client_id!: string; @IsNumber() @IsPositive() - readonly exp: number; + readonly exp!: number; @IsNumber() @IsPositive() - readonly iat: number; + readonly iat!: number; @IsString() @MinLength(1) - readonly iss: string; + readonly iss!: string; @IsString() @MinLength(1) - readonly scope: string; + readonly scope!: string; @IsString() @MinLength(1) - readonly token_type: string; + readonly token_type!: string; } class ExpiredTokenIntrospection { @IsBoolean() - readonly active: boolean; + readonly active!: boolean; } export class GetTokenIntrospectionValidTokenDto { @IsObject() @ValidateNested() @Type(() => ValidTokenIntrospection) - readonly token_introspection: ValidTokenIntrospection; + readonly token_introspection!: ValidTokenIntrospection; } export class GetTokenIntrospectionExpiredTokenDto { @IsObject() @ValidateNested() @Type(() => ExpiredTokenIntrospection) - readonly token_introspection: ExpiredTokenIntrospection; + readonly token_introspection!: ExpiredTokenIntrospection; } diff --git a/quality/cypress/support/api/steps/api-jwt-steps.ts b/quality/cypress/support/api/steps/api-jwt-steps.ts index 7981ea549f..47422baf8f 100644 --- a/quality/cypress/support/api/steps/api-jwt-steps.ts +++ b/quality/cypress/support/api/steps/api-jwt-steps.ts @@ -14,7 +14,7 @@ Then( /^(?:le |l')(entête du JWE|entête du JWS|payload du JWT) a (\d+) propriétés?$/, function (jwtPart: string, count: number) { cy.get("@jwt") - .its(jwtPartsMap[jwtPart]) + .its(jwtPartsMap[jwtPart as keyof typeof jwtPartsMap]) .then((part) => Object.keys(part)) .should("have.length", count); }, @@ -23,7 +23,9 @@ Then( Then( /^(?:le |l')(entête du JWE|entête du JWS|payload du JWT) a une propriété "([^"]+)"$/, function (jwtPart: string, property: string) { - cy.get("@jwt").its(jwtPartsMap[jwtPart]).should("have.property", property); + cy.get("@jwt") + .its(jwtPartsMap[jwtPart as keyof typeof jwtPartsMap]) + .should("have.property", property); }, ); @@ -31,7 +33,7 @@ Then( /^(?:le |l')(entête du JWE|entête du JWS|payload du JWT) n'a pas de propriété "([^"]+)"$/, function (jwtPart: string, property: string) { cy.get("@jwt") - .its(jwtPartsMap[jwtPart]) + .its(jwtPartsMap[jwtPart as keyof typeof jwtPartsMap]) .should("not.have.property", property); }, ); @@ -40,7 +42,7 @@ Then( /^(?:le |l')(entête du JWE|entête du JWS|payload du JWT) a une propriété "([^"]+)" égale à "([^"]+)"$/, function (jwtPart: string, property: string, value: string) { cy.get("@jwt") - .its(jwtPartsMap[jwtPart]) + .its(jwtPartsMap[jwtPart as keyof typeof jwtPartsMap]) .its(property) .should("equal", value); }, @@ -50,7 +52,7 @@ Then( /^(?:le |l')(entête du JWE|entête du JWS|payload du JWT) a une propriété "([^"]+)" égale à (\d+)$/, function (jwtPart: string, property: string, value: number) { cy.get("@jwt") - .its(jwtPartsMap[jwtPart]) + .its(jwtPartsMap[jwtPart as keyof typeof jwtPartsMap]) .its(property) .should("equal", value); }, @@ -61,7 +63,7 @@ Then( function (jwtPart: string, property: string, value: string) { const booleanValue = value === "true"; cy.get("@jwt") - .its(jwtPartsMap[jwtPart]) + .its(jwtPartsMap[jwtPart as keyof typeof jwtPartsMap]) .its(property) .should("equal", booleanValue); }, @@ -71,7 +73,7 @@ Then( /^(?:le |l')(entête du JWE|entête du JWS|payload du JWT) a une propriété "([^"]+)" contenant "([^"]+)"$/, function (jwtPart: string, property: string, value: string) { cy.get("@jwt") - .its(jwtPartsMap[jwtPart]) + .its(jwtPartsMap[jwtPart as keyof typeof jwtPartsMap]) .its(property) .should("include", value); }, diff --git a/quality/cypress/support/api/steps/api-request-steps.ts b/quality/cypress/support/api/steps/api-request-steps.ts index d463a829cc..e3215f67b1 100644 --- a/quality/cypress/support/api/steps/api-request-steps.ts +++ b/quality/cypress/support/api/steps/api-request-steps.ts @@ -17,27 +17,27 @@ Given("je prépare une requête {string}", function (requestKey: string) { Given( "je retire le paramètre {string} de la requête", function (property: string) { - expect(this.apiRequest.qs[property]).to.exist; - delete this.apiRequest.qs[property]; + expect((this.apiRequest!.qs as Record)[property]).to.exist; + delete (this.apiRequest!.qs as Record)[property]; }, ); Given( "je mets {string} dans le paramètre {string} de la requête", function (value: string, property: string) { - this.apiRequest.qs[property] = value; + (this.apiRequest!.qs as Record)[property] = value; }, ); Given("je retire {string} du corps de la requête", function (property: string) { - expect(this.apiRequest.body[property]).to.exist; - delete this.apiRequest.body[property]; + expect((this.apiRequest!.body as Record)[property]).to.exist; + delete (this.apiRequest!.body as Record)[property]; }); Given( "je mets {string} dans la propriété {string} du corps de la requête", function (value: string, property: string) { - this.apiRequest.body[property] = value; + (this.apiRequest!.body as Record)[property] = value; }, ); @@ -47,7 +47,7 @@ Given( cy.get(`@api:${dataKey}`) .should("exist") .then((value) => { - this.apiRequest.body[property] = value; + (this.apiRequest!.body as Record)[property] = value; }); }, ); @@ -55,7 +55,7 @@ Given( Given( "je configure la requête pour ne pas suivre les redirections", function () { - this.apiRequest.followRedirect = false; + this.apiRequest!.followRedirect = false; }, ); diff --git a/quality/cypress/support/common/helpers/accessibility-helper.ts b/quality/cypress/support/common/helpers/accessibility-helper.ts index f613966f88..d90af2c56d 100644 --- a/quality/cypress/support/common/helpers/accessibility-helper.ts +++ b/quality/cypress/support/common/helpers/accessibility-helper.ts @@ -23,7 +23,7 @@ export const cypressLog = (violations: Result[]): void => { $el: nodes, consoleProps, message: `[${help}](${helpUrl})`, - name: `${severityIndicators[impact]} A11Y`, + name: `${severityIndicators[impact as keyof typeof severityIndicators]} A11Y`, }); targets.forEach((target) => { diff --git a/quality/cypress/support/common/helpers/cookie-helper.ts b/quality/cypress/support/common/helpers/cookie-helper.ts index b8b4965d9e..49ff9d3bb8 100644 --- a/quality/cypress/support/common/helpers/cookie-helper.ts +++ b/quality/cypress/support/common/helpers/cookie-helper.ts @@ -35,7 +35,7 @@ export const forceSameSiteNone = (domains: { [key: string]: string }): void => { export const getCookieFromUrl = ( cookieName: string, cookieUrl: string, -): Cypress.Chainable => { +): Cypress.Chainable => { const url = new URL(cookieUrl); const domain = url.hostname; return cy.getCookie(cookieName, { domain }); diff --git a/quality/cypress/support/common/helpers/fixtures-helper.ts b/quality/cypress/support/common/helpers/fixtures-helper.ts index 0bf1dda17d..cd03881b59 100644 --- a/quality/cypress/support/common/helpers/fixtures-helper.ts +++ b/quality/cypress/support/common/helpers/fixtures-helper.ts @@ -1,3 +1,4 @@ +// @ts-expect-error — no types for lodash import { cloneDeep } from "lodash"; // Docker @@ -78,9 +79,9 @@ const { apiCommon, environment, idpConfigs, idpList, spConfigs, spList } = export const getServiceProviderByDescription = ( description: string, ): ServiceProvider => { - const serviceProvider: ServiceProvider = spList.find((serviceProvider) => + const serviceProvider = spList.find((serviceProvider) => serviceProvider.descriptions.includes(description), - ); + ) as ServiceProvider; expect( serviceProvider, `A service provider matches the description '${description}'`, @@ -95,9 +96,9 @@ export const getDefaultServiceProviderConfig = (): ServiceProviderConfig => { export const getIdentityProviderByDescription = ( description: string, ): IdentityProvider => { - const identityProvider: IdentityProvider = idpList.find((identityProvider) => + const identityProvider = idpList.find((identityProvider) => identityProvider.descriptions.includes(description), - ); + ) as IdentityProvider; expect( identityProvider, `An identity provider matches the description '${description}'`, diff --git a/quality/cypress/support/common/helpers/sp-claims-helper.ts b/quality/cypress/support/common/helpers/sp-claims-helper.ts index 3f9205cbea..b1c95c99f0 100644 --- a/quality/cypress/support/common/helpers/sp-claims-helper.ts +++ b/quality/cypress/support/common/helpers/sp-claims-helper.ts @@ -9,10 +9,12 @@ const getUserInfo = (): ChainableElement => cy.get("#userinfo").invoke("text").then(JSON.parse); export const getUserInfoProperty = (property: string): ChainableElement => - getUserInfo().then((userInfo) => userInfo[property]); + (getUserInfo() as unknown as Cypress.Chainable>).then( + (userInfo) => userInfo[property], + ) as unknown as ChainableElement; export const getScopeByDescription = (description: string): string => - scopes.find((scope) => scope.description === description).scopes.join(" "); + scopes.find((scope) => scope.description === description)!.scopes.join(" "); export const getUserInfoSignatureAlgorithmByDescription = ( description: string, @@ -37,14 +39,16 @@ export const checkMandatoryData = (isUserinfoSigned: boolean): void => { const mandatoryPatterns = isUserinfoSigned ? signedUserInfoMandatoryPatterns : nonSignedUserInfoMandatoryPatterns; - getUserInfo().then((userInfo) => { - Object.keys(mandatoryPatterns).forEach((key) => - expect(userInfo[key]).to.match( - mandatoryPatterns[key], - `${key} should be present.`, - ), - ); - }); + (getUserInfo() as unknown as Cypress.Chainable>).then( + (userInfo) => { + Object.keys(mandatoryPatterns).forEach((key) => + expect(String(userInfo[key])).to.match( + (mandatoryPatterns as Record)[key], + `${key} should be present.`, + ), + ); + }, + ); }; const aliasScopesClaims = { @@ -56,8 +60,10 @@ const aliasScopesClaims = { export const getClaims = (scope: string): string[] => { const claims = scope .split(" ") - .map((scope: string): string => - aliasScopesClaims[scope] ? aliasScopesClaims[scope] : scope, + .map((scope: string): string | string[] => + (aliasScopesClaims as Record)[scope] + ? (aliasScopesClaims as Record)[scope] + : scope, ) .flat(); return [...new Set(claims)]; @@ -72,18 +78,20 @@ export const checkExpectedUserClaims = ( const expectedClaims = getClaims(expectedScope); const userClaims = { ...defaultUserClaims, ...idpClaims }; - getUserInfo().then((userInfo) => { - expectedClaims - .filter((claimName) => claimName !== "sub" && claimName !== "email") - .forEach((claimName) => { - expect(userInfo[claimName]).to.deep.equal( - userClaims[claimName], - `The claim "${claimName}" should be "${JSON.stringify( - userClaims[claimName], - )}"`, - ); - }); - }); + (getUserInfo() as unknown as Cypress.Chainable>).then( + (userInfo) => { + expectedClaims + .filter((claimName) => claimName !== "sub" && claimName !== "email") + .forEach((claimName) => { + expect(userInfo[claimName]).to.deep.equal( + (userClaims as Record)[claimName], + `The claim "${claimName}" should be "${JSON.stringify( + (userClaims as Record)[claimName], + )}"`, + ); + }); + }, + ); }; export const checkNoExtraClaims = ( @@ -97,13 +105,17 @@ export const checkNoExtraClaims = ( const expectedScope = getScopeByDescription(expectedScopeDescription); const expectedClaims = getClaims(expectedScope); - getUserInfo().then((userInfo) => { - const extraClaimsName = Object.keys(userInfo).filter( - (key) => !mandatoryData[key] && !expectedClaims.includes(key), - ); - expect(extraClaimsName).to.deep.equal( - [], - "No extra claims should be sent.", - ); - }); + (getUserInfo() as unknown as Cypress.Chainable>).then( + (userInfo) => { + const extraClaimsName = Object.keys(userInfo).filter( + (key) => + !(mandatoryData as Record)[key] && + !expectedClaims.includes(key), + ); + expect(extraClaimsName).to.deep.equal( + [], + "No extra claims should be sent.", + ); + }, + ); }; diff --git a/quality/cypress/support/common/steps/accessibility-steps.ts b/quality/cypress/support/common/steps/accessibility-steps.ts index 2bb2268820..9fb55b009f 100644 --- a/quality/cypress/support/common/steps/accessibility-steps.ts +++ b/quality/cypress/support/common/steps/accessibility-steps.ts @@ -22,7 +22,7 @@ When("je vérifie l'accessibilité sur cette page", function () { const oldViolations = this.allViolations ?? []; this.allViolations = oldViolations.concat(this.newViolations); }; - cy.checkA11y(null, null, violationCallback, true); + cy.checkA11y(undefined, undefined, violationCallback, true); }; injectAxeOnce(); checkA11y(); diff --git a/quality/cypress/support/common/steps/image-snapshot-steps.ts b/quality/cypress/support/common/steps/image-snapshot-steps.ts index 870a8d866e..7fc057d7d9 100644 --- a/quality/cypress/support/common/steps/image-snapshot-steps.ts +++ b/quality/cypress/support/common/steps/image-snapshot-steps.ts @@ -28,7 +28,7 @@ const getSnapshotName = ( Then( "la copie d'écran {string} correspond à la page actuelle sur {string}", function (name: string, device: string) { - const { title: scenarioName } = this.test; + const { title: scenarioName } = this.test!; // Wait for the page to be still before taking a screenshot cy.wait(750); prepareScreenshot(); @@ -41,7 +41,7 @@ Then( Then( "la copie d'écran {string} sans {string} correspond à la page actuelle sur {string}", function (name: string, hiddenSelector: string, device: string) { - const { title: scenarioName } = this.test; + const { title: scenarioName } = this.test!; // Wait for the page to be still before taking a screenshot cy.wait(750); diff --git a/quality/cypress/support/common/steps/local-log-steps.ts b/quality/cypress/support/common/steps/local-log-steps.ts index 476cf13750..bbd2c06083 100644 --- a/quality/cypress/support/common/steps/local-log-steps.ts +++ b/quality/cypress/support/common/steps/local-log-steps.ts @@ -31,7 +31,7 @@ Then( const DELIMITOR = " et "; const extraEventVerification = prepareEventVerification( - info, + info ?? "", DELIMITOR, {}, valueMapping, @@ -94,7 +94,7 @@ const prepareEventVerification = ( keyMapping: Record = {}, valueMapping: Record = {}, ): Record => { - const expectedEvent = {}; + const expectedEvent: Record = {}; if (text) { text.split(delimitor).forEach((infoText) => { const result = infoText.match(/^"([^"]+)" "([^"]*)"$/); diff --git a/quality/cypress/support/common/types/service-provider-config.d.ts b/quality/cypress/support/common/types/service-provider-config.d.ts index ddf17e4817..11bd2b9975 100644 --- a/quality/cypress/support/common/types/service-provider-config.d.ts +++ b/quality/cypress/support/common/types/service-provider-config.d.ts @@ -1,6 +1,6 @@ export interface ServiceProviderConfig extends Record< string, - string | string[] + string | string[] | null > { name: string; redirectUri: string; @@ -9,6 +9,6 @@ export interface ServiceProviderConfig extends Record< scopes: string[]; active: string; type: string; - userinfo_signed_response_alg: string; + userinfo_signed_response_alg: string | null; id_token_signed_response_alg: string; } diff --git a/quality/cypress/support/exploitation/helpers/operator-user-provider.ts b/quality/cypress/support/exploitation/helpers/operator-user-provider.ts index 86f300f8ab..ab04367388 100644 --- a/quality/cypress/support/exploitation/helpers/operator-user-provider.ts +++ b/quality/cypress/support/exploitation/helpers/operator-user-provider.ts @@ -23,7 +23,8 @@ const users = [ export const getOperatorUserByType = (userType: string): OperatorUser => { const userData = users.find((user) => user.role === userType); - const operatorUser = new OperatorUser(userData); + expect(userData, `No user found with type '${userType}'`).to.exist; + const operatorUser = new OperatorUser(userData!); expect(operatorUser, `No operator user found with type '${userType}'`).to .exist; return operatorUser; diff --git a/quality/cypress/support/exploitation/pages/exploit-form-page.ts b/quality/cypress/support/exploitation/pages/exploit-form-page.ts index e2bdecf0e8..6fabeaff5a 100644 --- a/quality/cypress/support/exploitation/pages/exploit-form-page.ts +++ b/quality/cypress/support/exploitation/pages/exploit-form-page.ts @@ -44,10 +44,11 @@ export default class ExploitFormPage { }); } - fillDefaultValues(values: Record): void { + fillDefaultValues(values: Record): void { const elementAlreadySet: string[] = []; this.getAllFormInputs().each(($el) => { - const elementName = $el.attr("name"); + const elementName = $el.attr("name")!; + expect(elementName).to.exist; const value = values[elementName]; // If the html element has not been set already and a value exists if (!elementAlreadySet.includes(elementName) && value) { @@ -66,7 +67,7 @@ export default class ExploitFormPage { this.getVisibleInputFromName(name) .each(($el) => { if ($el.is(":checked")) { - allCheckedValues.push($el.attr("value")); + allCheckedValues.push($el.attr("value") as string); } }) .then(() => { @@ -97,6 +98,6 @@ export default class ExploitFormPage { * We use a debounce for mongoose watcher so it's not overloaded. * It can lead to some latency in the creation / update of an entity. */ - return cy.wait(1000); + return cy.wait(1000) as unknown as ChainableElement; } } diff --git a/quality/cypress/support/exploitation/pages/exploit-idp-list-page.ts b/quality/cypress/support/exploitation/pages/exploit-idp-list-page.ts index 434df65e9a..2aa7270424 100644 --- a/quality/cypress/support/exploitation/pages/exploit-idp-list-page.ts +++ b/quality/cypress/support/exploitation/pages/exploit-idp-list-page.ts @@ -4,7 +4,9 @@ import TotpModal from "./totp-modal-component"; export default class ExploitIdpListPage { getCreateIdpButton(): ChainableElement { - return cy.contains("Créer un fournisseur d'identité"); + return cy.contains( + "Créer un fournisseur d'identité", + ) as unknown as ChainableElement; } getIdpRow(idpName: string): ChainableElement { @@ -28,7 +30,7 @@ export default class ExploitIdpListPage { deleteAllIdpStartingWith(idpNamePrefix: string, user: OperatorUser): void { this.getIdpRowsStartingWith(idpNamePrefix).each(($idpRows) => { const idpName = $idpRows.attr("data-idp-name"); - this.deleteIdp(idpName, user); + this.deleteIdp(idpName!, user); }); } diff --git a/quality/cypress/support/exploitation/pages/exploit-sp-list-page.ts b/quality/cypress/support/exploitation/pages/exploit-sp-list-page.ts index dec715cea0..c6333a9b2d 100644 --- a/quality/cypress/support/exploitation/pages/exploit-sp-list-page.ts +++ b/quality/cypress/support/exploitation/pages/exploit-sp-list-page.ts @@ -4,7 +4,10 @@ import TotpModal from "./totp-modal-component"; export default class ExploitSpListPage { getCreateSpButton(): ChainableElement { - return cy.contains("a", "Créer un fournisseur de service"); + return cy.contains( + "a", + "Créer un fournisseur de service", + ) as unknown as ChainableElement; } getSpRow(spName: string): ChainableElement { diff --git a/quality/cypress/support/exploitation/steps/exploit-common-steps.ts b/quality/cypress/support/exploitation/steps/exploit-common-steps.ts index 6429fa35d7..1c180d14b2 100644 --- a/quality/cypress/support/exploitation/steps/exploit-common-steps.ts +++ b/quality/cypress/support/exploitation/steps/exploit-common-steps.ts @@ -1,5 +1,6 @@ import { Then, When } from "@badeball/cypress-cucumber-preprocessor"; import { getFcaAuthorizeUrl } from "../../common/helpers"; +import { OperatorUser } from "../helpers"; import TotpModal from "../pages/totp-modal-component"; Then( @@ -40,7 +41,7 @@ When( cy.get(`tr#${sub} i.fa-lock`).click(); cy.contains("Voulez-vous désactiver l'utilisateur").should("be.visible"); const totpModal = new TotpModal(); - totpModal.submitTotp(this.operatorUser); + totpModal.submitTotp(this.operatorUser as OperatorUser); }, ); @@ -50,7 +51,7 @@ When( cy.get(`tr#${sub} i.fa-unlock`).click(); cy.contains("Voulez-vous activer l'utilisateur").should("be.visible"); const totpModal = new TotpModal(); - totpModal.submitTotp(this.operatorUser); + totpModal.submitTotp(this.operatorUser as OperatorUser); }, ); diff --git a/quality/cypress/support/exploitation/steps/exploit-idp-form-steps.ts b/quality/cypress/support/exploitation/steps/exploit-idp-form-steps.ts index c17c754d09..4c0bb485f9 100644 --- a/quality/cypress/support/exploitation/steps/exploit-idp-form-steps.ts +++ b/quality/cypress/support/exploitation/steps/exploit-idp-form-steps.ts @@ -1,5 +1,6 @@ import { When } from "@badeball/cypress-cucumber-preprocessor"; import { getDefaultIdentityProviderConfig } from "../../common/helpers"; +import { OperatorUser } from "../helpers"; import ExploitIdpFormPage from "../pages/exploit-idp-form-page"; const exploitIdpFormPage = new ExploitIdpFormPage(); @@ -57,6 +58,6 @@ When( When( /^je valide le formulaire de (?:création|modification) de FI$/, function () { - exploitIdpFormPage.validateForm(this.operatorUser); + exploitIdpFormPage.validateForm(this.operatorUser as OperatorUser); }, ); diff --git a/quality/cypress/support/exploitation/steps/exploit-idp-list-steps.ts b/quality/cypress/support/exploitation/steps/exploit-idp-list-steps.ts index b2e508d432..d3020a7393 100644 --- a/quality/cypress/support/exploitation/steps/exploit-idp-list-steps.ts +++ b/quality/cypress/support/exploitation/steps/exploit-idp-list-steps.ts @@ -1,4 +1,5 @@ import { Then, When } from "@badeball/cypress-cucumber-preprocessor"; +import { OperatorUser } from "../helpers"; import ExploitIdpListPage from "../pages/exploit-idp-list-page"; const exploitIdpListPage = new ExploitIdpListPage(); @@ -17,7 +18,7 @@ When( When( /^je supprime le fournisseur d'identité "([^"]*)"$/, function (idpName: string) { - exploitIdpListPage.deleteIdp(idpName, this.operatorUser); + exploitIdpListPage.deleteIdp(idpName, this.operatorUser as OperatorUser); }, ); @@ -26,7 +27,7 @@ When( function (idpNamePrefix: string) { exploitIdpListPage.deleteAllIdpStartingWith( idpNamePrefix, - this.operatorUser, + this.operatorUser as OperatorUser, ); }, ); diff --git a/quality/cypress/support/exploitation/steps/exploit-sp-form-steps.ts b/quality/cypress/support/exploitation/steps/exploit-sp-form-steps.ts index 77c0214964..676b411d59 100644 --- a/quality/cypress/support/exploitation/steps/exploit-sp-form-steps.ts +++ b/quality/cypress/support/exploitation/steps/exploit-sp-form-steps.ts @@ -1,5 +1,6 @@ import { Then, When } from "@badeball/cypress-cucumber-preprocessor"; import { getDefaultServiceProviderConfig } from "../../common/helpers"; +import { OperatorUser } from "../helpers"; import ExploitSpFormPage from "../pages/exploit-sp-form-page"; const exploitSpFormPage = new ExploitSpFormPage(); @@ -40,6 +41,6 @@ Then( When( /^je valide le formulaire de (?:création|modification) de FS$/, function () { - exploitSpFormPage.validateForm(this.operatorUser); + exploitSpFormPage.validateForm(this.operatorUser as OperatorUser); }, ); diff --git a/quality/cypress/support/exploitation/steps/exploit-sp-list-steps.ts b/quality/cypress/support/exploitation/steps/exploit-sp-list-steps.ts index d72c05dd4f..d7dd8a8ad9 100644 --- a/quality/cypress/support/exploitation/steps/exploit-sp-list-steps.ts +++ b/quality/cypress/support/exploitation/steps/exploit-sp-list-steps.ts @@ -1,4 +1,5 @@ import { Then, When } from "@badeball/cypress-cucumber-preprocessor"; +import { OperatorUser } from "../helpers"; import ExploitSpListPage from "../pages/exploit-sp-list-page"; const exploitSpListPage = new ExploitSpListPage(); @@ -22,14 +23,17 @@ When( When( /^je supprime le fournisseur de service "([^"]*)"$/, function (spName: string) { - exploitSpListPage.deleteSp(spName, this.operatorUser); + exploitSpListPage.deleteSp(spName, this.operatorUser as OperatorUser); }, ); When( /^je supprime les fournisseurs de service commençant par "([^"]*)"$/, function (spName: string) { - exploitSpListPage.deleteAllSpStartingWith(spName, this.operatorUser); + exploitSpListPage.deleteAllSpStartingWith( + spName, + this.operatorUser as OperatorUser, + ); }, ); diff --git a/quality/cypress/support/usager/steps/contact-support-steps.ts b/quality/cypress/support/usager/steps/contact-support-steps.ts index 82e10804a2..895ce663ef 100644 --- a/quality/cypress/support/usager/steps/contact-support-steps.ts +++ b/quality/cypress/support/usager/steps/contact-support-steps.ts @@ -21,10 +21,10 @@ Then( getContactSupportLink() .invoke("attr", "href") .then((hrefValue) => { - const matches = hrefValue.match(/subject=([^&]+)&body=([^&]+)/); + const matches = hrefValue!.match(/subject=([^&]+)&body=([^&]+)/); expect(matches).to.have.length(3); - const subject = decodeURIComponent(matches[1]); - const body = decodeURIComponent(matches[2]); + const subject = decodeURIComponent(matches![1]); + const body = decodeURIComponent(matches![2]); expect(subject).to.contains(`Signaler l’erreur ${errorCode}`); expect(body).to.contains(`Je souhaitais me connecter à « ${spName} ».`); @@ -41,14 +41,16 @@ Then( getContactSupportLink() .invoke("attr", "href") .then((hrefValue) => { - const matches = hrefValue.match(/subject=([^&]+)&body=([^&]+)/); + const matches = hrefValue!.match(/subject=([^&]+)&body=([^&]+)/); expect(matches).to.have.length(3); - const httpEncodedBody = matches.pop(); + const httpEncodedBody = matches!.pop(); - const body = decodeURIComponent(httpEncodedBody); + const body = decodeURIComponent(httpEncodedBody!); const validationConstraintsMatch = body.match(/\[\s*\{[\s\S]*?\}\s*\]/); expect(validationConstraintsMatch).to.have.length(1); - const validationConstraints = JSON.parse(validationConstraintsMatch[0]); + const validationConstraints = JSON.parse( + validationConstraintsMatch![0], + ); const expectedValidationConstraints = [ { isEmail: "email must be an email" }, ]; @@ -58,7 +60,7 @@ Then( const validationTargetMatch = body.match(/\{\s*"sub"[\s\S]*?\}/); expect(validationTargetMatch).to.have.length(1); - const validationTarget = JSON.parse(validationTargetMatch[0]); + const validationTarget = JSON.parse(validationTargetMatch![0]); delete validationTarget.exp; delete validationTarget.iat; delete validationTarget.iss; diff --git a/quality/cypress/support/usager/steps/interaction-steps.ts b/quality/cypress/support/usager/steps/interaction-steps.ts index 4263d1ff30..776b42f5ea 100644 --- a/quality/cypress/support/usager/steps/interaction-steps.ts +++ b/quality/cypress/support/usager/steps/interaction-steps.ts @@ -36,12 +36,12 @@ Given( .its("request.query.state") .should("exist") .then((value: string) => { - this.apiRequest.qs["state"] = value; + (this.apiRequest!.qs as Record)["state"] = value; }); }, ); -Then("le bouton {string} est {string}", (buttonText, state) => { +Then("le bouton {string} est {string}", (buttonText: string, state: string) => { const assertion = state === "désactivé" ? "be.disabled" : "not.be.disabled"; cy.contains("button", buttonText).should(assertion); }); diff --git a/quality/cypress/support/usager/steps/service-provider-error-steps.ts b/quality/cypress/support/usager/steps/service-provider-error-steps.ts index 0af698545e..5177e5506c 100644 --- a/quality/cypress/support/usager/steps/service-provider-error-steps.ts +++ b/quality/cypress/support/usager/steps/service-provider-error-steps.ts @@ -6,9 +6,9 @@ const URL_TYPE_GROUP = 1; const checkErrorCallbackUrl = (url: string, containsQuery = true): void => { const match = url.match(ERROR_URL_REGEXP); - expect(match.length).to.equal(4); + expect(match!.length).to.equal(4); const delimitor = containsQuery ? "?" : "#"; - expect(match[URL_TYPE_GROUP]).to.equal(delimitor); + expect(match![URL_TYPE_GROUP]).to.equal(delimitor); }; Then( diff --git a/quality/cypress/support/usager/steps/service-provider-steps.ts b/quality/cypress/support/usager/steps/service-provider-steps.ts index 90e9df411b..285ed8feef 100644 --- a/quality/cypress/support/usager/steps/service-provider-steps.ts +++ b/quality/cypress/support/usager/steps/service-provider-steps.ts @@ -348,7 +348,7 @@ Given( .its("request.query.code") .should("exist") .then((value: string) => { - this.apiRequest.body["code"] = value; + (this.apiRequest!.body as Record)["code"] = value; }); }, ); diff --git a/quality/scripts/multiple-cucumber-html-reporter.ts b/quality/scripts/multiple-cucumber-html-reporter.ts index 98aa3f3f9e..a59e43e5f4 100644 --- a/quality/scripts/multiple-cucumber-html-reporter.ts +++ b/quality/scripts/multiple-cucumber-html-reporter.ts @@ -2,6 +2,7 @@ * Generate a HTML report * @link https://github.com/WasiqB/multiple-cucumber-html-reporter */ +// @ts-expect-error — no types for this module import reporter from "multiple-cucumber-html-reporter"; const gitLabProjectUrl = diff --git a/quality/scripts/parse-business-log.ts b/quality/scripts/parse-business-log.ts index a47718a757..937925bbb7 100644 --- a/quality/scripts/parse-business-log.ts +++ b/quality/scripts/parse-business-log.ts @@ -54,9 +54,7 @@ const interactionHasEvent = async ([ * rather than having no match at all, * usefull for debuging purpose. */ - const foundEvent: LogEvent = logs.find( - (log) => log.event === testEvent.event, - ); + const foundEvent = logs.find((log) => log.event === testEvent.event); if (!foundEvent) { console.error("Event not found");