13233 zapier update route to create workflow apikey etc (#13239)
Fix webhook creation utils and some tests
This commit is contained in:
@ -1,16 +1,8 @@
|
||||
{
|
||||
"name": "twenty-zapier",
|
||||
"version": "2.0.1",
|
||||
"version": "2.0.2",
|
||||
"description": "Effortlessly sync Twenty with 3000+ apps. Automate tasks, boost productivity, and supercharge your customer relationships!",
|
||||
"main": "src/index.ts",
|
||||
"scripts": {
|
||||
"nx": "NX_DEFAULT_PROJECT=twenty-zapier node ../../node_modules/nx/bin/nx.js",
|
||||
"format": "prettier . --write \"!build\"",
|
||||
"test": "yarn build && jest --testTimeout 10000 --rootDir ./lib/test",
|
||||
"validate": "yarn build && zapier validate",
|
||||
"versions": "yarn build && zapier versions",
|
||||
"watch": "yarn clean && npx tsc --watch"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^22.12.0",
|
||||
"npm": "please-use-yarn",
|
||||
@ -21,8 +13,11 @@
|
||||
"convertedByCLIVersion": "15.4.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sniptt/guards": "^0.2.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"zapier-platform-core": "15.5.1"
|
||||
"libphonenumber-js": "^1.10.26",
|
||||
"zapier-platform-core": "15.5.1",
|
||||
"zod": "3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jest": "29.7.0",
|
||||
|
||||
@ -12,6 +12,41 @@
|
||||
},
|
||||
"dependsOn": ["^build"]
|
||||
},
|
||||
"format": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"cwd": "{projectRoot}",
|
||||
"commands": ["prettier . --write \"!build\""]
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"cwd": "{projectRoot}",
|
||||
"commands": ["NODE_ENV=test && nx run twenty-zapier:build && jest --testTimeout 10000 --rootDir ./lib/test"]
|
||||
}
|
||||
},
|
||||
"validate": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"cwd": "{projectRoot}",
|
||||
"commands": ["nx run twenty-zapier:build && zapier validate"]
|
||||
}
|
||||
},
|
||||
"versions": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"cwd": "{projectRoot}",
|
||||
"commands": ["nx run twenty-zapier:build && zapier versions"]
|
||||
}
|
||||
},
|
||||
"watch":{
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"cwd": "{projectRoot}",
|
||||
"commands": ["nx run twenty-zapier:clean && npx tsc --watch"]
|
||||
}
|
||||
},
|
||||
"clean": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
|
||||
@ -10,56 +10,68 @@ const appTester = createAppTester(App);
|
||||
describe('triggers.trigger_record.created', () => {
|
||||
test('should succeed to subscribe', async () => {
|
||||
const bundle = getBundle({});
|
||||
|
||||
bundle.inputData.nameSingular = 'company';
|
||||
bundle.inputData.operation = DatabaseEventAction.CREATED;
|
||||
bundle.targetUrl = 'https://test.com';
|
||||
|
||||
const result = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.performSubscribe,
|
||||
bundle,
|
||||
);
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(result.id).toBeDefined();
|
||||
|
||||
const checkDbResult = await appTester(
|
||||
(z: ZObject, bundle: Bundle) =>
|
||||
requestDb(
|
||||
z,
|
||||
bundle,
|
||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operations}}}}`,
|
||||
`query webhook {webhook(input: {id: "${result.id}"}){id operations}}`,
|
||||
),
|
||||
bundle,
|
||||
);
|
||||
expect(checkDbResult.data.webhooks.edges[0].node.operations[0]).toEqual(
|
||||
'company.created',
|
||||
);
|
||||
|
||||
expect(checkDbResult.data.webhook.operations[0]).toEqual('company.created');
|
||||
});
|
||||
|
||||
test('should succeed to unsubscribe', async () => {
|
||||
const bundle = getBundle({});
|
||||
|
||||
bundle.inputData.nameSingular = 'company';
|
||||
bundle.inputData.operation = DatabaseEventAction.CREATED;
|
||||
bundle.targetUrl = 'https://test.com';
|
||||
|
||||
const result = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.performSubscribe,
|
||||
bundle,
|
||||
);
|
||||
|
||||
const unsubscribeBundle = getBundle({});
|
||||
|
||||
unsubscribeBundle.subscribeData = { id: result.id };
|
||||
|
||||
const unsubscribeResult = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.performUnsubscribe,
|
||||
unsubscribeBundle,
|
||||
);
|
||||
|
||||
expect(unsubscribeResult).toBeDefined();
|
||||
expect(unsubscribeResult.id).toEqual(result.id);
|
||||
|
||||
const checkDbResult = await appTester(
|
||||
(z: ZObject, bundle: Bundle) =>
|
||||
requestDb(
|
||||
z,
|
||||
bundle,
|
||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operations}}}}`,
|
||||
),
|
||||
requestDb(z, bundle, `query webhook {webhooks {id}}`),
|
||||
bundle,
|
||||
);
|
||||
expect(checkDbResult.data.webhooks.edges.length).toEqual(0);
|
||||
expect(
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
checkDbResult.data.webhooks.filter((webhook) => webhook.id === result.id)
|
||||
.length,
|
||||
).toEqual(0);
|
||||
});
|
||||
|
||||
test('should load company from webhook', async () => {
|
||||
const bundle = {
|
||||
cleanedRequest: {
|
||||
@ -77,24 +89,33 @@ describe('triggers.trigger_record.created', () => {
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const results = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.perform,
|
||||
bundle,
|
||||
);
|
||||
|
||||
expect(results.length).toEqual(1);
|
||||
|
||||
const company = results[0];
|
||||
|
||||
expect(company.record.id).toEqual('d6ccb1d1-a90b-4822-a992-a0dd946592c9');
|
||||
});
|
||||
it('should load companies from list', async () => {
|
||||
const bundle = getBundle({});
|
||||
|
||||
bundle.inputData.nameSingular = 'company';
|
||||
bundle.inputData.operation = DatabaseEventAction.CREATED;
|
||||
|
||||
const results = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.performList,
|
||||
bundle,
|
||||
);
|
||||
|
||||
expect(results.length).toBeGreaterThan(1);
|
||||
|
||||
const firstCompany = results[0];
|
||||
|
||||
expect(firstCompany.record).toBeDefined();
|
||||
});
|
||||
});
|
||||
@ -102,66 +123,83 @@ describe('triggers.trigger_record.created', () => {
|
||||
describe('triggers.trigger_record.update', () => {
|
||||
test('should succeed to subscribe', async () => {
|
||||
const bundle = getBundle({});
|
||||
|
||||
bundle.inputData.nameSingular = 'company';
|
||||
bundle.inputData.operation = DatabaseEventAction.UPDATED;
|
||||
bundle.targetUrl = 'https://test.com';
|
||||
|
||||
const result = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.performSubscribe,
|
||||
bundle,
|
||||
);
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(result.id).toBeDefined();
|
||||
|
||||
const checkDbResult = await appTester(
|
||||
(z: ZObject, bundle: Bundle) =>
|
||||
requestDb(
|
||||
z,
|
||||
bundle,
|
||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operations}}}}`,
|
||||
`query webhook {webhook(input: {id: "${result.id}"}){id operations}}`,
|
||||
),
|
||||
bundle,
|
||||
);
|
||||
expect(checkDbResult.data.webhooks.edges[0].node.operations[0]).toEqual(
|
||||
|
||||
expect(checkDbResult.data.webhooks.operations[0]).toEqual(
|
||||
'company.updated',
|
||||
);
|
||||
});
|
||||
test('should succeed to unsubscribe', async () => {
|
||||
const bundle = getBundle({});
|
||||
|
||||
bundle.inputData.nameSingular = 'company';
|
||||
bundle.inputData.operation = DatabaseEventAction.UPDATED;
|
||||
bundle.targetUrl = 'https://test.com';
|
||||
|
||||
const result = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.performSubscribe,
|
||||
bundle,
|
||||
);
|
||||
|
||||
const unsubscribeBundle = getBundle({});
|
||||
|
||||
unsubscribeBundle.subscribeData = { id: result.id };
|
||||
|
||||
const unsubscribeResult = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.performUnsubscribe,
|
||||
unsubscribeBundle,
|
||||
);
|
||||
|
||||
expect(unsubscribeResult).toBeDefined();
|
||||
expect(unsubscribeResult.id).toEqual(result.id);
|
||||
|
||||
const checkDbResult = await appTester(
|
||||
(z: ZObject, bundle: Bundle) =>
|
||||
requestDb(
|
||||
z,
|
||||
bundle,
|
||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operations}}}}`,
|
||||
),
|
||||
requestDb(z, bundle, `query webhook {webhooks {id}}`),
|
||||
bundle,
|
||||
);
|
||||
expect(checkDbResult.data.webhooks.edges.length).toEqual(0);
|
||||
expect(
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
checkDbResult.data.webhooks.filter((webhook) => webhook.id === result.id)
|
||||
.length,
|
||||
).toEqual(0);
|
||||
});
|
||||
it('should load companies from list', async () => {
|
||||
const bundle = getBundle({});
|
||||
|
||||
bundle.inputData.nameSingular = 'company';
|
||||
bundle.inputData.operation = DatabaseEventAction.UPDATED;
|
||||
|
||||
const results = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.performList,
|
||||
bundle,
|
||||
);
|
||||
|
||||
expect(results.length).toBeGreaterThan(1);
|
||||
|
||||
const firstCompany = results[0];
|
||||
|
||||
expect(firstCompany.record).toBeDefined();
|
||||
expect(firstCompany.updatedFields).toBeDefined();
|
||||
});
|
||||
@ -170,66 +208,83 @@ describe('triggers.trigger_record.update', () => {
|
||||
describe('triggers.trigger_record.delete', () => {
|
||||
test('should succeed to subscribe', async () => {
|
||||
const bundle = getBundle({});
|
||||
|
||||
bundle.inputData.nameSingular = 'company';
|
||||
bundle.inputData.operation = DatabaseEventAction.DELETED;
|
||||
bundle.targetUrl = 'https://test.com';
|
||||
|
||||
const result = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.performSubscribe,
|
||||
bundle,
|
||||
);
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(result.id).toBeDefined();
|
||||
|
||||
const checkDbResult = await appTester(
|
||||
(z: ZObject, bundle: Bundle) =>
|
||||
requestDb(
|
||||
z,
|
||||
bundle,
|
||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operations}}}}`,
|
||||
`query webhook {webhook(input: {id: "${result.id}"}){id operations}}`,
|
||||
),
|
||||
bundle,
|
||||
);
|
||||
expect(checkDbResult.data.webhooks.edges[0].node.operations[0]).toEqual(
|
||||
|
||||
expect(checkDbResult.data.webhooks.operations[0]).toEqual(
|
||||
'company.deleted',
|
||||
);
|
||||
});
|
||||
test('should succeed to unsubscribe', async () => {
|
||||
const bundle = getBundle({});
|
||||
|
||||
bundle.inputData.nameSingular = 'company';
|
||||
bundle.inputData.operation = DatabaseEventAction.DELETED;
|
||||
bundle.targetUrl = 'https://test.com';
|
||||
|
||||
const result = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.performSubscribe,
|
||||
bundle,
|
||||
);
|
||||
|
||||
const unsubscribeBundle = getBundle({});
|
||||
|
||||
unsubscribeBundle.subscribeData = { id: result.id };
|
||||
|
||||
const unsubscribeResult = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.performUnsubscribe,
|
||||
unsubscribeBundle,
|
||||
);
|
||||
|
||||
expect(unsubscribeResult).toBeDefined();
|
||||
expect(unsubscribeResult.id).toEqual(result.id);
|
||||
|
||||
const checkDbResult = await appTester(
|
||||
(z: ZObject, bundle: Bundle) =>
|
||||
requestDb(
|
||||
z,
|
||||
bundle,
|
||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operations}}}}`,
|
||||
),
|
||||
requestDb(z, bundle, `query webhook {webhooks {id}}`),
|
||||
bundle,
|
||||
);
|
||||
expect(checkDbResult.data.webhooks.edges.length).toEqual(0);
|
||||
expect(
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
checkDbResult.data.webhooks.filter((webhook) => webhook.id === result.id)
|
||||
.length,
|
||||
).toEqual(0);
|
||||
});
|
||||
it('should load companies from list', async () => {
|
||||
const bundle = getBundle({});
|
||||
|
||||
bundle.inputData.nameSingular = 'company';
|
||||
bundle.inputData.operation = DatabaseEventAction.DELETED;
|
||||
|
||||
const results = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.performList,
|
||||
bundle,
|
||||
);
|
||||
|
||||
expect(results.length).toBeGreaterThan(1);
|
||||
|
||||
const firstCompany = results[0];
|
||||
|
||||
expect(firstCompany).toBeDefined();
|
||||
expect(firstCompany.record.id).toBeDefined();
|
||||
expect(Object.keys(firstCompany).length).toEqual(1);
|
||||
|
||||
@ -179,24 +179,6 @@ describe('computeInputFields', () => {
|
||||
list: false,
|
||||
placeholder: undefined,
|
||||
},
|
||||
{
|
||||
key: 'xLink__url',
|
||||
label: 'X: Url',
|
||||
type: 'string',
|
||||
helpText: 'Contact’s X/Twitter account: Link Url',
|
||||
required: false,
|
||||
list: false,
|
||||
placeholder: undefined,
|
||||
},
|
||||
{
|
||||
key: 'xLink__label',
|
||||
label: 'X: Label',
|
||||
type: 'string',
|
||||
helpText: 'Contact’s X/Twitter account: Link Label',
|
||||
required: false,
|
||||
list: false,
|
||||
placeholder: undefined,
|
||||
},
|
||||
{
|
||||
key: 'whatsapp__primaryLinkLabel',
|
||||
label: 'Whatsapp: Primary Link Label',
|
||||
@ -224,15 +206,6 @@ describe('computeInputFields', () => {
|
||||
list: true,
|
||||
placeholder: '{ url: "", label: "" }',
|
||||
},
|
||||
{
|
||||
key: 'email',
|
||||
label: 'Email',
|
||||
type: 'string',
|
||||
helpText: 'Contact’s Email',
|
||||
required: false,
|
||||
list: false,
|
||||
placeholder: undefined,
|
||||
},
|
||||
{
|
||||
key: 'companyId',
|
||||
label: 'Company id (foreign key)',
|
||||
|
||||
@ -45,7 +45,7 @@ describe('utils.handleQueryParams', () => {
|
||||
'linkedinUrl: {url: "/linkedin_url", label: "Test linkedinUrl"}, ' +
|
||||
'whatsapp: {primaryLinkUrl: "/whatsapp_url", primaryLinkLabel: "Whatsapp Link", secondaryLinks: [{url: \'/secondary_whatsapp_url\',label: \'Secondary Whatsapp Link\'}]}, ' +
|
||||
'emails: {primaryEmail: "primary@email.com", additionalEmails: ["secondary@email.com"]}, ' +
|
||||
'phones: {primaryPhoneNumber: "322110011", primaryPhoneCountryCode: "FR", primaryPhoneCallingCode: "+33", additionalPhones: [{ phoneNumber: \'322110012\', countryCode: \'+33\' }]}, ' +
|
||||
'phones: {primaryPhoneNumber: "322110011", primaryPhoneCountryCode: "FR", primaryPhoneCallingCode: "+33", additionalPhones: [{ phoneNumber: \'322110012\', countryCode: \'FR\', callingCode: \'+33\' }]}, ' +
|
||||
'xUrl: {url: "/x_url", label: "Test xUrl"}, ' +
|
||||
'annualRecurringRevenue: 100000, ' +
|
||||
'idealCustomerProfile: true, ' +
|
||||
|
||||
@ -18,13 +18,15 @@ export const performSubscribe = async (z: ZObject, bundle: Bundle) => {
|
||||
operations: [
|
||||
`${bundle.inputData.nameSingular}.${bundle.inputData.operation}`,
|
||||
],
|
||||
secret: '',
|
||||
};
|
||||
const result = await requestDb(
|
||||
z,
|
||||
bundle,
|
||||
`mutation createWebhook {createWebhook(data:{${handleQueryParams(
|
||||
`mutation createWebhook {createWebhook(input:{${handleQueryParams(
|
||||
data,
|
||||
)}}) {id}}`,
|
||||
'metadata',
|
||||
);
|
||||
return result.data.createWebhook;
|
||||
};
|
||||
@ -34,7 +36,8 @@ export const performUnsubscribe = async (z: ZObject, bundle: Bundle) => {
|
||||
const result = await requestDb(
|
||||
z,
|
||||
bundle,
|
||||
`mutation deleteWebhook {deleteWebhook(${handleQueryParams(data)}) {id}}`,
|
||||
`mutation deleteWebhook {deleteWebhook(${handleQueryParams(data)})}`,
|
||||
'metadata',
|
||||
);
|
||||
return result.data.deleteWebhook;
|
||||
};
|
||||
|
||||
@ -57174,11 +57174,14 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "twenty-zapier@workspace:packages/twenty-zapier"
|
||||
dependencies:
|
||||
"@sniptt/guards": "npm:^0.2.0"
|
||||
dotenv: "npm:^16.4.5"
|
||||
jest: "npm:29.7.0"
|
||||
libphonenumber-js: "npm:^1.10.26"
|
||||
rimraf: "npm:^3.0.2"
|
||||
zapier-platform-cli: "npm:^15.4.1"
|
||||
zapier-platform-core: "npm:15.5.1"
|
||||
zod: "npm:3.23.8"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
|
||||
Reference in New Issue
Block a user