add jest testing
This commit is contained in:
parent
c73008fe03
commit
21df4f3f78
3
.babelrc
Normal file
3
.babelrc
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"presets": ["@babel/preset-env", "@babel/preset-typescript"]
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['@typescript-eslint'],
|
||||
plugins: ['@typescript-eslint', "jest"],
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
@ -27,6 +27,7 @@ module.exports = {
|
||||
"@typescript-eslint/restrict-template-expressions": "off",
|
||||
"@typescript-eslint/unbound-method": "off",
|
||||
"@typescript-eslint/quotes": "warn",
|
||||
"@typescript-eslint/no-unused-expressions": "off",
|
||||
"arrow-parens": "off",
|
||||
"class-methods-use-this": "off",
|
||||
"func-names": "off",
|
||||
@ -38,11 +39,14 @@ module.exports = {
|
||||
"no-continue": "off",
|
||||
"no-plusplus": "off",
|
||||
"object-curly-newline": "off",
|
||||
"no-alert": "off",
|
||||
"no-restricted-globals": "off",
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
es6: true,
|
||||
jest: true,
|
||||
},
|
||||
ignorePatterns: ['.eslintrc.js', 'deploy-config.js']
|
||||
ignorePatterns: ['.eslintrc.js', 'deploy-config.js'],
|
||||
};
|
||||
|
||||
8544
package-lock.json
generated
8544
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
16
package.json
16
package.json
@ -3,21 +3,28 @@
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.18.6",
|
||||
"@babel/preset-typescript": "^7.18.6",
|
||||
"@types/happypack": "^5.0.2",
|
||||
"@types/html-webpack-plugin": "^3.2.6",
|
||||
"@types/jest": "^28.1.4",
|
||||
"@types/node": "^17.0.40",
|
||||
"@types/sass-loader": "^8.0.3",
|
||||
"@types/webpack": "^5.28.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.27.1",
|
||||
"@typescript-eslint/parser": "^5.27.1",
|
||||
"babel-jest": "^28.1.2",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"css-loader": "^6.7.1",
|
||||
"dotenv": "^16.0.1",
|
||||
"eslint": "^8.17.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-config-airbnb-typescript": "^17.0.0",
|
||||
"eslint-plugin-jest": "^26.5.3",
|
||||
"eslint-webpack-plugin": "^3.1.1",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
"jest": "^28.1.2",
|
||||
"jest-environment-jsdom": "^28.1.2",
|
||||
"mini-css-extract-plugin": "^2.6.0",
|
||||
"sass": "^1.52.2",
|
||||
"sass-loader": "^13.0.0",
|
||||
@ -38,7 +45,9 @@
|
||||
"scripts": {
|
||||
"start": "webpack serve --mode=development",
|
||||
"build": "webpack --mode=production",
|
||||
"deploy": "node deploy-config"
|
||||
"deploy": "node deploy-config",
|
||||
"test": "npx jest",
|
||||
"test-watch": "npx jest --watch"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "ksv741",
|
||||
@ -52,5 +61,10 @@
|
||||
"module": "true",
|
||||
"dependencies": {
|
||||
"normalize.css": "^8.0.1"
|
||||
},
|
||||
"jest": {
|
||||
"transform": {
|
||||
"\\.[jt]sx?$": "babel-jest"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Store } from 'core/createStore';
|
||||
import { Store } from 'core/store/createStore';
|
||||
import { $ } from 'core/dom';
|
||||
import { Emitter } from 'core/Emitter';
|
||||
import { ExcelComponent } from 'core/ExcelComponent';
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { ActionType } from 'redux/types';
|
||||
import { Store } from './createStore';
|
||||
import { Dom } from './dom';
|
||||
import { DomListener } from './DomListener';
|
||||
import { Emitter } from './Emitter';
|
||||
import { Store } from 'core/store/createStore';
|
||||
import { Dom } from 'core/dom';
|
||||
import { DomListener } from 'core/DomListener';
|
||||
import { Emitter } from 'core/Emitter';
|
||||
|
||||
interface ExcelComponentClass {
|
||||
toHTML: () => string;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { StateType } from 'redux/types';
|
||||
import { Store } from './createStore';
|
||||
import { Store } from './store/createStore';
|
||||
import { isEqual } from './utils';
|
||||
|
||||
export class StoreSubscriber {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { initialStyleState } from '../constants';
|
||||
|
||||
type SelectorType = string | HTMLElement;
|
||||
export type SelectorType = string | HTMLElement;
|
||||
|
||||
export interface DomClass {
|
||||
html(html?: string): string | DomClass;
|
||||
|
||||
38
src/core/routes/Router.spec.js
Normal file
38
src/core/routes/Router.spec.js
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @jest-environment jsdom
|
||||
*/
|
||||
|
||||
import { Router } from './router';
|
||||
import { Page } from '../Page';
|
||||
|
||||
class DashboardPage extends Page {
|
||||
getRoot() {
|
||||
const root = document.createElement('div');
|
||||
root.innerHTML = 'dashboard';
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
class ExcelPage extends Page {}
|
||||
|
||||
describe('Router:', () => {
|
||||
let router;
|
||||
let $root;
|
||||
|
||||
beforeEach(() => {
|
||||
$root = document.createElement('div');
|
||||
router = new Router($root, {
|
||||
excel: ExcelPage,
|
||||
dashboard: DashboardPage,
|
||||
});
|
||||
});
|
||||
|
||||
test('should be defined', () => {
|
||||
expect(router).toBeDefined();
|
||||
});
|
||||
|
||||
test('should render Dasboard Page', () => {
|
||||
router.changePageHandler();
|
||||
expect($root.innerHTML).toBe('<div>dashboard</div>');
|
||||
});
|
||||
});
|
||||
@ -1,17 +1,19 @@
|
||||
import { DashboardPage } from 'pages/DashboardPage';
|
||||
import { ExcelPage } from 'pages/ExcelPage';
|
||||
import { $, Dom } from 'core/dom';
|
||||
import { $, Dom, SelectorType } from 'core/dom';
|
||||
import { ActiveRoute } from './ActiveRoute';
|
||||
|
||||
type RoutesType = {
|
||||
dashboard: DashboardPage
|
||||
excel: ExcelPage
|
||||
};
|
||||
|
||||
export class Router {
|
||||
private $placeholder: Dom;
|
||||
private routes: {
|
||||
dashboard: DashboardPage
|
||||
excel: ExcelPage
|
||||
};
|
||||
private page: DashboardPage | ExcelPage;
|
||||
private routes: RoutesType;
|
||||
private page: DashboardPage | ExcelPage | null;
|
||||
|
||||
constructor(selector: string, routes: any) {
|
||||
constructor(selector: SelectorType, routes: RoutesType) {
|
||||
if (!selector) throw new Error('Selector not provided');
|
||||
|
||||
this.$placeholder = $(selector);
|
||||
@ -47,8 +49,8 @@ export class Router {
|
||||
// @ts-ignore
|
||||
this.page = new Page(ActiveRoute.param);
|
||||
|
||||
this.$placeholder.append(this.page.getRoot());
|
||||
this.page.afterRender();
|
||||
this.$placeholder.append(this.page?.getRoot());
|
||||
this.page?.afterRender();
|
||||
}
|
||||
|
||||
destroy() {
|
||||
|
||||
77
src/core/store/createStore.spec.js
Normal file
77
src/core/store/createStore.spec.js
Normal file
@ -0,0 +1,77 @@
|
||||
import { Store } from './createStore';
|
||||
|
||||
const initialState = {
|
||||
count: 0,
|
||||
};
|
||||
|
||||
const reducer = (state, action) => {
|
||||
if (action.type === 'ADD') {
|
||||
return { ...state, count: state.count + 1 };
|
||||
}
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
describe('Create store', () => {
|
||||
let store;
|
||||
let handler;
|
||||
|
||||
beforeEach(() => {
|
||||
store = new Store(reducer, initialState);
|
||||
handler = jest.fn();
|
||||
});
|
||||
|
||||
test('should return store object', () => {
|
||||
expect(store).toBeDefined();
|
||||
expect(store.dispatch).toBeDefined();
|
||||
expect(store.subscribe).toBeDefined();
|
||||
expect(store.getState).not.toBeUndefined();
|
||||
});
|
||||
|
||||
test('should return object as a state', () => {
|
||||
expect(store.getState()).toBeInstanceOf(Object);
|
||||
});
|
||||
|
||||
test('should return default state', () => {
|
||||
expect(store.getState()).toEqual(initialState);
|
||||
});
|
||||
|
||||
test('should change state if actions exist', () => {
|
||||
store.dispatch({ type: 'ADD' });
|
||||
expect(store.getState().count).toBe(1);
|
||||
});
|
||||
|
||||
test("should NOT change state if actions don't exist", () => {
|
||||
store.dispatch({ type: 'NOT_EXISTING_TYPE' });
|
||||
expect(store.getState().count).toBe(0);
|
||||
});
|
||||
|
||||
test('should call subscriber', () => {
|
||||
store.subscribe(handler);
|
||||
store.dispatch({ type: 'ADD' });
|
||||
|
||||
expect(handler).toHaveBeenCalled();
|
||||
expect(handler).toHaveBeenCalledWith(store.getState());
|
||||
});
|
||||
|
||||
test('should NOT call sub if unsubscribe', () => {
|
||||
const unsub = store.subscribe(handler);
|
||||
unsub.unsubscribe();
|
||||
store.dispatch({ type: 'ADD' });
|
||||
|
||||
expect(handler).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should dispatch in async way', () => {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
store.dispatch({ type: 'ADD' });
|
||||
}, 500);
|
||||
|
||||
setTimeout(() => {
|
||||
expect(store.getState().count).toBe(1);
|
||||
resolve();
|
||||
}, 1000);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,4 +1,4 @@
|
||||
import { ActionType, ReducerType, StateType, SubscribeType } from '../redux/types';
|
||||
import { ActionType, ReducerType, StateType, SubscribeType } from 'redux/types';
|
||||
|
||||
export class Store {
|
||||
state: StateType;
|
||||
@ -3,7 +3,7 @@ import { Formula } from 'components/formula/Formula';
|
||||
import { Header } from 'components/header/Header';
|
||||
import { Table } from 'components/table/Table';
|
||||
import { Toolbar } from 'components/toolbar/Toolbar';
|
||||
import { Store } from 'core/createStore';
|
||||
import { Store } from 'core/store/createStore';
|
||||
import { Page } from 'core/Page';
|
||||
import { debounce, storage } from 'core/utils';
|
||||
import { rootReducer } from 'redux/rootReducer';
|
||||
|
||||
@ -19,7 +19,8 @@
|
||||
"compilerOptions": {
|
||||
"module": "CommonJS",
|
||||
"strictPropertyInitialization": true,
|
||||
"sourceMap": true
|
||||
"sourceMap": true,
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user