Skip to content

Commit

Permalink
change: [M3-8583] - Add support ticket mocks to MSW 2.0 (#10937)
Browse files Browse the repository at this point in the history
* Add getSupportTickets and createSupportTicket mocks

* Mock getSupportTicket and getSupportTicketReplies requests

* Fix getSupportTicket mock req, add closeSupportTicket req

* Mock createSupportTicketReply

* Clean up createSupportTicket req, fix getSupportTicketReplies req

* Add events

* Uncomment seeder

* Clean up in create request

* Added changeset: Add support ticket mocks to MSW 2.0

* Address feedback: add new entities to mergedContext in load function

* Address feedback: mock support ticket reply more accurately
  • Loading branch information
mjac0bs authored Oct 8, 2024
1 parent fb24626 commit 25ee272
Show file tree
Hide file tree
Showing 9 changed files with 264 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Tech Stories
---

Add support ticket mocks to MSW 2.0 ([#10937](https://github.com/linode/manager/pull/10937))
8 changes: 8 additions & 0 deletions packages/manager/src/dev-tools/load.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,14 @@ export async function loadDevTools(
...(seedContext?.regionAvailability || []),
],
regions: [...initialContext.regions, ...(seedContext?.regions || [])],
supportReplies: [
...initialContext.supportReplies,
...(seedContext?.supportReplies || []),
],
supportTickets: [
...initialContext.supportTickets,
...(seedContext?.supportTickets || []),
],
volumes: [...initialContext.volumes, ...(seedContext?.volumes || [])],
};

Expand Down
2 changes: 2 additions & 0 deletions packages/manager/src/mocks/mockState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export const emptyStore: MockState = {
placementGroups: [],
regionAvailability: [],
regions: [],
supportReplies: [],
supportTickets: [],
volumes: [],
};

Expand Down
2 changes: 2 additions & 0 deletions packages/manager/src/mocks/presets/baseline/crud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
import { linodeCrudPreset } from 'src/mocks/presets/crud/linodes';

import { placementGroupsCrudPreset } from '../crud/placementGroups';
import { supportTicketCrudPreset } from '../crud/supportTickets';
import { volumeCrudPreset } from '../crud/volumes';

import type { MockPresetBaseline } from 'src/mocks/types';
Expand All @@ -14,6 +15,7 @@ export const baselineCrudPreset: MockPresetBaseline = {
handlers: [
...linodeCrudPreset.handlers,
...placementGroupsCrudPreset.handlers,
...supportTicketCrudPreset.handlers,
...volumeCrudPreset.handlers,

// Events.
Expand Down
184 changes: 184 additions & 0 deletions packages/manager/src/mocks/presets/crud/handlers/supportTickets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import { DateTime } from 'luxon';
import { http } from 'msw';

import { supportReplyFactory, supportTicketFactory } from 'src/factories';
import { mswDB } from 'src/mocks/indexedDB';
import { queueEvents } from 'src/mocks/utilities/events';
import {
makeNotFoundResponse,
makePaginatedResponse,
makeResponse,
} from 'src/mocks/utilities/response';

import type { SupportReply, SupportTicket } from '@linode/api-v4';
import type { StrictResponse } from 'msw';
import type { MockState } from 'src/mocks/types';
import type {
APIErrorResponse,
APIPaginatedResponse,
} from 'src/mocks/utilities/response';

export const createSupportTicket = (mockState: MockState) => [
http.post(
'*/support/tickets',
async ({
request,
}): Promise<StrictResponse<APIErrorResponse | SupportTicket>> => {
const payload = await request.clone().json();

const supportTicket = supportTicketFactory.build({
closable: true,
description: payload['description'],
entity: {
id: 1,
label: 'mock-linode-1',
type: 'linode',
url: '/v4/linode/instances/1',
},
opened: DateTime.now().toISO(),
severity: 1,
status: 'open',
summary: payload['summary'],
updated: DateTime.now().toISO(),
});

await mswDB.add('supportTickets', supportTicket, mockState);

queueEvents({
event: {
action: 'ticket_create',
entity: {
id: supportTicket.id,
label: supportTicket.summary,
type: 'support_ticket',
url: `/v4/support/tickets/${supportTicket.id}`,
},
},
mockState,
sequence: [{ status: 'notification' }],
});

return makeResponse(supportTicket);
}
),
];

export const getSupportTickets = () => [
http.get(
'*/support/tickets',
async ({
request,
}): Promise<
StrictResponse<APIErrorResponse | APIPaginatedResponse<SupportTicket>>
> => {
const supportTickets = await mswDB.getAll('supportTickets');

if (!supportTickets) {
return makeNotFoundResponse();
}
return makePaginatedResponse({
data: supportTickets,
request,
});
}
),
http.get(
'*/support/tickets/:ticketId',
async ({
params,
}): Promise<StrictResponse<APIErrorResponse | SupportTicket>> => {
const id = Number(params.ticketId);
const supportTicket = await mswDB.get('supportTickets', id);

if (!supportTicket) {
return makeNotFoundResponse();
}
return makeResponse(supportTicket);
}
),
];

export const closeSupportTicket = (mockState: MockState) => [
http.post('*/support/tickets/:ticketId/close', async ({ params }) => {
const id = Number(params.ticketId);
const supportTicket = await mswDB.get('supportTickets', id);

if (!supportTicket) {
return makeNotFoundResponse();
}

mswDB.update(
'supportTickets',
id,
{ ...supportTicket, closed: DateTime.now().toISO(), status: 'closed' },
mockState
);

return makeResponse({});
}),
];

export const getSupportTicketReplies = () => [
http.get(
'*/support/tickets/:ticketId/replies',
async ({
params,
request,
}): Promise<
StrictResponse<APIErrorResponse | APIPaginatedResponse<SupportReply>>
> => {
const id = Number(params.ticketId);
const supportReplies = await mswDB.get('supportReplies', id);

if (!supportReplies) {
return makePaginatedResponse({
data: [],
request,
});
}
return makePaginatedResponse({
data: [supportReplies],
request,
});
}
),
];

export const createSupportTicketReply = (mockState: MockState) => [
http.post(
'*/support/tickets/:ticketId/replies',
async ({
params,
request,
}): Promise<StrictResponse<APIErrorResponse | SupportReply>> => {
const payload = await request.clone().json();
const id = Number(params.ticketId);
const supportTicket = await mswDB.get('supportTickets', id);

const supportTicketReply = supportReplyFactory.build({
created_by: 'test-account',
description: payload['description'],
friendly_name: 'test-account',
from_linode: false,
});

await mswDB.add('supportReplies', supportTicketReply, mockState);

queueEvents({
event: {
action: 'ticket_update',
entity: {
id: supportTicket?.id ?? -1,
label: supportTicket?.summary ?? null,
type: 'support_ticket',
url: `/v4/support/tickets/${supportTicket?.id}`,
},
},
mockState,
sequence: [{ status: 'notification' }],
});

return makeResponse(supportTicketReply);
}
),
];
8 changes: 7 additions & 1 deletion packages/manager/src/mocks/presets/crud/seeds/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { linodesSeeder } from './linodes';
import { placementGroupSeeder } from './placementGroups';
import { supportTicketsSeeder } from './supportTickets';
import { volumesSeeder } from './volumes';

export const dbSeeders = [linodesSeeder, placementGroupSeeder, volumesSeeder];
export const dbSeeders = [
linodesSeeder,
placementGroupSeeder,
supportTicketsSeeder,
volumesSeeder,
];
28 changes: 28 additions & 0 deletions packages/manager/src/mocks/presets/crud/seeds/supportTickets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { getSeedsCountMap } from 'src/dev-tools/utils';
import { supportTicketFactory } from 'src/factories';
import { mswDB } from 'src/mocks/indexedDB';

import type { MockSeeder, MockState } from 'src/mocks/types';

export const supportTicketsSeeder: MockSeeder = {
canUpdateCount: true,
desc: 'Support Tickets Seeds',
group: { id: 'Support Tickets' },
id: 'support-tickets:crud',
label: 'Support Tickets',

seeder: async (mockState: MockState) => {
const seedsCountMap = getSeedsCountMap();
const count = seedsCountMap[supportTicketsSeeder.id] ?? 0;
const supportTickets = supportTicketFactory.buildList(count);

const updatedMockState = {
...mockState,
supportTickets: mockState.supportTickets.concat(supportTickets),
};

await mswDB.saveStore(updatedMockState, 'seedState');

return updatedMockState;
},
};
22 changes: 22 additions & 0 deletions packages/manager/src/mocks/presets/crud/supportTickets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {
closeSupportTicket,
createSupportTicket,
createSupportTicketReply,
getSupportTicketReplies,
getSupportTickets,
} from 'src/mocks/presets/crud/handlers/supportTickets';

import type { MockPresetCrud } from 'src/mocks/types';

export const supportTicketCrudPreset: MockPresetCrud = {
group: { id: 'Support Tickets' },
handlers: [
createSupportTicket,
closeSupportTicket,
getSupportTickets,
getSupportTicketReplies,
createSupportTicketReply,
],
id: 'support-tickets:crud',
label: 'Support Tickets CRUD',
};
7 changes: 6 additions & 1 deletion packages/manager/src/mocks/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import type {
PlacementGroup,
Region,
RegionAvailability,
SupportReply,
SupportTicket,
Volume,
} from '@linode/api-v4';
import type { HttpHandler } from 'msw';
Expand Down Expand Up @@ -70,11 +72,12 @@ export interface MockPresetExtra extends MockPresetBase {
* Mock Preset Crud
*/
export type MockPresetCrudGroup = {
id: 'Linodes' | 'Placement Groups' | 'Volumes';
id: 'Linodes' | 'Placement Groups' | 'Support Tickets' | 'Volumes';
};
export type MockPresetCrudId =
| 'linodes:crud'
| 'placement-groups:crud'
| 'support-tickets:crud'
| 'volumes:crud';
export interface MockPresetCrud extends MockPresetBase {
canUpdateCount?: boolean;
Expand All @@ -96,6 +99,8 @@ export interface MockState {
placementGroups: PlacementGroup[];
regionAvailability: RegionAvailability[];
regions: Region[];
supportReplies: SupportReply[];
supportTickets: SupportTicket[];
volumes: Volume[];
}

Expand Down

0 comments on commit 25ee272

Please sign in to comment.