Testing

Unit tests

Karma + Jasmine, with specs colocated beside the code they cover (foo.service.ts / foo.service.spec.ts). There are around 246 spec files in src/.

$ npm test              # watch mode
$ npm run test:ci       # lint:quiet + headless Chrome + coverage
$ npm run test:pre-push # headless Chrome, no coverage (the pre-push hook)
$ npm run test:coverage # watch mode with coverage

Karma configuration

src/karma.conf.js

Frameworks

jasmine, @angular-devkit/build-angular

Chrome binary

process.env.CHROME_BIN = require('puppeteer').executablePath() — Puppeteer supplies Chrome, so no system install is needed.

Browser

ChromeHeadlessNoSandbox — headless with --no-sandbox, --disable-setuid-sandbox, --disable-gpu, for containerised CI.

Random order

Disabled (client.jasmine.random: false).

Coverage output

coverage/pyb-ng2-supplier-client/ as html, lcovonly and text-summary.

Fail fast

specReporters.failFast: true.

Spec order is deterministic

random: false means specs always run in the same order, so a suite with cross-spec state leakage can pass consistently and then fail when files are added or renamed. Reset shared state in beforeEach rather than relying on order.

src/test.ts bootstraps the environment and loads every *.spec.ts through require.context.

Shared mocks

tests/ sits outside src/ and is reachable through the @pyb-tests/* alias.

tests/mocks/store/user-initial-state.mock.ts

A baseline auth state.

tests/mocks/store/instant-advance.state.mock.ts

Instant Advance slice state.

tests/mocks/store/instant-advance-repayment.state.mock.ts

Repayment slice state.

tests/mocks/notifications/advance-line.mock.ts

Advance Line notification payload.

tests/mocks/notifications/long-term-contract.mock.ts

LTC notification payload.

tests/mocks/notifications/airwallex-pcard-terms.mock.ts

Airwallex terms notification payload.

tests/mocks/permissions/

permission.service.ts, permission.directive.ts, permissions.module.ts — stand-ins for ngx-permissions.

tests/mocks/pipe/

translate.pipe.mocks.ts, titlecase.pipe.mocks.ts.

tests/mocks/material/mat-icon.mocks.ts

MatIcon stub.

tests/mocks/reports/instant-advance.mock.ts

Report row fixtures.

tests/mocks/change-password.service.mock.ts

Password-change service stub.

tests/mocks/utils.ts

Shared helpers.

tests/utils/dispatch-event.ts

DOM event dispatch helper.

In-repo mocks follow the ResourceNameMockClassType convention, e.g. PermissionsServiceMock in core/pyb/services/permissions.service.mock.ts.

Testing libraries

ng-mocks

Component, directive, pipe and module mocking.

ng-bullet

Faster TestBed reconfiguration between specs.

jasmine-core, karma-jasmine

Framework and runner integration.

karma-coverage

Coverage reporting.

puppeteer

Supplies the headless Chrome binary.

What to test

Services with branching logic

PermissionsService, DocusignVerificationService, SuspensionReasonInitializerService, card operation services. These encode the business rules and have the highest defect cost.

Reducers

Pure functions with no setup — cheap and high value.

Selectors

Especially composed ones such as selectIsSupplierCancelled.

Effects

Use provideMockActions and marble testing for the async shape.

Guards

SellerCardListGuard and DocuSignGuard in particular — their routing decisions are hard to reproduce manually.

Flows

AdvanceLineWithdrawFlow branches on user state while building; both branches deserve a spec.

End-to-end tests

Cypress, in cypress/.

$ npm run cypress:open

cypress.json:

{
    "viewportWidth": 1200,
    "viewportHeight": 800,
    "env": { "environment": "stagging", "localUrl": "http://localhost:4200/" }
}

Specs

integration/auth/auth.spec.ts

Authentication.

integration/signing-in/signing-in.spec.ts

Sign-in journey.

integration/password-recovery/password-recovery.spec.ts

Password reset.

integration/2FA/2FA.spec.ts

Two-factor authentication.

integration/permissions/permissions.spec.ts

Permission-driven visibility.

integration/personal-data-access/personal-data-access.spec.ts

Personal data access.

Support and utilities

support/auth/login.command.ts

cy.login().

support/auth/autologin.command.ts

Token-based login that skips the form.

support/auth/logout.command.ts

cy.logout().

support/commands.ts, support/index.ts

Command registration.

utils/auth/auth.utils.ts

Auth helpers.

utils/bootstrap/bootstrap.utils.ts

App bootstrap helpers.

utils/http/http.utils.ts

Request interception helpers.

fixtures/user.json

The test user.

The suite concentrates on authentication and permissions — the two areas where a regression is both most likely and most damaging.

cypress/ has its own tsconfig.json and tsconfig.eslint.json, because Cypress types conflict with Jasmine types in the same project.

Protractor

e2e/ and the metronic-e2e project in angular.json are legacy Protractor scaffolding, superseded by Cypress.

CI

The test step in buildspec.yaml is commented out:

    pre_build:
        commands:
            - npm run pre-build
            # - npm run test:ci

The pipeline does not run tests. The Husky pre-push hook (npm run test:pre-push) is the only automated gate, so git push --no-verify lets untested code through.

Linting

$ npm run lint          # ESLint over ./src
$ npm run lint:quiet    # errors only (used by test:ci)
$ npm run lint:fix
$ npm run lint:cache    # content-hash cache for faster reruns

Configuration lives in .eslintrc.js, with @angular-eslint, @typescript-eslint, eslint-plugin-import, eslint-plugin-prefer-arrow, eslint-plugin-unused-imports and eslint-plugin-prettier.