Skip to content

Commit

Permalink
#38
Browse files Browse the repository at this point in the history
- preset/isomorphic: утилиты разнесены по отдельным файлам (major)
- добавлены тесты config и utils/axios (patch)
  • Loading branch information
krutoo committed Mar 7, 2024
1 parent 32fba0c commit 73ec87a
Show file tree
Hide file tree
Showing 34 changed files with 1,647 additions and 1,529 deletions.
20 changes: 20 additions & 0 deletions src/config/__test__/base.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { createBaseConfig } from '../base';
import { createConfigSource } from '../source';

describe('createBaseConfig', () => {
it('should works properly', () => {
const source = createConfigSource({
NODE_ENV: 'tests',
APP_NAME: 'foobar',
APP_VERSION: 'good',
});

const config = createBaseConfig(source);

expect(config).toEqual({
env: 'tests',
appName: 'foobar',
appVersion: 'good',
});
});
});
16 changes: 16 additions & 0 deletions src/config/__test__/source.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { createConfigSource } from '../source';

describe('createConfigSource', () => {
beforeEach(() => {
(globalThis as any).__ISOMORPH_ENV__ = {
NODE_ENV: 'tests',
};
});

it('should works properly', () => {
const source = createConfigSource({ EXTRA_VAR: '123' });

expect(source.get('NODE_ENV')).toBe('tests');
expect(source.get('EXTRA_VAR')).toBe('123');
});
});
10 changes: 4 additions & 6 deletions src/preset/bun-handler/providers/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,10 @@ import {
LogHandlerFactory,
} from '../../../http';
import { Fragment } from 'react';
import {
FetchLogging,
getFetchErrorLogging,
getFetchExtraAborting,
getFetchLogging,
} from '../../isomorphic/utils';
import { getFetchErrorLogging } from '../../isomorphic/utils/get-fetch-error-logging';
import { getFetchExtraAborting } from '../../isomorphic/utils/get-fetch-extra-aborting';
import { getFetchLogging } from '../../isomorphic/utils/get-fetch-logging';
import { FetchLogging } from '../../isomorphic/utils/fetch-logging';
import { PageAssets } from '../../isomorphic/types';
import { RESPONSE_EVENT_TYPE } from '../../isomorphic/constants';
import { getPageResponseFormat } from '../../server/utils/get-page-response-format';
Expand Down
3 changes: 2 additions & 1 deletion src/preset/isomorphic/providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { BaseConfig } from '../../../config/types';
import { Resolve } from '../../../di';
import { LogMiddlewareHandlerInit } from '../../../utils/axios/middleware/log';
import { KnownToken } from '../../../tokens';
import { AxiosLogging, SagaLogging } from '../utils';
import { AxiosLogging } from '../utils/axios-logging';
import { SagaLogging } from '../utils/saga-logging';
import createSagaMiddleware, { SagaMiddleware } from 'redux-saga';
import { applyMiddleware, configureFetch } from '../../../http';
import { CreateAxiosDefaults } from 'axios';
Expand Down
325 changes: 325 additions & 0 deletions src/preset/isomorphic/utils/__test__/axios-logging.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,325 @@
import {
AxiosDefaults,
AxiosRequestConfig,
AxiosResponse,
InternalAxiosRequestConfig,
} from 'axios';
import { Breadcrumb, DetailedError, Logger, createLogger } from '../../../../log';
import { AxiosLogging } from '../axios-logging';
import { severityFromStatus } from '../severity-from-status';

