add mock test (#7031)

* add mock test

* add custom testing headers

* use insomnia fetch

* fix types

* normalise error structure

* using insomniaFetch for log

* fix warning

* add modal for vaults

* remove status code assertion

* use org id

* check status code
This commit is contained in:
Jack Kavanagh authored and GitHub committed 2024-01-30 16:57:01 +01:00
1 parent 2d0042a83c
commit 01e048faab
7 files changed
+65 -60

No files matched your search

@@ -15,6 +15,7 @@ interface EnvOptions {
INSOMNIA_API_URL: string;
INSOMNIA_APP_WEBSITE_URL: string;
INSOMNIA_AI_URL: string;
INSOMNIA_MOCK_API_URL: string;
INSOMNIA_GITHUB_API_URL: string;
INSOMNIA_GITLAB_API_URL: string;
INSOMNIA_UPDATES_URL: string;
@@ -57,6 +58,7 @@ export const test = baseTest.extend<{
INSOMNIA_GITHUB_API_URL: webServerUrl + '/github-api/graphql',
INSOMNIA_GITLAB_API_URL: webServerUrl + '/gitlab-api',
INSOMNIA_UPDATES_URL: webServerUrl || 'https://updates.insomnia.rest',
INSOMNIA_MOCK_API_URL: 'https://mock.insomnia.moe',
INSOMNIA_SKIP_ONBOARDING: String(userConfig.skipOnboarding),
INSOMNIA_PUBLIC_KEY: userConfig.publicKey,
INSOMNIA_SECRET_KEY: userConfig.secretKey,
@@ -1,7 +1,6 @@
import { test } from '../../playwright/test';
// TODO: unskip this test when cloud mock is online
test.skip('can make a mock route', async ({ page }) => {
test('can make a mock route', async ({ page }) => {
test.slow(process.platform === 'darwin' || process.platform === 'win32', 'Slow app start on these platforms');
await page.getByLabel('New Mock Server').click();
await page.getByRole('button', { name: 'Create', exact: true }).click();
@@ -20,6 +19,5 @@ test.skip('can make a mock route', async ({ page }) => {
await page.getByRole('tab', { name: 'Preview' }).click();
await page.getByLabel('Preview').getByText('123').click();
await page.getByRole('tab', { name: 'Timeline' }).click();
await page.getByText('HTTP/1.1 201 Created').click();
await page.getByText('my-header:').click();
await page.getByText('201').click();
});
+4 -1
View File
@@ -7,6 +7,7 @@ interface FetchConfig {
method: 'POST' | 'PUT' | 'GET' | 'DELETE' | 'PATCH';
path: string;
sessionId: string | null;
organizationId?: string | null;
data?: unknown;
retries?: number;
origin?: string;
@@ -41,13 +42,15 @@ const exponentialBackOff = async (url: string, init: RequestInit, retries = 0):
}
};
export async function insomniaFetch<T = void>({ method, path, data, sessionId, origin }: FetchConfig): Promise<T> {
export async function insomniaFetch<T = void>({ method, path, data, sessionId, organizationId, origin }: FetchConfig): Promise<T> {
const config: RequestInit = {
method,
headers: {
'X-Insomnia-Client': getClientString(),
...(sessionId ? { 'X-Session-Id': sessionId } : {}),
...(data ? { 'Content-Type': 'application/json' } : {}),
...(organizationId ? { 'X-Insomnia-Org-Id': organizationId } : {}),
...(process.env.PLAYWRIGHT ? { 'X-Mockbin-Test': 'true' } : {}),
},
...(data ? { body: JSON.stringify(data) } : {}),
};
+27 -30
View File
@@ -84,30 +84,18 @@ const AvatarPlaceholder = ({ size, children }: { size: 'small' | 'medium'; child
};
export const Avatar = ({ src, alt, size = 'medium' }: { src: string; alt: string; size?: 'small' | 'medium' }) => {
return (
<TooltipTrigger>
<Button className="cursor-default">
{src ? (
<Suspense fallback={<AvatarPlaceholder size={size}>{getNameInitials(alt)}</AvatarPlaceholder>}>
<AvatarImage
src={src}
alt={alt}
size={size}
/>
</Suspense>
) : (
<AvatarPlaceholder size={size}>
{getNameInitials(alt)}
</AvatarPlaceholder>
)}
</Button>
<Tooltip
offset={8}
className="border select-none text-sm max-w-xs border-solid border-[--hl-sm] shadow-lg bg-[--color-bg] text-[--color-font] px-4 py-2 rounded-md overflow-y-auto max-h-[85vh] focus:outline-none"
>
{alt}
</Tooltip>
</TooltipTrigger>
return src ? (
<Suspense fallback={<AvatarPlaceholder size={size}>{getNameInitials(alt)}</AvatarPlaceholder>}>
<AvatarImage
src={src}
alt={alt}
size={size}
/>
</Suspense>
) : (
<AvatarPlaceholder size={size}>
{getNameInitials(alt)}
</AvatarPlaceholder>
);
};
@@ -124,12 +112,21 @@ export const AvatarGroup = ({ items, maxAvatars = 3, size = 'medium' }: { items:
}}
>
{avatars.map(avatar => (
<Avatar
size={size}
key={avatar.key}
src={avatar.src}
alt={avatar.alt}
/>
<TooltipTrigger key={avatar.key}>
<Button className="cursor-default">
<Avatar
size={size}
src={avatar.src}
alt={avatar.alt}
/>
</Button>
<Tooltip
offset={8}
className="border select-none text-sm max-w-xs border-solid border-[--hl-sm] shadow-lg bg-[--color-bg] text-[--color-font] px-4 py-2 rounded-md overflow-y-auto max-h-[85vh] focus:outline-none"
>
{avatar.alt}
</Tooltip>
</TooltipTrigger>
))}
{overflow > 0 && (
<TooltipTrigger>
@@ -1,8 +1,8 @@
import { AxiosResponse } from 'axios';
import * as Har from 'har-format';
import React, { Fragment, useEffect, useState } from 'react';
import { useRouteLoaderData } from 'react-router-dom';
import { getCurrentSessionId } from '../../../account/session';
import { getMockServiceURL, PREVIEW_MODE_SOURCE } from '../../../common/constants';
import { ResponseTimelineEntry } from '../../../main/network/libcurl-promise';
import * as models from '../../../models';
@@ -46,12 +46,14 @@ export const MockResponsePane = () => {
const fn = async () => {
const compoundId = mockRoute.parentId + mockRoute.name;
try {
const res: AxiosResponse<MockbinLogOutput> = await window.main.axiosRequest({
url: mockbinUrl + `/bin/log/${compoundId}`,
method: 'get',
const res = await window.main.insomniaFetch<MockbinLogOutput>({
origin: mockbinUrl,
path: `/bin/log/${compoundId}`,
method: 'GET',
sessionId: getCurrentSessionId(),
});
if (res?.data?.log) {
setLogs(res.data);
if (res?.log) {
setLogs(res);
return;
}
console.log('Error: fetching logs from remote', { mockbinUrl, res });
+17 -19
View File
@@ -1,4 +1,3 @@
import { AxiosResponse } from 'axios';
import * as Har from 'har-format';
import React from 'react';
import { LoaderFunction, useFetcher, useParams, useRouteLoaderData } from 'react-router-dom';
@@ -89,12 +88,7 @@ export const useMockRoutePatcher = () => {
});
};
};
interface MockbinResult {
data: string; // returns only the mock server id not the path
}
interface MockbinError {
data: { errors: string };
}
export const MockRouteRoute = () => {
const { mockServer, mockRoute } = useRouteLoaderData(':mockRouteId') as MockRouteLoaderData;
const patchMockRoute = useMockRoutePatcher();
@@ -105,9 +99,15 @@ export const MockRouteRoute = () => {
const upsertBinOnRemoteFromResponse = async (compoundId: string | null): Promise<string> => {
try {
const res: AxiosResponse<MockbinResult | MockbinError> = await window.main.axiosRequest({
url: mockbinUrl + `/bin/upsert/${compoundId}`,
method: 'put',
const res = await window.main.insomniaFetch<string | {
error: string;
message: string;
}>({
origin: mockbinUrl,
path: `/bin/upsert/${compoundId}`,
method: 'PUT',
organizationId,
sessionId: getCurrentSessionId(),
data: mockRouteToHar({
statusCode: mockRoute.statusCode,
statusText: mockRoute.statusText,
@@ -115,19 +115,17 @@ export const MockRouteRoute = () => {
mimeType: mockRoute.mimeType,
body: mockRoute.body,
}),
headers: {
'X-Session-ID': getCurrentSessionId(),
},
});
if (typeof res?.data === 'object' && 'errors' in res?.data && typeof res?.data?.errors === 'string') {
console.error('error response', res?.data?.errors);
return res?.data?.errors;
if (typeof res === 'object' && 'message' in res && 'error' in res) {
console.error('error response', res);
return `${res.error}: ${res.message}`;
}
if (typeof res?.data === 'string') {
if (typeof res === 'string') {
return '';
}
console.log('Error: invalid response from remote', { res, mockbinUrl });
return 'Invalid response from ' + mockbinUrl;
return 'Unexpected response, see console for details';
} catch (e) {
console.log(e);
return 'Unhandled error: ' + e.message;
@@ -150,7 +148,7 @@ export const MockRouteRoute = () => {
title: 'Network error',
message: (
<div>
<p>The request failed due to a network error: {mockbinUrl}</p>
<p>The request failed due to a network error made to {mockbinUrl}</p>
<pre className="pad-top-sm force-wrap selectable">
<code className="wide">{error}</code>
</pre>
@@ -579,6 +579,7 @@ const ProjectRoute: FC = () => {
};
const createNewMockServer = () => {
activeProject.remoteId ?
showPrompt({
title: 'Create New Mock Server',
submitName: 'Create',
@@ -597,6 +598,10 @@ const ProjectRoute: FC = () => {
}
);
},
}) :
showModal(AlertModal, {
title: 'Change Project',
message: 'Mock feature is only supported for Cloud projects.',
});
};