mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-27 22:49:56 -05:00
a97f384cdf
refs https://github.com/TryGhost/Product/issues/3745 --- This pull request adds a new feature to the `admin-x-settings` app that allows users to customize the colors of their email newsletters. It also simplifies and refactors the routing logic and the components related to integrations, newsletters, and users. It introduces new dependencies and components for color manipulation and selection, and updates the existing components and stories to use them.
219 lines
8.4 KiB
TypeScript
219 lines
8.4 KiB
TypeScript
import {Integration, IntegrationsResponseType} from '../../../../src/api/integrations';
|
|
import {Webhook, WebhooksResponseType} from '../../../../src/api/webhooks';
|
|
import {expect, test} from '@playwright/test';
|
|
import {globalDataRequests, limitRequests, mockApi, responseFixtures} from '../../../utils/e2e';
|
|
|
|
test.describe('Custom integrations', async () => {
|
|
test('Supports creating an integration and adding webhooks', async ({page}) => {
|
|
const integration = {
|
|
id: 'custom-id',
|
|
type: 'custom',
|
|
slug: 'my-integration',
|
|
name: 'My integration',
|
|
icon_image: null,
|
|
description: null,
|
|
created_at: '2023-01-01T00:00:00.000Z',
|
|
updated_at: '2023-01-01T00:00:00.000Z',
|
|
api_keys: [{
|
|
id: 'admin-key-id',
|
|
type: 'admin',
|
|
secret: 'admin-api-secret',
|
|
role_id: 'role-id',
|
|
integration_id: 'my-integration',
|
|
user_id: 'user-id',
|
|
last_seen_at: null,
|
|
last_seen_version: null,
|
|
created_at: '2023-01-01T00:00:00.000Z',
|
|
updated_at: '2023-01-01T00:00:00.000Z'
|
|
}, {
|
|
id: 'content-key-id',
|
|
type: 'content',
|
|
secret: 'content-api-secret',
|
|
role_id: 'role-id',
|
|
integration_id: 'my-integration',
|
|
user_id: 'user-id',
|
|
last_seen_at: null,
|
|
last_seen_version: null,
|
|
created_at: '2023-01-01T00:00:00.000Z',
|
|
updated_at: '2023-01-01T00:00:00.000Z'
|
|
}]
|
|
} satisfies Integration;
|
|
|
|
const webhook = {
|
|
id: 'webhook-id',
|
|
event: 'post.created',
|
|
target_url: 'https://example.com',
|
|
name: 'My webhook',
|
|
secret: null,
|
|
api_version: 'v3',
|
|
integration_id: integration.id,
|
|
last_triggered_at: null,
|
|
last_triggered_status: null,
|
|
last_triggered_error: null,
|
|
created_at: '2023-01-01T00:00:00.000Z',
|
|
updated_at: '2023-01-01T00:00:00.000Z'
|
|
} satisfies Webhook;
|
|
|
|
await mockApi({
|
|
page,
|
|
requests: {
|
|
...globalDataRequests,
|
|
browseIntegrations: {
|
|
method: 'GET',
|
|
path: '/integrations/?include=api_keys%2Cwebhooks',
|
|
response: {integrations: []} satisfies IntegrationsResponseType
|
|
},
|
|
addIntegration: {
|
|
method: 'POST',
|
|
path: '/integrations/?include=api_keys%2Cwebhooks',
|
|
response: {integrations: [integration]} satisfies IntegrationsResponseType
|
|
},
|
|
editIntegration: {
|
|
method: 'PUT',
|
|
path: `/integrations/${integration.id}/?include=api_keys%2Cwebhooks`,
|
|
response: {integrations: [{
|
|
...integration,
|
|
description: 'Test description'
|
|
}]} satisfies IntegrationsResponseType
|
|
},
|
|
deleteIntegration: {
|
|
method: 'DELETE',
|
|
path: `/integrations/${integration.id}/`,
|
|
response: null
|
|
},
|
|
createWebhook: {
|
|
method: 'POST',
|
|
path: '/webhooks/',
|
|
response: {webhooks: [webhook]} satisfies WebhooksResponseType
|
|
},
|
|
editWebhook: {
|
|
method: 'PUT',
|
|
path: `/webhooks/${webhook.id}/`,
|
|
response: {webhooks: [{
|
|
...webhook,
|
|
name: 'Updated webhook'
|
|
}]} satisfies WebhooksResponseType
|
|
},
|
|
deleteWebhook: {
|
|
method: 'DELETE',
|
|
path: `/webhooks/${webhook.id}/`,
|
|
response: null
|
|
},
|
|
refreshAPIKey: {
|
|
method: 'POST',
|
|
path: /\/api_key\/.+\/refresh/,
|
|
response: ({
|
|
integrations: [{
|
|
...integration,
|
|
api_keys: [{
|
|
...integration.api_keys[0],
|
|
secret: 'new-api-key'
|
|
}]
|
|
}]
|
|
} satisfies IntegrationsResponseType)
|
|
}
|
|
}
|
|
});
|
|
|
|
await page.goto('/');
|
|
|
|
const integrationsSection = page.getByTestId('integrations');
|
|
|
|
await integrationsSection.getByRole('button', {name: 'Add custom integration'}).click();
|
|
|
|
const createModal = page.getByTestId('add-integration-modal');
|
|
|
|
createModal.getByLabel('Name').fill('My integration');
|
|
createModal.getByRole('button', {name: 'Add'}).click();
|
|
|
|
const modal = page.getByTestId('custom-integration-modal');
|
|
|
|
// Regenerate API key
|
|
|
|
await expect(modal).toHaveText(/admin-api-secret/);
|
|
await modal.getByText('admin-api-secret').hover();
|
|
await modal.getByRole('button', {name: 'Regenerate'}).click();
|
|
await page.getByTestId('confirmation-modal').getByRole('button', {name: 'Regenerate Admin API Key'}).click();
|
|
|
|
await expect(modal).toHaveText(/Admin API Key was successfully regenerated/);
|
|
await expect(modal).toHaveText(/new-api-key/);
|
|
|
|
// Create webhook
|
|
|
|
await modal.getByRole('button', {name: 'Add webhook'}).click();
|
|
|
|
const webhookModal = page.getByTestId('webhook-modal');
|
|
|
|
await webhookModal.getByLabel('Name').fill('My webhook');
|
|
await webhookModal.getByLabel('Target URL').fill('https://example.com');
|
|
await webhookModal.getByLabel('Event').selectOption('Post created');
|
|
|
|
// Playwright fails unless you click twice, for some reason (timing issue with validations?)
|
|
await webhookModal.getByRole('button', {name: 'Add'}).click();
|
|
await webhookModal.getByRole('button', {name: 'Add'}).click();
|
|
|
|
await expect(modal).toHaveText(/My webhook/);
|
|
|
|
// Edit webhook
|
|
|
|
await modal.getByText('My webhook').click();
|
|
|
|
await webhookModal.getByLabel('Name').fill('Updated webhook');
|
|
await webhookModal.getByRole('button', {name: 'Update'}).click();
|
|
|
|
await expect(modal).toHaveText(/Updated webhook/);
|
|
|
|
// Delete webhook
|
|
|
|
await modal.getByText('Updated webhook').hover();
|
|
await modal.getByRole('button', {name: 'Delete'}).click();
|
|
await page.getByTestId('confirmation-modal').getByRole('button', {name: 'Delete webhook'}).click();
|
|
|
|
await expect(modal).not.toHaveText(/Updated webhook/);
|
|
|
|
// Edit integration
|
|
|
|
await modal.getByLabel('Description').fill('Test description');
|
|
await modal.getByRole('button', {name: 'Save & close'}).click();
|
|
|
|
await expect(integrationsSection).toHaveText(/Test description/);
|
|
|
|
// Delete integration
|
|
|
|
await integrationsSection.getByText('My integration').hover();
|
|
await integrationsSection.getByRole('button', {name: 'Delete'}).click();
|
|
await page.getByTestId('confirmation-modal').getByRole('button', {name: 'Delete integration'}).click();
|
|
|
|
await expect(integrationsSection).not.toHaveText(/My integration/);
|
|
});
|
|
|
|
test('Limits creating custom integrations', async ({page}) => {
|
|
await mockApi({page, requests: {
|
|
...globalDataRequests,
|
|
...limitRequests,
|
|
browseConfig: {
|
|
...globalDataRequests.browseConfig,
|
|
response: {
|
|
config: {
|
|
...responseFixtures.config.config,
|
|
hostSettings: {
|
|
limits: {
|
|
customIntegrations: {
|
|
disabled: true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}});
|
|
|
|
await page.goto('/');
|
|
|
|
const integrationsSection = page.getByTestId('integrations');
|
|
|
|
await integrationsSection.getByRole('button', {name: 'Add custom integration'}).click();
|
|
|
|
await expect(page.getByTestId('limit-modal')).toHaveText(/Your plan does not support custom integrations/);
|
|
});
|
|
});
|