--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import {
+ createWebhook,
+ deleteWebhook,
+ getDelivery,
+ searchDeliveries,
+ searchWebhooks,
+ updateWebhook,
+} from '../../api/webhooks';
+import { mockWebhook } from '../../helpers/mocks/webhook';
+import { mockPaging } from '../../helpers/testMocks';
+import {
+ WebhookCreatePayload,
+ WebhookResponse,
+ WebhookSearchDeliveriesPayload,
+ WebhookUpdatePayload,
+} from '../../types/webhook';
+import { deliveries, mockFullWebhookDeliveries, mockFullWebhookList } from './data/webhooks';
+
+jest.mock('../../api/webhooks');
+
+export default class WebhooksMock {
+ static readonly DEFAULT_PAGE_SIZE = 10;
+
+ project?: string;
+ webhooks: Array<WebhookResponse>;
+
+ constructor(project?: string) {
+ this.project = project;
+ this.webhooks = mockFullWebhookList(project);
+
+ jest.mocked(createWebhook).mockImplementation(this.handleCreateWebhook);
+ jest.mocked(searchWebhooks).mockImplementation(this.handleSearchWebhooks);
+ jest.mocked(updateWebhook).mockImplementation(this.handleUpdateWebhook);
+ jest.mocked(deleteWebhook).mockImplementation(this.handleDeleteWebhook);
+ jest.mocked(searchDeliveries).mockImplementation(this.handleSearchDeliveries);
+ jest.mocked(getDelivery).mockImplementation(this.handleGetDelivery);
+ }
+
+ reset = (project?: string) => {
+ this.project = project;
+ this.webhooks = mockFullWebhookList(project);
+ };
+
+ response = <T>(data: T): Promise<T> => {
+ return Promise.resolve(data);
+ };
+
+ addWebhook = (...webhooks: WebhookResponse[]) => {
+ this.webhooks.push(...webhooks);
+ };
+
+ handleCreateWebhook = (data: WebhookCreatePayload) => {
+ const webhook = mockWebhook({
+ name: data.name,
+ url: data.url,
+ hasSecret: Boolean(data.secret),
+ });
+ return this.response({
+ webhook,
+ });
+ };
+
+ handleSearchWebhooks = ({ project }: { project?: string }) => {
+ if (project !== this.project) {
+ throw new Error(
+ 'You are asking for webhooks of a project that is not mocked. Reset first the mock with the correct project'
+ );
+ }
+ return this.response({
+ webhooks: this.webhooks,
+ });
+ };
+
+ handleUpdateWebhook = (data: WebhookUpdatePayload) => {
+ const webhook = this.webhooks.find((webhook) => webhook.key === data.webhook);
+ if (!webhook) {
+ return Promise.reject(new Error('Webhook not found'));
+ }
+ webhook.hasSecret = Boolean(data.secret);
+ webhook.name = data.name;
+ webhook.url = data.url;
+ return this.response(undefined);
+ };
+
+ handleDeleteWebhook = ({ webhook }: { webhook: string }) => {
+ const index = this.webhooks.findIndex((w) => w.key === webhook);
+ if (index === -1) {
+ return Promise.reject(new Error('Webhook not found'));
+ }
+ this.webhooks.splice(index, 1);
+ return this.response(undefined);
+ };
+
+ handleSearchDeliveries = ({
+ webhook,
+ ps = WebhooksMock.DEFAULT_PAGE_SIZE,
+ p = 1,
+ }: WebhookSearchDeliveriesPayload) => {
+ const deliveries = mockFullWebhookDeliveries(webhook);
+ const start = (p - 1) * ps;
+ const end = start + ps;
+ const paging = mockPaging({ pageIndex: p, pageSize: ps, total: deliveries.length });
+ const page = deliveries.slice(start, end);
+ return this.response({
+ deliveries: page,
+ paging,
+ });
+ };
+
+ handleGetDelivery = ({ deliveryId }: { deliveryId: string }) => {
+ const delivery = deliveries.find((delivery) => delivery.id === deliveryId);
+ if (!delivery) {
+ return Promise.reject(new Error('Delivery not found'));
+ }
+ return this.response({
+ delivery: {
+ ...delivery,
+ payload: JSON.stringify({ id: delivery.id }),
+ },
+ });
+ };
+}
'297': [RULE_1, RULE_4],
},
};
+
+// Webhooks.
+export const WEBHOOK_GLOBAL_1 = 'global-webhook1';
+export const WEBHOOK_GLOBAL_1_LATEST_DELIVERY_ID = 'global-delivery1';
+export const WEBHOOK_GLOBAL_2 = 'global-webhook2';
+export const WEBHOOK_PROJECT_1 = 'project1';
+export const WEBHOOK_PROJECT_1_1 = 'project1-webhook1';
+export const WEBHOOK_PROJECT_1_2 = 'project1-webhook2';
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { cloneDeep } from 'lodash';
+import { mockComponent } from '../../../helpers/mocks/component';
+import { mockWebhook, mockWebhookDelivery } from '../../../helpers/mocks/webhook';
+import { ComponentQualifier } from '../../../types/component';
+import { WebhookDelivery, WebhookResponse } from '../../../types/webhook';
+import {
+ WEBHOOK_GLOBAL_1,
+ WEBHOOK_GLOBAL_1_LATEST_DELIVERY_ID,
+ WEBHOOK_GLOBAL_2,
+ WEBHOOK_PROJECT_1,
+ WEBHOOK_PROJECT_1_1,
+ WEBHOOK_PROJECT_1_2,
+} from './ids';
+
+export const webhookProject = mockComponent({
+ key: WEBHOOK_PROJECT_1,
+ qualifier: ComponentQualifier.Project,
+});
+
+const globalWebhook1Deliveries = [
+ mockWebhookDelivery({
+ at: '2019-06-24T09:45:52+0200',
+ id: WEBHOOK_GLOBAL_1_LATEST_DELIVERY_ID,
+ }),
+ ...Array.from({ length: 15 }).map((_, i) =>
+ mockWebhookDelivery({
+ id: `global-webhook-1-delivery-${i}`,
+ at: `2019-06-${(23 - i).toString().padStart(2, '0')}T09:45:52+0200`,
+ httpStatus: i % 2 === 0 ? 200 : undefined,
+ success: i % 2 === 0,
+ durationMs: 1000 + i * 100,
+ })
+ ),
+];
+
+const project1Webhook1Deliveries = [
+ mockWebhookDelivery({
+ id: 'project-1-delivery-1',
+ at: '2019-06-24T09:45:52+0200',
+ }),
+];
+
+export const deliveries = [...globalWebhook1Deliveries, ...project1Webhook1Deliveries];
+
+export const webhooks: Record<string, Array<WebhookResponse>> = {
+ global: [
+ mockWebhook({
+ key: WEBHOOK_GLOBAL_1,
+ name: 'Global webhook 1',
+ url: 'https://example.com/1',
+ latestDelivery: globalWebhook1Deliveries[0],
+ }),
+ mockWebhook({
+ key: WEBHOOK_GLOBAL_2,
+ name: 'Global webhook 2',
+ hasSecret: true,
+ url: 'https://example.com/2',
+ }),
+ ],
+ [webhookProject.key]: [
+ mockWebhook({
+ key: WEBHOOK_PROJECT_1_1,
+ name: 'Project 1 webhook 1',
+ url: 'https://example.com/1',
+ latestDelivery: project1Webhook1Deliveries[0],
+ }),
+ mockWebhook({
+ key: WEBHOOK_PROJECT_1_2,
+ name: 'Project 1 webhook 2',
+ url: 'https://example.com/2',
+ }),
+ ],
+};
+
+export function mockFullWebhookList(project?: string): Array<WebhookResponse> {
+ return cloneDeep(webhooks[project ?? 'global'] ?? []);
+}
+
+export function mockFullWebhookDeliveries(webhook?: string): Array<WebhookDelivery> {
+ return cloneDeep(webhook === WEBHOOK_GLOBAL_1 ? globalWebhook1Deliveries : []);
+}
WebhookCreatePayload,
WebhookDelivery,
WebhookResponse,
+ WebhookSearchDeliveriesPayload,
WebhookUpdatePayload,
} from '../types/webhook';
return post('/api/webhooks/update', data).catch(throwGlobalError);
}
-export function searchDeliveries(data: {
- ceTaskId?: string;
- componentKey?: string;
- webhook?: string;
- p?: number;
- ps?: number;
-}): Promise<{
+export function searchDeliveries(data: WebhookSearchDeliveriesPayload): Promise<{
deliveries: WebhookDelivery[];
paging: Paging;
}> {
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { WebhookDelivery } from '../../types/webhook';
+import { WebhookDelivery, WebhookResponse } from '../../types/webhook';
import { HttpStatus } from '../request';
export function mockWebhookDelivery(overrides: Partial<WebhookDelivery> = {}): WebhookDelivery {
...overrides,
};
}
+
+export function mockWebhook(overrides: Partial<WebhookResponse> = {}): WebhookResponse {
+ return {
+ hasSecret: false,
+ key: 'webhook1',
+ name: 'name',
+ url: 'http://example.com',
+ ...overrides,
+ };
+}
id: string;
success: boolean;
}
+
+export type WebhookSearchDeliveriesPayload = {
+ ceTaskId?: string;
+ componentKey?: string;
+ webhook?: string;
+ p?: number;
+ ps?: number;
+};