diff --git a/src/components/store/actions/blockReducerActions.ts b/src/components/store/actions/blockReducerActions.ts new file mode 100644 index 00000000..3592a9f3 --- /dev/null +++ b/src/components/store/actions/blockReducerActions.ts @@ -0,0 +1,39 @@ +import { OutputBlockData } from '../../../../types'; +import { BlockMutationType } from '../../../../types/events/block/mutation-type'; +import { ChangeBlockDataAction, CreateBlockAction, RemoveBlockAction } from '../../../../types/store/action'; + +/** + * Action creator for creating a new block in the store + * + * @param block - new block data + */ +export function makeCreateBlockAction(block: OutputBlockData): CreateBlockAction { + return { + type: BlockMutationType.Added, + data: block, + }; +} + +/** + * Action creator for changing block data in the store + * + * @param block - new block data + */ +export function makeChangeBlockAction(block: OutputBlockData): ChangeBlockDataAction { + return { + type: BlockMutationType.Changed, + data: block, + }; +} + +/** + * Action creator for removing block data from the store + * + * @param blockId - id of a block for removing + */ +export function makeRemoveBlockAction(blockId: string): RemoveBlockAction { + return { + type: BlockMutationType.Removed, + blockId, + }; +} diff --git a/src/components/store/demo.ts b/src/components/store/demo.ts deleted file mode 100644 index b62e0576..00000000 --- a/src/components/store/demo.ts +++ /dev/null @@ -1,79 +0,0 @@ -import store from './index'; -import { BlockMutationType } from '../../../types/events/block/mutation-type'; -import { EditorState } from '../../../types/store/editorState'; -import { Listener } from '../../../types/store/listener'; - -/** - * Handle changes with previous and current states - */ -const onDataChange = (): Listener => { - /** - * Initial state - */ - let currentState = store.getState(); - - /** - * onChange handler - * - * @param changedState - changed state after dispatching - */ - return (changedState: EditorState): void => { - const prevState = currentState; - - currentState = changedState; - - console.log('***'); - console.log('Previous state:', prevState); - console.log('Current state:', currentState); - console.log('***'); - }; -}; - -const unsubscribeOnDataChange = store.subscribe(onDataChange()); - -const block1 = { - id: '3JPEqh8_Wc', - type: 'header', - data: { - text: 'Editor.js', - level: 2, - }, -}; - -const block2 = { - id: 'AsbMKCuatV', - type: 'paragraph', - data: { - text: 'Hey. Meet the new Editor. On this page you can see it in action — try to edit this text.', - }, -}; - -const block2Changed = { - id: 'AsbMKCuatV', - type: 'paragraph', - data: { - text: 'Hey. Meet the new Editor. On this page you can see it in action — try to edit this text.', - }, -}; - -store.dispatch({ - type: BlockMutationType.Added, - data: block1, -}); - -store.dispatch({ - type: BlockMutationType.Added, - data: block2, -}); - -store.dispatch({ - type: BlockMutationType.Changed, - data: block2Changed, -}); - -store.dispatch({ - type: BlockMutationType.Removed, - blockId: block1.id, -}); - -unsubscribeOnDataChange(); diff --git a/test/cypress/tests/store/store.spec.ts b/test/cypress/tests/store/store.spec.ts new file mode 100644 index 00000000..a36ed322 --- /dev/null +++ b/test/cypress/tests/store/store.spec.ts @@ -0,0 +1,112 @@ +import createStore from '../../../../src/components/store/createStore'; +import { EditorState } from '../../../../types/store/editorState'; +import blocksReducer from '../../../../src/components/store/blocksReducer'; +import { makeChangeBlockAction, makeCreateBlockAction, makeRemoveBlockAction } from '../../../../src/components/store/actions/blockReducerActions'; + +describe('State manager', () => { + it('should create the store without initial state', () => { + const emptyReducer = (state: EditorState): EditorState => state; + + const store = createStore(emptyReducer); + + expect(store.getState()).to.deep.equal({ blocks: {} }); + }); + + it('should create the store with initial state', () => { + const emptyReducer = (state: EditorState): EditorState => state; + const initialState = { + blocks: { + '3JPEqh8_Wc': { + id: '3JPEqh8_Wc', + type: 'header', + data: { + text: 'Editor.js', + level: 2, + }, + }, + }, + }; + + const store = createStore(emptyReducer, initialState); + + expect(store.getState()).to.deep.equal(initialState); + }); + + describe('blocksReducer', () => { + it('should create a new block in the state', () => { + const store = createStore(blocksReducer); + const block = { + id: '3JPEqh8_Wc', + type: 'header', + data: { + text: 'Editor.js', + level: 2, + }, + }; + const expectedResult = { + blocks: { + '3JPEqh8_Wc': block, + }, + }; + + store.dispatch(makeCreateBlockAction(block)); + + expect(store.getState()).to.be.deep.equal(expectedResult); + }); + + it('should change block data in the state', () => { + const block = { + id: '3JPEqh8_Wc', + type: 'header', + data: { + text: 'Editor.js', + level: 2, + }, + }; + const store = createStore(blocksReducer, { + blocks: { + [block.id]: block, + }, + }); + const changedBlock = { + ...block, + data: { + ...block.data, + text: 'New Editor.js!', + }, + }; + const expectedResult = { + blocks: { + [changedBlock.id]: changedBlock, + }, + }; + + store.dispatch(makeChangeBlockAction(changedBlock)); + + expect(store.getState()).to.be.deep.equal(expectedResult); + }); + + it('should remove block data from the state', () => { + const block = { + id: '3JPEqh8_Wc', + type: 'header', + data: { + text: 'Editor.js', + level: 2, + }, + }; + const store = createStore(blocksReducer, { + blocks: { + [block.id]: block, + }, + }); + const expectedResult = { + blocks: {}, + }; + + store.dispatch(makeRemoveBlockAction(block.id)); + + expect(store.getState()).to.be.deep.equal(expectedResult); + }); + }); +}); diff --git a/types/store/action.ts b/types/store/action.ts index 21b7948d..87d8c700 100644 --- a/types/store/action.ts +++ b/types/store/action.ts @@ -5,7 +5,7 @@ import { BlockMutationType } from '../events/block/mutation-type'; * Action for creating a new block in the editor * This action will add the new block to the state */ -interface CreateBlockAction { +export interface CreateBlockAction { type: BlockMutationType.Added; data: OutputBlockData; } @@ -14,7 +14,7 @@ interface CreateBlockAction { * Action for changing data of an existing block * This action will change block data in the state by its id */ -interface ChangeBlockDataAction { +export interface ChangeBlockDataAction { type: BlockMutationType.Changed; data: OutputBlockData; } @@ -23,7 +23,7 @@ interface ChangeBlockDataAction { * Action for removing a block from the editor * This action will remove the block from the state by its id */ -interface RemoveBlockAction { +export interface RemoveBlockAction { type: BlockMutationType.Removed; blockId: string; }