From 02e015966c0d2e199a296c159cb47ad1b73a0008 Mon Sep 17 00:00:00 2001 From: Artem Niehrieiev Date: Fri, 12 Sep 2025 13:10:44 +0000 Subject: [PATCH] fix: update timestamp and date handling in DataAccessObjectOracle and createTestOracleTable --- .../saas-tests/table-oracledb-e2e.test.ts | 86 +++++++++++++++++++ backend/test/utils/create-test-table.ts | 3 +- .../data-access-object-oracle.ts | 14 ++- 3 files changed, 98 insertions(+), 5 deletions(-) diff --git a/backend/test/ava-tests/saas-tests/table-oracledb-e2e.test.ts b/backend/test/ava-tests/saas-tests/table-oracledb-e2e.test.ts index 6ff28fdf2..73892d408 100644 --- a/backend/test/ava-tests/saas-tests/table-oracledb-e2e.test.ts +++ b/backend/test/ava-tests/saas-tests/table-oracledb-e2e.test.ts @@ -2174,6 +2174,92 @@ test.serial(`${currentTest} should add row in table and return result`, async (t t.is(getLogsRO.logs[addRowLogIndex].affected_primary_key.id, 43); }); +test.serial(`${currentTest} should add row in table with date column and return result`, async (t) => { + const connectionToTestDB = getTestData(mockFactory).connectionToOracleDB; + const firstUserToken = (await registerUserAndReturnUserInfo(app)).token; + const { testTableName, testTableColumnName, testEntitiesSeedsCount, testTableSecondColumnName } = + await createTestOracleTable(connectionToTestDB); + + testTables.push(testTableName); + + const createConnectionResponse = await request(app.getHttpServer()) + .post('/connection') + .send(connectionToTestDB) + .set('Cookie', firstUserToken) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + const createConnectionRO = JSON.parse(createConnectionResponse.text); + t.is(createConnectionResponse.status, 201); + + const fakeName = faker.person.firstName(); + const fakeMail = faker.internet.email(); + + const row = { + id: 44, + [testTableColumnName]: fakeName, + [testTableSecondColumnName]: fakeMail, + updated_at: null, + }; + + const addRowInTableResponse = await request(app.getHttpServer()) + .post(`/table/row/${createConnectionRO.id}?tableName=${testTableName}`) + .send(JSON.stringify(row)) + .set('Cookie', firstUserToken) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + const addRowInTableRO = JSON.parse(addRowInTableResponse.text); + t.is(addRowInTableResponse.status, 201); + + t.is(addRowInTableRO.hasOwnProperty('row'), true); + t.is(addRowInTableRO.hasOwnProperty('structure'), true); + t.is(addRowInTableRO.hasOwnProperty('foreignKeys'), true); + t.is(addRowInTableRO.hasOwnProperty('primaryColumns'), true); + t.is(addRowInTableRO.hasOwnProperty('readonly_fields'), true); + t.is(addRowInTableRO.row[testTableColumnName], row[testTableColumnName]); + t.is(addRowInTableRO.row[testTableSecondColumnName], row[testTableSecondColumnName]); + + //checking that the line was added + const getTableRowsResponse = await request(app.getHttpServer()) + .get(`/table/rows/${createConnectionRO.id}?tableName=${testTableName}&page=1&perPage=50`) + .set('Cookie', firstUserToken) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + t.is(getTableRowsResponse.status, 200); + + const getTableRowsRO = JSON.parse(getTableRowsResponse.text); + + t.is(getTableRowsRO.hasOwnProperty('rows'), true); + t.is(getTableRowsRO.hasOwnProperty('primaryColumns'), true); + t.is(getTableRowsRO.hasOwnProperty('pagination'), true); + + const { rows, primaryColumns, pagination } = getTableRowsRO; + + t.is(rows.length, 43); + t.is(rows[42][testTableColumnName], row[testTableColumnName]); + t.is(rows[42][testTableSecondColumnName], row[testTableSecondColumnName]); + t.is(rows[42].id, rows[41].id + 2); + + // check that rows adding was logged + + const getLogsResponse = await request(app.getHttpServer()) + .get(`/logs/${createConnectionRO.id}?page=1&perPage=50`) + .set('Cookie', firstUserToken) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + t.is(getLogsResponse.status, 200); + const getLogsRO = JSON.parse(getLogsResponse.text); + t.is(getLogsRO.hasOwnProperty('logs'), true); + t.is(getLogsRO.hasOwnProperty('pagination'), true); + t.is(getLogsRO.logs.length > 0, true); + const addRowLogIndex = getLogsRO.logs.findIndex((log) => log.operationType === 'addRow'); + t.is(getLogsRO.logs[addRowLogIndex].hasOwnProperty('affected_primary_key'), true); + t.is(typeof getLogsRO.logs[addRowLogIndex].affected_primary_key, 'object'); + t.is(getLogsRO.logs[addRowLogIndex].affected_primary_key.hasOwnProperty('id'), true); + t.is(getLogsRO.logs[addRowLogIndex].affected_primary_key.id, 44); +}); + test.serial(`${currentTest} should throw an exception when connection id is not passed in request`, async (t) => { const connectionToTestDB = getTestData(mockFactory).connectionToOracleDB; const firstUserToken = (await registerUserAndReturnUserInfo(app)).token; diff --git a/backend/test/utils/create-test-table.ts b/backend/test/utils/create-test-table.ts index 9fa14a9a7..f3d84d933 100644 --- a/backend/test/utils/create-test-table.ts +++ b/backend/test/utils/create-test-table.ts @@ -379,7 +379,8 @@ export async function createTestOracleTable( table.integer(pColumnName); table.string(testTableColumnName); table.string(testTableSecondColumnName); - table.timestamps(); + table.timestamp('created_at'); + table.date('updated_at'); }); await Knex.schema.alterTable(testTableName, function (t) { t.primary([pColumnName], primaryKeyConstraintName); diff --git a/shared-code/src/data-access-layer/data-access-objects/data-access-object-oracle.ts b/shared-code/src/data-access-layer/data-access-objects/data-access-object-oracle.ts index 196f87486..c1cd97b9a 100644 --- a/shared-code/src/data-access-layer/data-access-objects/data-access-object-oracle.ts +++ b/shared-code/src/data-access-layer/data-access-objects/data-access-object-oracle.ts @@ -69,10 +69,16 @@ export class DataAccessObjectOracle extends BasicDataAccessObject implements IDa const keys = Object.keys(row); const values = keys.map((key) => { - if (timestampColumnNames.includes(key) && row[key]) { + if (timestampColumnNames.includes(key)) { + if (!row[key]) { + return row[key]; + } return this.formatTimestamp(row[key] as string); } - if (dateColumnNames.includes(key) && row[key]) { + if (dateColumnNames.includes(key)) { + if (!row[key]) { + return row[key]; + } return this.formatDate(new Date(row[key] as string)); } return `${row[key]}`; @@ -353,11 +359,11 @@ export class DataAccessObjectOracle extends BasicDataAccessObject implements IDa if (filteringFields && filteringFields.length > 0) { // eslint-disable-next-line prefer-const for (let { field, criteria, value } of filteringFields) { - if (datesColumnsNames.includes(field)) { + if (datesColumnsNames.includes(field) && value) { const valueToDate = new Date(String(value)); value = this.formatDate(valueToDate); } - if (timestampColumnNames.includes(field)) { + if (timestampColumnNames.includes(field) && value) { value = this.formatTimestamp(String(value)); } const operators = {