little refactor

This commit is contained in:
Sergey Krylov 2022-07-10 23:05:25 +05:00
parent f7e04814a5
commit 3bd194816e
30 changed files with 120 additions and 110 deletions

View File

@ -1,4 +1,4 @@
import { $, Dom } from 'core/dom'; import { $, Dom } from 'core/Dom';
export function Loader(): Dom { export function Loader(): Dom {
return $.create('div', 'loader') return $.create('div', 'loader')

View File

@ -1,5 +1,5 @@
import { $ } from 'core/dom'; import { $ } from 'core/Dom';
import { Emitter } from 'core/Emitter'; import { Observer } from 'core/Observer';
import { ExcelComponent } from 'core/ExcelComponent'; import { ExcelComponent } from 'core/ExcelComponent';
import { Store } from 'core/store/Store'; import { Store } from 'core/store/Store';
import { StoreSubscriber } from 'core/StoreSubscriber'; import { StoreSubscriber } from 'core/StoreSubscriber';
@ -10,15 +10,20 @@ interface ExcelOptionsType {
store: any, store: any,
} }
type BaseComponentOption = {
observer: Observer;
store: Store;
};
export class Excel { export class Excel {
components: any[]; components: any[];
emitter: Emitter; observer: Observer;
store: Store; store: Store;
subscriber: StoreSubscriber; subscriber: StoreSubscriber;
constructor(options: ExcelOptionsType) { constructor(options: ExcelOptionsType) {
this.components = options.components; this.components = options.components;
this.emitter = new Emitter(); this.observer = new Observer();
this.store = options.store; this.store = options.store;
this.subscriber = new StoreSubscriber(this.store); this.subscriber = new StoreSubscriber(this.store);
} }
@ -26,8 +31,8 @@ export class Excel {
getRoot() { getRoot() {
const $root = $.create('div', 'excel'); const $root = $.create('div', 'excel');
const componentOptions = { const componentOptions: BaseComponentOption = {
emitter: this.emitter, observer: this.observer,
store: this.store, store: this.store,
}; };

View File

@ -1,4 +1,4 @@
import { Dom } from 'core/dom'; import { Dom } from 'core/Dom';
import { ExcelComponent, ComponentOptionsType } from 'core/ExcelComponent'; import { ExcelComponent, ComponentOptionsType } from 'core/ExcelComponent';
export class Formula extends ExcelComponent { export class Formula extends ExcelComponent {
@ -8,13 +8,10 @@ export class Formula extends ExcelComponent {
constructor($root: Dom, options: ComponentOptionsType) { constructor($root: Dom, options: ComponentOptionsType) {
super($root, { super($root, {
// @ts-ignore next-line
eventListeners: ['input', 'keydown'],
// @ts-ignore next-line
name: 'Formula',
// @ts-ignore next-line
subscribe: ['currentText'],
...options, ...options,
eventListeners: ['input', 'keydown'],
name: 'Formula',
subscribe: ['currentText'],
}); });
} }
@ -30,7 +27,7 @@ export class Formula extends ExcelComponent {
this.formulaInput = this.$root.find('#formula-input'); this.formulaInput = this.$root.find('#formula-input');
this.$on('table:select-cell', (cell: Dom) => { this.$onEventFromObserver('table:select-cell', (cell: Dom) => {
this.formulaInput.text = cell.data.value || ''; this.formulaInput.text = cell.data.value || '';
}); });
} }
@ -44,7 +41,8 @@ export class Formula extends ExcelComponent {
if (!target) return; if (!target) return;
const text = (target as HTMLElement).innerText.trim(); const text = (target as HTMLElement).innerText.trim();
this.$emit('formula:input', text);
this.$emitEventToObserver('formula:input', text);
} }
onKeydown(event: KeyboardEvent) { onKeydown(event: KeyboardEvent) {
@ -53,7 +51,7 @@ export class Formula extends ExcelComponent {
if (preventedKeys.includes(event.key)) event.preventDefault(); if (preventedKeys.includes(event.key)) event.preventDefault();
if (event.key === 'Enter') { if (event.key === 'Enter') {
this.$emit('formula:enter-press'); this.$emitEventToObserver('formula:enter-press');
} }
} }
} }

View File

@ -1,18 +1,18 @@
import { ComponentOptionsType, ExcelComponent } from 'core/ExcelComponent';
import * as actions from 'redux/action-creators'; import * as actions from 'redux/action-creators';
import { $, Dom } from 'core/dom'; import { $, Dom } from 'core/Dom';
import { ActiveRoute } from 'core/routes/ActiveRoute'; import { ActiveRoute } from 'core/routes/ActiveRoute';
import { ExcelComponentState } from 'core/ExcelComponentState';
import { deleteTable } from 'redux/action-creators'; import { deleteTable } from 'redux/action-creators';
export class Header extends ExcelComponentState { export class Header extends ExcelComponent {
static className = 'excel__header'; static className = 'excel__header';
constructor($root: Dom, options: any) { constructor($root: Dom, options: ComponentOptionsType) {
super($root, { super($root, {
...options,
name: 'Header', name: 'Header',
eventListeners: ['input', 'click'], eventListeners: ['input', 'click'],
subscribe: ['title'], subscribe: ['title'],
...options,
}); });
} }

View File

@ -1,7 +1,7 @@
import { startCellId } from 'components/table/table.functions'; import { startCellId } from 'components/table/table.functions';
import * as actions from 'redux/action-creators'; import * as actions from 'redux/action-creators';
import { $, Dom } from 'core/dom'; import { $, Dom } from 'core/Dom';
import { ExcelComponent } from 'core/ExcelComponent'; import { ComponentOptionsType, ExcelComponent } from 'core/ExcelComponent';
import { TableSelection } from 'components/table/TableSelection'; import { TableSelection } from 'components/table/TableSelection';
import { changeCurrentStyles } from 'redux/action-creators'; import { changeCurrentStyles } from 'redux/action-creators';
import { createTable } from 'components/table/table.template'; import { createTable } from 'components/table/table.template';
@ -15,11 +15,11 @@ export class Table extends ExcelComponent {
private selection: TableSelection; private selection: TableSelection;
constructor($root: Dom, options: any) { constructor($root: Dom, options: ComponentOptionsType) {
super($root, { super($root, {
...options,
name: 'Table', name: 'Table',
eventListeners: ['mousedown', 'keydown', 'input'], eventListeners: ['mousedown', 'keydown', 'input'],
...options,
}); });
} }
@ -36,9 +36,9 @@ export class Table extends ExcelComponent {
this.initTable(); this.initTable();
this.$on('formula:input', this.updateCurrentText); this.$onEventFromObserver('formula:input', this.updateCurrentText);
this.$on('formula:enter-press', () => this.selection.current.focus()); this.$onEventFromObserver('formula:enter-press', () => this.selection.current.focus());
this.$on('toolbar:applyStyle', this.updateCurrentStyles); this.$onEventFromObserver('toolbar:applyStyle', this.updateCurrentStyles);
} }
initTable() { initTable() {
@ -55,12 +55,12 @@ export class Table extends ExcelComponent {
Object.keys(size.col).forEach(key => { Object.keys(size.col).forEach(key => {
const cols = this.$root.findAll(`[data-col="${key}"]`); const cols = this.$root.findAll(`[data-col="${key}"]`);
cols.forEach(el => $(el as HTMLElement).css({ width: `${size.col[key]}px` })); cols.forEach(el => $(el as HTMLElement).css({ width: `${size.col[+key]}px` }));
}); });
Object.keys(size.row).forEach(key => { Object.keys(size.row).forEach(key => {
const rows = this.$root.findAll(`[data-row="${key}"]`); const rows = this.$root.findAll(`[data-row="${key}"]`);
rows.forEach(el => $(el as HTMLElement).css({ height: `${size.row[key]}px` })); rows.forEach(el => $(el as HTMLElement).css({ height: `${size.row[+key]}px` }));
}); });
} }
@ -83,11 +83,11 @@ export class Table extends ExcelComponent {
const $cell = this.$root.find(`[data-id="${startCellId}"]`); const $cell = this.$root.find(`[data-id="${startCellId}"]`);
this.selection.select($cell); this.selection.select($cell);
this.$emit('table:select-cell', $cell); this.$emitEventToObserver('table:select-cell', $cell);
} }
emitSelectCallback() { emitSelectCallback() {
this.$emit('table:select-cell', this.selection.current); this.$emitEventToObserver('table:select-cell', this.selection.current);
const styles = this.selection.current?.getStyles(Object.keys(initialStyleState)); const styles = this.selection.current?.getStyles(Object.keys(initialStyleState));
this.dispatchToStore(changeCurrentStyles(styles)); this.dispatchToStore(changeCurrentStyles(styles));

View File

@ -1,4 +1,4 @@
import { $, Dom } from 'core/dom'; import { $, Dom } from 'core/Dom';
import { getParamsFromCellId, startCellId } from 'components/table/table.functions'; import { getParamsFromCellId, startCellId } from 'components/table/table.functions';
export class TableSelection { export class TableSelection {

View File

@ -1,5 +1,5 @@
import { startCellId } from 'components/table/table.functions'; import { startCellId } from 'components/table/table.functions';
import { $, Dom } from 'core/dom'; import { $, Dom } from 'core/Dom';
type CustomElementType = Element & { css: any }; type CustomElementType = Element & { css: any };
type ResizeReturnDataType = { value: number, id: string, type: string }; type ResizeReturnDataType = { value: number, id: string, type: string };

View File

@ -1,4 +1,4 @@
import { $ } from 'core/dom'; import { $ } from 'core/Dom';
import { TableSelection } from 'components/table/TableSelection'; import { TableSelection } from 'components/table/TableSelection';
import { getParamsFromCellId, isCell, startCellId } from 'components/table/table.functions'; import { getParamsFromCellId, isCell, startCellId } from 'components/table/table.functions';
@ -68,7 +68,10 @@ export function selectHandler(event: MouseEvent | KeyboardEvent, selection: Tabl
} }
case 'Tab': { case 'Tab': {
event.preventDefault(); event.preventDefault();
col++;
if (event.shiftKey) col--;
else col++;
break; break;
} }
default: break; default: break;

View File

@ -1,4 +1,4 @@
import { $ } from 'core/dom'; import { $ } from 'core/Dom';
export function isCell(event: Event): boolean { export function isCell(event: Event): boolean {
return $(event.target as HTMLElement).data.type === 'cell'; return $(event.target as HTMLElement).data.type === 'cell';

View File

@ -1,5 +1,5 @@
import { startCellId } from 'components/table/table.functions'; import { startCellId } from 'components/table/table.functions';
import { $, Dom } from 'core/dom'; import { $, Dom } from 'core/Dom';
import { ExcelComponentState } from 'core/ExcelComponentState'; import { ExcelComponentState } from 'core/ExcelComponentState';
import { ComponentOptionsType } from 'core/ExcelComponent'; import { ComponentOptionsType } from 'core/ExcelComponent';
import { createToolbar } from 'components/toolbar/toolbar.template'; import { createToolbar } from 'components/toolbar/toolbar.template';
@ -50,14 +50,14 @@ export class Toolbar extends ExcelComponentState {
const value = JSON.parse(stringValue); const value = JSON.parse(stringValue);
const key = Object.keys(value)[0]; const key = Object.keys(value)[0];
this.$emit('toolbar:applyStyle', value); this.$emitEventToObserver('toolbar:applyStyle', value);
this.setComponentState({ [key]: value[key] }); this.setComponentState({ [key]: value[key] });
} }
onChange(e: any) { onChange(e: any) {
const value = `${e.target.value.toString()}px`; const value = `${e.target.value.toString()}px`;
this.$emit('toolbar:applyStyle', { fontSize: value }); this.$emitEventToObserver('toolbar:applyStyle', { fontSize: value });
this.setComponentState({ fontSize: value }); this.setComponentState({ fontSize: value });
} }
} }

View File

@ -4,5 +4,5 @@ export type ToolbarStateType = {
textDecoration?: 'none' | 'underline'; textDecoration?: 'none' | 'underline';
justifyContent?: 'start' | 'center' | 'end'; justifyContent?: 'start' | 'center' | 'end';
alignItems?: 'start' | 'center' | 'end'; alignItems?: 'start' | 'center' | 'end';
fontSize?: any; fontSize?: string;
}; };

View File

@ -85,7 +85,7 @@ export function createToolbar(state: ToolbarStateType): string {
return buttons.join(' '); return buttons.join(' ');
} }
function createFontSizeButton(currentSize: string) { function createFontSizeButton(currentSize = '12px') {
const fontSizeInPixels = +currentSize.slice(0, -2); const fontSizeInPixels = +currentSize.slice(0, -2);
const options = []; const options = [];
@ -95,9 +95,11 @@ function createFontSizeButton(currentSize: string) {
} }
return ` return `
<div class="button">
<select class="button__size" id="button-size"> <select class="button__size" id="button-size">
${options.join('')} ${options.join('')}
</select> </select>
</div>
`; `;
} }

View File

@ -31,7 +31,7 @@ export class LocalStorageClient implements ClientDataType {
}); });
} }
norm(state) { norm(state: StateType) {
return { return {
...state, ...state,
currentStyles: { ...state.stylesState?.[startCellId] }, currentStyles: { ...state.stylesState?.[startCellId] },

View File

@ -1,4 +1,4 @@
import { Dom } from 'core/dom'; import { Dom } from 'core/Dom';
import { capitalize } from 'core/utils'; import { capitalize } from 'core/utils';
export class DomListener { export class DomListener {

View File

@ -1,34 +1,28 @@
import { ActionType } from 'redux/types'; import { ActionType, StateType } from 'redux/types';
import { Dom } from 'core/dom'; import { Dom } from 'core/Dom';
import { DomListener } from 'core/DomListener'; import { DomListener } from 'core/DomListener';
import { Emitter } from 'core/Emitter'; import { Observer } from 'core/Observer';
import { Store } from 'core/store/Store'; import { Store } from 'core/store/Store';
interface ExcelComponentClass {
toHTML: () => string;
prepare: () => void;
storeChanged?: (args: any) => void;
}
export type ComponentOptionsType = { export type ComponentOptionsType = {
eventListeners: string[]; eventListeners: string[];
name: string; name: string;
emitter: Emitter; observer: Observer;
store: Store; store: Store;
subscribe: string[], subscribe: (keyof StateType)[],
}; };
export abstract class ExcelComponent extends DomListener implements ExcelComponentClass { export abstract class ExcelComponent extends DomListener {
private name: string; private name: string;
private emitter: Emitter; private observer: Observer;
public store: Store; public store: Store;
private subscribe: string[]; private subscribe: (keyof StateType)[];
private unsubscribers: ((args?: any) => any)[]; private unsubscribers: ((args?: any) => any)[];
constructor($root: Dom, options: ComponentOptionsType) { constructor($root: Dom, options: ComponentOptionsType) {
super($root, options.eventListeners); super($root, options.eventListeners);
this.name = options.name; this.name = options.name;
this.emitter = options.emitter; this.observer = options.observer;
this.store = options.store; this.store = options.store;
this.subscribe = options.subscribe; this.subscribe = options.subscribe;
@ -44,12 +38,12 @@ export abstract class ExcelComponent extends DomListener implements ExcelCompone
return ''; return '';
} }
$emit(event: string, args?: any): void { $emitEventToObserver(event: string, args?: any): void {
this.emitter?.emit(event, args); this.observer?.emit(event, args);
} }
$on(event: string, callback: (args: any) => any) { $onEventFromObserver(event: string, callback: (args: any) => any) {
const unsub = this.emitter?.subscribe(event, callback); const unsub = this.observer?.subscribe(event, callback);
unsub && this.unsubscribers.push(unsub); unsub && this.unsubscribers.push(unsub);
} }
@ -58,10 +52,10 @@ export abstract class ExcelComponent extends DomListener implements ExcelCompone
} }
storeChanged(args?: any) { storeChanged(args?: any) {
console.log('CHANGE STORE: ', args); console.log('CHANGE STORE: ', args, ' in component ', this.name);
} }
isWatching(key: string) { isWatching(key: keyof StateType) {
return this.subscribe?.includes(key); return this.subscribe?.includes(key);
} }

View File

@ -1,4 +1,4 @@
import { Dom } from 'core/dom'; import { Dom } from 'core/Dom';
import { ExcelComponent, ComponentOptionsType } from 'core/ExcelComponent'; import { ExcelComponent, ComponentOptionsType } from 'core/ExcelComponent';
type ExcelComponentStateType = { type ExcelComponentStateType = {

View File

@ -1,4 +1,4 @@
export class Emitter { export class Observer {
private listeners: { private listeners: {
[k: string]: Array<(args?: any) => any> [k: string]: Array<(args?: any) => any>
}; };
@ -7,16 +7,6 @@ export class Emitter {
this.listeners = {}; this.listeners = {};
} }
emit(eventName: string, args: any[]) {
if (!Array.isArray(this.listeners[eventName])) return false;
this.listeners[eventName].forEach(listener => {
listener(args);
});
return true;
}
subscribe(eventName: string, callback: (args?: any) => any) { subscribe(eventName: string, callback: (args?: any) => any) {
this.listeners[eventName] = this.listeners[eventName] || []; this.listeners[eventName] = this.listeners[eventName] || [];
this.listeners[eventName].push(callback); this.listeners[eventName].push(callback);
@ -25,4 +15,12 @@ export class Emitter {
this.listeners[eventName] = this.listeners[eventName].filter(listener => listener !== callback); this.listeners[eventName] = this.listeners[eventName].filter(listener => listener !== callback);
}; };
} }
emit(eventName: string, args: any[]) {
if (!Array.isArray(this.listeners[eventName])) return false;
this.listeners[eventName].forEach(listener => listener(args));
return true;
}
} }

View File

@ -5,9 +5,9 @@ import { StateType } from 'redux/types';
export class StateProcessor { export class StateProcessor {
private client: ClientDataType; private client: ClientDataType;
constructor(client: ClientDataType, dalay = 300) { constructor(client: ClientDataType, delay = 300) {
this.client = client; this.client = client;
this.listen = debounce(this.listen.bind(this), dalay); this.listen = debounce(this.listen.bind(this), delay);
} }
listen(state: StateType) { listen(state: StateType) {

View File

@ -4,30 +4,29 @@ import { isEqual } from 'core/utils';
export class StoreSubscriber { export class StoreSubscriber {
sub: any; sub: any;
prevState: StateType; currentState: StateType;
constructor(private store: Store) { constructor(private store: Store) {
this.sub = null; this.sub = null;
this.prevState = {};
} }
subscribeComponents(components: any[]) { subscribeComponents(components: any[]) {
this.prevState = this.store.getState(); this.currentState = this.store.getState();
this.sub = this.store.subscribeFromStore((state: StateType) => { this.sub = this.store.subscribeToStore((newState: StateType) => {
if (!state) return; if (!newState) return;
Object.keys(state).forEach(key => { Object.keys(newState).forEach((key) => {
if (!isEqual(this.prevState[key], state[key])) { if (!isEqual(this.currentState[key as keyof StateType], newState[key as keyof StateType])) {
components.forEach(component => { components.forEach(component => {
if (component.isWatching(key)) { if (component.isWatching(key)) {
const changes = { [key]: state[key] }; component.storeChanged({ [key]: newState[key as keyof StateType] });
component.storeChanged(changes);
} }
}); });
} }
}); });
this.prevState = this.store.getState();
this.currentState = this.store.getState();
}); });
} }

View File

@ -1,4 +1,4 @@
import { $, Dom, SelectorType } from 'core/dom'; import { $, Dom, SelectorType } from 'core/Dom';
import { ActiveRoute } from 'core/routes/ActiveRoute'; import { ActiveRoute } from 'core/routes/ActiveRoute';
import { DashboardPage } from 'pages/DashboardPage'; import { DashboardPage } from 'pages/DashboardPage';
import { ExcelPage } from 'pages/ExcelPage'; import { ExcelPage } from 'pages/ExcelPage';
@ -34,8 +34,8 @@ export class Router {
} }
async changePageHandler() { async changePageHandler() {
this.$placeholder.clear().append(this.loader);
this.page?.destroy(); this.page?.destroy();
this.$placeholder.clear().append(this.loader);
let Page; let Page;

View File

@ -9,8 +9,9 @@ export class Store {
this.listeners = []; this.listeners = [];
} }
subscribeFromStore(fn: (state: StateType) => void): SubscribeType { subscribeToStore(fn: (state: StateType) => void): SubscribeType {
this.listeners.push(fn); this.listeners.push(fn);
return { return {
unsubscribe: () => { unsubscribe: () => {
this.listeners = this.listeners.filter((l: any) => l !== fn); this.listeners = this.listeners.filter((l: any) => l !== fn);
@ -23,7 +24,7 @@ export class Store {
this.listeners.forEach(listener => listener(this.state)); this.listeners.forEach(listener => listener(this.state));
} }
getState() { getState(): StateType {
return JSON.parse(JSON.stringify(this.state)); return JSON.parse(JSON.stringify(this.state));
} }
} }

View File

@ -1,5 +1,5 @@
import './styles/index.scss'; import './styles/index.scss';
import { Router } from 'core/routes/router'; import { Router } from 'core/routes/Router';
import { DashboardPage } from 'pages/DashboardPage'; import { DashboardPage } from 'pages/DashboardPage';
import { ExcelPage } from 'pages/ExcelPage'; import { ExcelPage } from 'pages/ExcelPage';

View File

@ -1,7 +1,7 @@
export abstract class AbstractPage { export abstract class AbstractPage {
params: any; params: string[];
constructor(params: any) { constructor(params: string[]) {
this.params = params || Date.now().toString(); this.params = params || Date.now().toString();
} }

View File

@ -1,4 +1,4 @@
import { $ } from 'core/dom'; import { $ } from 'core/Dom';
import { AbstractPage } from 'pages/AbstractPage'; import { AbstractPage } from 'pages/AbstractPage';
import { storage } from 'core/utils'; import { storage } from 'core/utils';

View File

@ -32,7 +32,7 @@ export class ExcelPage extends AbstractPage {
const state = await this.processor.get(); const state = await this.processor.get();
const store = new Store(rootReducer, state); const store = new Store(rootReducer, state);
this.storeSub = store.subscribeFromStore(this.processor.listen); this.storeSub = store.subscribeToStore(this.processor.listen);
this.excel = new Excel({ this.excel = new Excel({
components: [Header, Toolbar, Formula, Table], components: [Header, Toolbar, Formula, Table],

View File

@ -17,13 +17,13 @@ export function rootReducer(state: StateType, action: ActionType) {
const newState: StateType = { ...state }; const newState: StateType = { ...state };
const fieldName = `${action.resizeData?.type}State`; const fieldName = `${action.resizeData?.type}State`;
newState[fieldName][action.resizeData?.id] = action.resizeData?.value; newState[fieldName as 'colState' | 'rowState'][action.resizeData?.id] = action.resizeData?.value;
return { ...state, ...newState }; return { ...state, ...newState };
} }
case CHANGE_TEXT: { case CHANGE_TEXT: {
const newState: StateType = state.dataState || {}; const newState: { [k: string]: string } = state.dataState || {};
const fieldName = action.data.id; const fieldName = action.data.id;
newState[fieldName] = action.data.text; newState[fieldName] = action.data.text;

12
src/redux/types.d.ts vendored
View File

@ -1,10 +1,20 @@
import { ToolbarStateType } from 'components/toolbar/toolbar-types';
export type ActionType = { export type ActionType = {
type: string type: string
[k: string]: any [k: string]: any
}; };
export type StateType = { export type StateType = {
[k: string]: any colState: { [k: number]: number };
rowState: { [k: number]: number };
currentStyles: ToolbarStateType;
dataState: { [k: string]: string };
id: string;
openDate: string;
stylesState: { [k: string]: ToolbarStateType };
title: string;
currentText: string;
}; };
export type ReducerType = (state: StateType, action: ActionType) => StateType; export type ReducerType = (state: StateType, action: ActionType) => StateType;

View File

@ -2,7 +2,7 @@
* @jest-environment jsdom * @jest-environment jsdom
*/ */
import { Router } from '../src/core/routes/router'; import { Router } from '../src/core/routes/Router';
import { AbstractPage } from '../src/pages/AbstractPage'; import { AbstractPage } from '../src/pages/AbstractPage';
class DashboardPage extends AbstractPage { class DashboardPage extends AbstractPage {

View File

@ -1,4 +1,4 @@
import { Store } from '../src/core/store/createStore'; import { Store } from '../src/core/store/Store';
const initialState = { const initialState = {
count: 0, count: 0,
@ -24,7 +24,7 @@ describe('Create store', () => {
test('should return store object', () => { test('should return store object', () => {
expect(store).toBeDefined(); expect(store).toBeDefined();
expect(store.dispatchToStore).toBeDefined(); expect(store.dispatchToStore).toBeDefined();
expect(store.subscribeFromStore).toBeDefined(); expect(store.subscribeToStore).toBeDefined();
expect(store.getState).not.toBeUndefined(); expect(store.getState).not.toBeUndefined();
}); });
@ -47,7 +47,7 @@ describe('Create store', () => {
}); });
test('should call subscriber', () => { test('should call subscriber', () => {
store.subscribeFromStore(handler); store.subscribeToStore(handler);
store.dispatchToStore({ type: 'ADD' }); store.dispatchToStore({ type: 'ADD' });
expect(handler).toHaveBeenCalled(); expect(handler).toHaveBeenCalled();
@ -55,7 +55,7 @@ describe('Create store', () => {
}); });
test('should NOT call sub if unsubscribe', () => { test('should NOT call sub if unsubscribe', () => {
const unsub = store.subscribeFromStore(handler); const unsub = store.subscribeToStore(handler);
unsub.unsubscribe(); unsub.unsubscribe();
store.dispatchToStore({ type: 'ADD' }); store.dispatchToStore({ type: 'ADD' });