From 99dc56de5b163f00ea81ba5d4cb8252d1277600c Mon Sep 17 00:00:00 2001 From: Alex Bramhill Date: Fri, 11 Oct 2024 19:17:07 +0100 Subject: [PATCH 01/17] feat(dtfs2-6892): commonise entra id user schema, update all tests --- .../constants/tfm}/entra-id-user-groups.ts | 0 libs/common/src/constants/tfm/index.ts | 1 + .../src/schemas/audit-database-record.test.ts | 56 +++++++++------- libs/common/src/schemas/index.ts | 1 + .../src/schemas/iso-date-time-stamp.test.ts | 30 +++++---- libs/common/src/schemas/object-id.test.ts | 35 +++++----- .../src/schemas/portal-user.create.test.ts | 55 ++++++++++++++++ libs/common/src/schemas/portal-user.test.ts | 66 ------------------- .../src/schemas/portal-user.update.test.ts | 57 ++++++++++++++++ ...d-user.schema.entra-id-user-schema.test.ts | 9 +++ .../src/schemas/tfm}/entra-id-user.schema.ts | 4 +- libs/common/src/schemas/tfm/index.ts | 1 + .../schemas/with-schema-validation.tests.ts | 24 ------- libs/common/src/test-helpers/index.ts | 1 + libs/common/src/test-helpers/schemas/index.ts | 2 + .../with-entra-id-user-schema.tests.ts | 8 +-- .../test-helpers/schemas/with-schema.tests.ts | 23 +++++++ libs/common/src/types/tfm/entra-id-user.ts | 4 ++ libs/common/src/types/tfm/index.ts | 1 + .../server/constants/entra-id-user.ts | 23 ------- ...d-user.schema.entra-id-user-schema.test.ts | 9 --- ...ded-auth-code-request-state-schema.test.ts | 2 +- ...code-redirect-response-body-schema.test.ts | 2 +- ...ra-id-authentication-result-schema.test.ts | 3 +- .../server/schemas/entra-id.schema.ts | 4 +- .../server/schemas/index.ts | 1 - .../server/types/entra-id-user.ts | 4 -- 27 files changed, 234 insertions(+), 192 deletions(-) rename {trade-finance-manager-ui/server/constants => libs/common/src/constants/tfm}/entra-id-user-groups.ts (100%) create mode 100644 libs/common/src/schemas/portal-user.create.test.ts delete mode 100644 libs/common/src/schemas/portal-user.test.ts create mode 100644 libs/common/src/schemas/portal-user.update.test.ts create mode 100644 libs/common/src/schemas/tfm/entra-id-user.schema.entra-id-user-schema.test.ts rename {trade-finance-manager-ui/server/schemas => libs/common/src/schemas/tfm}/entra-id-user.schema.ts (80%) create mode 100644 libs/common/src/schemas/tfm/index.ts delete mode 100644 libs/common/src/schemas/with-schema-validation.tests.ts create mode 100644 libs/common/src/test-helpers/schemas/index.ts rename {trade-finance-manager-ui/server => libs/common/src/test-helpers}/schemas/with-entra-id-user-schema.tests.ts (95%) create mode 100644 libs/common/src/test-helpers/schemas/with-schema.tests.ts create mode 100644 libs/common/src/types/tfm/entra-id-user.ts delete mode 100644 trade-finance-manager-ui/server/constants/entra-id-user.ts delete mode 100644 trade-finance-manager-ui/server/schemas/entra-id-user.schema.entra-id-user-schema.test.ts delete mode 100644 trade-finance-manager-ui/server/types/entra-id-user.ts diff --git a/trade-finance-manager-ui/server/constants/entra-id-user-groups.ts b/libs/common/src/constants/tfm/entra-id-user-groups.ts similarity index 100% rename from trade-finance-manager-ui/server/constants/entra-id-user-groups.ts rename to libs/common/src/constants/tfm/entra-id-user-groups.ts diff --git a/libs/common/src/constants/tfm/index.ts b/libs/common/src/constants/tfm/index.ts index e64ec83580..41ec1ec816 100644 --- a/libs/common/src/constants/tfm/index.ts +++ b/libs/common/src/constants/tfm/index.ts @@ -1,3 +1,4 @@ export * from './team-ids'; export * from './teams'; export * from './deal-stage'; +export * from './entra-id-user-groups'; diff --git a/libs/common/src/schemas/audit-database-record.test.ts b/libs/common/src/schemas/audit-database-record.test.ts index 1de3a948aa..89cac14bfc 100644 --- a/libs/common/src/schemas/audit-database-record.test.ts +++ b/libs/common/src/schemas/audit-database-record.test.ts @@ -5,43 +5,51 @@ import { generateSystemAuditDatabaseRecord, generateTfmUserAuditDatabaseRecord, } from '../change-stream'; -import { withSchemaValidationTests } from './with-schema-validation.tests'; import { AUDIT_DATABASE_RECORD } from './audit-database-record'; +import { withSchemaTests } from '../test-helpers'; describe('AUDIT_DATABASE_RECORD', () => { - const A_VALID_AUDIT_RECORD = generateTfmUserAuditDatabaseRecord(new ObjectId()); - const { lastUpdatedAt: _lastUpdatedAt, ...AN_AUDIT_RECORD_WITH_MISSING_PARAMETER } = { ...A_VALID_AUDIT_RECORD }; - const AN_AUDIT_RECORD_WITH_INCORRECT_PARAMETER_TYPE = { ...A_VALID_AUDIT_RECORD, lastUpdatedAt: 1 }; + withSchemaTests({ + successTestCases: getSuccessTestCases(), + failureTestCases: getFailureTestCases(), + schema: AUDIT_DATABASE_RECORD, + }); +}); - const successTestCases = [ +const aValidAuditRecord = () => generateTfmUserAuditDatabaseRecord(new ObjectId()); + +function getSuccessTestCases() { + return [ { description: 'a valid tfm user audit database record', - testCase: generateTfmUserAuditDatabaseRecord(new ObjectId()), + aTestCase: () => generateTfmUserAuditDatabaseRecord(new ObjectId()), }, { description: 'a valid portal user audit database record', - testCase: generatePortalUserAuditDatabaseRecord(new ObjectId()), + aTestCase: () => generatePortalUserAuditDatabaseRecord(new ObjectId()), }, { description: 'a valid system audit database record', - testCase: generateSystemAuditDatabaseRecord(), + aTestCase: () => generateSystemAuditDatabaseRecord(), }, - { description: 'a valid audit record with no user logged in', testCase: generateNoUserLoggedInAuditDatabaseRecord() }, + { description: 'a valid audit record with no user logged in', aTestCase: () => generateNoUserLoggedInAuditDatabaseRecord() }, ]; +} - const failureTestCases = [ - { description: 'a string', testCase: 'string' }, - { description: 'an object', testCase: { An: 'object' } }, - { description: 'an array', testCase: ['array'] }, - { description: 'a matching object with an incorrect parameter type', testCase: AN_AUDIT_RECORD_WITH_INCORRECT_PARAMETER_TYPE }, - { description: 'a matching object with a missing parameter', testCase: AN_AUDIT_RECORD_WITH_MISSING_PARAMETER }, - { description: 'a matching object with an additional parameter', testCase: { ...A_VALID_AUDIT_RECORD, invalidField: true } }, +function getFailureTestCases() { + return [ + { description: 'a string', aTestCase: () => 'string' }, + { description: 'an object', aTestCase: () => ({ An: 'object' }) }, + { description: 'an array', aTestCase: () => ['array'] }, + { description: 'a matching object with an incorrect parameter type', aTestCase: () => ({ ...aValidAuditRecord(), _lastUpdatedAt: 1 }) }, + { + description: 'a matching object with a missing parameter', + aTestCase: () => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { lastUpdatedAt, ...rest } = aValidAuditRecord(); + return rest; + }, + }, + { description: 'a matching object with an additional parameter', aTestCase: () => ({ ...aValidAuditRecord(), invalidField: true }) }, ]; - - withSchemaValidationTests({ - successTestCases, - failureTestCases, - schema: AUDIT_DATABASE_RECORD, - schemaName: 'AUDIT_DATABASE_RECORD', - }); -}); +} diff --git a/libs/common/src/schemas/index.ts b/libs/common/src/schemas/index.ts index 18f69b950a..3c320f04e1 100644 --- a/libs/common/src/schemas/index.ts +++ b/libs/common/src/schemas/index.ts @@ -2,3 +2,4 @@ export * as PORTAL_USER from './portal-user'; export * as ISO_DATE_TIME_STAMP from './iso-date-time-stamp'; export { OBJECT_ID } from './object-id'; export * from './deal-cancellation'; +export * from './tfm'; diff --git a/libs/common/src/schemas/iso-date-time-stamp.test.ts b/libs/common/src/schemas/iso-date-time-stamp.test.ts index 96c8be1693..cb6cef28cb 100644 --- a/libs/common/src/schemas/iso-date-time-stamp.test.ts +++ b/libs/common/src/schemas/iso-date-time-stamp.test.ts @@ -1,19 +1,23 @@ +import { withSchemaTests } from '../test-helpers'; import { ISO_DATE_TIME_STAMP } from './iso-date-time-stamp'; -import { withSchemaValidationTests } from './with-schema-validation.tests'; describe('ISO_DATE_TIME_STAMP', () => { - const successTestCases = [{ description: 'a valid ISO date', testCase: '2024-05-17T15:35:32.496 +00:00' }]; - const failureTestCases = [ - { description: 'an object', testCase: { An: 'object' } }, - { description: 'an array', testCase: ['2024-05-17T15:35:32.496 +00:00'] }, - { description: 'an incorrectly formatted date', testCase: '2021-01-01T00:00:00' }, - { description: 'an incorrectly formatted date', testCase: '2024-05-17X15:35:32.496 +00:00' }, - ]; - - withSchemaValidationTests({ - successTestCases, - failureTestCases, + withSchemaTests({ + successTestCases: getSuccessTestCases(), + failureTestCases: getFailureTestCases(), schema: ISO_DATE_TIME_STAMP, - schemaName: 'IsoDateTimeStamp', }); }); + +function getSuccessTestCases() { + return [{ description: 'a valid ISO date', aTestCase: () => '2024-05-17T15:35:32.496 +00:00' }]; +} + +function getFailureTestCases() { + return [ + { description: 'an object', aTestCase: () => ({ An: 'object' }) }, + { description: 'an array', aTestCase: () => ['2024-05-17T15:35:32.496 +00:00'] }, + { description: 'an incorrectly formatted date', aTestCase: () => '2021-01-01T00:00:00' }, + { description: 'an incorrectly formatted date', aTestCase: () => '2024-05-17X15:35:32.496 +00:00' }, + ]; +} diff --git a/libs/common/src/schemas/object-id.test.ts b/libs/common/src/schemas/object-id.test.ts index d918aa2228..63182d35fc 100644 --- a/libs/common/src/schemas/object-id.test.ts +++ b/libs/common/src/schemas/object-id.test.ts @@ -1,23 +1,26 @@ import { ObjectId } from 'mongodb'; -import { withSchemaValidationTests } from './with-schema-validation.tests'; import { OBJECT_ID } from './object-id'; +import { withSchemaTests } from '../test-helpers'; describe('OBJECT_ID', () => { - const successTestCases = [ - { description: 'a valid ObjectId', testCase: new ObjectId() }, - { description: 'a valid string ObjectId', testCase: '075bcd157dcb851180e02a7c' }, - ]; - - const failureTestCases = [ - { description: 'a string', testCase: 'string' }, - { description: 'an object', testCase: { An: 'object' } }, - { description: 'an array', testCase: ['array'] }, - ]; - - withSchemaValidationTests({ - successTestCases, - failureTestCases, + withSchemaTests({ + successTestCases: getSuccessTestCases(), + failureTestCases: getFailureTestCases(), schema: OBJECT_ID, - schemaName: 'OBJECT_ID', }); }); + +function getSuccessTestCases() { + return [ + { description: 'a valid ObjectId', aTestCase: () => new ObjectId() }, + { description: 'a valid string ObjectId', aTestCase: () => '075bcd157dcb851180e02a7c' }, + ]; +} + +function getFailureTestCases() { + return [ + { description: 'a string', aTestCase: () => 'string' }, + { description: 'an object', aTestCase: () => ({ An: 'object' }) }, + { description: 'an array', aTestCase: () => ['array'] }, + ]; +} diff --git a/libs/common/src/schemas/portal-user.create.test.ts b/libs/common/src/schemas/portal-user.create.test.ts new file mode 100644 index 0000000000..8095eb6bb3 --- /dev/null +++ b/libs/common/src/schemas/portal-user.create.test.ts @@ -0,0 +1,55 @@ +import { ObjectId } from 'mongodb'; +import { generatePortalUserAuditDatabaseRecord } from '../change-stream'; +import { CREATE } from './portal-user'; +import { withSchemaTests } from '../test-helpers'; + +describe('PORTAL_USER', () => { + describe('CREATE', () => { + withSchemaTests({ + successTestCases: getSuccessTestCases(), + failureTestCases: getFailureTestCases(), + schema: CREATE, + }); + }); + + function getSuccessTestCases() { + return [{ description: 'a valid user', aTestCase: () => aValidPortalUser() }]; + } + + function getFailureTestCases() { + return [ + { description: 'a string', aTestCase: () => 'string' }, + { description: 'an object', aTestCase: () => ({ An: 'object' }) }, + { description: 'an array', aTestCase: () => ['array'] }, + { + description: 'a partial user', + aTestCase: () => { + const { username: _username, ...rest } = aValidPortalUser(); + return rest; + }, + }, + { description: 'a user with an additional parameter', aTestCase: () => ({ ...aValidPortalUser(), invalidField: true }) }, + ]; + } +}); + +function aValidPortalUser() { + return { + username: 'HSBC-maker-1', + firstname: 'Mister', + surname: 'One', + email: 'one@email.com', + timezone: 'Europe/London', + roles: ['maker'], + bank: { + id: '961', + name: 'HSBC', + emails: ['maker1@ukexportfinance.gov.uk', 'maker2@ukexportfinance.gov.uk'], + }, + isTrusted: false, + 'user-status': 'active', + salt: '01', + hash: '02', + auditRecord: generatePortalUserAuditDatabaseRecord(new ObjectId()), + }; +} diff --git a/libs/common/src/schemas/portal-user.test.ts b/libs/common/src/schemas/portal-user.test.ts deleted file mode 100644 index 8b56b9a50c..0000000000 --- a/libs/common/src/schemas/portal-user.test.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { ObjectId } from 'mongodb'; -import { generatePortalUserAuditDatabaseRecord } from '../change-stream'; -import { CREATE, UPDATE } from './portal-user'; -import { withSchemaValidationTests } from './with-schema-validation.tests'; - -describe('PORTAL_USER', () => { - const A_VALID_USER = { - username: 'HSBC-maker-1', - firstname: 'Mister', - surname: 'One', - email: 'one@email.com', - timezone: 'Europe/London', - roles: ['maker'], - bank: { - id: '961', - name: 'HSBC', - emails: ['maker1@ukexportfinance.gov.uk', 'maker2@ukexportfinance.gov.uk'], - }, - isTrusted: false, - 'user-status': 'active', - salt: '01', - hash: '02', - auditRecord: generatePortalUserAuditDatabaseRecord(new ObjectId()), - }; - - const { username: _username, ...A_PARTIAL_USER } = A_VALID_USER; - - describe('CREATE', () => { - const successTestCases = [{ description: 'a valid user', testCase: A_VALID_USER }]; - - const failureTestCases = [ - { description: 'a string', testCase: 'string' }, - { description: 'an object', testCase: { An: 'object' } }, - { description: 'an array', testCase: ['array'] }, - { description: 'a partial user', testCase: A_PARTIAL_USER }, - { description: 'a user with an additional parameter', testCase: { ...A_VALID_USER, invalidField: true } }, - ]; - - withSchemaValidationTests({ - successTestCases, - failureTestCases, - schema: CREATE, - schemaName: 'PORTAL_USER.CREATE', - }); - }); - - describe('UPDATE', () => { - const successTestCases = [ - { description: 'a valid user', testCase: A_VALID_USER }, - { description: 'a partial user', testCase: A_PARTIAL_USER }, - ]; - - const failureTestCases = [ - { description: 'a string', testCase: 'string' }, - { description: 'an object', testCase: { An: 'object' } }, - { description: 'an array', testCase: ['array'] }, - { description: 'a user with an additional parameter', testCase: { ...A_PARTIAL_USER, invalidField: true } }, - ]; - withSchemaValidationTests({ - successTestCases, - failureTestCases, - schema: UPDATE, - schemaName: 'PORTAL_USER.UPDATE', - }); - }); -}); diff --git a/libs/common/src/schemas/portal-user.update.test.ts b/libs/common/src/schemas/portal-user.update.test.ts new file mode 100644 index 0000000000..2881dbec72 --- /dev/null +++ b/libs/common/src/schemas/portal-user.update.test.ts @@ -0,0 +1,57 @@ +import { ObjectId } from 'mongodb'; +import { generatePortalUserAuditDatabaseRecord } from '../change-stream'; +import { UPDATE } from './portal-user'; +import { withSchemaTests } from '../test-helpers'; + +describe('PORTAL_USER', () => { + describe('UPDATE', () => { + withSchemaTests({ + successTestCases: getSuccessTestCases(), + failureTestCases: getFailureTestCases(), + schema: UPDATE, + }); + }); +}); + +function getSuccessTestCases() { + return [ + { description: 'a valid user', aTestCase: () => aValidPortalUser() }, + { + description: 'a partial user', + aTestCase: () => { + const { username: _username, ...rest } = aValidPortalUser(); + return rest; + }, + }, + ]; +} + +function getFailureTestCases() { + return [ + { description: 'a string', aTestCase: () => 'string' }, + { description: 'an object', aTestCase: () => ({ An: 'object' }) }, + { description: 'an array', aTestCase: () => ['array'] }, + { description: 'a user with an additional parameter', aTestCase: () => ({ ...aValidPortalUser(), invalidField: true }) }, + ]; +} + +function aValidPortalUser() { + return { + username: 'HSBC-maker-1', + firstname: 'Mister', + surname: 'One', + email: 'one@email.com', + timezone: 'Europe/London', + roles: ['maker'], + bank: { + id: '961', + name: 'HSBC', + emails: ['maker1@ukexportfinance.gov.uk', 'maker2@ukexportfinance.gov.uk'], + }, + isTrusted: false, + 'user-status': 'active', + salt: '01', + hash: '02', + auditRecord: generatePortalUserAuditDatabaseRecord(new ObjectId()), + }; +} diff --git a/libs/common/src/schemas/tfm/entra-id-user.schema.entra-id-user-schema.test.ts b/libs/common/src/schemas/tfm/entra-id-user.schema.entra-id-user-schema.test.ts new file mode 100644 index 0000000000..7392438097 --- /dev/null +++ b/libs/common/src/schemas/tfm/entra-id-user.schema.entra-id-user-schema.test.ts @@ -0,0 +1,9 @@ +import { withEntraIdUserSchemaTests } from '../../test-helpers'; +import { ENTRA_ID_USER_SCHEMA } from './entra-id-user.schema'; + +describe('ENTRA_ID_USER_SCHEMA', () => { + withEntraIdUserSchemaTests({ + schema: ENTRA_ID_USER_SCHEMA, + getTestObjectWithUpdatedUserParams: (entraIdUser) => entraIdUser, + }); +}); diff --git a/trade-finance-manager-ui/server/schemas/entra-id-user.schema.ts b/libs/common/src/schemas/tfm/entra-id-user.schema.ts similarity index 80% rename from trade-finance-manager-ui/server/schemas/entra-id-user.schema.ts rename to libs/common/src/schemas/tfm/entra-id-user.schema.ts index 8c99958722..d6c2863b1e 100644 --- a/trade-finance-manager-ui/server/schemas/entra-id-user.schema.ts +++ b/libs/common/src/schemas/tfm/entra-id-user.schema.ts @@ -5,9 +5,9 @@ */ import z from 'zod'; -import { ALL_ENTRA_ID_USER_GROUPS } from '../constants/entra-id-user-groups'; +import { ALL_ENTRA_ID_USER_GROUPS } from '../../constants'; -export const EntraIdUserSchema = z.object({ +export const ENTRA_ID_USER_SCHEMA = z.object({ oid: z.string(), verified_primary_email: z.array(z.string()), verified_secondary_email: z.array(z.string()), diff --git a/libs/common/src/schemas/tfm/index.ts b/libs/common/src/schemas/tfm/index.ts new file mode 100644 index 0000000000..8c8bc6b637 --- /dev/null +++ b/libs/common/src/schemas/tfm/index.ts @@ -0,0 +1 @@ +export * from './entra-id-user.schema'; diff --git a/libs/common/src/schemas/with-schema-validation.tests.ts b/libs/common/src/schemas/with-schema-validation.tests.ts deleted file mode 100644 index 6b46f79a8b..0000000000 --- a/libs/common/src/schemas/with-schema-validation.tests.ts +++ /dev/null @@ -1,24 +0,0 @@ -type TestCase = { testCase: unknown; description: string }; - -export const withSchemaValidationTests = ({ - successTestCases, - failureTestCases, - schema, - schemaName, -}: { - successTestCases: Array; - failureTestCases: Array; - schema: Zod.Schema; - schemaName: string; -}) => { - describe('when validating a valid input', () => { - it.each(successTestCases)(`should validate $description as a valid ${schemaName}`, ({ testCase }) => { - expect(schema.safeParse(testCase).success).toEqual(true); - }); - }); - describe('when validating an invalid input', () => { - it.each(failureTestCases)(`should not validate $description as a valid ${schemaName}`, ({ testCase }) => { - expect(schema.safeParse(testCase).success).toEqual(false); - }); - }); -}; diff --git a/libs/common/src/test-helpers/index.ts b/libs/common/src/test-helpers/index.ts index d39a68a4b7..c61212fbc8 100644 --- a/libs/common/src/test-helpers/index.ts +++ b/libs/common/src/test-helpers/index.ts @@ -3,3 +3,4 @@ export * from './test-api-error'; export * from './portal-session-user'; // './test-cases-backend' has its own export because it uses the 'supertest' and 'mongodb' packages export * from './test-cases-backend'; +export * from './schemas'; diff --git a/libs/common/src/test-helpers/schemas/index.ts b/libs/common/src/test-helpers/schemas/index.ts new file mode 100644 index 0000000000..cad4887211 --- /dev/null +++ b/libs/common/src/test-helpers/schemas/index.ts @@ -0,0 +1,2 @@ +export * from './with-schema.tests'; +export * from './with-entra-id-user-schema.tests'; diff --git a/trade-finance-manager-ui/server/schemas/with-entra-id-user-schema.tests.ts b/libs/common/src/test-helpers/schemas/with-entra-id-user-schema.tests.ts similarity index 95% rename from trade-finance-manager-ui/server/schemas/with-entra-id-user-schema.tests.ts rename to libs/common/src/test-helpers/schemas/with-entra-id-user-schema.tests.ts index b179aa1270..097e1cc4d0 100644 --- a/trade-finance-manager-ui/server/schemas/with-entra-id-user-schema.tests.ts +++ b/libs/common/src/test-helpers/schemas/with-entra-id-user-schema.tests.ts @@ -1,7 +1,7 @@ import { ZodSchema } from 'zod'; -import { withSchemaTests } from '../../test-helpers'; -import { EntraIdUser } from '../types/entra-id-user'; -import { ENTRA_ID_USER_GROUP } from '../constants/entra-id-user-groups'; +import { EntraIdUser } from '../../types/tfm/entra-id-user'; +import { ENTRA_ID_USER_GROUP } from '../../constants'; +import { withSchemaTests } from './with-schema.tests'; type TestCasesParams = { getTestObjectWithUpdatedUserParams: (entraIdUser: unknown) => unknown; @@ -23,7 +23,7 @@ export function aValidEntraIdUser(): EntraIdUser { } export function withEntraIdUserSchemaTests({ schema, getTestObjectWithUpdatedUserParams }: withEntraIdUserSchemaTestsParams) { - describe('with EntraIdUserSchema tests', () => { + describe('with ENTRA_ID_USER_SCHEMA tests', () => { withSchemaTests({ schema, failureTestCases: getFailureTestCases({ getTestObjectWithUpdatedUserParams }), diff --git a/libs/common/src/test-helpers/schemas/with-schema.tests.ts b/libs/common/src/test-helpers/schemas/with-schema.tests.ts new file mode 100644 index 0000000000..cfa980baeb --- /dev/null +++ b/libs/common/src/test-helpers/schemas/with-schema.tests.ts @@ -0,0 +1,23 @@ +import { ZodSchema } from 'zod'; + +type SchemaTestCases = { aTestCase: () => any; description: string }[]; + +export const withSchemaTests = ({ + schema, + failureTestCases, + successTestCases, +}: { + schema: ZodSchema; + failureTestCases: SchemaTestCases; + successTestCases: SchemaTestCases; +}) => { + it.each(failureTestCases)('should fail parsing if $description', ({ aTestCase }) => { + const { success } = schema.safeParse(aTestCase()); + expect(success).toBe(false); + }); + + it.each(successTestCases)('should pass parsing if $description', ({ aTestCase }) => { + const { success } = schema.safeParse(aTestCase()); + expect(success).toBe(true); + }); +}; diff --git a/libs/common/src/types/tfm/entra-id-user.ts b/libs/common/src/types/tfm/entra-id-user.ts new file mode 100644 index 0000000000..c1863ae7cd --- /dev/null +++ b/libs/common/src/types/tfm/entra-id-user.ts @@ -0,0 +1,4 @@ +import { z } from 'zod'; +import { ENTRA_ID_USER_SCHEMA } from '../../schemas'; + +export type EntraIdUser = z.infer; diff --git a/libs/common/src/types/tfm/index.ts b/libs/common/src/types/tfm/index.ts index d4c3740dc9..b11bcacf6f 100644 --- a/libs/common/src/types/tfm/index.ts +++ b/libs/common/src/types/tfm/index.ts @@ -1,3 +1,4 @@ export * from './deal-submission-type'; export * from './team-id'; export * from './team'; +export * from './entra-id-user'; diff --git a/trade-finance-manager-ui/server/constants/entra-id-user.ts b/trade-finance-manager-ui/server/constants/entra-id-user.ts deleted file mode 100644 index 141a6aeaf3..0000000000 --- a/trade-finance-manager-ui/server/constants/entra-id-user.ts +++ /dev/null @@ -1,23 +0,0 @@ -export const ALL_ENTRA_ID_USER_GROUPS = [ - 'AZURE_SSO_GROUP_UNDERWRITING_SUPPORT', - 'AZURE_SSO_GROUP_UNDERWRITER_MANAGERS', - 'AZURE_SSO_GROUP_UNDERWRITERS', - 'AZURE_SSO_GROUP_RISK_MANAGERS', - 'AZURE_SSO_GROUP_BUSINESS_SUPPORT', - 'AZURE_SSO_GROUP_PIM', - 'AZURE_SSO_GROUP_PDC_READ', - 'AZURE_SSO_GROUP_PDC_RECONCILE', -] as const; - -export type EntraIdUserGroups = (typeof ALL_ENTRA_ID_USER_GROUPS)[number]; - -export const ENTRA_ID_USER_GROUP = { - AZURE_SSO_GROUP_UNDERWRITING_SUPPORT: 'AZURE_SSO_GROUP_UNDERWRITING_SUPPORT', - AZURE_SSO_GROUP_UNDERWRITER_MANAGERS: 'AZURE_SSO_GROUP_UNDERWRITER_MANAGERS', - AZURE_SSO_GROUP_UNDERWRITERS: 'AZURE_SSO_GROUP_UNDERWRITERS', - AZURE_SSO_GROUP_RISK_MANAGERS: 'AZURE_SSO_GROUP_RISK_MANAGERS', - AZURE_SSO_GROUP_BUSINESS_SUPPORT: 'AZURE_SSO_GROUP_BUSINESS_SUPPORT', - AZURE_SSO_GROUP_PIM: 'AZURE_SSO_GROUP_PIM', - AZURE_SSO_GROUP_PDC_READ: 'AZURE_SSO_GROUP_PDC_READ', - AZURE_SSO_GROUP_PDC_RECONCILE: 'AZURE_SSO_GROUP_PDC_RECONCILE', -} as const satisfies Record; diff --git a/trade-finance-manager-ui/server/schemas/entra-id-user.schema.entra-id-user-schema.test.ts b/trade-finance-manager-ui/server/schemas/entra-id-user.schema.entra-id-user-schema.test.ts deleted file mode 100644 index 393d58e492..0000000000 --- a/trade-finance-manager-ui/server/schemas/entra-id-user.schema.entra-id-user-schema.test.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { EntraIdUserSchema } from './entra-id-user.schema'; -import { withEntraIdUserSchemaTests } from './with-entra-id-user-schema.tests'; - -describe('EntraIdUserSchema', () => { - withEntraIdUserSchemaTests({ - schema: EntraIdUserSchema, - getTestObjectWithUpdatedUserParams: (entraIdUser) => entraIdUser, - }); -}); diff --git a/trade-finance-manager-ui/server/schemas/entra-id.schema.decoded-auth-code-request-state-schema.test.ts b/trade-finance-manager-ui/server/schemas/entra-id.schema.decoded-auth-code-request-state-schema.test.ts index 5f3119ab95..a18954fdaa 100644 --- a/trade-finance-manager-ui/server/schemas/entra-id.schema.decoded-auth-code-request-state-schema.test.ts +++ b/trade-finance-manager-ui/server/schemas/entra-id.schema.decoded-auth-code-request-state-schema.test.ts @@ -1,5 +1,5 @@ +import { withSchemaTests } from '@ukef/dtfs2-common'; import { DecodedAuthCodeRequestState } from '../types/entra-id'; -import { withSchemaTests } from '../../test-helpers'; import { DecodedAuthCodeRequestStateSchema } from './entra-id.schema'; describe('DecodedAuthCodeRequestStateSchema', () => { diff --git a/trade-finance-manager-ui/server/schemas/entra-id.schema.entra-id-auth-code-redirect-response-body-schema.test.ts b/trade-finance-manager-ui/server/schemas/entra-id.schema.entra-id-auth-code-redirect-response-body-schema.test.ts index 154596fe93..2b3c5344e8 100644 --- a/trade-finance-manager-ui/server/schemas/entra-id.schema.entra-id-auth-code-redirect-response-body-schema.test.ts +++ b/trade-finance-manager-ui/server/schemas/entra-id.schema.entra-id-auth-code-redirect-response-body-schema.test.ts @@ -1,5 +1,5 @@ +import { withSchemaTests } from '@ukef/dtfs2-common'; import { EntraIdAuthCodeRedirectResponseBody } from '../types/entra-id'; -import { withSchemaTests } from '../../test-helpers'; import { EntraIdAuthCodeRedirectResponseBodySchema } from './entra-id.schema'; describe('EntraIdAuthCodeRedirectResponseBodySchema', () => { diff --git a/trade-finance-manager-ui/server/schemas/entra-id.schema.entra-id-authentication-result-schema.test.ts b/trade-finance-manager-ui/server/schemas/entra-id.schema.entra-id-authentication-result-schema.test.ts index 562bc5313c..3a47bf9c8f 100644 --- a/trade-finance-manager-ui/server/schemas/entra-id.schema.entra-id-authentication-result-schema.test.ts +++ b/trade-finance-manager-ui/server/schemas/entra-id.schema.entra-id-authentication-result-schema.test.ts @@ -1,7 +1,6 @@ +import { aValidEntraIdUser, withEntraIdUserSchemaTests, withSchemaTests } from '@ukef/dtfs2-common'; import { EntraIdAuthenticationResult } from '../types/entra-id'; -import { withSchemaTests } from '../../test-helpers'; import { EntraIdAuthenticationResultSchema } from './entra-id.schema'; -import { aValidEntraIdUser, withEntraIdUserSchemaTests } from './with-entra-id-user-schema.tests'; describe('EntraIdAuthenticationResultSchema', () => { withEntraIdUserSchemaTests({ diff --git a/trade-finance-manager-ui/server/schemas/entra-id.schema.ts b/trade-finance-manager-ui/server/schemas/entra-id.schema.ts index 04e2729c13..066fb4c8e0 100644 --- a/trade-finance-manager-ui/server/schemas/entra-id.schema.ts +++ b/trade-finance-manager-ui/server/schemas/entra-id.schema.ts @@ -1,5 +1,5 @@ +import { ENTRA_ID_USER_SCHEMA } from '@ukef/dtfs2-common/schemas'; import { z } from 'zod'; -import { EntraIdUserSchema } from './entra-id-user.schema'; export const DecodedAuthCodeRequestStateSchema = z.object({ csrfToken: z.string(), @@ -19,6 +19,6 @@ export const EntraIdAuthCodeRedirectResponseBodySchema = z.object({ export const EntraIdAuthenticationResultSchema = z.object({ accessToken: z.string(), account: z.object({ - idTokenClaims: EntraIdUserSchema, + idTokenClaims: ENTRA_ID_USER_SCHEMA, }), }); diff --git a/trade-finance-manager-ui/server/schemas/index.ts b/trade-finance-manager-ui/server/schemas/index.ts index ae5cef6525..47514b893e 100644 --- a/trade-finance-manager-ui/server/schemas/index.ts +++ b/trade-finance-manager-ui/server/schemas/index.ts @@ -1,2 +1 @@ export * from './entra-id.schema'; -export * from './entra-id-user.schema'; diff --git a/trade-finance-manager-ui/server/types/entra-id-user.ts b/trade-finance-manager-ui/server/types/entra-id-user.ts deleted file mode 100644 index 9e9c674b2a..0000000000 --- a/trade-finance-manager-ui/server/types/entra-id-user.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { z } from 'zod'; -import { EntraIdUserSchema } from '../schemas'; - -export type EntraIdUser = z.infer; From 788ad4b3d3d9cd1abc2c3f2c32ea7fe72de74c3f Mon Sep 17 00:00:00 2001 From: Alex Bramhill Date: Fri, 11 Oct 2024 19:24:10 +0100 Subject: [PATCH 02/17] feat(dtfs2-6892): update schemas to screaming snake case --- .../auth/auth-sso/unauthenticated-auth.controller.ts | 4 ++-- ....schema.decoded-auth-code-request-state-schema.test.ts | 6 +++--- ...tra-id-auth-code-redirect-response-body-schema.test.ts | 6 +++--- ...d.schema.entra-id-authentication-result-schema.test.ts | 8 ++++---- .../server/schemas/entra-id.schema.ts | 6 +++--- trade-finance-manager-ui/server/types/entra-id.ts | 8 ++++---- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/trade-finance-manager-ui/server/controllers/auth/auth-sso/unauthenticated-auth.controller.ts b/trade-finance-manager-ui/server/controllers/auth/auth-sso/unauthenticated-auth.controller.ts index c06b6a9e1a..673fa7bf96 100644 --- a/trade-finance-manager-ui/server/controllers/auth/auth-sso/unauthenticated-auth.controller.ts +++ b/trade-finance-manager-ui/server/controllers/auth/auth-sso/unauthenticated-auth.controller.ts @@ -2,11 +2,11 @@ import { Response } from 'express'; import { CustomExpressRequest, InvalidPayloadError } from '@ukef/dtfs2-common'; import { isVerifiedPayload } from '@ukef/dtfs2-common/payload-verification'; import { EntraIdAuthCodeRedirectResponseBody } from '../../../types/entra-id'; -import { EntraIdAuthCodeRedirectResponseBodySchema } from '../../../schemas'; +import { ENTRA_ID_AUTH_CODE_REDIRECT_RESPONSE_BODY_SCHEMA } from '../../../schemas'; export class UnauthenticatedAuthController { postSsoRedirect(req: CustomExpressRequest<{ reqBody: EntraIdAuthCodeRedirectResponseBody }>, res: Response) { - if (!isVerifiedPayload({ payload: req.body, template: EntraIdAuthCodeRedirectResponseBodySchema })) { + if (!isVerifiedPayload({ payload: req.body, template: ENTRA_ID_AUTH_CODE_REDIRECT_RESPONSE_BODY_SCHEMA })) { throw new InvalidPayloadError('Invalid payload from SSO redirect'); } diff --git a/trade-finance-manager-ui/server/schemas/entra-id.schema.decoded-auth-code-request-state-schema.test.ts b/trade-finance-manager-ui/server/schemas/entra-id.schema.decoded-auth-code-request-state-schema.test.ts index a18954fdaa..72a5d20190 100644 --- a/trade-finance-manager-ui/server/schemas/entra-id.schema.decoded-auth-code-request-state-schema.test.ts +++ b/trade-finance-manager-ui/server/schemas/entra-id.schema.decoded-auth-code-request-state-schema.test.ts @@ -1,10 +1,10 @@ import { withSchemaTests } from '@ukef/dtfs2-common'; import { DecodedAuthCodeRequestState } from '../types/entra-id'; -import { DecodedAuthCodeRequestStateSchema } from './entra-id.schema'; +import { DECODED_AUTH_CODE_REQUEST_STATE_SCHEMA } from './entra-id.schema'; -describe('DecodedAuthCodeRequestStateSchema', () => { +describe('DECODED_AUTH_CODE_REQUEST_STATE_SCHEMA', () => { withSchemaTests({ - schema: DecodedAuthCodeRequestStateSchema, + schema: DECODED_AUTH_CODE_REQUEST_STATE_SCHEMA, failureTestCases: getFailureTestCases(), successTestCases: getSuccessTestCases(), }); diff --git a/trade-finance-manager-ui/server/schemas/entra-id.schema.entra-id-auth-code-redirect-response-body-schema.test.ts b/trade-finance-manager-ui/server/schemas/entra-id.schema.entra-id-auth-code-redirect-response-body-schema.test.ts index 2b3c5344e8..7befdc198f 100644 --- a/trade-finance-manager-ui/server/schemas/entra-id.schema.entra-id-auth-code-redirect-response-body-schema.test.ts +++ b/trade-finance-manager-ui/server/schemas/entra-id.schema.entra-id-auth-code-redirect-response-body-schema.test.ts @@ -1,10 +1,10 @@ import { withSchemaTests } from '@ukef/dtfs2-common'; import { EntraIdAuthCodeRedirectResponseBody } from '../types/entra-id'; -import { EntraIdAuthCodeRedirectResponseBodySchema } from './entra-id.schema'; +import { ENTRA_ID_AUTH_CODE_REDIRECT_RESPONSE_BODY_SCHEMA } from './entra-id.schema'; -describe('EntraIdAuthCodeRedirectResponseBodySchema', () => { +describe('ENTRA_ID_AUTH_CODE_REDIRECT_RESPONSE_BODY_SCHEMA', () => { withSchemaTests({ - schema: EntraIdAuthCodeRedirectResponseBodySchema, + schema: ENTRA_ID_AUTH_CODE_REDIRECT_RESPONSE_BODY_SCHEMA, failureTestCases: getFailureTestCases(), successTestCases: getSuccessTestCases(), }); diff --git a/trade-finance-manager-ui/server/schemas/entra-id.schema.entra-id-authentication-result-schema.test.ts b/trade-finance-manager-ui/server/schemas/entra-id.schema.entra-id-authentication-result-schema.test.ts index 3a47bf9c8f..118caf461e 100644 --- a/trade-finance-manager-ui/server/schemas/entra-id.schema.entra-id-authentication-result-schema.test.ts +++ b/trade-finance-manager-ui/server/schemas/entra-id.schema.entra-id-authentication-result-schema.test.ts @@ -1,10 +1,10 @@ import { aValidEntraIdUser, withEntraIdUserSchemaTests, withSchemaTests } from '@ukef/dtfs2-common'; import { EntraIdAuthenticationResult } from '../types/entra-id'; -import { EntraIdAuthenticationResultSchema } from './entra-id.schema'; +import { ENTRA_ID_AUTHENTICATION_RESULT_SCHEMA } from './entra-id.schema'; -describe('EntraIdAuthenticationResultSchema', () => { +describe('ENTRA_ID_AUTHENTICATION_RESULT_SCHEMA', () => { withEntraIdUserSchemaTests({ - schema: EntraIdAuthenticationResultSchema, + schema: ENTRA_ID_AUTHENTICATION_RESULT_SCHEMA, getTestObjectWithUpdatedUserParams: (entraIdUser) => ({ ...aValidPayload(), account: { idTokenClaims: entraIdUser }, @@ -12,7 +12,7 @@ describe('EntraIdAuthenticationResultSchema', () => { }); withSchemaTests({ - schema: EntraIdAuthenticationResultSchema, + schema: ENTRA_ID_AUTHENTICATION_RESULT_SCHEMA, failureTestCases: getFailureTestCases(), successTestCases: getSuccessTestCases(), }); diff --git a/trade-finance-manager-ui/server/schemas/entra-id.schema.ts b/trade-finance-manager-ui/server/schemas/entra-id.schema.ts index 066fb4c8e0..8b98d2f15d 100644 --- a/trade-finance-manager-ui/server/schemas/entra-id.schema.ts +++ b/trade-finance-manager-ui/server/schemas/entra-id.schema.ts @@ -1,12 +1,12 @@ import { ENTRA_ID_USER_SCHEMA } from '@ukef/dtfs2-common/schemas'; import { z } from 'zod'; -export const DecodedAuthCodeRequestStateSchema = z.object({ +export const DECODED_AUTH_CODE_REQUEST_STATE_SCHEMA = z.object({ csrfToken: z.string(), successRedirect: z.string().optional(), }); -export const EntraIdAuthCodeRedirectResponseBodySchema = z.object({ +export const ENTRA_ID_AUTH_CODE_REDIRECT_RESPONSE_BODY_SCHEMA = z.object({ code: z.string(), client_info: z.string().optional(), state: z.string(), @@ -16,7 +16,7 @@ export const EntraIdAuthCodeRedirectResponseBodySchema = z.object({ // Note: there are many more fields in the authentication result, but these are // the only ones we care about // https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-common/src/response/AuthenticationResult.ts -export const EntraIdAuthenticationResultSchema = z.object({ +export const ENTRA_ID_AUTHENTICATION_RESULT_SCHEMA = z.object({ accessToken: z.string(), account: z.object({ idTokenClaims: ENTRA_ID_USER_SCHEMA, diff --git a/trade-finance-manager-ui/server/types/entra-id.ts b/trade-finance-manager-ui/server/types/entra-id.ts index a3b261ce30..a472571ac4 100644 --- a/trade-finance-manager-ui/server/types/entra-id.ts +++ b/trade-finance-manager-ui/server/types/entra-id.ts @@ -1,8 +1,8 @@ import { z } from 'zod'; -import { DecodedAuthCodeRequestStateSchema, EntraIdAuthCodeRedirectResponseBodySchema, EntraIdAuthenticationResultSchema } from '../schemas'; +import { DECODED_AUTH_CODE_REQUEST_STATE_SCHEMA, ENTRA_ID_AUTH_CODE_REDIRECT_RESPONSE_BODY_SCHEMA, ENTRA_ID_AUTHENTICATION_RESULT_SCHEMA } from '../schemas'; -export type DecodedAuthCodeRequestState = z.infer; +export type DecodedAuthCodeRequestState = z.infer; -export type EntraIdAuthCodeRedirectResponseBody = z.infer; +export type EntraIdAuthCodeRedirectResponseBody = z.infer; -export type EntraIdAuthenticationResult = z.infer; +export type EntraIdAuthenticationResult = z.infer; From 2f2245fc830ab94fbe9d781ed96d9f1bbf4a7a28 Mon Sep 17 00:00:00 2001 From: Alex Bramhill Date: Fri, 11 Oct 2024 20:28:13 +0100 Subject: [PATCH 03/17] feat(dtfs2-6892): commonise iana timezone type --- .../activities-controller/index.js | 3 +- .../controllers/application-details/index.js | 4 +-- .../filter-localiseTimestamp.ts | 3 +- libs/common/src/constants/date-timezones.ts | 8 ++++++ libs/common/src/constants/index.ts | 1 + libs/common/src/types/date-timezones.ts | 7 +++++ libs/common/src/types/index.ts | 1 + .../admin/user-edit.component-test.js | 8 +++--- .../bond-submission-details.component-test.js | 6 ++-- .../bond-transactions-table.component-test.js | 16 +++++------ .../contract-overview-table.component-test.js | 21 +++++++------- .../loan-transactions-table.component-test.js | 15 +++++----- ...tract-submission-details.component-test.js | 8 ++---- .../contract/contract-view.component-test.js | 17 ++++++----- .../loan-submission-details.component-test.js | 6 ++-- portal/server/constants/date.ts | 8 ------ .../filter-localiseTimestamp.test.ts | 28 ++++++++++--------- .../filter-localiseTimestamp.ts | 4 ++- 18 files changed, 85 insertions(+), 79 deletions(-) create mode 100644 libs/common/src/constants/date-timezones.ts create mode 100644 libs/common/src/types/date-timezones.ts diff --git a/gef-ui/server/controllers/activities-controller/index.js b/gef-ui/server/controllers/activities-controller/index.js index 619133366b..836fabe76f 100644 --- a/gef-ui/server/controllers/activities-controller/index.js +++ b/gef-ui/server/controllers/activities-controller/index.js @@ -1,4 +1,5 @@ const { fromUnixTime } = require('date-fns'); +const { TIMEZONES } = require('@ukef/dtfs2-common'); const { getApplication, getUserDetails } = require('../../services/api'); // maps portalActivities array to create array in correct format for mojTimeline @@ -52,7 +53,7 @@ const getPortalActivities = async (req, res) => { createdBy: `${deal.maker.firstname} ${deal.maker.surname}`, companyName: deal.exporter.companyName, dateCreated: deal.createdAt, - timezone: deal.maker.timezone || 'Europe/London', + timezone: deal.maker.timezone || TIMEZONES.LONDON, submissionDate: deal.submissionDate, manualInclusionNoticeSubmissionDate: deal?.manualInclusionNoticeSubmissionDate, }); diff --git a/gef-ui/server/controllers/application-details/index.js b/gef-ui/server/controllers/application-details/index.js index efaeabd582..a08a3358fb 100644 --- a/gef-ui/server/controllers/application-details/index.js +++ b/gef-ui/server/controllers/application-details/index.js @@ -1,5 +1,5 @@ const startCase = require('lodash/startCase'); -const { DEAL_TYPE } = require('@ukef/dtfs2-common'); +const { DEAL_TYPE, TIMEZONES } = require('@ukef/dtfs2-common'); const api = require('../../services/api'); const { canUpdateUnissuedFacilitiesCheck } = require('./canUpdateUnissuedFacilitiesCheck'); const { @@ -35,7 +35,7 @@ function buildHeader(app) { companyName: app.exporter?.companyName, applicationStatus: app.status, dateCreated: app.createdAt, - timezone: app.maker.timezone || 'Europe/London', + timezone: app.maker.timezone || TIMEZONES.LONDON, createdBy: `${app.maker.firstname} ${app.maker.surname}`, comments: app.comments, applicationType: app.submissionType, diff --git a/gef-ui/server/nunjucks-configuration/filter-localiseTimestamp.ts b/gef-ui/server/nunjucks-configuration/filter-localiseTimestamp.ts index 5339b22e3d..353819d540 100644 --- a/gef-ui/server/nunjucks-configuration/filter-localiseTimestamp.ts +++ b/gef-ui/server/nunjucks-configuration/filter-localiseTimestamp.ts @@ -1,3 +1,4 @@ +import { IanaTimezone } from '@ukef/dtfs2-common'; import { formatInTimeZone } from 'date-fns-tz'; /** @@ -10,7 +11,7 @@ import { formatInTimeZone } from 'date-fns-tz'; * * https://www.npmjs.com/package/date-fns-tz#formatintimezone */ -export const filterLocaliseTimestamp = (utcTimestamp: number | string, format: string, targetTimezone: string): string => { +export const filterLocaliseTimestamp = (utcTimestamp: number | string, format: string, targetTimezone: IanaTimezone): string => { if (!utcTimestamp) { return ''; } diff --git a/libs/common/src/constants/date-timezones.ts b/libs/common/src/constants/date-timezones.ts new file mode 100644 index 0000000000..8d4774efa3 --- /dev/null +++ b/libs/common/src/constants/date-timezones.ts @@ -0,0 +1,8 @@ +import { IanaTimezone } from '../types'; + +/** + * IANA timezones used in the codebase + * Note - If needing a full list, we should look to Intl.supportedValuesOf('timeZone') + * {@link https://www.iana.org/time-zones} + */ +export const IANA_TIMEZONES = { LONDON: 'Europe/London' } as const satisfies Record; diff --git a/libs/common/src/constants/index.ts b/libs/common/src/constants/index.ts index f7fc43df77..13d7d68cae 100644 --- a/libs/common/src/constants/index.ts +++ b/libs/common/src/constants/index.ts @@ -20,6 +20,7 @@ export * from './facility-type-mapped'; export * from './max-request-size'; export * from './request-platform-type'; export * from './date-formats'; +export * from './date-timezones'; export * from './url-character-allowances'; export * from './max-character-count'; export * from './deal-submission-type'; diff --git a/libs/common/src/types/date-timezones.ts b/libs/common/src/types/date-timezones.ts new file mode 100644 index 0000000000..5aa10a0c97 --- /dev/null +++ b/libs/common/src/types/date-timezones.ts @@ -0,0 +1,7 @@ +/** + * IANA timezone type + * Note - If needing a more restrictive type, we should look to internalise the + * return from Intl.supportedValuesOf('timeZone') + * {@link https://www.iana.org/time-zones} + */ +export type IanaTimezone = string; diff --git a/libs/common/src/types/index.ts b/libs/common/src/types/index.ts index b3a3170664..9ff5d36f67 100644 --- a/libs/common/src/types/index.ts +++ b/libs/common/src/types/index.ts @@ -27,3 +27,4 @@ export * from './tfm-deal-cancellation'; export * from './file'; export * from './fee-record-utilisation'; export * from './radio-item'; +export * from './date-timezones'; diff --git a/portal/component-tests/admin/user-edit.component-test.js b/portal/component-tests/admin/user-edit.component-test.js index bfee3cba18..6880e62a8a 100644 --- a/portal/component-tests/admin/user-edit.component-test.js +++ b/portal/component-tests/admin/user-edit.component-test.js @@ -1,14 +1,14 @@ -const pageRenderer = require('../pageRenderer'); const { - DATE: { LONDON_TIMEZONE }, -} = require('../../server/constants'); + TIMEZONES: { LONDON }, +} = require('@ukef/dtfs2-common'); +const pageRenderer = require('../pageRenderer'); const page = 'admin/user-edit.njk'; const render = pageRenderer(page); describe(page, () => { const adminUser = { - timezone: LONDON_TIMEZONE, + timezone: LONDON, roles: ['admin'], }; const newUser = { roles: [] }; diff --git a/portal/component-tests/bond/_macros/bond-submission-details.component-test.js b/portal/component-tests/bond/_macros/bond-submission-details.component-test.js index 3b3ec53bbc..861395c78b 100644 --- a/portal/component-tests/bond/_macros/bond-submission-details.component-test.js +++ b/portal/component-tests/bond/_macros/bond-submission-details.component-test.js @@ -1,11 +1,9 @@ const { ROLES: { MAKER }, + TIMEZONES: LONDON, } = require('@ukef/dtfs2-common'); const componentRenderer = require('../../componentRenderer'); const deal = require('../../fixtures/deal-fully-completed'); -const { - DATE: { LONDON_TIMEZONE }, -} = require('../../../server/constants'); const component = 'bond/_macros/bond-submission-details.njk'; const render = componentRenderer(component); @@ -14,7 +12,7 @@ describe(component, () => { let wrapper; const user = { roles: [MAKER], - timezone: LONDON_TIMEZONE, + timezone: LONDON, }; const bond = deal.bondTransactions.items[0]; diff --git a/portal/component-tests/contract/components/bond-transactions-table.component-test.js b/portal/component-tests/contract/components/bond-transactions-table.component-test.js index bfb14fc139..04e0cd7013 100644 --- a/portal/component-tests/contract/components/bond-transactions-table.component-test.js +++ b/portal/component-tests/contract/components/bond-transactions-table.component-test.js @@ -1,10 +1,10 @@ -import { ROLES } from '@ukef/dtfs2-common'; -import { DEAL, FACILITY } from '../../../server/constants/status'; -import { getNowAsEpoch } from '../../../server/helpers'; - const { - DATE: { LONDON_TIMEZONE }, -} = require('../../../server/constants'); + ROLES, + TIMEZONES: { LONDON }, +} = require('@ukef/dtfs2-common'); +const { DEAL, FACILITY } = require('../../../server/constants/status'); +const { getNowAsEpoch } = require('../../../server/helpers'); + const { NON_MAKER_OR_CHECKER_ROLES } = require('../../../test-helpers/common-role-lists'); const componentRenderer = require('../../componentRenderer'); @@ -100,7 +100,7 @@ describe(component, () => { }); describe('when user is checker', () => { - const user = { roles: [CHECKER], timezone: LONDON_TIMEZONE }; + const user = { roles: [CHECKER], timezone: LONDON }; commonTests(user); @@ -141,7 +141,7 @@ describe(component, () => { }); describe.each(NON_MAKER_OR_CHECKER_ROLES)('when user is %s', (nonMakerOrCheckerRole) => { - const user = { roles: [nonMakerOrCheckerRole], timezone: LONDON_TIMEZONE }; + const user = { roles: [nonMakerOrCheckerRole], timezone: LONDON }; commonTests(user); diff --git a/portal/component-tests/contract/components/contract-overview-table.component-test.js b/portal/component-tests/contract/components/contract-overview-table.component-test.js index 55e9c4bbaf..574638565e 100644 --- a/portal/component-tests/contract/components/contract-overview-table.component-test.js +++ b/portal/component-tests/contract/components/contract-overview-table.component-test.js @@ -1,6 +1,9 @@ const { formatInTimeZone } = require('date-fns-tz'); const { - DATE: { LONDON_TIMEZONE, FULL_DATE, FULL_DATE_AND_TIME }, + TIMEZONES: { LONDON }, +} = require('@ukef/dtfs2-common'); +const { + DATE: { FULL_DATE, FULL_DATE_AND_TIME }, } = require('../../../server/constants'); const { getNowAsEpoch } = require('../../../server/helpers'); const componentRenderer = require('../../componentRenderer'); @@ -40,7 +43,7 @@ describe(component, () => { let wrapper; beforeAll(() => { - const user = { timezone: LONDON_TIMEZONE }; + const user = { timezone: LONDON }; wrapper = render({ deal, user }); }); @@ -58,15 +61,15 @@ describe(component, () => { wrapper.expectText('[data-cy="checker"]').toRead(`${deal.details.checker.firstname} ${deal.details.checker.surname}`)); it('displays deal.details.submissionDate', () => - wrapper.expectText('[data-cy="submissionDate"]').toRead(formatInTimeZone(new Date(deal.details.submissionDate), LONDON_TIMEZONE, FULL_DATE))); + wrapper.expectText('[data-cy="submissionDate"]').toRead(formatInTimeZone(new Date(deal.details.submissionDate), LONDON, FULL_DATE))); it('displays deal.updatedAt', () => - wrapper.expectText('[data-cy="updatedAt"]').toRead(formatInTimeZone(new Date(deal.updatedAt), LONDON_TIMEZONE, FULL_DATE_AND_TIME))); + wrapper.expectText('[data-cy="updatedAt"]').toRead(formatInTimeZone(new Date(deal.updatedAt), LONDON, FULL_DATE_AND_TIME))); }); describe('when deal has manualInclusionApplicationSubmissionDate', () => { let wrapper; - const user = { timezone: LONDON_TIMEZONE }; + const user = { timezone: LONDON }; beforeAll(() => { wrapper = render({ deal: dealWithManualInclusionApplicationSubmissionDate, user }); @@ -78,11 +81,7 @@ describe(component, () => { wrapper .expectText('[data-cy="submissionDate"]') .toRead( - formatInTimeZone( - new Date(dealWithManualInclusionApplicationSubmissionDate.details.manualInclusionApplicationSubmissionDate), - LONDON_TIMEZONE, - FULL_DATE, - ), + formatInTimeZone(new Date(dealWithManualInclusionApplicationSubmissionDate.details.manualInclusionApplicationSubmissionDate), LONDON, FULL_DATE), )); }); @@ -103,7 +102,7 @@ describe(component, () => { }; beforeAll(() => { - const user = { timezone: LONDON_TIMEZONE }; + const user = { timezone: LONDON }; wrapper = render({ mockDeal, user }); }); diff --git a/portal/component-tests/contract/components/loan-transactions-table.component-test.js b/portal/component-tests/contract/components/loan-transactions-table.component-test.js index 9a149d86b8..bcd5223fa4 100644 --- a/portal/component-tests/contract/components/loan-transactions-table.component-test.js +++ b/portal/component-tests/contract/components/loan-transactions-table.component-test.js @@ -1,11 +1,10 @@ -import { ROLES } from '@ukef/dtfs2-common'; -import { UNCONDITIONAL } from '../../../server/constants/facility-stage'; - +const { + ROLES, + TIMEZONES: { LONDON }, +} = require('@ukef/dtfs2-common'); +const { UNCONDITIONAL } = require('../../../server/constants/facility-stage'); const { getNowAsEpoch } = require('../../../server/helpers'); const { NON_MAKER_ROLES } = require('../../../test-helpers/common-role-lists'); -const { - DATE: { LONDON_TIMEZONE }, -} = require('../../../server/constants'); const { MAKER } = ROLES; @@ -59,7 +58,7 @@ describe(component, () => { dealWithLoansThatCanChangeCoverDate.loanTransactions.items[1].issueFacilityDetailsSubmitted = true; describe('as a maker', () => { - const user = { roles: [MAKER], timezone: LONDON_TIMEZONE }; + const user = { roles: [MAKER], timezone: LONDON }; commonTests(user); @@ -135,7 +134,7 @@ describe(component, () => { }); describe.each(NON_MAKER_ROLES)('when viewed with the role %s', (nonMakerRole) => { - const user = { roles: [nonMakerRole], timezone: LONDON_TIMEZONE }; + const user = { roles: [nonMakerRole], timezone: LONDON }; commonTests(user); diff --git a/portal/component-tests/contract/contract-submission-details.component-test.js b/portal/component-tests/contract/contract-submission-details.component-test.js index 076530af46..749c77f697 100644 --- a/portal/component-tests/contract/contract-submission-details.component-test.js +++ b/portal/component-tests/contract/contract-submission-details.component-test.js @@ -1,12 +1,10 @@ const { ROLES: { MAKER }, + TIMEZONES: { LONDON }, } = require('@ukef/dtfs2-common'); const pageRenderer = require('../pageRenderer'); const dealFullyCompleted = require('../fixtures/deal-fully-completed'); -const { - DATE: { LONDON_TIMEZONE }, -} = require('../../server/constants'); const deal = { _id: '61f6fbaea2460c018a4189d7', ...dealFullyCompleted }; deal.bondTransactions.items[0]._id = '61f6fbaea2460c018a4189e1'; @@ -23,7 +21,7 @@ describe(page, () => { wrapper = render({ deal, user: { - timezone: LONDON_TIMEZONE, + timezone: LONDON, roles: [MAKER], }, editable: true, @@ -86,7 +84,7 @@ describe(page, () => { mandatoryCriteria: [], }, user: { - timezone: LONDON_TIMEZONE, + timezone: LONDON, roles: [MAKER], }, editable: true, diff --git a/portal/component-tests/contract/contract-view.component-test.js b/portal/component-tests/contract/contract-view.component-test.js index 4e63c6c64e..bfd294c4b0 100644 --- a/portal/component-tests/contract/contract-view.component-test.js +++ b/portal/component-tests/contract/contract-view.component-test.js @@ -1,15 +1,14 @@ -import { ROLES } from '@ukef/dtfs2-common'; -import { STATUS } from '../../server/constants'; - +const { + ROLES, + TIMEZONES: { LONDON }, +} = require('@ukef/dtfs2-common'); +const { STATUS } = require('../../server/constants'); const pageRenderer = require('../pageRenderer'); const page = 'contract/contract-view.njk'; const render = pageRenderer(page); const dealFullyCompleted = require('../fixtures/deal-fully-completed'); const { NON_MAKER_ROLES } = require('../../test-helpers/common-role-lists'); -const { - DATE: { LONDON_TIMEZONE }, -} = require('../../server/constants'); const { MAKER, CHECKER } = ROLES; @@ -40,7 +39,7 @@ const confirmedRequestStartDateParams = { describe(page, () => { describe("when viewed as a 'maker'", () => { - const user = { roles: [MAKER], timezone: LONDON_TIMEZONE }; + const user = { roles: [MAKER], timezone: LONDON }; commonTests(user); @@ -73,7 +72,7 @@ describe(page, () => { }); describe("when viewed as a 'checker'", () => { - const user = { roles: [CHECKER], timezone: LONDON_TIMEZONE }; + const user = { roles: [CHECKER], timezone: LONDON }; commonTests(user); @@ -104,7 +103,7 @@ describe(page, () => { }); describe.each(NON_MAKER_ROLES)("when viewed as a '%s'", (nonMakerRole) => { - const user = { roles: [nonMakerRole], timezone: LONDON_TIMEZONE }; + const user = { roles: [nonMakerRole], timezone: LONDON }; commonTests(user); diff --git a/portal/component-tests/loan/_macros/loan-submission-details.component-test.js b/portal/component-tests/loan/_macros/loan-submission-details.component-test.js index 3adcb55fef..3e3925ac7a 100644 --- a/portal/component-tests/loan/_macros/loan-submission-details.component-test.js +++ b/portal/component-tests/loan/_macros/loan-submission-details.component-test.js @@ -1,9 +1,7 @@ const { ROLES: { MAKER }, + TIMEZONES: { LONDON }, } = require('@ukef/dtfs2-common'); -const { - DATE: { LONDON_TIMEZONE }, -} = require('../../../server/constants'); const componentRenderer = require('../../componentRenderer'); const deal = require('../../fixtures/deal-fully-completed'); @@ -14,7 +12,7 @@ describe(component, () => { let wrapper; const user = { roles: [MAKER], - timezone: LONDON_TIMEZONE, + timezone: LONDON, }; const loan = deal.loanTransactions.items[0]; diff --git a/portal/server/constants/date.ts b/portal/server/constants/date.ts index 1c8a5336d2..435ade9506 100644 --- a/portal/server/constants/date.ts +++ b/portal/server/constants/date.ts @@ -1,11 +1,3 @@ -/** - * IANA timezone name for London - * - * {@link https://www.iana.org/time-zones} - * - */ -export const LONDON_TIMEZONE = 'Europe/London'; - /** * To use with date-fns/format * diff --git a/portal/server/nunjucks-configuration/filter-localiseTimestamp.test.ts b/portal/server/nunjucks-configuration/filter-localiseTimestamp.test.ts index 9ebc1010ec..c00f86a636 100644 --- a/portal/server/nunjucks-configuration/filter-localiseTimestamp.test.ts +++ b/portal/server/nunjucks-configuration/filter-localiseTimestamp.test.ts @@ -1,6 +1,8 @@ -import { LONDON_TIMEZONE } from '../constants/date'; +import { IANA_TIMEZONES } from '@ukef/dtfs2-common'; import { filterLocaliseTimestamp } from './filter-localiseTimestamp'; +const { LONDON } = IANA_TIMEZONES; + describe('nunjuck filters - dashIfEmpty', () => { describe('when timestamp is a valid number', () => { // 1707343200000 is Unix epoch for Wed Feb 07 2024 22:00:00 GMT+0000 @@ -9,21 +11,21 @@ describe('nunjuck filters - dashIfEmpty', () => { const mockValue = mockDate.valueOf(); it('should return the day of the month if given format `dd` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'dd', LONDON_TIMEZONE); + const result = filterLocaliseTimestamp(mockValue, 'dd', LONDON); const expected = '07'; expect(result).toEqual(expected); }); it('should return the month if given the format `MM` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'MM', LONDON_TIMEZONE); + const result = filterLocaliseTimestamp(mockValue, 'MM', LONDON); const expected = '02'; expect(result).toEqual(expected); }); it('should return the year if given the format `yyyy` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'yyyy', LONDON_TIMEZONE); + const result = filterLocaliseTimestamp(mockValue, 'yyyy', LONDON); const expected = '2024'; expect(result).toEqual(expected); @@ -44,21 +46,21 @@ describe('nunjuck filters - dashIfEmpty', () => { const mockValue = mockDate.valueOf().toString(); it('should return the day of the month if given format `dd` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'dd', LONDON_TIMEZONE); + const result = filterLocaliseTimestamp(mockValue, 'dd', LONDON); const expected = '07'; expect(result).toEqual(expected); }); it('should return the month if given the format `MM` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'MM', LONDON_TIMEZONE); + const result = filterLocaliseTimestamp(mockValue, 'MM', LONDON); const expected = '02'; expect(result).toEqual(expected); }); it('should return the year if given the format `yyyy` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'yyyy', LONDON_TIMEZONE); + const result = filterLocaliseTimestamp(mockValue, 'yyyy', LONDON); const expected = '2024'; expect(result).toEqual(expected); @@ -76,21 +78,21 @@ describe('nunjuck filters - dashIfEmpty', () => { const mockValue = ''; it('should return an empty string if given format `dd` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'dd', LONDON_TIMEZONE); + const result = filterLocaliseTimestamp(mockValue, 'dd', LONDON); const expected = ''; expect(result).toEqual(expected); }); it('should return an empty string if given the format `MM` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'MM', LONDON_TIMEZONE); + const result = filterLocaliseTimestamp(mockValue, 'MM', LONDON); const expected = ''; expect(result).toEqual(expected); }); it('should return an empty string if given the format `yyyy` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'yyyy', LONDON_TIMEZONE); + const result = filterLocaliseTimestamp(mockValue, 'yyyy', LONDON); const expected = ''; expect(result).toEqual(expected); @@ -108,21 +110,21 @@ describe('nunjuck filters - dashIfEmpty', () => { const mockValue = 'test'; it('should return `Invalid date` if given format `dd` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'dd', LONDON_TIMEZONE); + const result = filterLocaliseTimestamp(mockValue, 'dd', LONDON); const expected = 'Invalid date'; expect(result).toEqual(expected); }); it('should return `Invalid date` if given the format `MM` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'MM', LONDON_TIMEZONE); + const result = filterLocaliseTimestamp(mockValue, 'MM', LONDON); const expected = 'Invalid date'; expect(result).toEqual(expected); }); it('should return `Invalid date` if given the format `yyyy` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'yyyy', LONDON_TIMEZONE); + const result = filterLocaliseTimestamp(mockValue, 'yyyy', LONDON); const expected = 'Invalid date'; expect(result).toEqual(expected); diff --git a/portal/server/nunjucks-configuration/filter-localiseTimestamp.ts b/portal/server/nunjucks-configuration/filter-localiseTimestamp.ts index 44ff501ade..353819d540 100644 --- a/portal/server/nunjucks-configuration/filter-localiseTimestamp.ts +++ b/portal/server/nunjucks-configuration/filter-localiseTimestamp.ts @@ -1,3 +1,4 @@ +import { IanaTimezone } from '@ukef/dtfs2-common'; import { formatInTimeZone } from 'date-fns-tz'; /** @@ -10,12 +11,13 @@ import { formatInTimeZone } from 'date-fns-tz'; * * https://www.npmjs.com/package/date-fns-tz#formatintimezone */ -export const filterLocaliseTimestamp = (utcTimestamp: number | string, format: string, targetTimezone: string): string => { +export const filterLocaliseTimestamp = (utcTimestamp: number | string, format: string, targetTimezone: IanaTimezone): string => { if (!utcTimestamp) { return ''; } const timestamp = parseInt(String(utcTimestamp), 10); + // Implements behaviour inherited from moment to handle invalid dates if (Number.isNaN(timestamp)) { return 'Invalid date'; } From 1dd345ae5b6708d0f694d80671b3231dd9d613ab Mon Sep 17 00:00:00 2001 From: Alex Bramhill Date: Tue, 15 Oct 2024 10:38:33 +0100 Subject: [PATCH 04/17] feat(dtfs2-6892): review comments --- .../server/controllers/activities-controller/index.js | 6 ++++-- gef-ui/server/controllers/application-details/index.js | 7 +++++-- .../nunjucks-configuration/filter-localiseTimestamp.ts | 4 ++-- .../{date-timezones.ts => date-iana-timezones.ts} | 4 ++-- libs/common/src/constants/index.ts | 2 +- .../{date-timezones.ts => date-iana-timezones.ts} | 2 +- libs/common/src/types/index.ts | 2 +- .../contract-overview-table.component-test.js | 10 ++++------ .../filter-localiseTimestamp.test.ts | 4 ++-- .../nunjucks-configuration/filter-localiseTimestamp.ts | 4 ++-- 10 files changed, 24 insertions(+), 21 deletions(-) rename libs/common/src/constants/{date-timezones.ts => date-iana-timezones.ts} (52%) rename libs/common/src/types/{date-timezones.ts => date-iana-timezones.ts} (83%) diff --git a/gef-ui/server/controllers/activities-controller/index.js b/gef-ui/server/controllers/activities-controller/index.js index 836fabe76f..2b27045514 100644 --- a/gef-ui/server/controllers/activities-controller/index.js +++ b/gef-ui/server/controllers/activities-controller/index.js @@ -1,5 +1,7 @@ const { fromUnixTime } = require('date-fns'); -const { TIMEZONES } = require('@ukef/dtfs2-common'); +const { + TIMEZONES: { LONDON }, +} = require('@ukef/dtfs2-common'); const { getApplication, getUserDetails } = require('../../services/api'); // maps portalActivities array to create array in correct format for mojTimeline @@ -53,7 +55,7 @@ const getPortalActivities = async (req, res) => { createdBy: `${deal.maker.firstname} ${deal.maker.surname}`, companyName: deal.exporter.companyName, dateCreated: deal.createdAt, - timezone: deal.maker.timezone || TIMEZONES.LONDON, + timezone: deal.maker.timezone || LONDON, submissionDate: deal.submissionDate, manualInclusionNoticeSubmissionDate: deal?.manualInclusionNoticeSubmissionDate, }); diff --git a/gef-ui/server/controllers/application-details/index.js b/gef-ui/server/controllers/application-details/index.js index a08a3358fb..1fbe9a24a4 100644 --- a/gef-ui/server/controllers/application-details/index.js +++ b/gef-ui/server/controllers/application-details/index.js @@ -1,5 +1,8 @@ const startCase = require('lodash/startCase'); -const { DEAL_TYPE, TIMEZONES } = require('@ukef/dtfs2-common'); +const { + DEAL_TYPE, + TIMEZONES: { LONDON }, +} = require('@ukef/dtfs2-common'); const api = require('../../services/api'); const { canUpdateUnissuedFacilitiesCheck } = require('./canUpdateUnissuedFacilitiesCheck'); const { @@ -35,7 +38,7 @@ function buildHeader(app) { companyName: app.exporter?.companyName, applicationStatus: app.status, dateCreated: app.createdAt, - timezone: app.maker.timezone || TIMEZONES.LONDON, + timezone: app.maker.timezone || LONDON, createdBy: `${app.maker.firstname} ${app.maker.surname}`, comments: app.comments, applicationType: app.submissionType, diff --git a/gef-ui/server/nunjucks-configuration/filter-localiseTimestamp.ts b/gef-ui/server/nunjucks-configuration/filter-localiseTimestamp.ts index 353819d540..10707d8939 100644 --- a/gef-ui/server/nunjucks-configuration/filter-localiseTimestamp.ts +++ b/gef-ui/server/nunjucks-configuration/filter-localiseTimestamp.ts @@ -1,4 +1,4 @@ -import { IanaTimezone } from '@ukef/dtfs2-common'; +import { DateIanaTimezone } from '@ukef/dtfs2-common'; import { formatInTimeZone } from 'date-fns-tz'; /** @@ -11,7 +11,7 @@ import { formatInTimeZone } from 'date-fns-tz'; * * https://www.npmjs.com/package/date-fns-tz#formatintimezone */ -export const filterLocaliseTimestamp = (utcTimestamp: number | string, format: string, targetTimezone: IanaTimezone): string => { +export const filterLocaliseTimestamp = (utcTimestamp: number | string, format: string, targetTimezone: DateIanaTimezone): string => { if (!utcTimestamp) { return ''; } diff --git a/libs/common/src/constants/date-timezones.ts b/libs/common/src/constants/date-iana-timezones.ts similarity index 52% rename from libs/common/src/constants/date-timezones.ts rename to libs/common/src/constants/date-iana-timezones.ts index 8d4774efa3..a9e306e359 100644 --- a/libs/common/src/constants/date-timezones.ts +++ b/libs/common/src/constants/date-iana-timezones.ts @@ -1,8 +1,8 @@ -import { IanaTimezone } from '../types'; +import { DateIanaTimezone } from '../types'; /** * IANA timezones used in the codebase * Note - If needing a full list, we should look to Intl.supportedValuesOf('timeZone') * {@link https://www.iana.org/time-zones} */ -export const IANA_TIMEZONES = { LONDON: 'Europe/London' } as const satisfies Record; +export const DATE_IANA_TIMEZONES = { LONDON: 'Europe/London' } as const satisfies Record; diff --git a/libs/common/src/constants/index.ts b/libs/common/src/constants/index.ts index 13d7d68cae..b27cbf703a 100644 --- a/libs/common/src/constants/index.ts +++ b/libs/common/src/constants/index.ts @@ -20,7 +20,7 @@ export * from './facility-type-mapped'; export * from './max-request-size'; export * from './request-platform-type'; export * from './date-formats'; -export * from './date-timezones'; +export * from './date-iana-timezones'; export * from './url-character-allowances'; export * from './max-character-count'; export * from './deal-submission-type'; diff --git a/libs/common/src/types/date-timezones.ts b/libs/common/src/types/date-iana-timezones.ts similarity index 83% rename from libs/common/src/types/date-timezones.ts rename to libs/common/src/types/date-iana-timezones.ts index 5aa10a0c97..a9b80c6148 100644 --- a/libs/common/src/types/date-timezones.ts +++ b/libs/common/src/types/date-iana-timezones.ts @@ -4,4 +4,4 @@ * return from Intl.supportedValuesOf('timeZone') * {@link https://www.iana.org/time-zones} */ -export type IanaTimezone = string; +export type DateIanaTimezone = string; diff --git a/libs/common/src/types/index.ts b/libs/common/src/types/index.ts index 9ff5d36f67..6be42b1065 100644 --- a/libs/common/src/types/index.ts +++ b/libs/common/src/types/index.ts @@ -27,4 +27,4 @@ export * from './tfm-deal-cancellation'; export * from './file'; export * from './fee-record-utilisation'; export * from './radio-item'; -export * from './date-timezones'; +export * from './date-iana-timezones'; diff --git a/portal/component-tests/contract/components/contract-overview-table.component-test.js b/portal/component-tests/contract/components/contract-overview-table.component-test.js index 574638565e..7b7fa55b92 100644 --- a/portal/component-tests/contract/components/contract-overview-table.component-test.js +++ b/portal/component-tests/contract/components/contract-overview-table.component-test.js @@ -30,12 +30,14 @@ describe(component, () => { }, }; + const manualInclusionApplicationSubmissionDate = getNowAsEpoch(); + const dealWithManualInclusionApplicationSubmissionDate = { ...deal, submissionType: 'Manual Inclusion Notice', details: { ...deal.details, - manualInclusionApplicationSubmissionDate: getNowAsEpoch(), + manualInclusionApplicationSubmissionDate, }, }; @@ -78,11 +80,7 @@ describe(component, () => { it('displays MIA submission date table header', () => wrapper.expectText('[data-cy="submissionDateHeader"]').toRead('MIA Submission date')); it('displays deal.details.manualInclusionApplicationSubmissionDate', () => - wrapper - .expectText('[data-cy="submissionDate"]') - .toRead( - formatInTimeZone(new Date(dealWithManualInclusionApplicationSubmissionDate.details.manualInclusionApplicationSubmissionDate), LONDON, FULL_DATE), - )); + wrapper.expectText('[data-cy="submissionDate"]').toRead(formatInTimeZone(new Date(manualInclusionApplicationSubmissionDate), LONDON, FULL_DATE))); }); describe('renders - for any blank fields', () => { diff --git a/portal/server/nunjucks-configuration/filter-localiseTimestamp.test.ts b/portal/server/nunjucks-configuration/filter-localiseTimestamp.test.ts index c00f86a636..7030992afa 100644 --- a/portal/server/nunjucks-configuration/filter-localiseTimestamp.test.ts +++ b/portal/server/nunjucks-configuration/filter-localiseTimestamp.test.ts @@ -1,7 +1,7 @@ -import { IANA_TIMEZONES } from '@ukef/dtfs2-common'; +import { DATE_IANA_TIMEZONES } from '@ukef/dtfs2-common'; import { filterLocaliseTimestamp } from './filter-localiseTimestamp'; -const { LONDON } = IANA_TIMEZONES; +const { LONDON } = DATE_IANA_TIMEZONES; describe('nunjuck filters - dashIfEmpty', () => { describe('when timestamp is a valid number', () => { diff --git a/portal/server/nunjucks-configuration/filter-localiseTimestamp.ts b/portal/server/nunjucks-configuration/filter-localiseTimestamp.ts index 353819d540..10707d8939 100644 --- a/portal/server/nunjucks-configuration/filter-localiseTimestamp.ts +++ b/portal/server/nunjucks-configuration/filter-localiseTimestamp.ts @@ -1,4 +1,4 @@ -import { IanaTimezone } from '@ukef/dtfs2-common'; +import { DateIanaTimezone } from '@ukef/dtfs2-common'; import { formatInTimeZone } from 'date-fns-tz'; /** @@ -11,7 +11,7 @@ import { formatInTimeZone } from 'date-fns-tz'; * * https://www.npmjs.com/package/date-fns-tz#formatintimezone */ -export const filterLocaliseTimestamp = (utcTimestamp: number | string, format: string, targetTimezone: IanaTimezone): string => { +export const filterLocaliseTimestamp = (utcTimestamp: number | string, format: string, targetTimezone: DateIanaTimezone): string => { if (!utcTimestamp) { return ''; } From eef11cbf129d9c09de8475ac48c4ace9dfa302f4 Mon Sep 17 00:00:00 2001 From: Alex Bramhill Date: Tue, 15 Oct 2024 15:00:37 +0100 Subject: [PATCH 05/17] feat(dtfs2-6892): fix tests --- gef-ui/server/controllers/activities-controller/index.js | 2 +- gef-ui/server/controllers/application-details/index.js | 2 +- portal/component-tests/admin/user-edit.component-test.js | 2 +- .../components/bond-transactions-table.component-test.js | 2 +- .../components/contract-overview-table.component-test.js | 2 +- .../components/loan-transactions-table.component-test.js | 2 +- .../contract/contract-submission-details.component-test.js | 2 +- portal/component-tests/contract/contract-view.component-test.js | 2 +- .../loan/_macros/loan-submission-details.component-test.js | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/gef-ui/server/controllers/activities-controller/index.js b/gef-ui/server/controllers/activities-controller/index.js index 2b27045514..ebf2f5f3cb 100644 --- a/gef-ui/server/controllers/activities-controller/index.js +++ b/gef-ui/server/controllers/activities-controller/index.js @@ -1,6 +1,6 @@ const { fromUnixTime } = require('date-fns'); const { - TIMEZONES: { LONDON }, + DATE_IANA_TIMEZONES: { LONDON }, } = require('@ukef/dtfs2-common'); const { getApplication, getUserDetails } = require('../../services/api'); diff --git a/gef-ui/server/controllers/application-details/index.js b/gef-ui/server/controllers/application-details/index.js index 1fbe9a24a4..054fb39fab 100644 --- a/gef-ui/server/controllers/application-details/index.js +++ b/gef-ui/server/controllers/application-details/index.js @@ -1,7 +1,7 @@ const startCase = require('lodash/startCase'); const { DEAL_TYPE, - TIMEZONES: { LONDON }, + DATE_IANA_TIMEZONES: { LONDON }, } = require('@ukef/dtfs2-common'); const api = require('../../services/api'); const { canUpdateUnissuedFacilitiesCheck } = require('./canUpdateUnissuedFacilitiesCheck'); diff --git a/portal/component-tests/admin/user-edit.component-test.js b/portal/component-tests/admin/user-edit.component-test.js index 6880e62a8a..def748a197 100644 --- a/portal/component-tests/admin/user-edit.component-test.js +++ b/portal/component-tests/admin/user-edit.component-test.js @@ -1,5 +1,5 @@ const { - TIMEZONES: { LONDON }, + DATE_IANA_TIMEZONES: { LONDON }, } = require('@ukef/dtfs2-common'); const pageRenderer = require('../pageRenderer'); diff --git a/portal/component-tests/contract/components/bond-transactions-table.component-test.js b/portal/component-tests/contract/components/bond-transactions-table.component-test.js index 04e0cd7013..07a49990c0 100644 --- a/portal/component-tests/contract/components/bond-transactions-table.component-test.js +++ b/portal/component-tests/contract/components/bond-transactions-table.component-test.js @@ -1,6 +1,6 @@ const { ROLES, - TIMEZONES: { LONDON }, + DATE_IANA_TIMEZONES: { LONDON }, } = require('@ukef/dtfs2-common'); const { DEAL, FACILITY } = require('../../../server/constants/status'); const { getNowAsEpoch } = require('../../../server/helpers'); diff --git a/portal/component-tests/contract/components/contract-overview-table.component-test.js b/portal/component-tests/contract/components/contract-overview-table.component-test.js index 7b7fa55b92..fc36a5840f 100644 --- a/portal/component-tests/contract/components/contract-overview-table.component-test.js +++ b/portal/component-tests/contract/components/contract-overview-table.component-test.js @@ -1,6 +1,6 @@ const { formatInTimeZone } = require('date-fns-tz'); const { - TIMEZONES: { LONDON }, + DATE_IANA_TIMEZONES: { LONDON }, } = require('@ukef/dtfs2-common'); const { DATE: { FULL_DATE, FULL_DATE_AND_TIME }, diff --git a/portal/component-tests/contract/components/loan-transactions-table.component-test.js b/portal/component-tests/contract/components/loan-transactions-table.component-test.js index bcd5223fa4..f954328880 100644 --- a/portal/component-tests/contract/components/loan-transactions-table.component-test.js +++ b/portal/component-tests/contract/components/loan-transactions-table.component-test.js @@ -1,6 +1,6 @@ const { ROLES, - TIMEZONES: { LONDON }, + DATE_IANA_TIMEZONES: { LONDON }, } = require('@ukef/dtfs2-common'); const { UNCONDITIONAL } = require('../../../server/constants/facility-stage'); const { getNowAsEpoch } = require('../../../server/helpers'); diff --git a/portal/component-tests/contract/contract-submission-details.component-test.js b/portal/component-tests/contract/contract-submission-details.component-test.js index 749c77f697..c8ca5ceeea 100644 --- a/portal/component-tests/contract/contract-submission-details.component-test.js +++ b/portal/component-tests/contract/contract-submission-details.component-test.js @@ -1,6 +1,6 @@ const { ROLES: { MAKER }, - TIMEZONES: { LONDON }, + DATE_IANA_TIMEZONES: { LONDON }, } = require('@ukef/dtfs2-common'); const pageRenderer = require('../pageRenderer'); diff --git a/portal/component-tests/contract/contract-view.component-test.js b/portal/component-tests/contract/contract-view.component-test.js index bfd294c4b0..52333f5e7e 100644 --- a/portal/component-tests/contract/contract-view.component-test.js +++ b/portal/component-tests/contract/contract-view.component-test.js @@ -1,6 +1,6 @@ const { ROLES, - TIMEZONES: { LONDON }, + DATE_IANA_TIMEZONES: { LONDON }, } = require('@ukef/dtfs2-common'); const { STATUS } = require('../../server/constants'); const pageRenderer = require('../pageRenderer'); diff --git a/portal/component-tests/loan/_macros/loan-submission-details.component-test.js b/portal/component-tests/loan/_macros/loan-submission-details.component-test.js index 3e3925ac7a..5f9fd24679 100644 --- a/portal/component-tests/loan/_macros/loan-submission-details.component-test.js +++ b/portal/component-tests/loan/_macros/loan-submission-details.component-test.js @@ -1,6 +1,6 @@ const { ROLES: { MAKER }, - TIMEZONES: { LONDON }, + DATE_IANA_TIMEZONES: { LONDON }, } = require('@ukef/dtfs2-common'); const componentRenderer = require('../../componentRenderer'); const deal = require('../../fixtures/deal-fully-completed'); From a8b54be77d74c010273d3a397233c98553ccc307 Mon Sep 17 00:00:00 2001 From: Alex Bramhill Date: Tue, 15 Oct 2024 20:19:41 +0100 Subject: [PATCH 06/17] feat(dtfs2-6892): update to default timezone using env var as per review comment --- .../activities-controller/index.js | 6 ++-- .../controllers/application-details/index.js | 7 ++--- .../src/configs/date-iana-timezones.config.ts | 18 ++++++++++++ libs/common/src/configs/index.ts | 1 + .../src/constants/date-iana-timezones.ts | 8 ------ libs/common/src/index.ts | 1 + .../admin/user-edit.component-test.js | 6 ++-- .../bond-submission-details.component-test.js | 4 +-- .../bond-transactions-table.component-test.js | 9 ++---- .../contract-overview-table.component-test.js | 20 +++++++------ .../loan-transactions-table.component-test.js | 9 ++---- ...tract-submission-details.component-test.js | 6 ++-- .../contract/contract-view.component-test.js | 11 +++----- .../loan-submission-details.component-test.js | 4 +-- .../filter-localiseTimestamp.test.ts | 28 +++++++++---------- 15 files changed, 67 insertions(+), 71 deletions(-) create mode 100644 libs/common/src/configs/date-iana-timezones.config.ts create mode 100644 libs/common/src/configs/index.ts delete mode 100644 libs/common/src/constants/date-iana-timezones.ts diff --git a/gef-ui/server/controllers/activities-controller/index.js b/gef-ui/server/controllers/activities-controller/index.js index ebf2f5f3cb..edcef5cfad 100644 --- a/gef-ui/server/controllers/activities-controller/index.js +++ b/gef-ui/server/controllers/activities-controller/index.js @@ -1,7 +1,5 @@ const { fromUnixTime } = require('date-fns'); -const { - DATE_IANA_TIMEZONES: { LONDON }, -} = require('@ukef/dtfs2-common'); +const { dateIanaTimezoneConfig } = require('@ukef/dtfs2-common'); const { getApplication, getUserDetails } = require('../../services/api'); // maps portalActivities array to create array in correct format for mojTimeline @@ -55,7 +53,7 @@ const getPortalActivities = async (req, res) => { createdBy: `${deal.maker.firstname} ${deal.maker.surname}`, companyName: deal.exporter.companyName, dateCreated: deal.createdAt, - timezone: deal.maker.timezone || LONDON, + timezone: deal.maker.timezone || dateIanaTimezoneConfig.DEFAULT, submissionDate: deal.submissionDate, manualInclusionNoticeSubmissionDate: deal?.manualInclusionNoticeSubmissionDate, }); diff --git a/gef-ui/server/controllers/application-details/index.js b/gef-ui/server/controllers/application-details/index.js index 054fb39fab..373d69131b 100644 --- a/gef-ui/server/controllers/application-details/index.js +++ b/gef-ui/server/controllers/application-details/index.js @@ -1,8 +1,5 @@ const startCase = require('lodash/startCase'); -const { - DEAL_TYPE, - DATE_IANA_TIMEZONES: { LONDON }, -} = require('@ukef/dtfs2-common'); +const { DEAL_TYPE, dateIanaTimezoneConfig } = require('@ukef/dtfs2-common'); const api = require('../../services/api'); const { canUpdateUnissuedFacilitiesCheck } = require('./canUpdateUnissuedFacilitiesCheck'); const { @@ -38,7 +35,7 @@ function buildHeader(app) { companyName: app.exporter?.companyName, applicationStatus: app.status, dateCreated: app.createdAt, - timezone: app.maker.timezone || LONDON, + timezone: app.maker.timezone || dateIanaTimezoneConfig.DEFAULT, createdBy: `${app.maker.firstname} ${app.maker.surname}`, comments: app.comments, applicationType: app.submissionType, diff --git a/libs/common/src/configs/date-iana-timezones.config.ts b/libs/common/src/configs/date-iana-timezones.config.ts new file mode 100644 index 0000000000..d981cc27f4 --- /dev/null +++ b/libs/common/src/configs/date-iana-timezones.config.ts @@ -0,0 +1,18 @@ +import dotenv from 'dotenv'; +import { z } from 'zod'; + +dotenv.config(); + +/** + * {@link https://www.iana.org/time-zones} + * There is no default provided in this config, as this would allow for inconsistency in microservices. + */ +const defaultIanaTimezoneConfigSchema = z + .object({ + TZ: z.string(), + }) + .transform((validatedEnvVars) => ({ + DEFAULT: validatedEnvVars.TZ, + })); + +export const dateIanaTimezoneConfig = defaultIanaTimezoneConfigSchema.parse(process.env); diff --git a/libs/common/src/configs/index.ts b/libs/common/src/configs/index.ts new file mode 100644 index 0000000000..2abb6348f9 --- /dev/null +++ b/libs/common/src/configs/index.ts @@ -0,0 +1 @@ +export * from './date-iana-timezones.config'; diff --git a/libs/common/src/constants/date-iana-timezones.ts b/libs/common/src/constants/date-iana-timezones.ts deleted file mode 100644 index a9e306e359..0000000000 --- a/libs/common/src/constants/date-iana-timezones.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { DateIanaTimezone } from '../types'; - -/** - * IANA timezones used in the codebase - * Note - If needing a full list, we should look to Intl.supportedValuesOf('timeZone') - * {@link https://www.iana.org/time-zones} - */ -export const DATE_IANA_TIMEZONES = { LONDON: 'Europe/London' } as const satisfies Record; diff --git a/libs/common/src/index.ts b/libs/common/src/index.ts index 2ba4614915..591232a17c 100644 --- a/libs/common/src/index.ts +++ b/libs/common/src/index.ts @@ -8,3 +8,4 @@ export * from './middleware'; export * from './utils'; export * from './constants'; export * from './errors'; +export * from './configs'; diff --git a/portal/component-tests/admin/user-edit.component-test.js b/portal/component-tests/admin/user-edit.component-test.js index def748a197..a7987317ba 100644 --- a/portal/component-tests/admin/user-edit.component-test.js +++ b/portal/component-tests/admin/user-edit.component-test.js @@ -1,6 +1,4 @@ -const { - DATE_IANA_TIMEZONES: { LONDON }, -} = require('@ukef/dtfs2-common'); +const { dateIanaTimezoneConfig } = require('@ukef/dtfs2-common'); const pageRenderer = require('../pageRenderer'); const page = 'admin/user-edit.njk'; @@ -8,7 +6,7 @@ const render = pageRenderer(page); describe(page, () => { const adminUser = { - timezone: LONDON, + timezone: dateIanaTimezoneConfig.DEFAULT, roles: ['admin'], }; const newUser = { roles: [] }; diff --git a/portal/component-tests/bond/_macros/bond-submission-details.component-test.js b/portal/component-tests/bond/_macros/bond-submission-details.component-test.js index 861395c78b..e2144dbd7a 100644 --- a/portal/component-tests/bond/_macros/bond-submission-details.component-test.js +++ b/portal/component-tests/bond/_macros/bond-submission-details.component-test.js @@ -1,6 +1,6 @@ const { ROLES: { MAKER }, - TIMEZONES: LONDON, + dateIanaTimezoneConfig, } = require('@ukef/dtfs2-common'); const componentRenderer = require('../../componentRenderer'); const deal = require('../../fixtures/deal-fully-completed'); @@ -12,7 +12,7 @@ describe(component, () => { let wrapper; const user = { roles: [MAKER], - timezone: LONDON, + timezone: dateIanaTimezoneConfig.DEFAULT, }; const bond = deal.bondTransactions.items[0]; diff --git a/portal/component-tests/contract/components/bond-transactions-table.component-test.js b/portal/component-tests/contract/components/bond-transactions-table.component-test.js index 07a49990c0..fcb220abeb 100644 --- a/portal/component-tests/contract/components/bond-transactions-table.component-test.js +++ b/portal/component-tests/contract/components/bond-transactions-table.component-test.js @@ -1,7 +1,4 @@ -const { - ROLES, - DATE_IANA_TIMEZONES: { LONDON }, -} = require('@ukef/dtfs2-common'); +const { ROLES, dateIanaTimezoneConfig } = require('@ukef/dtfs2-common'); const { DEAL, FACILITY } = require('../../../server/constants/status'); const { getNowAsEpoch } = require('../../../server/helpers'); @@ -100,7 +97,7 @@ describe(component, () => { }); describe('when user is checker', () => { - const user = { roles: [CHECKER], timezone: LONDON }; + const user = { roles: [CHECKER], timezone: dateIanaTimezoneConfig.DEFAULT }; commonTests(user); @@ -141,7 +138,7 @@ describe(component, () => { }); describe.each(NON_MAKER_OR_CHECKER_ROLES)('when user is %s', (nonMakerOrCheckerRole) => { - const user = { roles: [nonMakerOrCheckerRole], timezone: LONDON }; + const user = { roles: [nonMakerOrCheckerRole], timezone: dateIanaTimezoneConfig.DEFAULT }; commonTests(user); diff --git a/portal/component-tests/contract/components/contract-overview-table.component-test.js b/portal/component-tests/contract/components/contract-overview-table.component-test.js index fc36a5840f..971a716495 100644 --- a/portal/component-tests/contract/components/contract-overview-table.component-test.js +++ b/portal/component-tests/contract/components/contract-overview-table.component-test.js @@ -1,7 +1,5 @@ const { formatInTimeZone } = require('date-fns-tz'); -const { - DATE_IANA_TIMEZONES: { LONDON }, -} = require('@ukef/dtfs2-common'); +const { dateIanaTimezoneConfig } = require('@ukef/dtfs2-common'); const { DATE: { FULL_DATE, FULL_DATE_AND_TIME }, } = require('../../../server/constants'); @@ -45,7 +43,7 @@ describe(component, () => { let wrapper; beforeAll(() => { - const user = { timezone: LONDON }; + const user = { timezone: dateIanaTimezoneConfig.DEFAULT }; wrapper = render({ deal, user }); }); @@ -63,15 +61,17 @@ describe(component, () => { wrapper.expectText('[data-cy="checker"]').toRead(`${deal.details.checker.firstname} ${deal.details.checker.surname}`)); it('displays deal.details.submissionDate', () => - wrapper.expectText('[data-cy="submissionDate"]').toRead(formatInTimeZone(new Date(deal.details.submissionDate), LONDON, FULL_DATE))); + wrapper + .expectText('[data-cy="submissionDate"]') + .toRead(formatInTimeZone(new Date(deal.details.submissionDate), dateIanaTimezoneConfig.DEFAULT, FULL_DATE))); it('displays deal.updatedAt', () => - wrapper.expectText('[data-cy="updatedAt"]').toRead(formatInTimeZone(new Date(deal.updatedAt), LONDON, FULL_DATE_AND_TIME))); + wrapper.expectText('[data-cy="updatedAt"]').toRead(formatInTimeZone(new Date(deal.updatedAt), dateIanaTimezoneConfig.DEFAULT, FULL_DATE_AND_TIME))); }); describe('when deal has manualInclusionApplicationSubmissionDate', () => { let wrapper; - const user = { timezone: LONDON }; + const user = { timezone: dateIanaTimezoneConfig.DEFAULT }; beforeAll(() => { wrapper = render({ deal: dealWithManualInclusionApplicationSubmissionDate, user }); @@ -80,7 +80,9 @@ describe(component, () => { it('displays MIA submission date table header', () => wrapper.expectText('[data-cy="submissionDateHeader"]').toRead('MIA Submission date')); it('displays deal.details.manualInclusionApplicationSubmissionDate', () => - wrapper.expectText('[data-cy="submissionDate"]').toRead(formatInTimeZone(new Date(manualInclusionApplicationSubmissionDate), LONDON, FULL_DATE))); + wrapper + .expectText('[data-cy="submissionDate"]') + .toRead(formatInTimeZone(new Date(manualInclusionApplicationSubmissionDate), dateIanaTimezoneConfig.DEFAULT, FULL_DATE))); }); describe('renders - for any blank fields', () => { @@ -100,7 +102,7 @@ describe(component, () => { }; beforeAll(() => { - const user = { timezone: LONDON }; + const user = { timezone: dateIanaTimezoneConfig.DEFAULT }; wrapper = render({ mockDeal, user }); }); diff --git a/portal/component-tests/contract/components/loan-transactions-table.component-test.js b/portal/component-tests/contract/components/loan-transactions-table.component-test.js index f954328880..aa34953eb7 100644 --- a/portal/component-tests/contract/components/loan-transactions-table.component-test.js +++ b/portal/component-tests/contract/components/loan-transactions-table.component-test.js @@ -1,7 +1,4 @@ -const { - ROLES, - DATE_IANA_TIMEZONES: { LONDON }, -} = require('@ukef/dtfs2-common'); +const { ROLES, dateIanaTimezoneConfig } = require('@ukef/dtfs2-common'); const { UNCONDITIONAL } = require('../../../server/constants/facility-stage'); const { getNowAsEpoch } = require('../../../server/helpers'); const { NON_MAKER_ROLES } = require('../../../test-helpers/common-role-lists'); @@ -58,7 +55,7 @@ describe(component, () => { dealWithLoansThatCanChangeCoverDate.loanTransactions.items[1].issueFacilityDetailsSubmitted = true; describe('as a maker', () => { - const user = { roles: [MAKER], timezone: LONDON }; + const user = { roles: [MAKER], timezone: dateIanaTimezoneConfig.DEFAULT }; commonTests(user); @@ -134,7 +131,7 @@ describe(component, () => { }); describe.each(NON_MAKER_ROLES)('when viewed with the role %s', (nonMakerRole) => { - const user = { roles: [nonMakerRole], timezone: LONDON }; + const user = { roles: [nonMakerRole], timezone: dateIanaTimezoneConfig.DEFAULT }; commonTests(user); diff --git a/portal/component-tests/contract/contract-submission-details.component-test.js b/portal/component-tests/contract/contract-submission-details.component-test.js index c8ca5ceeea..05cc62a18e 100644 --- a/portal/component-tests/contract/contract-submission-details.component-test.js +++ b/portal/component-tests/contract/contract-submission-details.component-test.js @@ -1,6 +1,6 @@ const { ROLES: { MAKER }, - DATE_IANA_TIMEZONES: { LONDON }, + dateIanaTimezoneConfig, } = require('@ukef/dtfs2-common'); const pageRenderer = require('../pageRenderer'); @@ -21,7 +21,7 @@ describe(page, () => { wrapper = render({ deal, user: { - timezone: LONDON, + timezone: dateIanaTimezoneConfig.DEFAULT, roles: [MAKER], }, editable: true, @@ -84,7 +84,7 @@ describe(page, () => { mandatoryCriteria: [], }, user: { - timezone: LONDON, + timezone: dateIanaTimezoneConfig.DEFAULT, roles: [MAKER], }, editable: true, diff --git a/portal/component-tests/contract/contract-view.component-test.js b/portal/component-tests/contract/contract-view.component-test.js index 52333f5e7e..9e59c42fa1 100644 --- a/portal/component-tests/contract/contract-view.component-test.js +++ b/portal/component-tests/contract/contract-view.component-test.js @@ -1,7 +1,4 @@ -const { - ROLES, - DATE_IANA_TIMEZONES: { LONDON }, -} = require('@ukef/dtfs2-common'); +const { ROLES, dateIanaTimezoneConfig } = require('@ukef/dtfs2-common'); const { STATUS } = require('../../server/constants'); const pageRenderer = require('../pageRenderer'); @@ -39,7 +36,7 @@ const confirmedRequestStartDateParams = { describe(page, () => { describe("when viewed as a 'maker'", () => { - const user = { roles: [MAKER], timezone: LONDON }; + const user = { roles: [MAKER], timezone: dateIanaTimezoneConfig.DEFAULT }; commonTests(user); @@ -72,7 +69,7 @@ describe(page, () => { }); describe("when viewed as a 'checker'", () => { - const user = { roles: [CHECKER], timezone: LONDON }; + const user = { roles: [CHECKER], timezone: dateIanaTimezoneConfig.DEFAULT }; commonTests(user); @@ -103,7 +100,7 @@ describe(page, () => { }); describe.each(NON_MAKER_ROLES)("when viewed as a '%s'", (nonMakerRole) => { - const user = { roles: [nonMakerRole], timezone: LONDON }; + const user = { roles: [nonMakerRole], timezone: dateIanaTimezoneConfig.DEFAULT }; commonTests(user); diff --git a/portal/component-tests/loan/_macros/loan-submission-details.component-test.js b/portal/component-tests/loan/_macros/loan-submission-details.component-test.js index 5f9fd24679..88359c07e0 100644 --- a/portal/component-tests/loan/_macros/loan-submission-details.component-test.js +++ b/portal/component-tests/loan/_macros/loan-submission-details.component-test.js @@ -1,6 +1,6 @@ const { ROLES: { MAKER }, - DATE_IANA_TIMEZONES: { LONDON }, + dateIanaTimezoneConfig, } = require('@ukef/dtfs2-common'); const componentRenderer = require('../../componentRenderer'); const deal = require('../../fixtures/deal-fully-completed'); @@ -12,7 +12,7 @@ describe(component, () => { let wrapper; const user = { roles: [MAKER], - timezone: LONDON, + timezone: dateIanaTimezoneConfig.DEFAULT, }; const loan = deal.loanTransactions.items[0]; diff --git a/portal/server/nunjucks-configuration/filter-localiseTimestamp.test.ts b/portal/server/nunjucks-configuration/filter-localiseTimestamp.test.ts index 7030992afa..1492ce755f 100644 --- a/portal/server/nunjucks-configuration/filter-localiseTimestamp.test.ts +++ b/portal/server/nunjucks-configuration/filter-localiseTimestamp.test.ts @@ -1,8 +1,6 @@ -import { DATE_IANA_TIMEZONES } from '@ukef/dtfs2-common'; +import { dateIanaTimezoneConfig } from '@ukef/dtfs2-common'; import { filterLocaliseTimestamp } from './filter-localiseTimestamp'; -const { LONDON } = DATE_IANA_TIMEZONES; - describe('nunjuck filters - dashIfEmpty', () => { describe('when timestamp is a valid number', () => { // 1707343200000 is Unix epoch for Wed Feb 07 2024 22:00:00 GMT+0000 @@ -11,21 +9,21 @@ describe('nunjuck filters - dashIfEmpty', () => { const mockValue = mockDate.valueOf(); it('should return the day of the month if given format `dd` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'dd', LONDON); + const result = filterLocaliseTimestamp(mockValue, 'dd', dateIanaTimezoneConfig.DEFAULT); const expected = '07'; expect(result).toEqual(expected); }); it('should return the month if given the format `MM` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'MM', LONDON); + const result = filterLocaliseTimestamp(mockValue, 'MM', dateIanaTimezoneConfig.DEFAULT); const expected = '02'; expect(result).toEqual(expected); }); it('should return the year if given the format `yyyy` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'yyyy', LONDON); + const result = filterLocaliseTimestamp(mockValue, 'yyyy', dateIanaTimezoneConfig.DEFAULT); const expected = '2024'; expect(result).toEqual(expected); @@ -46,21 +44,21 @@ describe('nunjuck filters - dashIfEmpty', () => { const mockValue = mockDate.valueOf().toString(); it('should return the day of the month if given format `dd` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'dd', LONDON); + const result = filterLocaliseTimestamp(mockValue, 'dd', dateIanaTimezoneConfig.DEFAULT); const expected = '07'; expect(result).toEqual(expected); }); it('should return the month if given the format `MM` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'MM', LONDON); + const result = filterLocaliseTimestamp(mockValue, 'MM', dateIanaTimezoneConfig.DEFAULT); const expected = '02'; expect(result).toEqual(expected); }); it('should return the year if given the format `yyyy` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'yyyy', LONDON); + const result = filterLocaliseTimestamp(mockValue, 'yyyy', dateIanaTimezoneConfig.DEFAULT); const expected = '2024'; expect(result).toEqual(expected); @@ -78,21 +76,21 @@ describe('nunjuck filters - dashIfEmpty', () => { const mockValue = ''; it('should return an empty string if given format `dd` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'dd', LONDON); + const result = filterLocaliseTimestamp(mockValue, 'dd', dateIanaTimezoneConfig.DEFAULT); const expected = ''; expect(result).toEqual(expected); }); it('should return an empty string if given the format `MM` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'MM', LONDON); + const result = filterLocaliseTimestamp(mockValue, 'MM', dateIanaTimezoneConfig.DEFAULT); const expected = ''; expect(result).toEqual(expected); }); it('should return an empty string if given the format `yyyy` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'yyyy', LONDON); + const result = filterLocaliseTimestamp(mockValue, 'yyyy', dateIanaTimezoneConfig.DEFAULT); const expected = ''; expect(result).toEqual(expected); @@ -110,21 +108,21 @@ describe('nunjuck filters - dashIfEmpty', () => { const mockValue = 'test'; it('should return `Invalid date` if given format `dd` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'dd', LONDON); + const result = filterLocaliseTimestamp(mockValue, 'dd', dateIanaTimezoneConfig.DEFAULT); const expected = 'Invalid date'; expect(result).toEqual(expected); }); it('should return `Invalid date` if given the format `MM` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'MM', LONDON); + const result = filterLocaliseTimestamp(mockValue, 'MM', dateIanaTimezoneConfig.DEFAULT); const expected = 'Invalid date'; expect(result).toEqual(expected); }); it('should return `Invalid date` if given the format `yyyy` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'yyyy', LONDON); + const result = filterLocaliseTimestamp(mockValue, 'yyyy', dateIanaTimezoneConfig.DEFAULT); const expected = 'Invalid date'; expect(result).toEqual(expected); From 3343ed2062219a0a6638469b3820d2e29a233976 Mon Sep 17 00:00:00 2001 From: Alex Bramhill Date: Tue, 15 Oct 2024 20:27:14 +0100 Subject: [PATCH 07/17] feat(dtfs2-6892): update to default timezone using env var as per review comment --- libs/common/src/constants/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/common/src/constants/index.ts b/libs/common/src/constants/index.ts index b27cbf703a..f7fc43df77 100644 --- a/libs/common/src/constants/index.ts +++ b/libs/common/src/constants/index.ts @@ -20,7 +20,6 @@ export * from './facility-type-mapped'; export * from './max-request-size'; export * from './request-platform-type'; export * from './date-formats'; -export * from './date-iana-timezones'; export * from './url-character-allowances'; export * from './max-character-count'; export * from './deal-submission-type'; From 1391ef9a96b05011fa8c771508c0cbae2d2f3f8b Mon Sep 17 00:00:00 2001 From: Alex Bramhill Date: Tue, 15 Oct 2024 20:30:30 +0100 Subject: [PATCH 08/17] feat(dtfs2-6892): update to default timezone using env var as per review comment --- libs/common/src/configs/date-iana-timezones.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/common/src/configs/date-iana-timezones.config.ts b/libs/common/src/configs/date-iana-timezones.config.ts index d981cc27f4..3513df3e0a 100644 --- a/libs/common/src/configs/date-iana-timezones.config.ts +++ b/libs/common/src/configs/date-iana-timezones.config.ts @@ -5,7 +5,7 @@ dotenv.config(); /** * {@link https://www.iana.org/time-zones} - * There is no default provided in this config, as this would allow for inconsistency in microservices. + * There is no default for unset values in this config, as this would allow for inconsistency in microservices. */ const defaultIanaTimezoneConfigSchema = z .object({ From 5c64ab3cfb9949c3eb1b11e565e7df51d4491892 Mon Sep 17 00:00:00 2001 From: Alex Bramhill Date: Wed, 16 Oct 2024 11:01:22 +0100 Subject: [PATCH 09/17] feat(dtfs2-6892): update deployment scripts with TZ --- .../workflows/development_infrastructure.yml | 21 ++++++++++------ .../workflows/production_infrastructure.yml | 21 ++++++++++------ .github/workflows/staging_infrastructure.yml | 25 ++++++++++++------- 3 files changed, 44 insertions(+), 23 deletions(-) diff --git a/.github/workflows/development_infrastructure.yml b/.github/workflows/development_infrastructure.yml index a86e301b8c..5779fcad61 100644 --- a/.github/workflows/development_infrastructure.yml +++ b/.github/workflows/development_infrastructure.yml @@ -1126,7 +1126,8 @@ jobs: GOV_NOTIFY_API_KEY="${{ secrets.GOV_NOTIFY_API_KEY }}" \ MONGO_INITDB_DATABASE="${{ env.database_name }}" \ MONGODB_URI="$mongo_connection_string" \ - RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} + RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ + TZ="${{ vars.TZ }}" dtfs-central-api: name: DTFS Central API @@ -1265,7 +1266,8 @@ jobs: WEBSITES_PORT=5000 \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ CHANGE_STREAM_ENABLED="${{ vars.CHANGE_STREAM_ENABLED}}" \ - DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" + DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" \ + TZ="${{ vars.TZ }}" - name: Secrets uses: azure/cli@v2 @@ -1448,7 +1450,8 @@ jobs: CLAMAV_PORT="$clamav_port" \ CHANGE_STREAM_ENABLED="${{ vars.CHANGE_STREAM_ENABLED}}" \ DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" \ - GEF_DEAL_VERSION=${{ vars.GEF_DEAL_VERSION }} + GEF_DEAL_VERSION=${{ vars.GEF_DEAL_VERSION }} \ + TZ="${{ vars.TZ }}" - name: Secrets uses: azure/cli@v2 @@ -1635,7 +1638,8 @@ jobs: WEBSITES_PORT=5000 \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ CHANGE_STREAM_ENABLED="${{ vars.CHANGE_STREAM_ENABLED}}" \ - DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" + DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" \ + TZ="${{ vars.TZ }}" - name: Secrets uses: azure/cli@v2 @@ -1836,7 +1840,8 @@ jobs: RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ UTILISATION_REPORT_MAX_FILE_SIZE_BYTES=${{ vars.UTILISATION_REPORT_MAX_FILE_SIZE_BYTES }} \ CLAMAV_HOST="$clamav_host" \ - CLAMAV_PORT="$clamav_port" + CLAMAV_PORT="$clamav_port" \ + TZ="${{ vars.TZ }}" - name: Secrets uses: azure/cli@v2 @@ -2000,7 +2005,8 @@ jobs: ESTORE_CRON_MANAGER_SCHEDULE="${{ vars.ESTORE_CRON_MANAGER_SCHEDULE }}" \ HTTPS=1 \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ - FF_TFM_SSO_ENABLED="${{ vars.FF_TFM_SSO_ENABLED }}" + FF_TFM_SSO_ENABLED="${{ vars.FF_TFM_SSO_ENABLED }}" \ + TZ="${{ vars.TZ }}" - name: Secrets uses: azure/cli@v2 @@ -2160,7 +2166,8 @@ jobs: EXTERNAL_API_URL="http://$EXTERNAL_API_URL" \ HTTPS=1 \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ - GEF_DEAL_VERSION=${{ vars.GEF_DEAL_VERSION }} + GEF_DEAL_VERSION=${{ vars.GEF_DEAL_VERSION }} \ + TZ="${{ vars.TZ }}" - name: Secrets uses: azure/cli@v2 diff --git a/.github/workflows/production_infrastructure.yml b/.github/workflows/production_infrastructure.yml index fb8dd491b2..37ca85efdf 100644 --- a/.github/workflows/production_infrastructure.yml +++ b/.github/workflows/production_infrastructure.yml @@ -1128,7 +1128,8 @@ jobs: GOV_NOTIFY_API_KEY="${{ secrets.GOV_NOTIFY_API_KEY }}" \ MONGO_INITDB_DATABASE="${{ env.database_name }}" \ MONGODB_URI="$mongo_connection_string" \ - RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} + RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ + TZ="${{ vars.TZ }}" dtfs-central-api: name: DTFS Central API @@ -1267,7 +1268,8 @@ jobs: WEBSITES_PORT=5000 \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ CHANGE_STREAM_ENABLED="${{ vars.CHANGE_STREAM_ENABLED}}" \ - DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" + DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" \ + TZ="${{ vars.TZ }}" - name: Secrets uses: azure/cli@v2 @@ -1449,7 +1451,8 @@ jobs: CLAMAV_PORT="$clamav_port" \ CHANGE_STREAM_ENABLED="${{ vars.CHANGE_STREAM_ENABLED}}" \ DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" \ - GEF_DEAL_VERSION=${{ vars.GEF_DEAL_VERSION }} + GEF_DEAL_VERSION=${{ vars.GEF_DEAL_VERSION }} \ + TZ="${{ vars.TZ }}" - name: Secrets uses: azure/cli@v2 @@ -1636,7 +1639,8 @@ jobs: WEBSITES_PORT=5000 \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ CHANGE_STREAM_ENABLED="${{ vars.CHANGE_STREAM_ENABLED}}" \ - DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" + DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" \ + TZ="${{ vars.TZ }}" - name: Secrets uses: azure/cli@v2 @@ -1823,7 +1827,8 @@ jobs: EXTERNAL_API_URL="http://$EXTERNAL_API_URL" \ HTTPS=1 \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ - UTILISATION_REPORT_MAX_FILE_SIZE_BYTES=${{ vars.UTILISATION_REPORT_MAX_FILE_SIZE_BYTES }} + UTILISATION_REPORT_MAX_FILE_SIZE_BYTES=${{ vars.UTILISATION_REPORT_MAX_FILE_SIZE_BYTES }} \ + TZ="${{ vars.TZ }}" - name: Secrets uses: azure/cli@v2 @@ -1992,7 +1997,8 @@ jobs: ENTRA_ID_CLOUD_INSTANCE="${{ vars.ENTRA_ID_CLOUD_INSTANCE }}" \ ENTRA_ID_TENANT_ID="${{ vars.ENTRA_ID_TENANT_ID }}" \ ENTRA_ID_CLIENT_SECRET="${{ vars.ENTRA_ID_CLIENT_SECRET }}" \ - ENTRA_ID_REDIRECT_URL="${{ vars.ENTRA_ID_REDIRECT_URL }}" + ENTRA_ID_REDIRECT_URL="${{ vars.ENTRA_ID_REDIRECT_URL }}" \ + TZ="${{ vars.TZ }}" - name: Secrets uses: azure/cli@v2 @@ -2152,7 +2158,8 @@ jobs: EXTERNAL_API_URL="http://$EXTERNAL_API_URL" \ HTTPS=1 \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ - GEF_DEAL_VERSION=${{ vars.GEF_DEAL_VERSION }} + GEF_DEAL_VERSION=${{ vars.GEF_DEAL_VERSION }} \ + TZ="${{ vars.TZ }}" - name: Secrets uses: azure/cli@v2 diff --git a/.github/workflows/staging_infrastructure.yml b/.github/workflows/staging_infrastructure.yml index 071c9795d1..9f444179d9 100644 --- a/.github/workflows/staging_infrastructure.yml +++ b/.github/workflows/staging_infrastructure.yml @@ -4,7 +4,7 @@ on: push: branches: [infrastructure] paths: - - ".github/workflows/staging_infrastructure.yml" + - '.github/workflows/staging_infrastructure.yml' env: # Environment @@ -20,7 +20,7 @@ env: app_service_plan_egress_cidr: 172.16.52.0/28 vm_cidr: 172.16.53.0/28 aca_clam_av_cidr: 172.16.52.32/27 - vnet_address_prefixes: "172.16.50.0/23 172.16.52.0/23 172.16.70.0/23" # App service settings + vnet_address_prefixes: '172.16.50.0/23 172.16.52.0/23 172.16.70.0/23' # App service settings production_subnet_cidr: 10.60.0.0/16 palo_alto_next_hop: 10.50.0.100 @@ -1128,7 +1128,8 @@ jobs: GOV_NOTIFY_API_KEY="${{ secrets.GOV_NOTIFY_API_KEY }}" \ MONGO_INITDB_DATABASE="${{ env.database_name }}" \ MONGODB_URI="$mongo_connection_string" \ - RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} + RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ + TZ="${{ vars.TZ }}" dtfs-central-api: name: DTFS Central API @@ -1267,7 +1268,8 @@ jobs: WEBSITES_PORT=5000 \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ CHANGE_STREAM_ENABLED="${{ vars.CHANGE_STREAM_ENABLED}}" \ - DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" + DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" \ + TZ="${{ vars.TZ }}" - name: Secrets uses: azure/cli@v2 @@ -1449,7 +1451,8 @@ jobs: CLAMAV_PORT="$clamav_port" \ CHANGE_STREAM_ENABLED="${{ vars.CHANGE_STREAM_ENABLED}}" \ DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" \ - GEF_DEAL_VERSION=${{ vars.GEF_DEAL_VERSION }} + GEF_DEAL_VERSION=${{ vars.GEF_DEAL_VERSION }} \ + TZ="${{ vars.TZ }}" - name: Secrets uses: azure/cli@v2 @@ -1636,7 +1639,8 @@ jobs: WEBSITES_PORT=5000 \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ CHANGE_STREAM_ENABLED="${{ vars.CHANGE_STREAM_ENABLED}}" \ - DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" + DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" \ + TZ="${{ vars.TZ }}" - name: Secrets uses: azure/cli@v2 @@ -1823,7 +1827,8 @@ jobs: EXTERNAL_API_URL="http://$EXTERNAL_API_URL" \ HTTPS=1 \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ - UTILISATION_REPORT_MAX_FILE_SIZE_BYTES=${{ vars.UTILISATION_REPORT_MAX_FILE_SIZE_BYTES }} + UTILISATION_REPORT_MAX_FILE_SIZE_BYTES=${{ vars.UTILISATION_REPORT_MAX_FILE_SIZE_BYTES }} \ + TZ="${{ vars.TZ }}" - name: Secrets uses: azure/cli@v2 @@ -1992,7 +1997,8 @@ jobs: ENTRA_ID_CLOUD_INSTANCE="${{ vars.ENTRA_ID_CLOUD_INSTANCE }}" \ ENTRA_ID_TENANT_ID="${{ vars.ENTRA_ID_TENANT_ID }}" \ ENTRA_ID_CLIENT_SECRET="${{ vars.ENTRA_ID_CLIENT_SECRET }}" \ - ENTRA_ID_REDIRECT_URL="${{ vars.ENTRA_ID_REDIRECT_URL }}" + ENTRA_ID_REDIRECT_URL="${{ vars.ENTRA_ID_REDIRECT_URL }}" \ + TZ="${{ vars.TZ }}" - name: Secrets uses: azure/cli@v2 @@ -2152,7 +2158,8 @@ jobs: EXTERNAL_API_URL="http://$EXTERNAL_API_URL" \ HTTPS=1 \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ - GEF_DEAL_VERSION=${{ vars.GEF_DEAL_VERSION }} + GEF_DEAL_VERSION=${{ vars.GEF_DEAL_VERSION }} \ + TZ="${{ vars.TZ }}" - name: Secrets uses: azure/cli@v2 From 1e2e3a2d65458d1f70648ab095727e7b49e1b8d3 Mon Sep 17 00:00:00 2001 From: Alex Bramhill Date: Wed, 16 Oct 2024 11:48:33 +0100 Subject: [PATCH 10/17] feat(dtfs2-6892): update e2e tests config --- e2e-tests/gef/cypress.config.js | 3 ++- e2e-tests/portal/cypress.config.js | 3 ++- e2e-tests/tfm/cypress.config.js | 3 ++- e2e-tests/ukef/cypress.config.js | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/e2e-tests/gef/cypress.config.js b/e2e-tests/gef/cypress.config.js index 1c9e8caf5c..9899db922c 100644 --- a/e2e-tests/gef/cypress.config.js +++ b/e2e-tests/gef/cypress.config.js @@ -6,9 +6,10 @@ const { createTasks } = require('../support/tasks'); // Read from root `./.env` directory dotenv.config({ path: path.resolve(__dirname, '../../.env') }); -const { PORTAL_API_KEY } = process.env; +const { TZ, PORTAL_API_KEY } = process.env; module.exports = defineConfig({ + TZ, dealApiProtocol: 'http://', dealApiHost: 'localhost', dealApiPort: '5001', diff --git a/e2e-tests/portal/cypress.config.js b/e2e-tests/portal/cypress.config.js index 253d3fecfb..d60fbeec21 100644 --- a/e2e-tests/portal/cypress.config.js +++ b/e2e-tests/portal/cypress.config.js @@ -6,9 +6,10 @@ const { createTasks } = require('../support/tasks'); // Read from root `./.env` directory dotenv.config({ path: path.resolve(__dirname, '../../.env') }); -const { CONTACT_US_EMAIL_ADDRESS, PORTAL_API_KEY } = process.env; +const { TZ, CONTACT_US_EMAIL_ADDRESS, PORTAL_API_KEY } = process.env; module.exports = defineConfig({ + TZ, apiProtocol: 'http://', apiHost: 'localhost', apiPort: '5001', diff --git a/e2e-tests/tfm/cypress.config.js b/e2e-tests/tfm/cypress.config.js index 5eafca012d..cae76903a1 100644 --- a/e2e-tests/tfm/cypress.config.js +++ b/e2e-tests/tfm/cypress.config.js @@ -6,9 +6,10 @@ const { createTasks } = require('../support/tasks'); // Read from root `./.env` directory dotenv.config({ path: path.resolve(__dirname, '../../.env') }); -const { TFM_API_KEY } = process.env; +const { TZ, TFM_API_KEY } = process.env; module.exports = defineConfig({ + TZ, dealApiProtocol: 'http://', dealApiHost: 'localhost', dealApiPort: '5001', diff --git a/e2e-tests/ukef/cypress.config.js b/e2e-tests/ukef/cypress.config.js index 962448b282..2c06bfdf5c 100644 --- a/e2e-tests/ukef/cypress.config.js +++ b/e2e-tests/ukef/cypress.config.js @@ -6,9 +6,10 @@ const { createTasks } = require('../support/tasks'); // Read from root `./.env` directory dotenv.config({ path: path.resolve(__dirname, '../../.env') }); -const { PORTAL_API_KEY, TFM_API_KEY } = process.env; +const { TZ, PORTAL_API_KEY, TFM_API_KEY } = process.env; module.exports = defineConfig({ + TZ, centralApiProtocol: 'http://', centralApiHost: 'localhost', centralApiPort: '5005', From 71ab73d6dfdada2023908976827b765ae9c945d4 Mon Sep 17 00:00:00 2001 From: Alex Bramhill Date: Wed, 16 Oct 2024 11:55:17 +0100 Subject: [PATCH 11/17] feat(dtfs2-6892): update TZ var to not cast to string as per review comment --- .../workflows/development_infrastructure.yml | 55 +++++-------------- .../workflows/production_infrastructure.yml | 43 ++++----------- .github/workflows/staging_infrastructure.yml | 39 ++++--------- 3 files changed, 35 insertions(+), 102 deletions(-) diff --git a/.github/workflows/development_infrastructure.yml b/.github/workflows/development_infrastructure.yml index 5779fcad61..cd041af2f0 100644 --- a/.github/workflows/development_infrastructure.yml +++ b/.github/workflows/development_infrastructure.yml @@ -4,7 +4,7 @@ on: push: branches: [infrastructure] paths: - - ".github/workflows/development_infrastructure.yml" + - '.github/workflows/development_infrastructure.yml' env: # Environment @@ -20,7 +20,7 @@ env: app_service_plan_egress_cidr: 172.16.42.0/28 vm_cidr: 172.16.43.0/28 aca_clam_av_cidr: 172.16.42.32/27 - vnet_address_prefixes: "172.16.40.0/22 172.16.60.0/23" + vnet_address_prefixes: '172.16.40.0/22 172.16.60.0/23' production_subnet_cidr: 10.60.0.0/16 palo_alto_next_hop: 10.50.0.100 api_portal_access_port: 44232 @@ -1127,7 +1127,7 @@ jobs: MONGO_INITDB_DATABASE="${{ env.database_name }}" \ MONGODB_URI="$mongo_connection_string" \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} dtfs-central-api: name: DTFS Central API @@ -1267,7 +1267,7 @@ jobs: RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ CHANGE_STREAM_ENABLED="${{ vars.CHANGE_STREAM_ENABLED}}" \ DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} - name: Secrets uses: azure/cli@v2 @@ -1292,18 +1292,7 @@ jobs: portal-api: name: Portal API - needs: - [ - set-environment, - vnet, - private-dns, - cosmos-db-private, - clamav, - external-api, - dtfs-central-api, - file-storage, - trade-finance-manager-api, - ] + needs: [set-environment, vnet, private-dns, cosmos-db-private, clamav, external-api, dtfs-central-api, file-storage, trade-finance-manager-api] environment: name: ${{ needs.set-environment.outputs.environment }} runs-on: [self-hosted, linux, deployment] @@ -1451,7 +1440,7 @@ jobs: CHANGE_STREAM_ENABLED="${{ vars.CHANGE_STREAM_ENABLED}}" \ DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" \ GEF_DEAL_VERSION=${{ vars.GEF_DEAL_VERSION }} \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} - name: Secrets uses: azure/cli@v2 @@ -1495,15 +1484,7 @@ jobs: trade-finance-manager-api: name: Trade Finance Manager API - needs: - [ - set-environment, - vnet, - private-dns, - cosmos-db-private, - external-api, - dtfs-central-api, - ] + needs: [set-environment, vnet, private-dns, cosmos-db-private, external-api, dtfs-central-api] environment: name: ${{ needs.set-environment.outputs.environment }} runs-on: [self-hosted, linux, deployment] @@ -1639,7 +1620,7 @@ jobs: RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ CHANGE_STREAM_ENABLED="${{ vars.CHANGE_STREAM_ENABLED}}" \ DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} - name: Secrets uses: azure/cli@v2 @@ -1679,16 +1660,7 @@ jobs: # START UI setup portal-ui: name: Portal UI - needs: - [ - set-environment, - vnet, - private-dns, - clamav, - portal-api, - external-api, - redis, - ] + needs: [set-environment, vnet, private-dns, clamav, portal-api, external-api, redis] environment: name: ${{ needs.set-environment.outputs.environment }} runs-on: [self-hosted, linux, deployment] @@ -1841,7 +1813,7 @@ jobs: UTILISATION_REPORT_MAX_FILE_SIZE_BYTES=${{ vars.UTILISATION_REPORT_MAX_FILE_SIZE_BYTES }} \ CLAMAV_HOST="$clamav_host" \ CLAMAV_PORT="$clamav_port" \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} - name: Secrets uses: azure/cli@v2 @@ -1854,8 +1826,7 @@ jobs: trade-finance-manager-ui: name: Trade Finance Manager UI - needs: - [set-environment, vnet, private-dns, trade-finance-manager-api, redis] + needs: [set-environment, vnet, private-dns, trade-finance-manager-api, redis] environment: name: ${{ needs.set-environment.outputs.environment }} runs-on: [self-hosted, linux, deployment] @@ -2006,7 +1977,7 @@ jobs: HTTPS=1 \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ FF_TFM_SSO_ENABLED="${{ vars.FF_TFM_SSO_ENABLED }}" \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} - name: Secrets uses: azure/cli@v2 @@ -2167,7 +2138,7 @@ jobs: HTTPS=1 \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ GEF_DEAL_VERSION=${{ vars.GEF_DEAL_VERSION }} \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} - name: Secrets uses: azure/cli@v2 diff --git a/.github/workflows/production_infrastructure.yml b/.github/workflows/production_infrastructure.yml index 37ca85efdf..99a78fccf2 100644 --- a/.github/workflows/production_infrastructure.yml +++ b/.github/workflows/production_infrastructure.yml @@ -4,7 +4,7 @@ on: push: branches: [infrastructure] paths: - - ".github/workflows/production_infrastructure.yml" + - '.github/workflows/production_infrastructure.yml' env: # Environment @@ -20,7 +20,7 @@ env: app_service_plan_egress_cidr: 172.16.32.0/28 vm_cidr: 172.16.33.0/28 aca_clam_av_cidr: 172.16.32.32/27 - vnet_address_prefixes: "172.16.30.0/23 172.16.32.0/23" + vnet_address_prefixes: '172.16.30.0/23 172.16.32.0/23' production_subnet_cidr: 10.60.0.0/16 palo_alto_next_hop: 10.50.0.100 @@ -1129,7 +1129,7 @@ jobs: MONGO_INITDB_DATABASE="${{ env.database_name }}" \ MONGODB_URI="$mongo_connection_string" \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} dtfs-central-api: name: DTFS Central API @@ -1269,7 +1269,7 @@ jobs: RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ CHANGE_STREAM_ENABLED="${{ vars.CHANGE_STREAM_ENABLED}}" \ DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} - name: Secrets uses: azure/cli@v2 @@ -1294,17 +1294,7 @@ jobs: portal-api: name: Portal API - needs: - [ - set-environment, - vnet, - private-dns, - cosmos-db-private, - external-api, - dtfs-central-api, - file-storage, - trade-finance-manager-api, - ] + needs: [set-environment, vnet, private-dns, cosmos-db-private, external-api, dtfs-central-api, file-storage, trade-finance-manager-api] environment: name: ${{ needs.set-environment.outputs.environment }} runs-on: [self-hosted, linux, deployment] @@ -1452,7 +1442,7 @@ jobs: CHANGE_STREAM_ENABLED="${{ vars.CHANGE_STREAM_ENABLED}}" \ DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" \ GEF_DEAL_VERSION=${{ vars.GEF_DEAL_VERSION }} \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} - name: Secrets uses: azure/cli@v2 @@ -1496,15 +1486,7 @@ jobs: trade-finance-manager-api: name: Trade Finance Manager API - needs: - [ - set-environment, - vnet, - private-dns, - cosmos-db-private, - external-api, - dtfs-central-api, - ] + needs: [set-environment, vnet, private-dns, cosmos-db-private, external-api, dtfs-central-api] environment: name: ${{ needs.set-environment.outputs.environment }} runs-on: [self-hosted, linux, deployment] @@ -1640,7 +1622,7 @@ jobs: RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ CHANGE_STREAM_ENABLED="${{ vars.CHANGE_STREAM_ENABLED}}" \ DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} - name: Secrets uses: azure/cli@v2 @@ -1828,7 +1810,7 @@ jobs: HTTPS=1 \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ UTILISATION_REPORT_MAX_FILE_SIZE_BYTES=${{ vars.UTILISATION_REPORT_MAX_FILE_SIZE_BYTES }} \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} - name: Secrets uses: azure/cli@v2 @@ -1841,8 +1823,7 @@ jobs: trade-finance-manager-ui: name: Trade Finance Manager UI - needs: - [set-environment, vnet, private-dns, trade-finance-manager-api, redis] + needs: [set-environment, vnet, private-dns, trade-finance-manager-api, redis] environment: name: ${{ needs.set-environment.outputs.environment }} runs-on: [self-hosted, linux, deployment] @@ -1998,7 +1979,7 @@ jobs: ENTRA_ID_TENANT_ID="${{ vars.ENTRA_ID_TENANT_ID }}" \ ENTRA_ID_CLIENT_SECRET="${{ vars.ENTRA_ID_CLIENT_SECRET }}" \ ENTRA_ID_REDIRECT_URL="${{ vars.ENTRA_ID_REDIRECT_URL }}" \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} - name: Secrets uses: azure/cli@v2 @@ -2159,7 +2140,7 @@ jobs: HTTPS=1 \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ GEF_DEAL_VERSION=${{ vars.GEF_DEAL_VERSION }} \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} - name: Secrets uses: azure/cli@v2 diff --git a/.github/workflows/staging_infrastructure.yml b/.github/workflows/staging_infrastructure.yml index 9f444179d9..1490d9dbb0 100644 --- a/.github/workflows/staging_infrastructure.yml +++ b/.github/workflows/staging_infrastructure.yml @@ -1129,7 +1129,7 @@ jobs: MONGO_INITDB_DATABASE="${{ env.database_name }}" \ MONGODB_URI="$mongo_connection_string" \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} dtfs-central-api: name: DTFS Central API @@ -1269,7 +1269,7 @@ jobs: RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ CHANGE_STREAM_ENABLED="${{ vars.CHANGE_STREAM_ENABLED}}" \ DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} - name: Secrets uses: azure/cli@v2 @@ -1294,17 +1294,7 @@ jobs: portal-api: name: Portal API - needs: - [ - set-environment, - vnet, - private-dns, - cosmos-db-private, - external-api, - dtfs-central-api, - file-storage, - trade-finance-manager-api, - ] + needs: [set-environment, vnet, private-dns, cosmos-db-private, external-api, dtfs-central-api, file-storage, trade-finance-manager-api] environment: name: ${{ needs.set-environment.outputs.environment }} runs-on: [self-hosted, linux, deployment] @@ -1452,7 +1442,7 @@ jobs: CHANGE_STREAM_ENABLED="${{ vars.CHANGE_STREAM_ENABLED}}" \ DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" \ GEF_DEAL_VERSION=${{ vars.GEF_DEAL_VERSION }} \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} - name: Secrets uses: azure/cli@v2 @@ -1496,15 +1486,7 @@ jobs: trade-finance-manager-api: name: Trade Finance Manager API - needs: - [ - set-environment, - vnet, - private-dns, - cosmos-db-private, - external-api, - dtfs-central-api, - ] + needs: [set-environment, vnet, private-dns, cosmos-db-private, external-api, dtfs-central-api] environment: name: ${{ needs.set-environment.outputs.environment }} runs-on: [self-hosted, linux, deployment] @@ -1640,7 +1622,7 @@ jobs: RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ CHANGE_STREAM_ENABLED="${{ vars.CHANGE_STREAM_ENABLED}}" \ DELETION_AUDIT_LOGS_TTL_SECONDS="${{ vars.DELETION_AUDIT_LOGS_TTL_SECONDS}}" \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} - name: Secrets uses: azure/cli@v2 @@ -1828,7 +1810,7 @@ jobs: HTTPS=1 \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ UTILISATION_REPORT_MAX_FILE_SIZE_BYTES=${{ vars.UTILISATION_REPORT_MAX_FILE_SIZE_BYTES }} \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} - name: Secrets uses: azure/cli@v2 @@ -1841,8 +1823,7 @@ jobs: trade-finance-manager-ui: name: Trade Finance Manager UI - needs: - [set-environment, vnet, private-dns, trade-finance-manager-api, redis] + needs: [set-environment, vnet, private-dns, trade-finance-manager-api, redis] environment: name: ${{ needs.set-environment.outputs.environment }} runs-on: [self-hosted, linux, deployment] @@ -1998,7 +1979,7 @@ jobs: ENTRA_ID_TENANT_ID="${{ vars.ENTRA_ID_TENANT_ID }}" \ ENTRA_ID_CLIENT_SECRET="${{ vars.ENTRA_ID_CLIENT_SECRET }}" \ ENTRA_ID_REDIRECT_URL="${{ vars.ENTRA_ID_REDIRECT_URL }}" \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} - name: Secrets uses: azure/cli@v2 @@ -2159,7 +2140,7 @@ jobs: HTTPS=1 \ RATE_LIMIT_THRESHOLD=${{ vars.RATE_LIMIT_THRESHOLD }} \ GEF_DEAL_VERSION=${{ vars.GEF_DEAL_VERSION }} \ - TZ="${{ vars.TZ }}" + TZ=${{ vars.TZ }} - name: Secrets uses: azure/cli@v2 From f603ffcc912f60b35fb3f71687a6e0b14a78010a Mon Sep 17 00:00:00 2001 From: Alex Bramhill Date: Wed, 16 Oct 2024 12:11:22 +0100 Subject: [PATCH 12/17] feat(dtfs2-6892): update e2e test config --- e2e-tests/portal/cypress.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/e2e-tests/portal/cypress.config.js b/e2e-tests/portal/cypress.config.js index d60fbeec21..7486fe24f5 100644 --- a/e2e-tests/portal/cypress.config.js +++ b/e2e-tests/portal/cypress.config.js @@ -38,6 +38,7 @@ module.exports = defineConfig({ }, env: { CONTACT_US_EMAIL_ADDRESS, + TZ, }, }, experimentalCspAllowList: ['child-src', 'default-src', 'frame-src', 'form-action', 'script-src', 'script-src-elem'], From 9da499e3587fafe46f1f9537cb97f5041c7202d4 Mon Sep 17 00:00:00 2001 From: Alex Bramhill Date: Wed, 16 Oct 2024 12:15:06 +0100 Subject: [PATCH 13/17] feat(dtfs2-6892): update test file --- .github/workflows/test.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 76a847e0d6..b631303d7f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -84,7 +84,7 @@ on: env: environment: dev - TZ: ${{ vars.TIMEZONE }} + TZ: 'Europe/London' credentials: ${{ secrets.AZURE_DIGITAL_DEV }} MONGODB_URI: ${{ secrets.MONGODB_URI }} MONGO_INITDB_DATABASE: ${{ secrets.MONGO_INITDB_DATABASE }} @@ -610,7 +610,8 @@ jobs: fail-fast: false # Single dimension matrix matrix: - spec: [ + spec: + [ 'case/activities/*.spec.js', 'case/AIN/*.spec.js', 'case/deal-cancellation-disabled/*.spec.js', From dbc336b89ead3c20e06d5853a3342a81e9e9e508 Mon Sep 17 00:00:00 2001 From: Alex Bramhill Date: Wed, 16 Oct 2024 12:33:02 +0100 Subject: [PATCH 14/17] feat(dtfs2-6892): update test file --- .../workflows/development_infrastructure.yml | 37 +++++++++++++++++-- .../workflows/production_infrastructure.yml | 25 +++++++++++-- .github/workflows/staging_infrastructure.yml | 25 +++++++++++-- .github/workflows/test.yml | 5 +-- e2e-tests/portal/cypress.config.js | 1 - 5 files changed, 79 insertions(+), 14 deletions(-) diff --git a/.github/workflows/development_infrastructure.yml b/.github/workflows/development_infrastructure.yml index cd041af2f0..3bbca593e0 100644 --- a/.github/workflows/development_infrastructure.yml +++ b/.github/workflows/development_infrastructure.yml @@ -1292,7 +1292,18 @@ jobs: portal-api: name: Portal API - needs: [set-environment, vnet, private-dns, cosmos-db-private, clamav, external-api, dtfs-central-api, file-storage, trade-finance-manager-api] + needs: + [ + set-environment, + vnet, + private-dns, + cosmos-db-private, + clamav, + external-api, + dtfs-central-api, + file-storage, + trade-finance-manager-api, + ] environment: name: ${{ needs.set-environment.outputs.environment }} runs-on: [self-hosted, linux, deployment] @@ -1484,7 +1495,15 @@ jobs: trade-finance-manager-api: name: Trade Finance Manager API - needs: [set-environment, vnet, private-dns, cosmos-db-private, external-api, dtfs-central-api] + needs: + [ + set-environment, + vnet, + private-dns, + cosmos-db-private, + external-api, + dtfs-central-api, + ] environment: name: ${{ needs.set-environment.outputs.environment }} runs-on: [self-hosted, linux, deployment] @@ -1660,7 +1679,16 @@ jobs: # START UI setup portal-ui: name: Portal UI - needs: [set-environment, vnet, private-dns, clamav, portal-api, external-api, redis] + needs: + [ + set-environment, + vnet, + private-dns, + clamav, + portal-api, + external-api, + redis, + ] environment: name: ${{ needs.set-environment.outputs.environment }} runs-on: [self-hosted, linux, deployment] @@ -1826,7 +1854,8 @@ jobs: trade-finance-manager-ui: name: Trade Finance Manager UI - needs: [set-environment, vnet, private-dns, trade-finance-manager-api, redis] + needs: + [set-environment, vnet, private-dns, trade-finance-manager-api, redis] environment: name: ${{ needs.set-environment.outputs.environment }} runs-on: [self-hosted, linux, deployment] diff --git a/.github/workflows/production_infrastructure.yml b/.github/workflows/production_infrastructure.yml index 99a78fccf2..0cb27009b9 100644 --- a/.github/workflows/production_infrastructure.yml +++ b/.github/workflows/production_infrastructure.yml @@ -1294,7 +1294,17 @@ jobs: portal-api: name: Portal API - needs: [set-environment, vnet, private-dns, cosmos-db-private, external-api, dtfs-central-api, file-storage, trade-finance-manager-api] + needs: + [ + set-environment, + vnet, + private-dns, + cosmos-db-private, + external-api, + dtfs-central-api, + file-storage, + trade-finance-manager-api, + ] environment: name: ${{ needs.set-environment.outputs.environment }} runs-on: [self-hosted, linux, deployment] @@ -1486,7 +1496,15 @@ jobs: trade-finance-manager-api: name: Trade Finance Manager API - needs: [set-environment, vnet, private-dns, cosmos-db-private, external-api, dtfs-central-api] + needs: + [ + set-environment, + vnet, + private-dns, + cosmos-db-private, + external-api, + dtfs-central-api, + ] environment: name: ${{ needs.set-environment.outputs.environment }} runs-on: [self-hosted, linux, deployment] @@ -1823,7 +1841,8 @@ jobs: trade-finance-manager-ui: name: Trade Finance Manager UI - needs: [set-environment, vnet, private-dns, trade-finance-manager-api, redis] + needs: + [set-environment, vnet, private-dns, trade-finance-manager-api, redis] environment: name: ${{ needs.set-environment.outputs.environment }} runs-on: [self-hosted, linux, deployment] diff --git a/.github/workflows/staging_infrastructure.yml b/.github/workflows/staging_infrastructure.yml index 1490d9dbb0..70d8bdddfa 100644 --- a/.github/workflows/staging_infrastructure.yml +++ b/.github/workflows/staging_infrastructure.yml @@ -1294,7 +1294,17 @@ jobs: portal-api: name: Portal API - needs: [set-environment, vnet, private-dns, cosmos-db-private, external-api, dtfs-central-api, file-storage, trade-finance-manager-api] + needs: + [ + set-environment, + vnet, + private-dns, + cosmos-db-private, + external-api, + dtfs-central-api, + file-storage, + trade-finance-manager-api, + ] environment: name: ${{ needs.set-environment.outputs.environment }} runs-on: [self-hosted, linux, deployment] @@ -1486,7 +1496,15 @@ jobs: trade-finance-manager-api: name: Trade Finance Manager API - needs: [set-environment, vnet, private-dns, cosmos-db-private, external-api, dtfs-central-api] + needs: + [ + set-environment, + vnet, + private-dns, + cosmos-db-private, + external-api, + dtfs-central-api, + ] environment: name: ${{ needs.set-environment.outputs.environment }} runs-on: [self-hosted, linux, deployment] @@ -1823,7 +1841,8 @@ jobs: trade-finance-manager-ui: name: Trade Finance Manager UI - needs: [set-environment, vnet, private-dns, trade-finance-manager-api, redis] + needs: + [set-environment, vnet, private-dns, trade-finance-manager-api, redis] environment: name: ${{ needs.set-environment.outputs.environment }} runs-on: [self-hosted, linux, deployment] diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b631303d7f..76a847e0d6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -84,7 +84,7 @@ on: env: environment: dev - TZ: 'Europe/London' + TZ: ${{ vars.TIMEZONE }} credentials: ${{ secrets.AZURE_DIGITAL_DEV }} MONGODB_URI: ${{ secrets.MONGODB_URI }} MONGO_INITDB_DATABASE: ${{ secrets.MONGO_INITDB_DATABASE }} @@ -610,8 +610,7 @@ jobs: fail-fast: false # Single dimension matrix matrix: - spec: - [ + spec: [ 'case/activities/*.spec.js', 'case/AIN/*.spec.js', 'case/deal-cancellation-disabled/*.spec.js', diff --git a/e2e-tests/portal/cypress.config.js b/e2e-tests/portal/cypress.config.js index 7486fe24f5..d60fbeec21 100644 --- a/e2e-tests/portal/cypress.config.js +++ b/e2e-tests/portal/cypress.config.js @@ -38,7 +38,6 @@ module.exports = defineConfig({ }, env: { CONTACT_US_EMAIL_ADDRESS, - TZ, }, }, experimentalCspAllowList: ['child-src', 'default-src', 'frame-src', 'form-action', 'script-src', 'script-src-elem'], From 789f360e84fdf0991f1eaae64b03ff378c3a26a5 Mon Sep 17 00:00:00 2001 From: Abhi Markan Date: Wed, 16 Oct 2024 20:35:25 +0100 Subject: [PATCH 15/17] fix(DTFS2-6892): timezone support on e2e tests --- e2e-tests/gef/cypress.config.js | 5 ++++- e2e-tests/portal/cypress.config.js | 3 ++- e2e-tests/tfm/cypress.config.js | 5 ++++- e2e-tests/ukef/cypress.config.js | 5 ++++- .../controllers/activities-controller/index.js | 4 ++-- .../controllers/application-details/index.js | 4 ++-- .../src/configs/date-iana-timezones.config.ts | 18 ------------------ libs/common/src/configs/index.ts | 1 - libs/common/src/index.ts | 2 +- libs/common/src/schemas/timezone-iana.ts | 14 ++++++++++++++ 10 files changed, 33 insertions(+), 28 deletions(-) delete mode 100644 libs/common/src/configs/date-iana-timezones.config.ts delete mode 100644 libs/common/src/configs/index.ts create mode 100644 libs/common/src/schemas/timezone-iana.ts diff --git a/e2e-tests/gef/cypress.config.js b/e2e-tests/gef/cypress.config.js index 9899db922c..daacab56fc 100644 --- a/e2e-tests/gef/cypress.config.js +++ b/e2e-tests/gef/cypress.config.js @@ -6,7 +6,7 @@ const { createTasks } = require('../support/tasks'); // Read from root `./.env` directory dotenv.config({ path: path.resolve(__dirname, '../../.env') }); -const { TZ, PORTAL_API_KEY } = process.env; +const { PORTAL_API_KEY, TZ } = process.env; module.exports = defineConfig({ TZ, @@ -37,6 +37,9 @@ module.exports = defineConfig({ setupNodeEvents(on) { on('task', createTasks()); }, + env: { + TZ, + }, }, experimentalCspAllowList: ['child-src', 'default-src', 'frame-src', 'form-action', 'script-src', 'script-src-elem'], }); diff --git a/e2e-tests/portal/cypress.config.js b/e2e-tests/portal/cypress.config.js index d60fbeec21..ae7e6cca6d 100644 --- a/e2e-tests/portal/cypress.config.js +++ b/e2e-tests/portal/cypress.config.js @@ -6,7 +6,7 @@ const { createTasks } = require('../support/tasks'); // Read from root `./.env` directory dotenv.config({ path: path.resolve(__dirname, '../../.env') }); -const { TZ, CONTACT_US_EMAIL_ADDRESS, PORTAL_API_KEY } = process.env; +const { CONTACT_US_EMAIL_ADDRESS, PORTAL_API_KEY, TZ } = process.env; module.exports = defineConfig({ TZ, @@ -37,6 +37,7 @@ module.exports = defineConfig({ on('task', createTasks()); }, env: { + TZ, CONTACT_US_EMAIL_ADDRESS, }, }, diff --git a/e2e-tests/tfm/cypress.config.js b/e2e-tests/tfm/cypress.config.js index cae76903a1..8bf21cd483 100644 --- a/e2e-tests/tfm/cypress.config.js +++ b/e2e-tests/tfm/cypress.config.js @@ -6,7 +6,7 @@ const { createTasks } = require('../support/tasks'); // Read from root `./.env` directory dotenv.config({ path: path.resolve(__dirname, '../../.env') }); -const { TZ, TFM_API_KEY } = process.env; +const { TFM_API_KEY, TZ } = process.env; module.exports = defineConfig({ TZ, @@ -41,6 +41,9 @@ module.exports = defineConfig({ setupNodeEvents(on) { on('task', createTasks()); }, + env: { + TZ, + }, }, experimentalCspAllowList: ['child-src', 'default-src', 'frame-src', 'form-action', 'script-src', 'script-src-elem'], }); diff --git a/e2e-tests/ukef/cypress.config.js b/e2e-tests/ukef/cypress.config.js index 2c06bfdf5c..dca476f63b 100644 --- a/e2e-tests/ukef/cypress.config.js +++ b/e2e-tests/ukef/cypress.config.js @@ -6,7 +6,7 @@ const { createTasks } = require('../support/tasks'); // Read from root `./.env` directory dotenv.config({ path: path.resolve(__dirname, '../../.env') }); -const { TZ, PORTAL_API_KEY, TFM_API_KEY } = process.env; +const { PORTAL_API_KEY, TFM_API_KEY, TZ } = process.env; module.exports = defineConfig({ TZ, @@ -38,6 +38,9 @@ module.exports = defineConfig({ setupNodeEvents(on) { on('task', createTasks()); }, + env: { + TZ, + }, }, experimentalCspAllowList: ['child-src', 'default-src', 'frame-src', 'form-action', 'script-src', 'script-src-elem'], }); diff --git a/gef-ui/server/controllers/activities-controller/index.js b/gef-ui/server/controllers/activities-controller/index.js index edcef5cfad..279ebbb4e5 100644 --- a/gef-ui/server/controllers/activities-controller/index.js +++ b/gef-ui/server/controllers/activities-controller/index.js @@ -1,5 +1,5 @@ const { fromUnixTime } = require('date-fns'); -const { dateIanaTimezoneConfig } = require('@ukef/dtfs2-common'); +const { timeZoneConfig } = require('@ukef/dtfs2-common'); const { getApplication, getUserDetails } = require('../../services/api'); // maps portalActivities array to create array in correct format for mojTimeline @@ -53,7 +53,7 @@ const getPortalActivities = async (req, res) => { createdBy: `${deal.maker.firstname} ${deal.maker.surname}`, companyName: deal.exporter.companyName, dateCreated: deal.createdAt, - timezone: deal.maker.timezone || dateIanaTimezoneConfig.DEFAULT, + timezone: deal.maker.timezone || timeZoneConfig.TZ, submissionDate: deal.submissionDate, manualInclusionNoticeSubmissionDate: deal?.manualInclusionNoticeSubmissionDate, }); diff --git a/gef-ui/server/controllers/application-details/index.js b/gef-ui/server/controllers/application-details/index.js index 373d69131b..f7aa4e31a6 100644 --- a/gef-ui/server/controllers/application-details/index.js +++ b/gef-ui/server/controllers/application-details/index.js @@ -1,5 +1,5 @@ const startCase = require('lodash/startCase'); -const { DEAL_TYPE, dateIanaTimezoneConfig } = require('@ukef/dtfs2-common'); +const { DEAL_TYPE, timeZoneConfig } = require('@ukef/dtfs2-common'); const api = require('../../services/api'); const { canUpdateUnissuedFacilitiesCheck } = require('./canUpdateUnissuedFacilitiesCheck'); const { @@ -35,7 +35,7 @@ function buildHeader(app) { companyName: app.exporter?.companyName, applicationStatus: app.status, dateCreated: app.createdAt, - timezone: app.maker.timezone || dateIanaTimezoneConfig.DEFAULT, + timezone: app.maker.timezone || timeZoneConfig.TZ, createdBy: `${app.maker.firstname} ${app.maker.surname}`, comments: app.comments, applicationType: app.submissionType, diff --git a/libs/common/src/configs/date-iana-timezones.config.ts b/libs/common/src/configs/date-iana-timezones.config.ts deleted file mode 100644 index 3513df3e0a..0000000000 --- a/libs/common/src/configs/date-iana-timezones.config.ts +++ /dev/null @@ -1,18 +0,0 @@ -import dotenv from 'dotenv'; -import { z } from 'zod'; - -dotenv.config(); - -/** - * {@link https://www.iana.org/time-zones} - * There is no default for unset values in this config, as this would allow for inconsistency in microservices. - */ -const defaultIanaTimezoneConfigSchema = z - .object({ - TZ: z.string(), - }) - .transform((validatedEnvVars) => ({ - DEFAULT: validatedEnvVars.TZ, - })); - -export const dateIanaTimezoneConfig = defaultIanaTimezoneConfigSchema.parse(process.env); diff --git a/libs/common/src/configs/index.ts b/libs/common/src/configs/index.ts deleted file mode 100644 index 2abb6348f9..0000000000 --- a/libs/common/src/configs/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './date-iana-timezones.config'; diff --git a/libs/common/src/index.ts b/libs/common/src/index.ts index 591232a17c..e56f8fd95f 100644 --- a/libs/common/src/index.ts +++ b/libs/common/src/index.ts @@ -8,4 +8,4 @@ export * from './middleware'; export * from './utils'; export * from './constants'; export * from './errors'; -export * from './configs'; +export * from './schemas/timezone-iana'; diff --git a/libs/common/src/schemas/timezone-iana.ts b/libs/common/src/schemas/timezone-iana.ts new file mode 100644 index 0000000000..a13238389d --- /dev/null +++ b/libs/common/src/schemas/timezone-iana.ts @@ -0,0 +1,14 @@ +import { z } from 'zod'; +import dotenv from 'dotenv'; + +dotenv.config(); + +/** + * {@link https://www.iana.org/time-zones} + * There is no default for unset values in this config, as this would allow for inconsistency in microservices. + */ +const defaultTimeZoneSchema = z.object({ + TZ: z.string(), +}); + +export const timeZoneConfig = defaultTimeZoneSchema.parse(process.env); From 4860d4e6e0d3f2f155d52628c7b3f02126fb472e Mon Sep 17 00:00:00 2001 From: Abhi Markan Date: Thu, 17 Oct 2024 06:59:05 +0100 Subject: [PATCH 16/17] fix(DTFS2-6892): added default value to timezone env variable --- e2e-tests/gef/cypress.config.js | 7 +++---- e2e-tests/portal/cypress.config.js | 9 ++++----- e2e-tests/tfm/cypress.config.js | 7 +++---- e2e-tests/ukef/cypress.config.js | 7 +++---- libs/common/src/schemas/timezone-iana.ts | 10 ++++++++-- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/e2e-tests/gef/cypress.config.js b/e2e-tests/gef/cypress.config.js index daacab56fc..1aa747fc7b 100644 --- a/e2e-tests/gef/cypress.config.js +++ b/e2e-tests/gef/cypress.config.js @@ -9,7 +9,9 @@ dotenv.config({ path: path.resolve(__dirname, '../../.env') }); const { PORTAL_API_KEY, TZ } = process.env; module.exports = defineConfig({ - TZ, + env: { + TZ, + }, dealApiProtocol: 'http://', dealApiHost: 'localhost', dealApiPort: '5001', @@ -37,9 +39,6 @@ module.exports = defineConfig({ setupNodeEvents(on) { on('task', createTasks()); }, - env: { - TZ, - }, }, experimentalCspAllowList: ['child-src', 'default-src', 'frame-src', 'form-action', 'script-src', 'script-src-elem'], }); diff --git a/e2e-tests/portal/cypress.config.js b/e2e-tests/portal/cypress.config.js index ae7e6cca6d..2e0f02e431 100644 --- a/e2e-tests/portal/cypress.config.js +++ b/e2e-tests/portal/cypress.config.js @@ -9,7 +9,10 @@ dotenv.config({ path: path.resolve(__dirname, '../../.env') }); const { CONTACT_US_EMAIL_ADDRESS, PORTAL_API_KEY, TZ } = process.env; module.exports = defineConfig({ - TZ, + env: { + TZ, + CONTACT_US_EMAIL_ADDRESS, + }, apiProtocol: 'http://', apiHost: 'localhost', apiPort: '5001', @@ -36,10 +39,6 @@ module.exports = defineConfig({ setupNodeEvents(on) { on('task', createTasks()); }, - env: { - TZ, - CONTACT_US_EMAIL_ADDRESS, - }, }, experimentalCspAllowList: ['child-src', 'default-src', 'frame-src', 'form-action', 'script-src', 'script-src-elem'], }); diff --git a/e2e-tests/tfm/cypress.config.js b/e2e-tests/tfm/cypress.config.js index 8bf21cd483..3c222b95e9 100644 --- a/e2e-tests/tfm/cypress.config.js +++ b/e2e-tests/tfm/cypress.config.js @@ -9,7 +9,9 @@ dotenv.config({ path: path.resolve(__dirname, '../../.env') }); const { TFM_API_KEY, TZ } = process.env; module.exports = defineConfig({ - TZ, + env: { + TZ, + }, dealApiProtocol: 'http://', dealApiHost: 'localhost', dealApiPort: '5001', @@ -41,9 +43,6 @@ module.exports = defineConfig({ setupNodeEvents(on) { on('task', createTasks()); }, - env: { - TZ, - }, }, experimentalCspAllowList: ['child-src', 'default-src', 'frame-src', 'form-action', 'script-src', 'script-src-elem'], }); diff --git a/e2e-tests/ukef/cypress.config.js b/e2e-tests/ukef/cypress.config.js index dca476f63b..c2074679be 100644 --- a/e2e-tests/ukef/cypress.config.js +++ b/e2e-tests/ukef/cypress.config.js @@ -9,7 +9,9 @@ dotenv.config({ path: path.resolve(__dirname, '../../.env') }); const { PORTAL_API_KEY, TFM_API_KEY, TZ } = process.env; module.exports = defineConfig({ - TZ, + env: { + TZ, + }, centralApiProtocol: 'http://', centralApiHost: 'localhost', centralApiPort: '5005', @@ -38,9 +40,6 @@ module.exports = defineConfig({ setupNodeEvents(on) { on('task', createTasks()); }, - env: { - TZ, - }, }, experimentalCspAllowList: ['child-src', 'default-src', 'frame-src', 'form-action', 'script-src', 'script-src-elem'], }); diff --git a/libs/common/src/schemas/timezone-iana.ts b/libs/common/src/schemas/timezone-iana.ts index a13238389d..2367fc4d30 100644 --- a/libs/common/src/schemas/timezone-iana.ts +++ b/libs/common/src/schemas/timezone-iana.ts @@ -3,12 +3,18 @@ import dotenv from 'dotenv'; dotenv.config(); +const { TZ } = process.env; + /** * {@link https://www.iana.org/time-zones} * There is no default for unset values in this config, as this would allow for inconsistency in microservices. */ const defaultTimeZoneSchema = z.object({ - TZ: z.string(), + TZ: z.string().default('Europe/London'), }); -export const timeZoneConfig = defaultTimeZoneSchema.parse(process.env); +const data = { + TZ, +}; + +export const timeZoneConfig = defaultTimeZoneSchema.parse(data); From 81316cba246c9a50b345d3ca275b7d90f2fc2761 Mon Sep 17 00:00:00 2001 From: Alex Bramhill Date: Thu, 17 Oct 2024 10:43:47 +0100 Subject: [PATCH 17/17] feat(dtfs2-6892): fix issue with timezone config --- libs/common/src/index.ts | 2 +- .../schemas/{timezone-iana.ts => timezone.ts} | 14 +++++++--- .../admin/user-edit.component-test.js | 4 +-- .../bond-submission-details.component-test.js | 4 +-- .../bond-transactions-table.component-test.js | 6 ++--- .../contract-overview-table.component-test.js | 16 +++++------- .../loan-transactions-table.component-test.js | 6 ++--- ...tract-submission-details.component-test.js | 6 ++--- .../contract/contract-view.component-test.js | 8 +++--- .../loan-submission-details.component-test.js | 4 +-- .../filter-localiseTimestamp.test.ts | 26 +++++++++---------- 11 files changed, 50 insertions(+), 46 deletions(-) rename libs/common/src/schemas/{timezone-iana.ts => timezone.ts} (53%) diff --git a/libs/common/src/index.ts b/libs/common/src/index.ts index e56f8fd95f..ef5d520c2b 100644 --- a/libs/common/src/index.ts +++ b/libs/common/src/index.ts @@ -8,4 +8,4 @@ export * from './middleware'; export * from './utils'; export * from './constants'; export * from './errors'; -export * from './schemas/timezone-iana'; +export * from './schemas/timezone'; diff --git a/libs/common/src/schemas/timezone-iana.ts b/libs/common/src/schemas/timezone.ts similarity index 53% rename from libs/common/src/schemas/timezone-iana.ts rename to libs/common/src/schemas/timezone.ts index 2367fc4d30..dc69440c0c 100644 --- a/libs/common/src/schemas/timezone-iana.ts +++ b/libs/common/src/schemas/timezone.ts @@ -9,12 +9,18 @@ const { TZ } = process.env; * {@link https://www.iana.org/time-zones} * There is no default for unset values in this config, as this would allow for inconsistency in microservices. */ -const defaultTimeZoneSchema = z.object({ - TZ: z.string().default('Europe/London'), -}); +const timezoneConfigSchema = z + .object({ + TZ: z.string().default('Europe/London'), + }) + .transform((parsedEnvVars) => { + return { + DEFAULT: parsedEnvVars.TZ, + }; + }); const data = { TZ, }; -export const timeZoneConfig = defaultTimeZoneSchema.parse(data); +export const timezoneConfig = timezoneConfigSchema.parse(data); diff --git a/portal/component-tests/admin/user-edit.component-test.js b/portal/component-tests/admin/user-edit.component-test.js index a7987317ba..68e5ce9699 100644 --- a/portal/component-tests/admin/user-edit.component-test.js +++ b/portal/component-tests/admin/user-edit.component-test.js @@ -1,4 +1,4 @@ -const { dateIanaTimezoneConfig } = require('@ukef/dtfs2-common'); +const { timezoneConfig } = require('@ukef/dtfs2-common'); const pageRenderer = require('../pageRenderer'); const page = 'admin/user-edit.njk'; @@ -6,7 +6,7 @@ const render = pageRenderer(page); describe(page, () => { const adminUser = { - timezone: dateIanaTimezoneConfig.DEFAULT, + timezone: timezoneConfig.DEFAULT, roles: ['admin'], }; const newUser = { roles: [] }; diff --git a/portal/component-tests/bond/_macros/bond-submission-details.component-test.js b/portal/component-tests/bond/_macros/bond-submission-details.component-test.js index e2144dbd7a..56fa5a4f23 100644 --- a/portal/component-tests/bond/_macros/bond-submission-details.component-test.js +++ b/portal/component-tests/bond/_macros/bond-submission-details.component-test.js @@ -1,6 +1,6 @@ const { ROLES: { MAKER }, - dateIanaTimezoneConfig, + timezoneConfig, } = require('@ukef/dtfs2-common'); const componentRenderer = require('../../componentRenderer'); const deal = require('../../fixtures/deal-fully-completed'); @@ -12,7 +12,7 @@ describe(component, () => { let wrapper; const user = { roles: [MAKER], - timezone: dateIanaTimezoneConfig.DEFAULT, + timezone: timezoneConfig.DEFAULT, }; const bond = deal.bondTransactions.items[0]; diff --git a/portal/component-tests/contract/components/bond-transactions-table.component-test.js b/portal/component-tests/contract/components/bond-transactions-table.component-test.js index fcb220abeb..8d48c4e2ae 100644 --- a/portal/component-tests/contract/components/bond-transactions-table.component-test.js +++ b/portal/component-tests/contract/components/bond-transactions-table.component-test.js @@ -1,4 +1,4 @@ -const { ROLES, dateIanaTimezoneConfig } = require('@ukef/dtfs2-common'); +const { ROLES, timezoneConfig } = require('@ukef/dtfs2-common'); const { DEAL, FACILITY } = require('../../../server/constants/status'); const { getNowAsEpoch } = require('../../../server/helpers'); @@ -97,7 +97,7 @@ describe(component, () => { }); describe('when user is checker', () => { - const user = { roles: [CHECKER], timezone: dateIanaTimezoneConfig.DEFAULT }; + const user = { roles: [CHECKER], timezone: timezoneConfig.DEFAULT }; commonTests(user); @@ -138,7 +138,7 @@ describe(component, () => { }); describe.each(NON_MAKER_OR_CHECKER_ROLES)('when user is %s', (nonMakerOrCheckerRole) => { - const user = { roles: [nonMakerOrCheckerRole], timezone: dateIanaTimezoneConfig.DEFAULT }; + const user = { roles: [nonMakerOrCheckerRole], timezone: timezoneConfig.DEFAULT }; commonTests(user); diff --git a/portal/component-tests/contract/components/contract-overview-table.component-test.js b/portal/component-tests/contract/components/contract-overview-table.component-test.js index 971a716495..e4412224f4 100644 --- a/portal/component-tests/contract/components/contract-overview-table.component-test.js +++ b/portal/component-tests/contract/components/contract-overview-table.component-test.js @@ -1,5 +1,5 @@ const { formatInTimeZone } = require('date-fns-tz'); -const { dateIanaTimezoneConfig } = require('@ukef/dtfs2-common'); +const { timezoneConfig } = require('@ukef/dtfs2-common'); const { DATE: { FULL_DATE, FULL_DATE_AND_TIME }, } = require('../../../server/constants'); @@ -43,7 +43,7 @@ describe(component, () => { let wrapper; beforeAll(() => { - const user = { timezone: dateIanaTimezoneConfig.DEFAULT }; + const user = { timezone: timezoneConfig.DEFAULT }; wrapper = render({ deal, user }); }); @@ -61,17 +61,15 @@ describe(component, () => { wrapper.expectText('[data-cy="checker"]').toRead(`${deal.details.checker.firstname} ${deal.details.checker.surname}`)); it('displays deal.details.submissionDate', () => - wrapper - .expectText('[data-cy="submissionDate"]') - .toRead(formatInTimeZone(new Date(deal.details.submissionDate), dateIanaTimezoneConfig.DEFAULT, FULL_DATE))); + wrapper.expectText('[data-cy="submissionDate"]').toRead(formatInTimeZone(new Date(deal.details.submissionDate), timezoneConfig.DEFAULT, FULL_DATE))); it('displays deal.updatedAt', () => - wrapper.expectText('[data-cy="updatedAt"]').toRead(formatInTimeZone(new Date(deal.updatedAt), dateIanaTimezoneConfig.DEFAULT, FULL_DATE_AND_TIME))); + wrapper.expectText('[data-cy="updatedAt"]').toRead(formatInTimeZone(new Date(deal.updatedAt), timezoneConfig.DEFAULT, FULL_DATE_AND_TIME))); }); describe('when deal has manualInclusionApplicationSubmissionDate', () => { let wrapper; - const user = { timezone: dateIanaTimezoneConfig.DEFAULT }; + const user = { timezone: timezoneConfig.DEFAULT }; beforeAll(() => { wrapper = render({ deal: dealWithManualInclusionApplicationSubmissionDate, user }); @@ -82,7 +80,7 @@ describe(component, () => { it('displays deal.details.manualInclusionApplicationSubmissionDate', () => wrapper .expectText('[data-cy="submissionDate"]') - .toRead(formatInTimeZone(new Date(manualInclusionApplicationSubmissionDate), dateIanaTimezoneConfig.DEFAULT, FULL_DATE))); + .toRead(formatInTimeZone(new Date(manualInclusionApplicationSubmissionDate), timezoneConfig.DEFAULT, FULL_DATE))); }); describe('renders - for any blank fields', () => { @@ -102,7 +100,7 @@ describe(component, () => { }; beforeAll(() => { - const user = { timezone: dateIanaTimezoneConfig.DEFAULT }; + const user = { timezone: timezoneConfig.DEFAULT }; wrapper = render({ mockDeal, user }); }); diff --git a/portal/component-tests/contract/components/loan-transactions-table.component-test.js b/portal/component-tests/contract/components/loan-transactions-table.component-test.js index aa34953eb7..7e9632b89b 100644 --- a/portal/component-tests/contract/components/loan-transactions-table.component-test.js +++ b/portal/component-tests/contract/components/loan-transactions-table.component-test.js @@ -1,4 +1,4 @@ -const { ROLES, dateIanaTimezoneConfig } = require('@ukef/dtfs2-common'); +const { ROLES, timezoneConfig } = require('@ukef/dtfs2-common'); const { UNCONDITIONAL } = require('../../../server/constants/facility-stage'); const { getNowAsEpoch } = require('../../../server/helpers'); const { NON_MAKER_ROLES } = require('../../../test-helpers/common-role-lists'); @@ -55,7 +55,7 @@ describe(component, () => { dealWithLoansThatCanChangeCoverDate.loanTransactions.items[1].issueFacilityDetailsSubmitted = true; describe('as a maker', () => { - const user = { roles: [MAKER], timezone: dateIanaTimezoneConfig.DEFAULT }; + const user = { roles: [MAKER], timezone: timezoneConfig.DEFAULT }; commonTests(user); @@ -131,7 +131,7 @@ describe(component, () => { }); describe.each(NON_MAKER_ROLES)('when viewed with the role %s', (nonMakerRole) => { - const user = { roles: [nonMakerRole], timezone: dateIanaTimezoneConfig.DEFAULT }; + const user = { roles: [nonMakerRole], timezone: timezoneConfig.DEFAULT }; commonTests(user); diff --git a/portal/component-tests/contract/contract-submission-details.component-test.js b/portal/component-tests/contract/contract-submission-details.component-test.js index 05cc62a18e..0a8633278e 100644 --- a/portal/component-tests/contract/contract-submission-details.component-test.js +++ b/portal/component-tests/contract/contract-submission-details.component-test.js @@ -1,6 +1,6 @@ const { ROLES: { MAKER }, - dateIanaTimezoneConfig, + timezoneConfig, } = require('@ukef/dtfs2-common'); const pageRenderer = require('../pageRenderer'); @@ -21,7 +21,7 @@ describe(page, () => { wrapper = render({ deal, user: { - timezone: dateIanaTimezoneConfig.DEFAULT, + timezone: timezoneConfig.DEFAULT, roles: [MAKER], }, editable: true, @@ -84,7 +84,7 @@ describe(page, () => { mandatoryCriteria: [], }, user: { - timezone: dateIanaTimezoneConfig.DEFAULT, + timezone: timezoneConfig.DEFAULT, roles: [MAKER], }, editable: true, diff --git a/portal/component-tests/contract/contract-view.component-test.js b/portal/component-tests/contract/contract-view.component-test.js index 9e59c42fa1..eed489453f 100644 --- a/portal/component-tests/contract/contract-view.component-test.js +++ b/portal/component-tests/contract/contract-view.component-test.js @@ -1,4 +1,4 @@ -const { ROLES, dateIanaTimezoneConfig } = require('@ukef/dtfs2-common'); +const { ROLES, timezoneConfig } = require('@ukef/dtfs2-common'); const { STATUS } = require('../../server/constants'); const pageRenderer = require('../pageRenderer'); @@ -36,7 +36,7 @@ const confirmedRequestStartDateParams = { describe(page, () => { describe("when viewed as a 'maker'", () => { - const user = { roles: [MAKER], timezone: dateIanaTimezoneConfig.DEFAULT }; + const user = { roles: [MAKER], timezone: timezoneConfig.DEFAULT }; commonTests(user); @@ -69,7 +69,7 @@ describe(page, () => { }); describe("when viewed as a 'checker'", () => { - const user = { roles: [CHECKER], timezone: dateIanaTimezoneConfig.DEFAULT }; + const user = { roles: [CHECKER], timezone: timezoneConfig.DEFAULT }; commonTests(user); @@ -100,7 +100,7 @@ describe(page, () => { }); describe.each(NON_MAKER_ROLES)("when viewed as a '%s'", (nonMakerRole) => { - const user = { roles: [nonMakerRole], timezone: dateIanaTimezoneConfig.DEFAULT }; + const user = { roles: [nonMakerRole], timezone: timezoneConfig.DEFAULT }; commonTests(user); diff --git a/portal/component-tests/loan/_macros/loan-submission-details.component-test.js b/portal/component-tests/loan/_macros/loan-submission-details.component-test.js index 88359c07e0..af10277a0a 100644 --- a/portal/component-tests/loan/_macros/loan-submission-details.component-test.js +++ b/portal/component-tests/loan/_macros/loan-submission-details.component-test.js @@ -1,6 +1,6 @@ const { ROLES: { MAKER }, - dateIanaTimezoneConfig, + timezoneConfig, } = require('@ukef/dtfs2-common'); const componentRenderer = require('../../componentRenderer'); const deal = require('../../fixtures/deal-fully-completed'); @@ -12,7 +12,7 @@ describe(component, () => { let wrapper; const user = { roles: [MAKER], - timezone: dateIanaTimezoneConfig.DEFAULT, + timezone: timezoneConfig.DEFAULT, }; const loan = deal.loanTransactions.items[0]; diff --git a/portal/server/nunjucks-configuration/filter-localiseTimestamp.test.ts b/portal/server/nunjucks-configuration/filter-localiseTimestamp.test.ts index 1492ce755f..f6974001b8 100644 --- a/portal/server/nunjucks-configuration/filter-localiseTimestamp.test.ts +++ b/portal/server/nunjucks-configuration/filter-localiseTimestamp.test.ts @@ -1,4 +1,4 @@ -import { dateIanaTimezoneConfig } from '@ukef/dtfs2-common'; +import { timezoneConfig } from '@ukef/dtfs2-common'; import { filterLocaliseTimestamp } from './filter-localiseTimestamp'; describe('nunjuck filters - dashIfEmpty', () => { @@ -9,21 +9,21 @@ describe('nunjuck filters - dashIfEmpty', () => { const mockValue = mockDate.valueOf(); it('should return the day of the month if given format `dd` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'dd', dateIanaTimezoneConfig.DEFAULT); + const result = filterLocaliseTimestamp(mockValue, 'dd', timezoneConfig.DEFAULT); const expected = '07'; expect(result).toEqual(expected); }); it('should return the month if given the format `MM` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'MM', dateIanaTimezoneConfig.DEFAULT); + const result = filterLocaliseTimestamp(mockValue, 'MM', timezoneConfig.DEFAULT); const expected = '02'; expect(result).toEqual(expected); }); it('should return the year if given the format `yyyy` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'yyyy', dateIanaTimezoneConfig.DEFAULT); + const result = filterLocaliseTimestamp(mockValue, 'yyyy', timezoneConfig.DEFAULT); const expected = '2024'; expect(result).toEqual(expected); @@ -44,21 +44,21 @@ describe('nunjuck filters - dashIfEmpty', () => { const mockValue = mockDate.valueOf().toString(); it('should return the day of the month if given format `dd` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'dd', dateIanaTimezoneConfig.DEFAULT); + const result = filterLocaliseTimestamp(mockValue, 'dd', timezoneConfig.DEFAULT); const expected = '07'; expect(result).toEqual(expected); }); it('should return the month if given the format `MM` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'MM', dateIanaTimezoneConfig.DEFAULT); + const result = filterLocaliseTimestamp(mockValue, 'MM', timezoneConfig.DEFAULT); const expected = '02'; expect(result).toEqual(expected); }); it('should return the year if given the format `yyyy` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'yyyy', dateIanaTimezoneConfig.DEFAULT); + const result = filterLocaliseTimestamp(mockValue, 'yyyy', timezoneConfig.DEFAULT); const expected = '2024'; expect(result).toEqual(expected); @@ -76,21 +76,21 @@ describe('nunjuck filters - dashIfEmpty', () => { const mockValue = ''; it('should return an empty string if given format `dd` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'dd', dateIanaTimezoneConfig.DEFAULT); + const result = filterLocaliseTimestamp(mockValue, 'dd', timezoneConfig.DEFAULT); const expected = ''; expect(result).toEqual(expected); }); it('should return an empty string if given the format `MM` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'MM', dateIanaTimezoneConfig.DEFAULT); + const result = filterLocaliseTimestamp(mockValue, 'MM', timezoneConfig.DEFAULT); const expected = ''; expect(result).toEqual(expected); }); it('should return an empty string if given the format `yyyy` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'yyyy', dateIanaTimezoneConfig.DEFAULT); + const result = filterLocaliseTimestamp(mockValue, 'yyyy', timezoneConfig.DEFAULT); const expected = ''; expect(result).toEqual(expected); @@ -108,21 +108,21 @@ describe('nunjuck filters - dashIfEmpty', () => { const mockValue = 'test'; it('should return `Invalid date` if given format `dd` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'dd', dateIanaTimezoneConfig.DEFAULT); + const result = filterLocaliseTimestamp(mockValue, 'dd', timezoneConfig.DEFAULT); const expected = 'Invalid date'; expect(result).toEqual(expected); }); it('should return `Invalid date` if given the format `MM` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'MM', dateIanaTimezoneConfig.DEFAULT); + const result = filterLocaliseTimestamp(mockValue, 'MM', timezoneConfig.DEFAULT); const expected = 'Invalid date'; expect(result).toEqual(expected); }); it('should return `Invalid date` if given the format `yyyy` and timezone `Europe/London`', () => { - const result = filterLocaliseTimestamp(mockValue, 'yyyy', dateIanaTimezoneConfig.DEFAULT); + const result = filterLocaliseTimestamp(mockValue, 'yyyy', timezoneConfig.DEFAULT); const expected = 'Invalid date'; expect(result).toEqual(expected);