feat(TEAMCACQ-23995): Добавлен модуль msb-acquiring

This commit is contained in:
Dmitriy Pogonyshev
2025-12-09 00:27:02 +08:00
parent 9f6c083664
commit 2b6954902b
29 changed files with 362 additions and 0 deletions
+5
View File
@@ -64,6 +64,10 @@ const ACCOUNTS_PATHS = {
OPEN_ACCOUNT_ORDERS_LIST: `${PATHS.ACCOUNTS}/open-account`, OPEN_ACCOUNT_ORDERS_LIST: `${PATHS.ACCOUNTS}/open-account`,
} as const; } as const;
const ACQUIRING_PATHS = {
HOME: PATHS.ACQUIRING,
};
const BUSINESS_CARDS_PATHS = { const BUSINESS_CARDS_PATHS = {
HOME: `${PATHS.BUSINESS_CARDS}/cards`, HOME: `${PATHS.BUSINESS_CARDS}/cards`,
DETAILS: `${PATHS.BUSINESS_CARDS}/cards-view/:id`, DETAILS: `${PATHS.BUSINESS_CARDS}/cards-view/:id`,
@@ -165,6 +169,7 @@ export {
CROSS_SELLING_JSON, CROSS_SELLING_JSON,
CROSS_BORDER_AB_PAYMENTS, CROSS_BORDER_AB_PAYMENTS,
ACCOUNTS_PATHS, ACCOUNTS_PATHS,
ACQUIRING_PATHS,
BUSINESS_CARDS_PATHS, BUSINESS_CARDS_PATHS,
CROSS_SALE_PATHS, CROSS_SALE_PATHS,
EXTERNAL_LINKS, EXTERNAL_LINKS,
+1
View File
@@ -12,6 +12,7 @@ const modules = [
'msb-fea', 'msb-fea',
'msb-partner-check', 'msb-partner-check',
'msb-treasury-deals', 'msb-treasury-deals',
'msb-acquiring'
]; ];
async function build() { async function build() {
+3
View File
@@ -0,0 +1,3 @@
# msb-accounts
Модуль "Эквайринг" МСБ
+24
View File
@@ -0,0 +1,24 @@
/* eslint-disable jest/no-jest-import */
import { pathsToModuleNameMapper } from 'ts-jest';
import { compilerOptions } from './tsconfig.json';
const config = {
clearMocks: true,
testEnvironment: 'jsdom',
transform: {
'^.+\\.(ts|tsx)$': 'ts-jest',
},
verbose: true,
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
roots: ['<rootDir>'],
modulePaths: [compilerOptions.baseUrl],
moduleNameMapper: {
...pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/' }),
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/src/mocks/fileMock.js',
'\\.(css|less|scss|sass)$': 'identity-obj-proxy',
},
setupFilesAfterEnv: ['<rootDir>/src/mocks/setupTests.ts'],
};
export default config;
+79
View File
@@ -0,0 +1,79 @@
{
"name": "msb-acquiring",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "build-app start",
"build:dev": "build-app build:dev",
"build": "build-app build",
"lint-fix": "eslint --fix --ext .js,.jsx,.ts,.tsx ./src",
"check-types": "tsc",
"lint": "eslint --ext .js,.jsx,.ts,.tsx ./src --max-warnings=0",
"stylelint": "stylelint --fix --ext .js,.jsx,.ts,.tsx ./src --max-warnings=0",
"lint:ci": "eslint --quiet --ext .js,.jsx,.ts,.tsx ./src",
"format": "prettier --write ./src",
"check-format": "prettier -c .",
"test:coverage": "echo 'skipped'",
"test": "jest --passWithNoTests",
"precommit": "lint-staged"
},
"author": "Pogonyshev Dmitriy",
"license": "ISC",
"dependencies": {
"@emotion/react": "11.8.1",
"@emotion/styled": "11.8.1",
"@fractal-ui/core": "30.15.0",
"@fractal-ui/extended": "30.15.0",
"@fractal-ui/form": "30.15.0",
"@fractal-ui/layout": "30.15.0",
"@fractal-ui/library": "31.4.0",
"@fractal-ui/overlays": "30.15.0",
"@fractal-ui/styling": "30.18.0",
"@fractal-ui/table": "30.15.0",
"@fractal-ui/visualization": "30.15.0",
"@msb/fractal-ui-composites": "30.15.1",
"@msb/http": "^1.0.0",
"@msb/mf-utils": "^1.0.0",
"@msb/shared": "^1.0.0",
"@styled-system/css": "^5.1.5",
"dayjs": "^1.11.3",
"react": "17.0.2",
"react-animate-height": "^2.0.23",
"react-dnd": "^11.1.3",
"react-dnd-html5-backend": "^11.1.3",
"react-dom": "17.0.2",
"react-final-form": "6.5.3",
"react-router-dom": "5.2.0",
"react-test-renderer": "17.0.2",
"styled-system": "5.1.5",
"virtua": "^0.31.0"
},
"devDependencies": {
"@eco/lint-staged-config": "21.10.0",
"@fractal-ui/layout": "30.15.0",
"@msb/mf-builder": "1.0.0",
"@testing-library/jest-dom": "5.16.2",
"@testing-library/react": "12.1.3",
"@testing-library/react-hooks": "7.0.2",
"@testing-library/user-event": "13.5.0",
"@types/jest": "^27.4.0",
"@types/react": "17.0.36",
"@types/react-dom": "17.0.2",
"@types/react-router-dom": "5.1.7",
"@types/react-test-renderer": "17.0.2",
"@types/react-transition-group": "4.4.1",
"@types/styled-system": "5.1.15",
"@types/styled-system__css": "5.0.16",
"jest": "^27.0.6",
"jest-environment-jsdom": "^27.5.1",
"json-server": "^0.16.3",
"lint-staged": "^12.3.4",
"react-test-renderer": "17.0.2"
},
"browserslist": [
">0.2%",
"not dead",
"not op_mini all"
]
}
+2
View File
@@ -0,0 +1,2 @@
export { FractalThemeProvider } from './providers';
export { AppRouter } from './router';
@@ -0,0 +1,11 @@
import type { FC } from 'react';
import { ThemeProvider } from '@emotion/react';
import { useTheme } from '@fractal-ui/styling';
const FractalThemeProvider: FC = ({ children }) => {
const theme = useTheme();
return <ThemeProvider theme={theme}>{children}</ThemeProvider>;
};
export { FractalThemeProvider };
@@ -0,0 +1 @@
export * from './FractalThemeProvider';
@@ -0,0 +1 @@
export { AppRouter } from './router';
@@ -0,0 +1,11 @@
import { ACQUIRING_PATHS } from '@msb/shared';
import { Route, Switch } from 'react-router-dom';
import { AcquiringMainPage } from '@/pages/AcquiringMainPage';
const AppRouter = () => (
<Switch>
<Route exact component={AcquiringMainPage} path={ACQUIRING_PATHS.HOME} />
</Switch>
);
export { AppRouter };
+19
View File
@@ -0,0 +1,19 @@
import { StrictMode } from 'react';
import { FractalThemeProvider } from '@fractal-ui/styling';
import { render } from 'react-dom';
import App from './exposes/App';
// Глобальные стили
import '@fractal-ui/styling/dist/fonts.css';
const rootNode = document.querySelector('#root');
render(
<StrictMode>
<FractalThemeProvider theme="Light">
<App />
</FractalThemeProvider>
</StrictMode>,
rootNode
);
+9
View File
@@ -0,0 +1,9 @@
declare module '*.svg' {
const content: string;
export default content;
}
declare module '*.webp' {
const content: any;
export default content;
}
@@ -0,0 +1,6 @@
import type { ReactElement } from 'react';
import { AppRouter } from '@/app/router';
const App = (): ReactElement => <AppRouter />;
export default App;
+3
View File
@@ -0,0 +1,3 @@
import('./bootstrap');
export default {};
@@ -0,0 +1 @@
module.exports = 'test-file-stub';
@@ -0,0 +1,21 @@
export class MatchMediaMock {
private handlers: Array<(event: MediaQueryListEvent) => void> = [];
mock(matches: boolean): {
matches: boolean;
addEventListener(_event: string, handler: (event: MediaQueryListEvent) => void): void;
removeEventListener(): void;
} {
return {
matches,
addEventListener: (_event: string, handler: (event: MediaQueryListEvent) => void) => {
this.handlers.push(handler);
},
removeEventListener: jest.fn(),
};
}
dispatchEvent(event: MediaQueryListEvent): void {
for (const handler of this.handlers) handler(event);
}
}
@@ -0,0 +1,11 @@
type ResizeObserverCallback = (entries: ResizeObserverEntry[], observer: ResizeObserver) => void;
export class ResizeObserverMock {
private callback: ResizeObserverCallback;
constructor(callback: ResizeObserverCallback) {
this.callback = callback;
}
observe(): void {}
unobserve(): void {}
disconnect(): void {}
}
@@ -0,0 +1,50 @@
import { MatchMediaMock } from './matchMediaMock';
import { ResizeObserverMock } from './resizeObserverMock';
jest.spyOn(window.console, 'error').mockImplementation();
const matchMediaMock = new MatchMediaMock();
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation(() => matchMediaMock.mock(false)),
});
global.ResizeObserver = ResizeObserverMock;
const mockIntersectionObserver = jest.fn();
mockIntersectionObserver.mockReturnValue({
observe: () => null,
unobserve: () => null,
disconnect: () => null,
});
window.IntersectionObserver = mockIntersectionObserver;
const mockAxiosInstance = {
get: jest.fn(),
post: jest.fn(),
put: jest.fn(),
delete: jest.fn(),
interceptors: {
request: { use: jest.fn(), eject: jest.fn() },
response: { use: jest.fn(), eject: jest.fn() },
},
};
jest.mock('axios', () => ({
__esModule: true,
default: {
create: jest.fn(() => mockAxiosInstance),
},
}));
jest.mock('egoroof-blowfish', () => ({
__esModule: true,
Blowfish: jest.fn().mockImplementation(() => ({
encode: jest.fn().mockReturnValue('encoded'),
decode: jest.fn().mockReturnValue('decoded'),
})),
}));
export {};
@@ -0,0 +1,25 @@
/* eslint-disable jest/no-mocks-import */
import { render } from '@msb/shared/lib/tests/customRender';
import '@testing-library/jest-dom';
import { screen } from '@testing-library/react';
import { LOCALIZATION } from '../constants';
import { AcquiringMainPage } from '../ui/AcquiringMainPage';
const historyPushMock = jest.fn();
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useHistory: () => ({
push: historyPushMock,
}),
}));
const renderAccountsMainPage = () => render(<AcquiringMainPage />);
describe('AcquiringMainPage', () => {
it('должен отображать эквайринг', () => {
renderAccountsMainPage();
expect(screen.queryByText(LOCALIZATION.ACQUIRING)).toBeInTheDocument();
});
});
@@ -0,0 +1 @@
export * from './localization';
@@ -0,0 +1,5 @@
const LOCALIZATION = {
ACQUIRING: 'Эквайринг',
};
export { LOCALIZATION };
@@ -0,0 +1 @@
export * from './ui';
@@ -0,0 +1,6 @@
import { type ReactElement } from 'react';
import { LOCALIZATION } from '../constants';
const AcquiringMainPage = (): ReactElement => <div>{LOCALIZATION.ACQUIRING}</div>;
export { AcquiringMainPage };
@@ -0,0 +1 @@
export { AcquiringMainPage } from './AcquiringMainPage';
+9
View File
@@ -0,0 +1,9 @@
declare module '*.png' {
const value: any;
export = value;
}
declare module '*.svg' {
const content: React.FunctionComponent<React.SVGAttributes<SVGElement>>;
export default content;
}
+10
View File
@@ -0,0 +1,10 @@
import { ReactNode } from 'react';
import { ThemeType } from '@fractal-ui/styling';
declare module '@fractal-ui/styling' {
export declare const FractalThemeProvider: React.FC<{
/** Название темы. */
theme?: ThemeType;
children: ReactNode;
}>;
}
+18
View File
@@ -0,0 +1,18 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/app/*": ["./src/app/*"],
"@/shared/*": ["src/shared/*"],
"@/pages/*": ["./src/pages/*"],
"@/widgets/*": ["./src/widgets/*"],
"@/features/*": ["./src/features/*"],
"@/entities/*": ["./src/entities/*"],
"@/mocks/*": ["./src/mocks/*"]
},
"types": ["node", "jest"]
},
"include": ["src"],
"exclude": ["node_modules", "./webpack.config.ts"]
}
+27
View File
@@ -0,0 +1,27 @@
import type { IWebpackAppConfig } from '@msb/mf-builder';
import { normalizePackageName } from '@msb/mf-builder';
import path from 'node:path';
import packageJson from './package.json';
const packageName = normalizePackageName(packageJson.name);
const config: IWebpackAppConfig = {
moduleName: packageJson.name,
paths: {
outputPath: path.resolve(__dirname, '../../msb-acquiring'),
publicUrl: '/msb-acquiring/',
},
devServerOptions: {
port: 3012,
},
moduleFederationOptions: {
exposes: {
'./App': {
import: path.resolve(__dirname, 'src/exposes/App.tsx'),
name: `${packageName}_remote`,
},
},
},
};
export default config;
+1
View File
@@ -65,6 +65,7 @@ const config: IWebpackAppConfig = {
{ context: ['/msb-business-cards'], target: 'http://localhost:3011', changeOrigin: true }, { context: ['/msb-business-cards'], target: 'http://localhost:3011', changeOrigin: true },
{ context: ['/msb-accounts'], target: 'http://localhost:3006', changeOrigin: true }, { context: ['/msb-accounts'], target: 'http://localhost:3006', changeOrigin: true },
{ context: ['/msb-treasury-deals'], target: 'http://localhost:3010', changeOrigin: true }, { context: ['/msb-treasury-deals'], target: 'http://localhost:3010', changeOrigin: true },
{ context: ['/msb-acquiring'], target: 'http://localhost:3012', changeOrigin: true },
{ {
context: ['/api', '/.well-known'], context: ['/api', '/.well-known'],
target: 'https://client.stage.gboteam.ru', target: 'https://client.stage.gboteam.ru',