remove axios, better api

This commit is contained in:
Sebastian 2023-01-02 15:11:28 -03:00
parent d48ea17c63
commit d1aa79eae8
No known key found for this signature in database
GPG Key ID: BE4FF68352439FC1
6 changed files with 44 additions and 180 deletions

View File

@ -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'
}, },

View File

@ -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",

View File

@ -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];
}
}

View File

@ -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";
/** /**

View File

@ -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) {

View File

@ -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,