Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions backend/test/ava-tests/saas-tests/table-dynamodb-e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1526,6 +1526,96 @@ should return all found rows with search, pagination: page=1, perPage=2 and DESC
},
);

test.serial(`${currentTest} with search, with pagination, with sorting and with filtering by id
should return all found rows with search, pagination: page=1, perPage=2 and DESC sorting and with multi filtering`, async (t) => {
try {
const connectionToTestDB = getTestData(mockFactory).dynamoDBConnection;
const firstUserToken = (await registerUserAndReturnUserInfo(app)).token;
const { testTableName, testTableColumnName, insertedSearchedIds } = await createTestTable(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 createTableSettingsDTO = mockFactory.generateTableSettings(
createConnectionRO.id,
testTableName,
[],
undefined,
undefined,
3,
QueryOrderingEnum.DESC,
'id',
undefined,
undefined,
undefined,
undefined,
undefined,
);

const createTableSettingsResponse = await request(app.getHttpServer())
.post(`/settings?connectionId=${createConnectionRO.id}&tableName=${testTableName}`)
.send(createTableSettingsDTO)
.set('Cookie', firstUserToken)
.set('Content-Type', 'application/json')
.set('Accept', 'application/json');
t.is(createTableSettingsResponse.status, 201);

const fieldname = 'age';
const idFieldName = 'id';
const idFieldValue = 21;
const fieldGtvalue = 14;
// const fieldLtvalue = 95;

const filters = {
// [fieldname]: { gt: fieldGtvalue },
[idFieldName]: { eq: idFieldValue },
};

const getTableRowsResponse = await request(app.getHttpServer())
.post(
`/table/rows/find/${createConnectionRO.id}?tableName=${testTableName}&page=1&perPage=3`,
)
.send({ filters })
.set('Cookie', firstUserToken)
.set('Content-Type', 'application/json')
.set('Accept', 'application/json');
t.is(getTableRowsResponse.status, 201);

const getTableRowsRO = JSON.parse(getTableRowsResponse.text);
console.log('🚀 ~ getTableRowsRO:', getTableRowsRO.rows);

t.is(typeof getTableRowsRO, 'object');
t.is(getTableRowsRO.hasOwnProperty('rows'), true);
t.is(getTableRowsRO.hasOwnProperty('primaryColumns'), true);
t.is(getTableRowsRO.hasOwnProperty('pagination'), true);
t.is(getTableRowsRO.rows.length, 1);
t.is(Object.keys(getTableRowsRO.rows[0]).length, 11);

const findRowId = 21;

t.is(getTableRowsRO.rows[0].id, findRowId);
t.is(getTableRowsRO.rows[0][testTableColumnName], testSearchedUserName);

t.is(getTableRowsRO.pagination.currentPage, 1);
t.is(getTableRowsRO.pagination.perPage, 3);

t.is(typeof getTableRowsRO.primaryColumns, 'object');
t.is(getTableRowsRO.primaryColumns[0].hasOwnProperty('column_name'), true);
t.is(getTableRowsRO.primaryColumns[0].hasOwnProperty('data_type'), true);
} catch (e) {
console.error(e);
throw e;
}
});

test.serial(`${currentTest} should throw an exception when connection id is not passed in request`, async (t) => {
try {
const connectionToTestDB = getTestData(mockFactory).dynamoDBConnection;
Expand Down
10 changes: 9 additions & 1 deletion backend/test/utils/create-test-table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ export async function createTestDynamoDBTable(
} catch (error) {
console.error(`Error creating dynamodb table: ${error.message}`);
}

const insertedSearchedIds: Array<{ number: number; id: string }> = [];
const documentClient = DynamoDBDocumentClient.from(dynamoDb);
try {
for (let i = 0; i < testEntitiesSeedsCount; i++) {
Expand All @@ -552,6 +552,13 @@ export async function createTestDynamoDBTable(
binary_set_column: { BS: [Buffer.from('value1'), Buffer.from('value2')] },
};

if (isSearchedUser) {
insertedSearchedIds.push({
number: i,
id: String(item.id.N),
});
}

const params: PutItemCommandInput = {
TableName: testTableName,
Item: item as any,
Expand All @@ -568,6 +575,7 @@ export async function createTestDynamoDBTable(
testTableColumnName: testTableColumnName,
testTableSecondColumnName: testTableSecondColumnName,
testEntitiesSeedsCount: testEntitiesSeedsCount,
insertedSearchedIds,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,30 +305,33 @@ export class DataAccessObjectDynamoDB extends BasicDataAccessObject implements I
const { field, criteria, value } = filter;
expressionAttributeNames[`#${field}`] = field;
const uniquePlaceholder = `:${field}${index}`;
const fieldInfo = tableStructure.find((el) => el.column_name === field);
const isNumberField = fieldInfo?.data_type === 'number';

switch (criteria) {
case FilterCriteriaEnum.eq:
filterExpression += ` AND #${field} = ${uniquePlaceholder}`;
expressionAttributeValues[uniquePlaceholder] = { S: value };
expressionAttributeValues[uniquePlaceholder] = isNumberField ? { N: String(value) } : { S: value };
break;
case FilterCriteriaEnum.contains:
filterExpression += ` AND contains(#${field}, ${uniquePlaceholder})`;
expressionAttributeValues[uniquePlaceholder] = { S: value };
break;
case FilterCriteriaEnum.gt:
filterExpression += ` AND #${field} > ${uniquePlaceholder}`;
expressionAttributeValues[uniquePlaceholder] = { N: value };
expressionAttributeValues[uniquePlaceholder] = isNumberField ? { N: String(value) } : { S: value };
break;
case FilterCriteriaEnum.lt:
filterExpression += ` AND #${field} < ${uniquePlaceholder}`;
expressionAttributeValues[uniquePlaceholder] = { N: value };
expressionAttributeValues[uniquePlaceholder] = isNumberField ? { N: String(value) } : { S: value };
break;
case FilterCriteriaEnum.gte:
filterExpression += ` AND #${field} >= ${uniquePlaceholder}`;
expressionAttributeValues[uniquePlaceholder] = { N: value };
expressionAttributeValues[uniquePlaceholder] = isNumberField ? { N: String(value) } : { S: value };
break;
case FilterCriteriaEnum.lte:
filterExpression += ` AND #${field} <= ${uniquePlaceholder}`;
expressionAttributeValues[uniquePlaceholder] = { N: value };
expressionAttributeValues[uniquePlaceholder] = isNumberField ? { N: String(value) } : { S: value };
break;
case FilterCriteriaEnum.icontains:
filterExpression += ` AND NOT contains(#${field}, ${uniquePlaceholder})`;
Expand All @@ -348,6 +351,9 @@ export class DataAccessObjectDynamoDB extends BasicDataAccessObject implements I
default:
break;
}
if (index === 0) {
filterExpression = filterExpression.replace(/^ AND /, '');
}
});
}

Expand Down Expand Up @@ -383,7 +389,6 @@ export class DataAccessObjectDynamoDB extends BasicDataAccessObject implements I
const result = await dynamoDb.scan(params);

rows = rows.concat(result.Items);

lastEvaluatedKey = result.LastEvaluatedKey;
} while (lastEvaluatedKey);

Expand Down