Skip to content

Commit

Permalink
Поправил тесты
Browse files Browse the repository at this point in the history
  • Loading branch information
LeMarck committed Mar 4, 2024
1 parent 256ec49 commit 1b6f6f4
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 30 deletions.
7 changes: 2 additions & 5 deletions src/effect.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,11 @@ describe('createEffect', () => {
})
);

fetchApiFx.pending.watch(watcherMock);
fetchApiFx.pending.watch((value) => watcherMock(value));

await fetchApiFx(100);

expect(watcherMock.mock.calls).toEqual([
[true, true],
[false, false],
]);
expect(watcherMock.mock.calls).toEqual([[false], [true], [false]]);
});

it('`.done/doneData`: события, которое срабатывают с результатом выполнения эффекта', async () => {
Expand Down
44 changes: 29 additions & 15 deletions src/store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,61 +22,75 @@ describe('createStore', () => {
expect($store.getState()).toBe(1);
});

it('Не обновлять стор если редьюсер возвращает `undefined`', () => {
const eventMock = jest.fn(<T>() => createEvent<T>())();
const $store = createStore(0).on(eventMock, (state) => state);

expect($store.getState()).toBe(0);

eventMock(undefined);

expect($store.getState()).toBe(0);
});

it('`.watch`: вызывает функцию с сайд-эффектами при каждом обновлении стора', () => {
const watcherMock = jest.fn();
const triggerWatcherMock = jest.fn();
const add = createEvent<number>();
const foo = createEvent<number>();
const $store = createStore(0).on(add, (state, payload) => state + payload);

$store.watch(watcherMock);
$store.watch(foo, watcherMock);
$store.watch((value) => watcherMock(value));
$store.watch(foo, triggerWatcherMock);

add(4);
expect(watcherMock).toHaveBeenCalledWith(4, 4);
expect(watcherMock).toHaveBeenCalledWith(4);
expect(triggerWatcherMock).not.toHaveBeenCalled();
expect($store.getState()).toBe(4);

add(3);
expect(watcherMock).toHaveBeenCalledWith(7, 3);
expect(watcherMock).toHaveBeenCalledWith(7);
expect(triggerWatcherMock).not.toHaveBeenCalled();
expect($store.getState()).toBe(7);

foo(42);
expect(watcherMock).toHaveBeenCalledWith(7, 42);
expect($store.getState()).toBe(7);
expect(triggerWatcherMock).toHaveBeenCalledWith(7, 42);
});

it('`unwatch` прекращает отслеживание', () => {
const watcherMock = jest.fn();
const add = createEvent<number>();
const $store = createStore(0).on(add, (state, payload) => state + payload);

const unwatch = $store.watch(watcherMock);
const unwatch = $store.watch((value) => watcherMock(value));

add(42);
expect(watcherMock).toHaveBeenCalledWith(42, 42);
expect(watcherMock).toHaveBeenCalledWith(42);
expect($store.getState()).toBe(42);

unwatch();
add(123);
add(456);
expect(watcherMock).toHaveBeenCalledTimes(1);
expect(watcherMock).toHaveBeenCalledTimes(2);
});

it('`.map`: создает производный стор на основе данных из исходного', () => {
const watcherMock = jest.fn();
const changed = createEvent<string>();
const $title = createStore('').on(changed, (_, newTitle) => newTitle);

$title.map((title) => title.length).watch(watcherMock);
$title.map((title) => title.length).watch((length) => watcherMock(length));

changed('hello');
expect(watcherMock).toHaveBeenCalledWith(5, 5);
expect(watcherMock).toHaveBeenCalledTimes(1);
expect(watcherMock).toHaveBeenCalledWith(5);
expect(watcherMock).toHaveBeenCalledTimes(2);

changed('world');
expect(watcherMock).toHaveBeenCalledTimes(1);
expect(watcherMock).toHaveBeenCalledTimes(2);

changed('hello world');
expect(watcherMock).toHaveBeenCalledWith(11, 11);
expect(watcherMock).toHaveBeenCalledTimes(2);
expect(watcherMock).toHaveBeenCalledWith(11);
expect(watcherMock).toHaveBeenCalledTimes(3);
});

it('`.off`: удаляет обработчик для данного триггера', () => {
Expand Down
25 changes: 15 additions & 10 deletions src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export interface Store<State> {
trigger: Unit<Payload> | Array<Unit<Payload>>,
reducer: (state: State, payload: Payload) => State
): Store<State>;
watch<Payload>(watcher: (state: State, payload: Payload) => void): Unsubscribe;
watch(watcher: (state: State) => void): Unsubscribe;
watch<Payload>(trigger: Unit<Payload>, fn: (state: State, payload: Payload) => void): Unsubscribe;
off<Payload>(trigger: Unit<Payload>): void;
reset(...triggers: Array<Unit> | [Array<Unit>]): Store<State>;
Expand All @@ -20,15 +20,17 @@ export interface Store<State> {
}

export function createStore<State>(defaultState: State): Store<State> {
const watchers: Set<(state: State, payload: any) => void> = new Set();
const watchers: Set<(state: State) => void> = new Set();
const subscribers: Map<Unit<unknown>, () => void> = new Map();
const initialState = { ...{ defaultState } };

let state = defaultState;

function update<Payload>(newState: State, payload: Payload): void {
function update(newState: State): void {
if (newState === undefined || newState === state) return;

state = newState;
watchers.forEach((watcher) => watcher(state, payload));
watchers.forEach((watcher) => watcher(state));
}

const store = {
Expand All @@ -41,7 +43,7 @@ export function createStore<State>(defaultState: State): Store<State> {
store.off(clock);
subscribers.set(
clock as Unit<unknown>,
clock.watch((payload: Payload) => update(reducer(state, payload), payload))
clock.watch((payload: Payload) => update(reducer(state, payload)))
);
});

Expand All @@ -56,7 +58,7 @@ export function createStore<State>(defaultState: State): Store<State> {
}
},
watch<Payload>(
triggerOrWatcher: Unit<Payload> | ((state: State, payload: Payload) => void),
triggerOrWatcher: Unit<Payload> | ((state: State) => void),
fn?: (state: State, payload: Payload) => void
): Unsubscribe {
const argumentsSize = arguments.length;
Expand All @@ -68,11 +70,14 @@ export function createStore<State>(defaultState: State): Store<State> {

watchers.add(triggerOrWatcher);

triggerOrWatcher(store.getState());

return () => watchers.delete(triggerOrWatcher);
},
map<LastState>(fn: (state: State, lastState?: LastState) => LastState): Store<LastState> {
const updateStore = createEvent<LastState>();
const newStore = createStore<LastState | undefined>(undefined).on(updateStore, (_, newState) => newState);
map<NewState>(fn: (state: State, lastState?: NewState) => NewState): Store<NewState> {
const lastResult = fn(store.getState());
const updateStore = createEvent<NewState>();
const newStore = createStore<NewState>(lastResult).on(updateStore, (_, newState) => newState);

store.watch((s: State) => {
const lastState = newStore.getState();
Expand All @@ -83,7 +88,7 @@ export function createStore<State>(defaultState: State): Store<State> {
}
});

return newStore as Store<LastState>;
return newStore as Store<NewState>;
},
reset(...triggers: Array<Unit> | [Array<Unit>]): Store<State> {
triggers.forEach((trigger) => {
Expand Down

0 comments on commit 1b6f6f4

Please sign in to comment.