|
|
@ -3,6 +3,7 @@ import { DashboardPage } from '../pages/Dashboard'; |
|
|
|
import setup from '../setup'; |
|
|
|
import setup from '../setup'; |
|
|
|
import makeServer from '../setup/server'; |
|
|
|
import makeServer from '../setup/server'; |
|
|
|
import { WebhookFormPage } from '../pages/Dashboard/WebhookForm'; |
|
|
|
import { WebhookFormPage } from '../pages/Dashboard/WebhookForm'; |
|
|
|
|
|
|
|
import { isSubset } from '../utils'; |
|
|
|
|
|
|
|
|
|
|
|
const hookPath = 'http://localhost:9090/hook'; |
|
|
|
const hookPath = 'http://localhost:9090/hook'; |
|
|
|
|
|
|
|
|
|
|
@ -16,9 +17,11 @@ async function clearServerData({ request }) { |
|
|
|
await expect(await response.json()).toBe(0); |
|
|
|
await expect(await response.json()).toBe(0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async function verifyHookTrigger(count: number, value: string, request) { |
|
|
|
async function verifyHookTrigger(count: number, value: string, request, expectedData?: any) { |
|
|
|
// Retry since there can be lag between the time the hook is triggered and the time the server receives the request
|
|
|
|
// Retry since there can be lag between the time the hook is triggered and the time the server receives the request
|
|
|
|
let response; |
|
|
|
let response; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// retry since there can be lag between the time the hook is triggered and the time the server receives the request
|
|
|
|
for (let i = 0; i < 20; i++) { |
|
|
|
for (let i = 0; i < 20; i++) { |
|
|
|
response = await request.get(hookPath + '/count'); |
|
|
|
response = await request.get(hookPath + '/count'); |
|
|
|
if ((await response.json()) === count) { |
|
|
|
if ((await response.json()) === count) { |
|
|
@ -30,17 +33,43 @@ async function verifyHookTrigger(count: number, value: string, request) { |
|
|
|
|
|
|
|
|
|
|
|
if (count) { |
|
|
|
if (count) { |
|
|
|
let response; |
|
|
|
let response; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// retry since there can be lag between the time the hook is triggered and the time the server receives the request
|
|
|
|
for (let i = 0; i < 20; i++) { |
|
|
|
for (let i = 0; i < 20; i++) { |
|
|
|
response = await request.get(hookPath + '/last'); |
|
|
|
response = await request.get(hookPath + '/last'); |
|
|
|
if ((await response.json()).Title === value) { |
|
|
|
const rspJson = await response.json(); |
|
|
|
|
|
|
|
if (rspJson.data.rows[0].Title === value) { |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
await new Promise(resolve => setTimeout(resolve, 150)); |
|
|
|
await new Promise(resolve => setTimeout(resolve, 150)); |
|
|
|
} |
|
|
|
} |
|
|
|
await expect((await response.json()).Title).toBe(value); |
|
|
|
const rspJson = await response.json(); |
|
|
|
|
|
|
|
await expect(rspJson?.data?.rows[0]?.Title).toBe(value); |
|
|
|
|
|
|
|
if (expectedData) { |
|
|
|
|
|
|
|
await expect(isSubset(rspJson, expectedData)).toBe(true); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function buildExpectedResponseData(type, value) { |
|
|
|
|
|
|
|
const expectedData = { |
|
|
|
|
|
|
|
type: 'records.after.insert', |
|
|
|
|
|
|
|
data: { |
|
|
|
|
|
|
|
table_name: 'Test', |
|
|
|
|
|
|
|
view_name: 'Test', |
|
|
|
|
|
|
|
rows: [ |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Title: 'Poole', |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
], |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
expectedData.type = type; |
|
|
|
|
|
|
|
expectedData.data.rows[0].Title = value; |
|
|
|
|
|
|
|
return expectedData; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
test.describe.serial('Webhook', () => { |
|
|
|
test.describe.serial('Webhook', () => { |
|
|
|
// start a server locally for webhook tests
|
|
|
|
// start a server locally for webhook tests
|
|
|
|
|
|
|
|
|
|
|
@ -58,7 +87,7 @@ test.describe.serial('Webhook', () => { |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
test('CRUD', async ({ request, page }) => { |
|
|
|
test('CRUD', async ({ request, page }) => { |
|
|
|
// todo: Waiting for the server to start
|
|
|
|
// Waiting for the server to start
|
|
|
|
await page.waitForTimeout(1000); |
|
|
|
await page.waitForTimeout(1000); |
|
|
|
|
|
|
|
|
|
|
|
// close 'Team & Auth' tab
|
|
|
|
// close 'Team & Auth' tab
|
|
|
@ -66,6 +95,12 @@ test.describe.serial('Webhook', () => { |
|
|
|
await dashboard.closeTab({ title: 'Team & Auth' }); |
|
|
|
await dashboard.closeTab({ title: 'Team & Auth' }); |
|
|
|
await dashboard.treeView.createTable({ title: 'Test' }); |
|
|
|
await dashboard.treeView.createTable({ title: 'Test' }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// hook order
|
|
|
|
|
|
|
|
// hook-1: after insert
|
|
|
|
|
|
|
|
// - verify trigger after insert
|
|
|
|
|
|
|
|
// - verify no trigger after edit
|
|
|
|
|
|
|
|
// - verify no trigger after delete
|
|
|
|
|
|
|
|
|
|
|
|
// after insert hook
|
|
|
|
// after insert hook
|
|
|
|
await webhook.create({ |
|
|
|
await webhook.create({ |
|
|
|
title: 'hook-1', |
|
|
|
title: 'hook-1', |
|
|
@ -77,12 +112,24 @@ test.describe.serial('Webhook', () => { |
|
|
|
columnHeader: 'Title', |
|
|
|
columnHeader: 'Title', |
|
|
|
value: 'Poole', |
|
|
|
value: 'Poole', |
|
|
|
}); |
|
|
|
}); |
|
|
|
await verifyHookTrigger(1, 'Poole', request); |
|
|
|
await verifyHookTrigger(1, 'Poole', request, buildExpectedResponseData('records.after.insert', 'Poole')); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// trigger edit row & delete row
|
|
|
|
|
|
|
|
// verify that the hook is not triggered (count doesn't change in this case)
|
|
|
|
await dashboard.grid.editRow({ index: 0, value: 'Delaware' }); |
|
|
|
await dashboard.grid.editRow({ index: 0, value: 'Delaware' }); |
|
|
|
await verifyHookTrigger(1, 'Poole', request); |
|
|
|
await verifyHookTrigger(1, 'Poole', request); |
|
|
|
await dashboard.grid.deleteRow(0); |
|
|
|
await dashboard.grid.deleteRow(0); |
|
|
|
await verifyHookTrigger(1, 'Poole', request); |
|
|
|
await verifyHookTrigger(1, 'Poole', request); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// hook order
|
|
|
|
|
|
|
|
// hook-1: after insert
|
|
|
|
|
|
|
|
// hook-2: after update
|
|
|
|
|
|
|
|
// - verify trigger after insert
|
|
|
|
|
|
|
|
// - verify trigger after edit
|
|
|
|
|
|
|
|
// - verify no trigger after delete
|
|
|
|
|
|
|
|
|
|
|
|
// after update hook
|
|
|
|
// after update hook
|
|
|
|
await webhook.create({ |
|
|
|
await webhook.create({ |
|
|
|
title: 'hook-2', |
|
|
|
title: 'hook-2', |
|
|
@ -95,12 +142,22 @@ test.describe.serial('Webhook', () => { |
|
|
|
columnHeader: 'Title', |
|
|
|
columnHeader: 'Title', |
|
|
|
value: 'Poole', |
|
|
|
value: 'Poole', |
|
|
|
}); |
|
|
|
}); |
|
|
|
await verifyHookTrigger(1, 'Poole', request); |
|
|
|
await verifyHookTrigger(1, 'Poole', request, buildExpectedResponseData('records.after.insert', 'Poole')); |
|
|
|
await dashboard.grid.editRow({ index: 0, value: 'Delaware' }); |
|
|
|
await dashboard.grid.editRow({ index: 0, value: 'Delaware' }); |
|
|
|
await verifyHookTrigger(2, 'Delaware', request); |
|
|
|
await verifyHookTrigger(2, 'Delaware', request, buildExpectedResponseData('records.after.update', 'Delaware')); |
|
|
|
await dashboard.grid.deleteRow(0); |
|
|
|
await dashboard.grid.deleteRow(0); |
|
|
|
await verifyHookTrigger(2, 'Delaware', request); |
|
|
|
await verifyHookTrigger(2, 'Delaware', request); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// hook order
|
|
|
|
|
|
|
|
// hook-1: after insert
|
|
|
|
|
|
|
|
// hook-2: after update
|
|
|
|
|
|
|
|
// hook-3: after delete
|
|
|
|
|
|
|
|
// - verify trigger after insert
|
|
|
|
|
|
|
|
// - verify trigger after edit
|
|
|
|
|
|
|
|
// - verify trigger after delete
|
|
|
|
|
|
|
|
|
|
|
|
// after delete hook
|
|
|
|
// after delete hook
|
|
|
|
await webhook.create({ |
|
|
|
await webhook.create({ |
|
|
|
title: 'hook-3', |
|
|
|
title: 'hook-3', |
|
|
@ -112,13 +169,24 @@ test.describe.serial('Webhook', () => { |
|
|
|
columnHeader: 'Title', |
|
|
|
columnHeader: 'Title', |
|
|
|
value: 'Poole', |
|
|
|
value: 'Poole', |
|
|
|
}); |
|
|
|
}); |
|
|
|
await verifyHookTrigger(1, 'Poole', request); |
|
|
|
await verifyHookTrigger(1, 'Poole', request, buildExpectedResponseData('records.after.insert', 'Poole')); |
|
|
|
await dashboard.grid.editRow({ index: 0, value: 'Delaware' }); |
|
|
|
await dashboard.grid.editRow({ index: 0, value: 'Delaware' }); |
|
|
|
await verifyHookTrigger(2, 'Delaware', request); |
|
|
|
await verifyHookTrigger(2, 'Delaware', request, buildExpectedResponseData('records.after.update', 'Delaware')); |
|
|
|
await dashboard.grid.deleteRow(0); |
|
|
|
await dashboard.grid.deleteRow(0); |
|
|
|
await verifyHookTrigger(3, 'Delaware', request); |
|
|
|
await verifyHookTrigger(3, 'Delaware', request, buildExpectedResponseData('records.after.delete', 'Delaware')); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
// modify webhook
|
|
|
|
// modify webhook
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// hook order
|
|
|
|
|
|
|
|
// hook-1: after delete
|
|
|
|
|
|
|
|
// hook-2: after delete
|
|
|
|
|
|
|
|
// hook-3: after delete
|
|
|
|
|
|
|
|
// - verify no trigger after insert
|
|
|
|
|
|
|
|
// - verify no trigger after edit
|
|
|
|
|
|
|
|
// - verify trigger after delete
|
|
|
|
|
|
|
|
|
|
|
|
await webhook.open({ index: 0 }); |
|
|
|
await webhook.open({ index: 0 }); |
|
|
|
await webhook.configureWebhook({ |
|
|
|
await webhook.configureWebhook({ |
|
|
|
title: 'hook-1-modified', |
|
|
|
title: 'hook-1-modified', |
|
|
@ -140,13 +208,28 @@ test.describe.serial('Webhook', () => { |
|
|
|
columnHeader: 'Title', |
|
|
|
columnHeader: 'Title', |
|
|
|
value: 'Poole', |
|
|
|
value: 'Poole', |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// for insert & edit, the hook should not be triggered (count doesn't change in this case)
|
|
|
|
await verifyHookTrigger(0, 'Poole', request); |
|
|
|
await verifyHookTrigger(0, 'Poole', request); |
|
|
|
await dashboard.grid.editRow({ index: 0, value: 'Delaware' }); |
|
|
|
await dashboard.grid.editRow({ index: 0, value: 'Delaware' }); |
|
|
|
await verifyHookTrigger(0, 'Delaware', request); |
|
|
|
await verifyHookTrigger(0, 'Delaware', request); |
|
|
|
await dashboard.grid.deleteRow(0); |
|
|
|
await dashboard.grid.deleteRow(0); |
|
|
|
await verifyHookTrigger(3, 'Delaware', request); |
|
|
|
|
|
|
|
|
|
|
|
// for delete, the hook should be triggered (thrice in this case)
|
|
|
|
|
|
|
|
await verifyHookTrigger(3, 'Delaware', request, buildExpectedResponseData('records.after.delete', 'Delaware')); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
// delete webhook
|
|
|
|
// delete webhook
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// hook order
|
|
|
|
|
|
|
|
// hook-1: -
|
|
|
|
|
|
|
|
// hook-2: -
|
|
|
|
|
|
|
|
// hook-3: -
|
|
|
|
|
|
|
|
// - verify no trigger after insert
|
|
|
|
|
|
|
|
// - verify no trigger after edit
|
|
|
|
|
|
|
|
// - verify no trigger after delete
|
|
|
|
|
|
|
|
|
|
|
|
await webhook.delete({ index: 0 }); |
|
|
|
await webhook.delete({ index: 0 }); |
|
|
|
await webhook.delete({ index: 0 }); |
|
|
|
await webhook.delete({ index: 0 }); |
|
|
|
await webhook.delete({ index: 0 }); |
|
|
|
await webhook.delete({ index: 0 }); |
|
|
@ -212,7 +295,18 @@ test.describe.serial('Webhook', () => { |
|
|
|
save: true, |
|
|
|
save: true, |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// verify
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// webhook with condition
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// hook order
|
|
|
|
|
|
|
|
// hook-1: after insert where Title is like 'Poole'
|
|
|
|
|
|
|
|
// hook-2: after update where Title is like 'Poole'
|
|
|
|
|
|
|
|
// hook-3: after delete where Title is like 'Poole'
|
|
|
|
|
|
|
|
// - verify trigger after insert gets triggered only when Title is like 'Poole'
|
|
|
|
|
|
|
|
// - verify trigger after edit gets triggered only when Title is like 'Poole'
|
|
|
|
|
|
|
|
// - verify trigger after delete gets triggered only when Title is like 'Poole'
|
|
|
|
|
|
|
|
|
|
|
|
await clearServerData({ request }); |
|
|
|
await clearServerData({ request }); |
|
|
|
await dashboard.grid.addNewRow({ |
|
|
|
await dashboard.grid.addNewRow({ |
|
|
|
index: 0, |
|
|
|
index: 0, |
|
|
@ -224,15 +318,25 @@ test.describe.serial('Webhook', () => { |
|
|
|
columnHeader: 'Title', |
|
|
|
columnHeader: 'Title', |
|
|
|
value: 'Delaware', |
|
|
|
value: 'Delaware', |
|
|
|
}); |
|
|
|
}); |
|
|
|
await verifyHookTrigger(1, 'Poole', request); |
|
|
|
await verifyHookTrigger(1, 'Poole', request, buildExpectedResponseData('records.after.insert', 'Poole')); |
|
|
|
await dashboard.grid.editRow({ index: 0, value: 'Delaware' }); |
|
|
|
await dashboard.grid.editRow({ index: 0, value: 'Delaware' }); |
|
|
|
await dashboard.grid.editRow({ index: 1, value: 'Poole' }); |
|
|
|
await dashboard.grid.editRow({ index: 1, value: 'Poole' }); |
|
|
|
await verifyHookTrigger(2, 'Poole', request); |
|
|
|
await verifyHookTrigger(2, 'Poole', request, buildExpectedResponseData('records.after.update', 'Poole')); |
|
|
|
await dashboard.grid.deleteRow(1); |
|
|
|
await dashboard.grid.deleteRow(1); |
|
|
|
await dashboard.grid.deleteRow(0); |
|
|
|
await dashboard.grid.deleteRow(0); |
|
|
|
await verifyHookTrigger(3, 'Poole', request); |
|
|
|
await verifyHookTrigger(3, 'Poole', request, buildExpectedResponseData('records.after.delete', 'Poole')); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
// Delete condition
|
|
|
|
// webhook after conditions are removed
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// hook order
|
|
|
|
|
|
|
|
// hook-1: after insert
|
|
|
|
|
|
|
|
// hook-2: after update
|
|
|
|
|
|
|
|
// hook-3: after delete
|
|
|
|
|
|
|
|
// - verify trigger after insert gets triggered when Title is like 'Poole' or not
|
|
|
|
|
|
|
|
// - verify trigger after edit gets triggered when Title is like 'Poole' or not
|
|
|
|
|
|
|
|
// - verify trigger after delete gets triggered when Title is like 'Poole' or not
|
|
|
|
await webhook.open({ index: 2 }); |
|
|
|
await webhook.open({ index: 2 }); |
|
|
|
await webhook.deleteCondition({ save: true }); |
|
|
|
await webhook.deleteCondition({ save: true }); |
|
|
|
await webhook.open({ index: 1 }); |
|
|
|
await webhook.open({ index: 1 }); |
|
|
@ -251,12 +355,12 @@ test.describe.serial('Webhook', () => { |
|
|
|
columnHeader: 'Title', |
|
|
|
columnHeader: 'Title', |
|
|
|
value: 'Delaware', |
|
|
|
value: 'Delaware', |
|
|
|
}); |
|
|
|
}); |
|
|
|
await verifyHookTrigger(2, 'Delaware', request); |
|
|
|
await verifyHookTrigger(2, 'Delaware', request, buildExpectedResponseData('records.after.insert', 'Delaware')); |
|
|
|
await dashboard.grid.editRow({ index: 0, value: 'Delaware' }); |
|
|
|
await dashboard.grid.editRow({ index: 0, value: 'Delaware' }); |
|
|
|
await dashboard.grid.editRow({ index: 1, value: 'Poole' }); |
|
|
|
await dashboard.grid.editRow({ index: 1, value: 'Poole' }); |
|
|
|
await verifyHookTrigger(4, 'Poole', request); |
|
|
|
await verifyHookTrigger(4, 'Poole', request, buildExpectedResponseData('records.after.update', 'Poole')); |
|
|
|
await dashboard.grid.deleteRow(1); |
|
|
|
await dashboard.grid.deleteRow(1); |
|
|
|
await dashboard.grid.deleteRow(0); |
|
|
|
await dashboard.grid.deleteRow(0); |
|
|
|
await verifyHookTrigger(6, 'Delaware', request); |
|
|
|
await verifyHookTrigger(6, 'Delaware', request, buildExpectedResponseData('records.after.delete', 'Delaware')); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|