remove axios, better api
This commit is contained in:
parent
d48ea17c63
commit
d1aa79eae8
@ -78,7 +78,7 @@ const buildConfigNode = {
|
|||||||
|
|
||||||
const buildConfigBrowser = {
|
const buildConfigBrowser = {
|
||||||
...buildConfigBase,
|
...buildConfigBase,
|
||||||
entryPoints: ["src/tests/axios.ts", "src/tests/swr.ts", "src/index.browser.ts", "src/live-reload.ts", 'src/stories.tsx'],
|
entryPoints: ["src/tests/mock.ts", "src/tests/swr.ts", "src/index.browser.ts", "src/live-reload.ts", 'src/stories.tsx'],
|
||||||
outExtension: {
|
outExtension: {
|
||||||
'.js': '.mjs'
|
'.js': '.mjs'
|
||||||
},
|
},
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
"private": false,
|
"private": false,
|
||||||
"exports": {
|
"exports": {
|
||||||
"./lib/tests/swr": "./lib/tests/swr.mjs",
|
"./lib/tests/swr": "./lib/tests/swr.mjs",
|
||||||
"./lib/tests/axios": "./lib/tests/axios.mjs",
|
"./lib/tests/mock": "./lib/tests/mock.mjs",
|
||||||
"./lib/index.browser": "./lib/index.browser.mjs",
|
"./lib/index.browser": "./lib/index.browser.mjs",
|
||||||
"./lib/index.node": "./lib/index.node.cjs"
|
"./lib/index.node": "./lib/index.node.cjs"
|
||||||
},
|
},
|
||||||
@ -29,7 +29,6 @@
|
|||||||
"@types/node": "^18.11.17",
|
"@types/node": "^18.11.17",
|
||||||
"@types/web": "^0.0.82",
|
"@types/web": "^0.0.82",
|
||||||
"@types/ws": "^8.5.3",
|
"@types/ws": "^8.5.3",
|
||||||
"axios": "^1.2.1",
|
|
||||||
"chokidar": "^3.5.3",
|
"chokidar": "^3.5.3",
|
||||||
"esbuild": "^0.14.21",
|
"esbuild": "^0.14.21",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
|
@ -1,136 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of GNU Taler
|
|
||||||
(C) 2022 Taler Systems S.A.
|
|
||||||
|
|
||||||
GNU Taler is free software; you can redistribute it and/or modify it under the
|
|
||||||
terms of the GNU General Public License as published by the Free Software
|
|
||||||
Foundation; either version 3, or (at your option) any later version.
|
|
||||||
|
|
||||||
GNU Taler 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
|
||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
|
|
||||||
// import axios, { AxiosPromise, AxiosRequestConfig } from "axios";
|
|
||||||
import * as axios from "axios";
|
|
||||||
import {
|
|
||||||
setAxiosRequestAsTestingEnvironment,
|
|
||||||
mockAxiosOnce,
|
|
||||||
} from "../utils/axios.js";
|
|
||||||
|
|
||||||
const TESTING_DEBUG_LOG = process.env["TESTING_DEBUG_LOG"] !== undefined;
|
|
||||||
|
|
||||||
const defaultCallback = (
|
|
||||||
actualQuery?: axios.AxiosRequestConfig,
|
|
||||||
): axios.AxiosPromise<any> => {
|
|
||||||
if (TESTING_DEBUG_LOG) {
|
|
||||||
console.log("UNEXPECTED QUERY", actualQuery);
|
|
||||||
}
|
|
||||||
throw Error(
|
|
||||||
"Default Axios mock callback is called, this mean that the test did a tried to use axios but there was no expectation in place, try using JEST_DEBUG_LOG env",
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
setAxiosRequestAsTestingEnvironment(defaultCallback);
|
|
||||||
|
|
||||||
export type Query<Req, Res> = {
|
|
||||||
method: axios.Method;
|
|
||||||
url: string;
|
|
||||||
code?: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
type ExpectationValues = {
|
|
||||||
query: Query<any, any>;
|
|
||||||
params?: {
|
|
||||||
auth?: string;
|
|
||||||
request?: object;
|
|
||||||
qparam?: Record<string, string>;
|
|
||||||
response?: object;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
type TestValues = [
|
|
||||||
axios.AxiosRequestConfig | undefined,
|
|
||||||
ExpectationValues | undefined,
|
|
||||||
];
|
|
||||||
|
|
||||||
export class AxiosMockEnvironment {
|
|
||||||
expectations: Array<
|
|
||||||
| {
|
|
||||||
query: Query<any, any>;
|
|
||||||
auth?: string;
|
|
||||||
params?: {
|
|
||||||
request?: object;
|
|
||||||
qparam?: Record<string, string>;
|
|
||||||
response?: object;
|
|
||||||
};
|
|
||||||
result: { args: axios.AxiosRequestConfig | undefined };
|
|
||||||
}
|
|
||||||
| undefined
|
|
||||||
> = [];
|
|
||||||
// axiosMock: jest.MockedFunction<axios.AxiosStatic>
|
|
||||||
|
|
||||||
addRequestExpectation<
|
|
||||||
RequestType extends object,
|
|
||||||
ResponseType extends object,
|
|
||||||
>(
|
|
||||||
expectedQuery: Query<RequestType, ResponseType>,
|
|
||||||
params: {
|
|
||||||
auth?: string;
|
|
||||||
request?: RequestType;
|
|
||||||
qparam?: any;
|
|
||||||
response?: ResponseType;
|
|
||||||
},
|
|
||||||
): void {
|
|
||||||
const result = mockAxiosOnce(function (
|
|
||||||
actualQuery?: axios.AxiosRequestConfig,
|
|
||||||
): axios.AxiosPromise {
|
|
||||||
if (TESTING_DEBUG_LOG) {
|
|
||||||
console.log("query to the backend is made", actualQuery);
|
|
||||||
}
|
|
||||||
if (!expectedQuery) {
|
|
||||||
return Promise.reject("a query was made but it was not expected");
|
|
||||||
}
|
|
||||||
if (TESTING_DEBUG_LOG) {
|
|
||||||
console.log("expected query:", params?.request);
|
|
||||||
console.log("expected qparams:", params?.qparam);
|
|
||||||
console.log("sending response:", params?.response);
|
|
||||||
}
|
|
||||||
|
|
||||||
const responseCode = expectedQuery.code || 200;
|
|
||||||
|
|
||||||
//This response is what buildRequestOk is expecting in file hook/backend.ts
|
|
||||||
if (responseCode >= 200 && responseCode < 300) {
|
|
||||||
return Promise.resolve({
|
|
||||||
data: params?.response,
|
|
||||||
config: {
|
|
||||||
data: params?.response,
|
|
||||||
params: actualQuery?.params || {},
|
|
||||||
},
|
|
||||||
request: { params: actualQuery?.params || {} },
|
|
||||||
} as any);
|
|
||||||
}
|
|
||||||
//This response is what buildRequestFailed is expecting in file hook/backend.ts
|
|
||||||
return Promise.reject({
|
|
||||||
response: {
|
|
||||||
status: responseCode,
|
|
||||||
},
|
|
||||||
request: {
|
|
||||||
data: params?.response,
|
|
||||||
params: actualQuery?.params || {},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} as any);
|
|
||||||
|
|
||||||
this.expectations.push({ query: expectedQuery, params, result });
|
|
||||||
}
|
|
||||||
|
|
||||||
getLastTestValues(): TestValues {
|
|
||||||
const expectedQuery = this.expectations.shift();
|
|
||||||
|
|
||||||
return [expectedQuery?.result.args, expectedQuery];
|
|
||||||
}
|
|
||||||
}
|
|
@ -44,31 +44,6 @@ export function createExample<Props>(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// export function createExampleWithCustomContext<Props, ContextProps>(
|
|
||||||
// Component: FunctionalComponent<Props>,
|
|
||||||
// props: Partial<Props> | (() => Partial<Props>),
|
|
||||||
// ContextProvider: FunctionalComponent<ContextProps>,
|
|
||||||
// contextProps: Partial<ContextProps>,
|
|
||||||
// ): ComponentChildren {
|
|
||||||
// /**
|
|
||||||
// * FIXME:
|
|
||||||
// * This may not be useful since the example can be created with context
|
|
||||||
// * already
|
|
||||||
// */
|
|
||||||
// const evaluatedProps = typeof props === "function" ? props() : props;
|
|
||||||
// const Render = (args: any): VNode => create(Component, args);
|
|
||||||
// const WithContext = (args: any): VNode =>
|
|
||||||
// create(ContextProvider, {
|
|
||||||
// ...contextProps,
|
|
||||||
// children: [Render(args)],
|
|
||||||
// } as any);
|
|
||||||
|
|
||||||
// return {
|
|
||||||
// component: WithContext,
|
|
||||||
// props: evaluatedProps,
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
const isNode = typeof window === "undefined";
|
const isNode = typeof window === "undefined";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,8 +48,10 @@ type ExpectationValues = {
|
|||||||
query: Query<any, any>;
|
query: Query<any, any>;
|
||||||
auth?: string;
|
auth?: string;
|
||||||
params?: {
|
params?: {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
request?: object;
|
request?: object;
|
||||||
qparam?: Record<string, string>;
|
qparam?: Record<string, string>;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
response?: object;
|
response?: object;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -59,7 +61,7 @@ type TestValues = {
|
|||||||
lastQuery: ExpectationValues | undefined;
|
lastQuery: ExpectationValues | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
const logger = new Logger("testing/swr.ts");
|
const logger = new Logger("testing/mock.ts");
|
||||||
|
|
||||||
export abstract class MockEnvironment {
|
export abstract class MockEnvironment {
|
||||||
expectations: Array<ExpectationValues> = [];
|
expectations: Array<ExpectationValues> = [];
|
||||||
@ -69,11 +71,13 @@ export abstract class MockEnvironment {
|
|||||||
debug: boolean;
|
debug: boolean;
|
||||||
constructor(debug: boolean) {
|
constructor(debug: boolean) {
|
||||||
this.debug = debug;
|
this.debug = debug;
|
||||||
this.registerRequest.bind(this);
|
this.saveRequestAndGetMockedResponse.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public addRequestExpectation<
|
public addRequestExpectation<
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
RequestType extends object,
|
RequestType extends object,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
ResponseType extends object,
|
ResponseType extends object,
|
||||||
>(
|
>(
|
||||||
query: Query<RequestType, ResponseType>,
|
query: Query<RequestType, ResponseType>,
|
||||||
@ -89,13 +93,12 @@ export abstract class MockEnvironment {
|
|||||||
if (this.debug) {
|
if (this.debug) {
|
||||||
logger.info("saving query as expected", expected);
|
logger.info("saving query as expected", expected);
|
||||||
}
|
}
|
||||||
this.mockApiIfNeeded();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract mockApiIfNeeded(): void;
|
public saveRequestAndGetMockedResponse<
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
public registerRequest<
|
|
||||||
RequestType extends object,
|
RequestType extends object,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
ResponseType extends object,
|
ResponseType extends object,
|
||||||
>(
|
>(
|
||||||
query: Query<RequestType, ResponseType>,
|
query: Query<RequestType, ResponseType>,
|
||||||
@ -167,8 +170,8 @@ export abstract class MockEnvironment {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private assertNextRequest(idx: number): AssertStatus {
|
private assertNextRequest(index: number): AssertStatus {
|
||||||
const { currentExpectedQuery, lastQuery } = this.getLastTestValues(idx);
|
const { currentExpectedQuery, lastQuery } = this.getLastTestValues(index);
|
||||||
|
|
||||||
if (!currentExpectedQuery) {
|
if (!currentExpectedQuery) {
|
||||||
return {
|
return {
|
||||||
@ -194,6 +197,9 @@ export abstract class MockEnvironment {
|
|||||||
return {
|
return {
|
||||||
result: "error-difference",
|
result: "error-difference",
|
||||||
diff: "url",
|
diff: "url",
|
||||||
|
last: lastQuery.query.url,
|
||||||
|
expected: currentExpectedQuery.query.url,
|
||||||
|
index,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -206,6 +212,9 @@ export abstract class MockEnvironment {
|
|||||||
return {
|
return {
|
||||||
result: "error-difference",
|
result: "error-difference",
|
||||||
diff: "query-body",
|
diff: "query-body",
|
||||||
|
expected: currentExpectedQuery.params?.request,
|
||||||
|
last: lastQuery.params?.request,
|
||||||
|
index,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
@ -214,12 +223,18 @@ export abstract class MockEnvironment {
|
|||||||
return {
|
return {
|
||||||
result: "error-difference",
|
result: "error-difference",
|
||||||
diff: "query-params",
|
diff: "query-params",
|
||||||
|
expected: currentExpectedQuery.params?.qparam,
|
||||||
|
last: lastQuery.params?.qparam,
|
||||||
|
index,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (!deepEquals(currentExpectedQuery.auth, lastQuery.auth)) {
|
if (!deepEquals(currentExpectedQuery.auth, lastQuery.auth)) {
|
||||||
return {
|
return {
|
||||||
result: "error-difference",
|
result: "error-difference",
|
||||||
diff: "query-auth",
|
diff: "query-auth",
|
||||||
|
expected: currentExpectedQuery.auth,
|
||||||
|
last: lastQuery.auth,
|
||||||
|
index,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,18 +284,30 @@ interface AssertExpectedQueryMethodMismatch {
|
|||||||
interface AssertExpectedQueryUrlMismatch {
|
interface AssertExpectedQueryUrlMismatch {
|
||||||
result: "error-difference";
|
result: "error-difference";
|
||||||
diff: "url";
|
diff: "url";
|
||||||
|
last: string;
|
||||||
|
expected: string;
|
||||||
|
index: number;
|
||||||
}
|
}
|
||||||
interface AssertExpectedQueryAuthMismatch {
|
interface AssertExpectedQueryAuthMismatch {
|
||||||
result: "error-difference";
|
result: "error-difference";
|
||||||
diff: "query-auth";
|
diff: "query-auth";
|
||||||
|
last: string | undefined;
|
||||||
|
expected: string | undefined;
|
||||||
|
index: number;
|
||||||
}
|
}
|
||||||
interface AssertExpectedQueryBodyMismatch {
|
interface AssertExpectedQueryBodyMismatch {
|
||||||
result: "error-difference";
|
result: "error-difference";
|
||||||
diff: "query-body";
|
diff: "query-body";
|
||||||
|
last: any;
|
||||||
|
expected: any;
|
||||||
|
index: number;
|
||||||
}
|
}
|
||||||
interface AssertExpectedQueryParamsMismatch {
|
interface AssertExpectedQueryParamsMismatch {
|
||||||
result: "error-difference";
|
result: "error-difference";
|
||||||
diff: "query-params";
|
diff: "query-params";
|
||||||
|
last: any;
|
||||||
|
expected: any;
|
||||||
|
index: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -383,7 +410,9 @@ function deepEquals(
|
|||||||
|
|
||||||
let keyIterator: string;
|
let keyIterator: string;
|
||||||
while (keySize--) {
|
while (keySize--) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
const _a = a as Record<string, object>;
|
const _a = a as Record<string, object>;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
const _b = b as Record<string, object>;
|
const _b = b as Record<string, object>;
|
||||||
|
|
||||||
keyIterator = aKeys[keySize];
|
keyIterator = aKeys[keySize];
|
||||||
@ -400,6 +429,7 @@ function deepEquals(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
function allKeysFromObject(obj: object): Array<string> {
|
function allKeysFromObject(obj: object): Array<string> {
|
||||||
const keys = [];
|
const keys = [];
|
||||||
for (const key in obj) {
|
for (const key in obj) {
|
||||||
|
@ -15,10 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { ComponentChildren, FunctionalComponent, h, VNode } from "preact";
|
import { ComponentChildren, FunctionalComponent, h, VNode } from "preact";
|
||||||
import { MockEnvironment, Query } from "./mock.js";
|
import { MockEnvironment } from "./mock.js";
|
||||||
import { SWRConfig } from "swr";
|
import { SWRConfig } from "swr";
|
||||||
|
|
||||||
export { Query };
|
|
||||||
/**
|
/**
|
||||||
* Helper for hook that use SWR inside.
|
* Helper for hook that use SWR inside.
|
||||||
*
|
*
|
||||||
@ -30,14 +29,10 @@ export class SwrMockEnvironment extends MockEnvironment {
|
|||||||
super(debug);
|
super(debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
mockApiIfNeeded(): void {
|
|
||||||
null; // do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
public buildTestingContext(): FunctionalComponent<{
|
public buildTestingContext(): FunctionalComponent<{
|
||||||
children: ComponentChildren;
|
children: ComponentChildren;
|
||||||
}> {
|
}> {
|
||||||
const __REGISTER_REQUEST = this.registerRequest.bind(this);
|
const __SAVE_REQUEST_AND_GET_MOCKED_RESPONSE = this.saveRequestAndGetMockedResponse.bind(this);
|
||||||
return function TestingContext({
|
return function TestingContext({
|
||||||
children,
|
children,
|
||||||
}: {
|
}: {
|
||||||
@ -47,8 +42,9 @@ export class SwrMockEnvironment extends MockEnvironment {
|
|||||||
SWRConfig,
|
SWRConfig,
|
||||||
{
|
{
|
||||||
value: {
|
value: {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
fetcher: (url: string, options: object) => {
|
fetcher: (url: string, options: object) => {
|
||||||
const mocked = __REGISTER_REQUEST(
|
const mocked = __SAVE_REQUEST_AND_GET_MOCKED_RESPONSE(
|
||||||
{
|
{
|
||||||
method: "get",
|
method: "get",
|
||||||
url,
|
url,
|
||||||
|
Loading…
Reference in New Issue
Block a user