Skip to content

Commit

Permalink
Merge pull request #7273 from nocodb/test/pw-test-mysql-improvements
Browse files Browse the repository at this point in the history
pw formula tests, check formula not supported error
  • Loading branch information
pranavxc committed Dec 22, 2023
2 parents 75515c1 + c95d95a commit ddb72f9
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 25 deletions.
12 changes: 10 additions & 2 deletions tests/playwright/pages/Base.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Locator, Page } from '@playwright/test';
import { expect, Locator, Page } from '@playwright/test';
import { readFileSync } from 'fs';

type ResponseSelector = (json: any) => boolean;
Expand All @@ -16,6 +16,12 @@ export default abstract class BasePage {
await this.rootPage.locator('.ant-message .ant-message-notice-content', { hasText: message }).last().isVisible();
}

async verifyLastToast({ message }: { message: string }) {
await expect(
this.rootPage.locator('.ant-message .ant-message-notice-content', { hasText: message }).last()
).toHaveText(message);
}

async waitForResponse({
// Playwright action that triggers the request i.e locatorSomething.click()
uiAction,
Expand All @@ -24,18 +30,20 @@ export default abstract class BasePage {
// A function that takes the response body and returns true if the response is the one we are looking for
responseJsonMatcher,
timeout,
responseStatusCodeToMatch = 200,
}: {
uiAction: () => Promise<any>;
requestUrlPathToMatch: string;
httpMethodsToMatch?: string[];
responseJsonMatcher?: ResponseSelector;
timeout?: number;
responseStatusCodeToMatch?: number;
}) {
const [res] = await Promise.all([
this.rootPage.waitForResponse(
res =>
res.url().includes(requestUrlPathToMatch) &&
res.status() === 200 &&
res.status() === responseStatusCodeToMatch &&
httpMethodsToMatch.includes(res.request().method()),
timeout ? { timeout } : undefined
),
Expand Down
14 changes: 14 additions & 0 deletions tests/playwright/pages/Dashboard/Grid/Column/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,20 @@ export class ColumnPageObject extends BasePage {
await this.rootPage.waitForTimeout(200);
}

async saveFail({ errorMessage }: { errorMessage?: string } = {}) {
await this.waitForResponse({
uiAction: async () => await this.get().locator('button:has-text("Save")').click(),
requestUrlPathToMatch: 'api/v1/db/meta',
httpMethodsToMatch: ['GET', 'PATCH'],
responseStatusCodeToMatch: 400,
});
await this.verifyLastToast({
message: errorMessage,
});
await this.get().waitFor({ state: 'visible' });
await this.rootPage.waitForTimeout(200);
}

async verify({ title, isVisible = true }: { title: string; isVisible?: boolean }) {
if (!isVisible) {
return await expect(this.getColumnHeader(title)).not.toBeVisible();
Expand Down
63 changes: 40 additions & 23 deletions tests/playwright/tests/db/columns/columnFormula.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { test } from '@playwright/test';
import { DashboardPage } from '../../../pages/Dashboard';
import setup, { NcContext, unsetup } from '../../../setup';
import { enableQuickRun, isPg, isSqlite } from '../../../setup/db';
import { enableQuickRun, isMysql, isPg, isSqlite } from '../../../setup/db';

// Add formula to be verified here & store expected results for 5 rows
// Column data from City table (Sakila DB)
Expand All @@ -19,6 +19,7 @@ const formulaDataByDbType = (context: NcContext, index: number) => {
{
formula: '1 + 1',
result: ['2', '2', '2', '2', '2'],
unSupDbType: [],
},
{
formula: 'ADD({CityId}, {CountryId}) + AVG({CityId}, {CountryId}) + LEN({City})',
Expand Down Expand Up @@ -92,6 +93,7 @@ const formulaDataByDbType = (context: NcContext, index: number) => {
{
formula: 'VALUE("12ab-c345")',
result: ['-12345', '-12345', '-12345', '-12345', '-12345'],
unSupDbType: ['sqlite3'],
},
{
formula: 'TRUE()',
Expand All @@ -101,19 +103,6 @@ const formulaDataByDbType = (context: NcContext, index: number) => {
formula: 'FALSE()',
result: ['0', '0', '0', '0', '0'],
},
{
formula: 'REGEX_MATCH({City}, "a[a-z]a")',
result: ['0', '0', '0', '0', '1'],
},
{
formula: 'REGEX_EXTRACT({City}, "a[a-z]a")',
result: ['', '', '', '', 'ana'],
},
{
formula: 'REGEX_REPLACE({City}, "a[a-z]a","...")',
result: ['A Corua (La Corua)', 'Abha', 'Abu Dhabi', 'Acua', 'Ad...'],
},

{
formula: '"City Name: " & {City}',
result: [
Expand All @@ -137,12 +126,30 @@ const formulaDataByDbType = (context: NcContext, index: number) => {
formula: 'RECORD_ID()',
result: ['1', '2', '3', '4', '5'],
},
{
formula: 'REGEX_MATCH({City}, "a[a-z]a")',
result: ['0', '0', '0', '0', '1'],
unSupDbType: ['sqlite3'],
},
{
// TODO: this is bug in mysql, its being case in-sensitive.
formula: 'REGEX_EXTRACT({City}, "a[a-z]a")',
result: ['', '', '', '', 'ana'],
unSupDbType: ['sqlite3'],
},
{
// TODO: this is bug in mysql, its being case in-sensitive.
formula: 'REGEX_REPLACE({City}, "a[a-z]a","...")',
result: ['A Corua (La Corua)', 'Abha', 'Abu Dhabi', 'Acua', 'Ad...'],
unSupDbType: ['sqlite3'],
},
];
else
return [
{
formula: `DATETIME_DIFF("2023/10/14", "2023/01/12", "y")`,
result: ['0', '0', '0', '0', '0'],
unSupDbType: [],
},
{
formula: `DATETIME_DIFF("2023-01-12", "2021-08-29", "y")`,
Expand Down Expand Up @@ -180,9 +187,16 @@ const formulaDataByDbType = (context: NcContext, index: number) => {
},
{
formula: `LOG({CityId}) + EXP({CityId}) + POWER({CityId}, 3) + SQRT({CountryId})`,
result: isPg(context)
? ['13.04566088154786', '24.74547123273205', '57.61253379902822', '126.94617671688704', '283.9609869087087']
: ['13.04566088154786', '25.137588417628013', '58.23402483297667', '127.73041108667896', '284.8714548168068'],
result:
isPg(context) || isSqlite(context)
? ['13.04566088154786', '24.74547123273205', '57.61253379902822', '126.94617671688704', '283.9609869087087']
: [
'13.04566088154786',
'25.137588417628013',
'58.23402483297667',
'127.73041108667896',
'284.8714548168068',
],
},
{
formula: `NOW()`,
Expand Down Expand Up @@ -245,26 +259,29 @@ test.describe('Virtual Columns', () => {
async function formulaTestSpec(index: number) {
// close 'Team & Auth' tab
const formulaData = formulaDataByDbType(context, index);
const dbType = context.base.sources[0].type;
await dashboard.closeTab({ title: 'Team & Auth' });

await dashboard.treeView.openTable({ title: 'City' });
// Create formula column
// Create dummy formula column which will then be updated for every testcase
await dashboard.grid.column.create({
title: 'NC_MATH_0',
type: 'Formula',
formula: formulaData[1].formula,
formula: '1 + 1',
});

// verify different formula's
for (let i = 1; i < formulaData.length; i++) {
// Sqlite does not support log function
if (isSqlite(context) && formulaData[i].formula.includes('LOG(')) continue;

for (let i = 0; i < formulaData.length; i++) {
await dashboard.grid.column.openEdit({
title: 'NC_MATH_0',
type: 'Formula',
formula: formulaData[i].formula,
});
if (formulaData[i].unSupDbType?.includes(dbType)) {
// assert for message not supported or greyed out save button.
await dashboard.grid.column.saveFail({ errorMessage: 'Invalid Formula' });
continue;
}
await dashboard.grid.column.save({ isUpdated: true });
if (formulaData[i].formula !== `NOW()`) {
await formulaResultVerify({
Expand Down

0 comments on commit ddb72f9

Please sign in to comment.