describe('AxiosLogging', () => {
const logger: Logger = {
log: jest.fn(),
info: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
debug: jest.fn(),
subscribe: jest.fn(),
};

beforeEach(() => {
(logger.info as jest.Mock).mockClear();
(logger.error as jest.Mock).mockClear();
});

it('methods should do nothing when disabled', () => {
const spy = jest.fn();
const someLogger = createLogger();
const handler = new AxiosLogging(someLogger, { config: {}, defaults: { headers: {} as any } });

someLogger.subscribe(spy);
handler.disabled = () => true;

expect(spy).toHaveBeenCalledTimes(0);

handler.beforeRequest();

expect(spy).toHaveBeenCalledTimes(0);

handler.afterResponse({
response: {
status: 200,
statusText: '200',
data: {},
headers: {},
config: {} as any,
},
config: {},
defaults: { headers: {} as any },
});

expect(spy).toHaveBeenCalledTimes(0);

handler.onCatch({
config: {},
defaults: { headers: {} as any },
error: new Error('fake error'),
});

expect(spy).toHaveBeenCalledTimes(0);
});

it('should log ready url properly when baseURL and url provided', async () => {
const config: InternalAxiosRequestConfig<any> = {
url: '/foo/bar',
} as any;

const defaults: AxiosDefaults<any> = {
headers: {} as any,
baseURL: 'https://sima.com/',
};

const response: AxiosResponse = {
status: 200,
statusText: '200',
data: {},
headers: {},
config,
};

const handler = new AxiosLogging(logger, { config, defaults });

handler.beforeRequest();
handler.afterResponse({ config, defaults, response });

expect(logger.info).toHaveBeenCalledTimes(2);
expect((logger.info as jest.Mock).mock.calls[0]).toEqual([
new Breadcrumb({
category: 'http.request',
type: 'http',
data: {
url: 'https://sima.com/foo/bar',
method: 'get',
params: undefined,
},
level: 'info',
}),
]);
expect((logger.info as jest.Mock).mock.calls[1]).toEqual([
new Breadcrumb({
category: 'http.response',
type: 'http',
data: {
url: 'https://sima.com/foo/bar',
method: 'get',
params: undefined,
status_code: 200,
},
level: 'info',
}),
]);
});

it('should log ready url properly when only baseURL provided', async () => {
const config: InternalAxiosRequestConfig<any> = {} as any;

const defaults: AxiosDefaults<any> = {
headers: {} as any,
baseURL: 'https://sima.com/',
};

const response: AxiosResponse = {
status: 200,
statusText: '200',
data: {},
headers: {},
config: {} as any,
};

const handler = new AxiosLogging(logger, { config, defaults });

handler.beforeRequest();
handler.afterResponse({ config, defaults, response });

expect(logger.info).toHaveBeenCalledTimes(2);
expect((logger.info as jest.Mock).mock.calls[0]).toEqual([
new Breadcrumb({
category: 'http.request',
type: 'http',
data: {
url: 'https://sima.com/',
method: 'get',
params: undefined,
},
level: 'info',
}),
]);
expect((logger.info as jest.Mock).mock.calls[1]).toEqual([
new Breadcrumb({
category: 'http.response',
type: 'http',
data: {
url: 'https://sima.com/',
method: 'get',
params: undefined,
status_code: 200,
},
level: 'info',
}),
]);
});

it('should log ready url properly when only url provided', async () => {
const config: AxiosRequestConfig<any> = {
url: 'https://ya.ru',
params: { foo: 'bar' },
};

const defaults: AxiosDefaults<any> = {
headers: {} as any,
};

const response: AxiosResponse = {
status: 200,
statusText: '200',
data: {},
headers: {},
config: {} as any,
};

const handler = new AxiosLogging(logger, { config, defaults });

handler.beforeRequest();
handler.afterResponse({ config, defaults, response });

expect(logger.info).toHaveBeenCalledTimes(2);
expect((logger.info as jest.Mock).mock.calls[0]).toEqual([
new Breadcrumb({
category: 'http.request',
type: 'http',
data: {
url: 'https://ya.ru',
method: 'get',
params: { foo: 'bar' },
},
level: 'info',
}),
]);
expect((logger.info as jest.Mock).mock.calls[1]).toEqual([
new Breadcrumb({
category: 'http.response',
type: 'http',
data: {
url: 'https://ya.ru',
method: 'get',
params: { foo: 'bar' },
status_code: 200,
},
level: 'info',
}),
]);
});

it('should log axios error', async () => {
const error = {
name: 'TestError',
message: 'test',
response: { status: 407 },
isAxiosError: true,
toJSON: () => error,
};

const config: AxiosRequestConfig<any> = {
url: 'https://ya.ru',
params: { bar: 'baz' },
};

const defaults: AxiosDefaults<any> = {
headers: {} as any,
};

const handler = new AxiosLogging(logger, { config, defaults });

expect(logger.error).toHaveBeenCalledTimes(0);
expect(logger.info).toHaveBeenCalledTimes(0);

handler.beforeRequest();
handler.onCatch({ config, defaults, error });

expect(logger.error).toHaveBeenCalledTimes(1);
expect(logger.info).toHaveBeenCalledTimes(2);
});

it('should log axios error without status', async () => {
const error = {
name: 'TestError',
message: 'test',
response: { status: undefined },
isAxiosError: true,
toJSON: () => error,
};

const config: AxiosRequestConfig<any> = {
url: 'https://ya.ru',
};

const defaults: AxiosDefaults<any> = {
headers: {} as any,
};

const handler = new AxiosLogging(logger, { config, defaults });

expect(logger.error).toHaveBeenCalledTimes(0);
expect(logger.info).toHaveBeenCalledTimes(0);

handler.beforeRequest();
handler.onCatch({ config, defaults, error });

expect(logger.error).toHaveBeenCalledTimes(1);
expect(logger.info).toHaveBeenCalledTimes(1);

const loggerErrorArgument: any = (logger.error as jest.Mock).mock.calls[0][0];

expect(loggerErrorArgument instanceof DetailedError).toBe(true);
expect(loggerErrorArgument).toEqual(
new DetailedError(`HTTP request failed, status code: UNKNOWN, error message: test`, {
level: severityFromStatus(error.response?.status),
context: {
key: 'Request details',
data: {
error,
url: 'https://ya.ru',
baseURL: undefined,
method: 'GET',
headers: {
...config.headers,
...defaults.headers.get,
},
params: { bar: 'baz' },
data: undefined,
},
},
}),
);

expect(loggerErrorArgument.data.context[1].data.error).toBe(error);
});

it('should log NOT axios error', async () => {
const error = {
name: 'TestError',
message: 'test',
response: { status: 407 },
};

const config: AxiosRequestConfig<any> = {
url: 'https://ya.ru',
};

const defaults: AxiosDefaults<any> = {
headers: {} as any,
};

const handler = new AxiosLogging(logger, { config, defaults });

expect(logger.error).toHaveBeenCalledTimes(0);
expect(logger.info).toHaveBeenCalledTimes(0);

handler.beforeRequest();
handler.onCatch({ config, defaults, error });

expect(logger.error).toHaveBeenCalledTimes(1);
expect(logger.info).toHaveBeenCalledTimes(1);
});
});
Loading

0 comments on commit 73ec87a

Please sign in to comment.