mirror of
https://github.com/Kong/insomnia.git
synced 2026-10-26 08:38:58 -04:00
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:
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();
|
||||
});
|
||||
@@ -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) } : {}),
|
||||
};
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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.',
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user