floppy-disk 1.1.3 → 1.2.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -563,13 +563,18 @@ const useLoginMutation = createMutation(
563
563
 
564
564
  function Login() {
565
565
  const { mutate, isWaiting } = useLoginMutation();
566
+ const showToast = useToast();
566
567
  return (
567
568
  <div>
568
569
  <button
569
570
  disabled={isWaiting}
570
571
  onClick={() =>
571
- mutate({ email: 'foo@bar.baz', password: 's3cREt' }).then(() => {
572
- showToast('Login success');
572
+ mutate({ email: 'foo@bar.baz', password: 's3cREt' }).then(({ response, error }) => {
573
+ if (error) {
574
+ showToast('Login failed');
575
+ } else {
576
+ showToast('Login success');
577
+ }
573
578
  })
574
579
  }
575
580
  >
@@ -1,5 +1,5 @@
1
1
  import { InitStoreOptions } from '../vanilla';
2
- export declare type MutationState<TVar, TResponse = any, TError = unknown> = {
2
+ export type MutationState<TVar, TResponse = any, TError = unknown> = {
3
3
  /**
4
4
  * Network fetching status.
5
5
  */
@@ -19,7 +19,7 @@ export declare type MutationState<TVar, TResponse = any, TError = unknown> = {
19
19
  variables?: TVar;
20
20
  }>;
21
21
  };
22
- export declare type CreateMutationOptions<TVar, TResponse = any, TError = unknown> = InitStoreOptions<MutationState<TVar, TResponse, TError>> & {
22
+ export type CreateMutationOptions<TVar, TResponse = any, TError = unknown> = InitStoreOptions<MutationState<TVar, TResponse, TError>> & {
23
23
  onMutate?: (variables: TVar | undefined, stateBeforeMutate: MutationState<TVar, TResponse, TError>) => void;
24
24
  onSuccess?: (response: TResponse, variables: TVar | undefined, stateBeforeMutate: MutationState<TVar, TResponse, TError>) => void;
25
25
  onError?: (error: TError, variables: TVar | undefined, stateBeforeMutate: MutationState<TVar, TResponse, TError>) => void;
@@ -1,6 +1,6 @@
1
1
  import { CreateStoresOptions, StoreKey } from './create-stores';
2
- export declare type QueryStatus = 'loading' | 'success' | 'error';
3
- export declare type QueryState<TKey extends StoreKey = StoreKey, TResponse = any, TData = TResponse, TError = unknown> = {
2
+ export type QueryStatus = 'loading' | 'success' | 'error';
3
+ export type QueryState<TKey extends StoreKey = StoreKey, TResponse = any, TData = TResponse, TError = unknown> = {
4
4
  /**
5
5
  * Query store key, an object that will be hashed into a string as a query store identifier.
6
6
  */
@@ -95,7 +95,7 @@ export declare type QueryState<TKey extends StoreKey = StoreKey, TResponse = any
95
95
  pageParams: any[];
96
96
  hasNextPage: boolean;
97
97
  };
98
- export declare type CreateQueryOptions<TKey extends StoreKey = StoreKey, TResponse = any, TData = TResponse, TError = unknown> = CreateStoresOptions<TKey, QueryState<TKey, TResponse, TData, TError>> & {
98
+ export type CreateQueryOptions<TKey extends StoreKey = StoreKey, TResponse = any, TData = TResponse, TError = unknown> = CreateStoresOptions<TKey, QueryState<TKey, TResponse, TData, TError>> & {
99
99
  select?: (response: TResponse, state: Pick<QueryState<TKey, TResponse, TData, TError>, 'data' | 'key'>) => TData;
100
100
  /**
101
101
  * Stale time in miliseconds.
@@ -104,11 +104,11 @@ export declare type CreateQueryOptions<TKey extends StoreKey = StoreKey, TRespon
104
104
  */
105
105
  staleTime?: number;
106
106
  /**
107
- * Number of maximum retries.
107
+ * Number of maximum error retries.
108
108
  *
109
109
  * Defaults to `1`.
110
110
  */
111
- retry?: number;
111
+ retry?: number | ((error: TError, key: TKey) => number);
112
112
  /**
113
113
  * Auto call the query when the component is mounted.
114
114
  *
@@ -78,8 +78,8 @@ export const createQuery = (queryFn, options = {}) => {
78
78
  isRefetching: false,
79
79
  isRefetchError: false,
80
80
  isPreviousData: false,
81
- data: responseAllPages.reduce((prev, response) => {
82
- return select(response, { key, data: prev });
81
+ data: responseAllPages.reduce((prev, responseCurrentPage) => {
82
+ return select(responseCurrentPage, { key, data: prev });
83
83
  }, null),
84
84
  response,
85
85
  responseUpdatedAt: Date.now(),
@@ -116,7 +116,8 @@ export const createQuery = (queryFn, options = {}) => {
116
116
  pageParam,
117
117
  hasNextPage: pageParam !== undefined,
118
118
  });
119
- if (prevState.retryCount < retry) {
119
+ const retryCount = typeof retry === 'function' ? retry(error, key) : retry;
120
+ if (typeof retryCount === 'number' && prevState.retryCount < retryCount) {
120
121
  set({ retryCount: prevState.retryCount + 1, isGoingToRetry: true });
121
122
  callQuery();
122
123
  }
@@ -1,9 +1,9 @@
1
1
  import { InitStoreOptions, SelectDeps, SetStoreData, StoreData, StoreInitializer, Subscribers } from '../vanilla';
2
- export declare type WatchProps<T> = {
2
+ export type WatchProps<T> = {
3
3
  selectDeps?: SelectDeps<T>;
4
4
  render: (state: T) => any;
5
5
  };
6
- export declare type UseStore<T extends StoreData> = {
6
+ export type UseStore<T extends StoreData> = {
7
7
  /**
8
8
  * @param selectDeps A function that return the dependency array (just like in `useEffect`), to trigger reactivity.
9
9
  * Defaults to `undefined` (reactive to all state change) if you didn't set `defaultDeps` on `createStore`.
@@ -1,12 +1,12 @@
1
1
  import { InitStoreOptions, SelectDeps, SetStoreData, StoreData, Subscribers } from '../vanilla';
2
2
  import { WatchProps } from './create-store';
3
- export declare type StoreKey = Record<string, any> | undefined;
4
- export declare type StoresInitializer<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = (api: {
3
+ export type StoreKey = Record<string, any> | undefined;
4
+ export type StoresInitializer<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = (api: {
5
5
  key: TKey;
6
6
  get: () => T;
7
7
  set: (value: SetStoreData<T>, silent?: boolean) => void;
8
8
  }) => T;
9
- export declare type UseStores<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = {
9
+ export type UseStores<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = {
10
10
  /**
11
11
  * @param key (Optional) Store key, an object that will be hashed into a string as a store identifier.
12
12
  *
@@ -27,7 +27,7 @@ export declare type UseStores<TKey extends StoreKey = StoreKey, T extends StoreD
27
27
  storeKey?: TKey;
28
28
  }) => any;
29
29
  };
30
- export declare type CreateStoresOptions<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = InitStoreOptions<T> & {
30
+ export type CreateStoresOptions<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = InitStoreOptions<T> & {
31
31
  onBeforeChangeKey?: (nextKey: TKey, prevKey: TKey) => void;
32
32
  defaultDeps?: SelectDeps<T>;
33
33
  };
@@ -1,5 +1,5 @@
1
- import { ReactNode } from 'react';
1
+ import React, { ReactNode } from 'react';
2
2
  export declare const withContext: <T>(initFn: () => T) => readonly [({ children, onInitialize, }: {
3
3
  children: ReactNode;
4
4
  onInitialize?: ((value: T) => void) | undefined;
5
- }) => JSX.Element, () => T | null];
5
+ }) => React.JSX.Element, () => T | null];
package/esm/vanilla.d.ts CHANGED
@@ -1,20 +1,20 @@
1
- export declare type StoreData = Record<string, any>;
2
- export declare type SetStoreData<T> = Partial<T> | ((prevState: T) => Partial<T>);
3
- export declare type SelectDeps<T> = ((state: T) => any[]) | undefined;
4
- export declare type Subscribers<T> = Map<(state: T) => void, SelectDeps<T>>;
5
- export declare type StoreInitializer<T> = (api: {
1
+ export type StoreData = Record<string, any>;
2
+ export type SetStoreData<T> = Partial<T> | ((prevState: T) => Partial<T>);
3
+ export type SelectDeps<T> = ((state: T) => any[]) | undefined;
4
+ export type Subscribers<T> = Map<(state: T) => void, SelectDeps<T>>;
5
+ export type StoreInitializer<T> = (api: {
6
6
  get: () => T;
7
7
  set: (value: SetStoreData<T>, silent?: boolean) => void;
8
8
  }) => T;
9
- export declare type StoreEvent<T> = (state: T) => void;
10
- export declare type InitStoreOptions<T> = {
9
+ export type StoreEvent<T> = (state: T) => void;
10
+ export type InitStoreOptions<T> = {
11
11
  intercept?: (nextState: T, prevState: T) => Partial<T>;
12
12
  onFirstSubscribe?: StoreEvent<T>;
13
13
  onSubscribe?: StoreEvent<T>;
14
14
  onUnsubscribe?: StoreEvent<T>;
15
15
  onLastUnsubscribe?: StoreEvent<T>;
16
16
  };
17
- export declare type InitStoreReturn<T> = {
17
+ export type InitStoreReturn<T> = {
18
18
  get: () => T;
19
19
  set: (value: SetStoreData<T>, silent?: boolean) => void;
20
20
  subscribe: (fn: (state: T) => void, selectDeps?: SelectDeps<T>) => () => void;
@@ -1,5 +1,5 @@
1
1
  import { InitStoreOptions } from '../vanilla';
2
- export declare type MutationState<TVar, TResponse = any, TError = unknown> = {
2
+ export type MutationState<TVar, TResponse = any, TError = unknown> = {
3
3
  /**
4
4
  * Network fetching status.
5
5
  */
@@ -19,7 +19,7 @@ export declare type MutationState<TVar, TResponse = any, TError = unknown> = {
19
19
  variables?: TVar;
20
20
  }>;
21
21
  };
22
- export declare type CreateMutationOptions<TVar, TResponse = any, TError = unknown> = InitStoreOptions<MutationState<TVar, TResponse, TError>> & {
22
+ export type CreateMutationOptions<TVar, TResponse = any, TError = unknown> = InitStoreOptions<MutationState<TVar, TResponse, TError>> & {
23
23
  onMutate?: (variables: TVar | undefined, stateBeforeMutate: MutationState<TVar, TResponse, TError>) => void;
24
24
  onSuccess?: (response: TResponse, variables: TVar | undefined, stateBeforeMutate: MutationState<TVar, TResponse, TError>) => void;
25
25
  onError?: (error: TError, variables: TVar | undefined, stateBeforeMutate: MutationState<TVar, TResponse, TError>) => void;
@@ -1,6 +1,6 @@
1
1
  import { CreateStoresOptions, StoreKey } from './create-stores';
2
- export declare type QueryStatus = 'loading' | 'success' | 'error';
3
- export declare type QueryState<TKey extends StoreKey = StoreKey, TResponse = any, TData = TResponse, TError = unknown> = {
2
+ export type QueryStatus = 'loading' | 'success' | 'error';
3
+ export type QueryState<TKey extends StoreKey = StoreKey, TResponse = any, TData = TResponse, TError = unknown> = {
4
4
  /**
5
5
  * Query store key, an object that will be hashed into a string as a query store identifier.
6
6
  */
@@ -95,7 +95,7 @@ export declare type QueryState<TKey extends StoreKey = StoreKey, TResponse = any
95
95
  pageParams: any[];
96
96
  hasNextPage: boolean;
97
97
  };
98
- export declare type CreateQueryOptions<TKey extends StoreKey = StoreKey, TResponse = any, TData = TResponse, TError = unknown> = CreateStoresOptions<TKey, QueryState<TKey, TResponse, TData, TError>> & {
98
+ export type CreateQueryOptions<TKey extends StoreKey = StoreKey, TResponse = any, TData = TResponse, TError = unknown> = CreateStoresOptions<TKey, QueryState<TKey, TResponse, TData, TError>> & {
99
99
  select?: (response: TResponse, state: Pick<QueryState<TKey, TResponse, TData, TError>, 'data' | 'key'>) => TData;
100
100
  /**
101
101
  * Stale time in miliseconds.
@@ -104,11 +104,11 @@ export declare type CreateQueryOptions<TKey extends StoreKey = StoreKey, TRespon
104
104
  */
105
105
  staleTime?: number;
106
106
  /**
107
- * Number of maximum retries.
107
+ * Number of maximum error retries.
108
108
  *
109
109
  * Defaults to `1`.
110
110
  */
111
- retry?: number;
111
+ retry?: number | ((error: TError, key: TKey) => number);
112
112
  /**
113
113
  * Auto call the query when the component is mounted.
114
114
  *
@@ -81,8 +81,8 @@ const createQuery = (queryFn, options = {}) => {
81
81
  isRefetching: false,
82
82
  isRefetchError: false,
83
83
  isPreviousData: false,
84
- data: responseAllPages.reduce((prev, response) => {
85
- return select(response, { key, data: prev });
84
+ data: responseAllPages.reduce((prev, responseCurrentPage) => {
85
+ return select(responseCurrentPage, { key, data: prev });
86
86
  }, null),
87
87
  response,
88
88
  responseUpdatedAt: Date.now(),
@@ -119,7 +119,8 @@ const createQuery = (queryFn, options = {}) => {
119
119
  pageParam,
120
120
  hasNextPage: pageParam !== undefined,
121
121
  });
122
- if (prevState.retryCount < retry) {
122
+ const retryCount = typeof retry === 'function' ? retry(error, key) : retry;
123
+ if (typeof retryCount === 'number' && prevState.retryCount < retryCount) {
123
124
  set({ retryCount: prevState.retryCount + 1, isGoingToRetry: true });
124
125
  callQuery();
125
126
  }
@@ -1,9 +1,9 @@
1
1
  import { InitStoreOptions, SelectDeps, SetStoreData, StoreData, StoreInitializer, Subscribers } from '../vanilla';
2
- export declare type WatchProps<T> = {
2
+ export type WatchProps<T> = {
3
3
  selectDeps?: SelectDeps<T>;
4
4
  render: (state: T) => any;
5
5
  };
6
- export declare type UseStore<T extends StoreData> = {
6
+ export type UseStore<T extends StoreData> = {
7
7
  /**
8
8
  * @param selectDeps A function that return the dependency array (just like in `useEffect`), to trigger reactivity.
9
9
  * Defaults to `undefined` (reactive to all state change) if you didn't set `defaultDeps` on `createStore`.
@@ -1,12 +1,12 @@
1
1
  import { InitStoreOptions, SelectDeps, SetStoreData, StoreData, Subscribers } from '../vanilla';
2
2
  import { WatchProps } from './create-store';
3
- export declare type StoreKey = Record<string, any> | undefined;
4
- export declare type StoresInitializer<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = (api: {
3
+ export type StoreKey = Record<string, any> | undefined;
4
+ export type StoresInitializer<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = (api: {
5
5
  key: TKey;
6
6
  get: () => T;
7
7
  set: (value: SetStoreData<T>, silent?: boolean) => void;
8
8
  }) => T;
9
- export declare type UseStores<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = {
9
+ export type UseStores<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = {
10
10
  /**
11
11
  * @param key (Optional) Store key, an object that will be hashed into a string as a store identifier.
12
12
  *
@@ -27,7 +27,7 @@ export declare type UseStores<TKey extends StoreKey = StoreKey, T extends StoreD
27
27
  storeKey?: TKey;
28
28
  }) => any;
29
29
  };
30
- export declare type CreateStoresOptions<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = InitStoreOptions<T> & {
30
+ export type CreateStoresOptions<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = InitStoreOptions<T> & {
31
31
  onBeforeChangeKey?: (nextKey: TKey, prevKey: TKey) => void;
32
32
  defaultDeps?: SelectDeps<T>;
33
33
  };
@@ -1,5 +1,5 @@
1
- import { ReactNode } from 'react';
1
+ import React, { ReactNode } from 'react';
2
2
  export declare const withContext: <T>(initFn: () => T) => readonly [({ children, onInitialize, }: {
3
3
  children: ReactNode;
4
4
  onInitialize?: ((value: T) => void) | undefined;
5
- }) => JSX.Element, () => T | null];
5
+ }) => React.JSX.Element, () => T | null];
package/lib/vanilla.d.ts CHANGED
@@ -1,20 +1,20 @@
1
- export declare type StoreData = Record<string, any>;
2
- export declare type SetStoreData<T> = Partial<T> | ((prevState: T) => Partial<T>);
3
- export declare type SelectDeps<T> = ((state: T) => any[]) | undefined;
4
- export declare type Subscribers<T> = Map<(state: T) => void, SelectDeps<T>>;
5
- export declare type StoreInitializer<T> = (api: {
1
+ export type StoreData = Record<string, any>;
2
+ export type SetStoreData<T> = Partial<T> | ((prevState: T) => Partial<T>);
3
+ export type SelectDeps<T> = ((state: T) => any[]) | undefined;
4
+ export type Subscribers<T> = Map<(state: T) => void, SelectDeps<T>>;
5
+ export type StoreInitializer<T> = (api: {
6
6
  get: () => T;
7
7
  set: (value: SetStoreData<T>, silent?: boolean) => void;
8
8
  }) => T;
9
- export declare type StoreEvent<T> = (state: T) => void;
10
- export declare type InitStoreOptions<T> = {
9
+ export type StoreEvent<T> = (state: T) => void;
10
+ export type InitStoreOptions<T> = {
11
11
  intercept?: (nextState: T, prevState: T) => Partial<T>;
12
12
  onFirstSubscribe?: StoreEvent<T>;
13
13
  onSubscribe?: StoreEvent<T>;
14
14
  onUnsubscribe?: StoreEvent<T>;
15
15
  onLastUnsubscribe?: StoreEvent<T>;
16
16
  };
17
- export declare type InitStoreReturn<T> = {
17
+ export type InitStoreReturn<T> = {
18
18
  get: () => T;
19
19
  set: (value: SetStoreData<T>, silent?: boolean) => void;
20
20
  subscribe: (fn: (state: T) => void, selectDeps?: SelectDeps<T>) => () => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "floppy-disk",
3
- "version": "1.1.3",
3
+ "version": "1.2.0-beta.2",
4
4
  "description": "FloppyDisk - lightweight, simple, and powerful state management library",
5
5
  "keywords": [
6
6
  "state",
@@ -48,26 +48,30 @@
48
48
  "semantic-release": "semantic-release"
49
49
  },
50
50
  "devDependencies": {
51
+ "@babel/plugin-proposal-private-property-in-object": "^7.21.11",
51
52
  "@commitlint/cli": "^17.7.1",
52
53
  "@commitlint/config-conventional": "^17.7.0",
54
+ "@testing-library/react-hooks": "^8.0.1",
53
55
  "@types/jest": "^29.5.3",
54
- "@types/react": "^18.0.9",
55
- "@types/react-dom": "^18.0.4",
56
+ "@types/react": "^18.2.20",
57
+ "@types/react-dom": "^18.2.7",
56
58
  "eslint": "^8.47.0",
57
59
  "eslint-config-prettier": "^9.0.0",
58
60
  "eslint-config-react-app": "^7.0.1",
59
61
  "eslint-plugin-simple-import-sort": "^10.0.0",
60
- "husky": "^8.0.1",
62
+ "husky": "^8.0.3",
61
63
  "jest": "^29.6.2",
64
+ "jest-environment-jsdom": "^29.6.2",
62
65
  "lint-staged": "^14.0.0",
63
- "prettier": "^2.6.2",
64
- "react": "^18.1.0",
65
- "react-dom": "^18.1.0",
66
- "rimraf": "^3.0.2",
67
- "semantic-release": "^21.0.7",
66
+ "prettier": "^3.0.2",
67
+ "react": "^18.2.0",
68
+ "react-dom": "^18.2.0",
69
+ "react-test-renderer": "^18.2.0",
70
+ "rimraf": "^5.0.1",
71
+ "semantic-release": "^21.0.9",
68
72
  "ts-jest": "^29.1.1",
69
73
  "ts-node": "^10.9.1",
70
- "typescript": "^4.6.4"
74
+ "typescript": "^5.1.6"
71
75
  },
72
76
  "peerDependencies": {
73
77
  "react": "^17.0.0 || ^18.0.0",
@@ -1 +0,0 @@
1
- export {};
@@ -1,67 +0,0 @@
1
- import { initStore } from '../vanilla';
2
- describe('initStore', () => {
3
- const initialData = {
4
- counter: 0,
5
- text: 'initial text',
6
- };
7
- const onFirstSubscribeMock = jest.fn();
8
- const onSubscribeMock = jest.fn();
9
- const onUnsubscribeMock = jest.fn();
10
- const onLastUnsubscribeMock = jest.fn();
11
- const mockStoreInitializer = jest.fn(() => initialData);
12
- const options = {
13
- onFirstSubscribe: onFirstSubscribeMock,
14
- onSubscribe: onSubscribeMock,
15
- onUnsubscribe: onUnsubscribeMock,
16
- onLastUnsubscribe: onLastUnsubscribeMock,
17
- };
18
- let store;
19
- beforeEach(() => {
20
- store = initStore(mockStoreInitializer, options);
21
- });
22
- afterEach(() => {
23
- onFirstSubscribeMock.mockClear();
24
- onSubscribeMock.mockClear();
25
- onUnsubscribeMock.mockClear();
26
- onLastUnsubscribeMock.mockClear();
27
- });
28
- it('should initialize the store with initial data', () => {
29
- expect(store.get()).toEqual(initialData);
30
- });
31
- it('should call onFirstSubscribe & onSubscribe when subscriber is added', () => {
32
- const subscriber1 = jest.fn();
33
- const subscriber2 = jest.fn();
34
- store.subscribe(subscriber1);
35
- expect(onFirstSubscribeMock).toHaveBeenCalledWith(initialData);
36
- expect(onSubscribeMock).toHaveBeenCalledWith(initialData);
37
- store.subscribe(subscriber2);
38
- expect(onFirstSubscribeMock).toHaveBeenCalledTimes(1);
39
- expect(onSubscribeMock).toHaveBeenCalledWith(initialData);
40
- });
41
- it('should call onUnsubscribe & onLastUnsubscribe when subscriber is removed', () => {
42
- const subscriber1 = jest.fn();
43
- const subscriber2 = jest.fn();
44
- const unsub1 = store.subscribe(subscriber1);
45
- const unsub2 = store.subscribe(subscriber2);
46
- unsub1();
47
- expect(onUnsubscribeMock).toHaveBeenCalledWith(initialData);
48
- expect(onLastUnsubscribeMock).not.toHaveBeenCalled();
49
- unsub2();
50
- expect(onUnsubscribeMock).toHaveBeenCalledWith(initialData);
51
- expect(onLastUnsubscribeMock).toHaveBeenCalledTimes(1);
52
- });
53
- it('should update the store data when set is called with partial data', () => {
54
- store.set({ counter: 1 });
55
- expect(store.get().counter).toEqual(1);
56
- expect(store.get().text).toEqual(initialData.text);
57
- });
58
- it('should call subscribers when set is called', () => {
59
- const subscriber1 = jest.fn();
60
- const subscriber2 = jest.fn();
61
- store.subscribe(subscriber1);
62
- store.subscribe(subscriber2);
63
- store.set({ counter: 2 });
64
- expect(subscriber1).toHaveBeenCalledWith(store.get());
65
- expect(subscriber2).toHaveBeenCalledWith(store.get());
66
- });
67
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,69 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const vanilla_1 = require("../vanilla");
4
- describe('initStore', () => {
5
- const initialData = {
6
- counter: 0,
7
- text: 'initial text',
8
- };
9
- const onFirstSubscribeMock = jest.fn();
10
- const onSubscribeMock = jest.fn();
11
- const onUnsubscribeMock = jest.fn();
12
- const onLastUnsubscribeMock = jest.fn();
13
- const mockStoreInitializer = jest.fn(() => initialData);
14
- const options = {
15
- onFirstSubscribe: onFirstSubscribeMock,
16
- onSubscribe: onSubscribeMock,
17
- onUnsubscribe: onUnsubscribeMock,
18
- onLastUnsubscribe: onLastUnsubscribeMock,
19
- };
20
- let store;
21
- beforeEach(() => {
22
- store = (0, vanilla_1.initStore)(mockStoreInitializer, options);
23
- });
24
- afterEach(() => {
25
- onFirstSubscribeMock.mockClear();
26
- onSubscribeMock.mockClear();
27
- onUnsubscribeMock.mockClear();
28
- onLastUnsubscribeMock.mockClear();
29
- });
30
- it('should initialize the store with initial data', () => {
31
- expect(store.get()).toEqual(initialData);
32
- });
33
- it('should call onFirstSubscribe & onSubscribe when subscriber is added', () => {
34
- const subscriber1 = jest.fn();
35
- const subscriber2 = jest.fn();
36
- store.subscribe(subscriber1);
37
- expect(onFirstSubscribeMock).toHaveBeenCalledWith(initialData);
38
- expect(onSubscribeMock).toHaveBeenCalledWith(initialData);
39
- store.subscribe(subscriber2);
40
- expect(onFirstSubscribeMock).toHaveBeenCalledTimes(1);
41
- expect(onSubscribeMock).toHaveBeenCalledWith(initialData);
42
- });
43
- it('should call onUnsubscribe & onLastUnsubscribe when subscriber is removed', () => {
44
- const subscriber1 = jest.fn();
45
- const subscriber2 = jest.fn();
46
- const unsub1 = store.subscribe(subscriber1);
47
- const unsub2 = store.subscribe(subscriber2);
48
- unsub1();
49
- expect(onUnsubscribeMock).toHaveBeenCalledWith(initialData);
50
- expect(onLastUnsubscribeMock).not.toHaveBeenCalled();
51
- unsub2();
52
- expect(onUnsubscribeMock).toHaveBeenCalledWith(initialData);
53
- expect(onLastUnsubscribeMock).toHaveBeenCalledTimes(1);
54
- });
55
- it('should update the store data when set is called with partial data', () => {
56
- store.set({ counter: 1 });
57
- expect(store.get().counter).toEqual(1);
58
- expect(store.get().text).toEqual(initialData.text);
59
- });
60
- it('should call subscribers when set is called', () => {
61
- const subscriber1 = jest.fn();
62
- const subscriber2 = jest.fn();
63
- store.subscribe(subscriber1);
64
- store.subscribe(subscriber2);
65
- store.set({ counter: 2 });
66
- expect(subscriber1).toHaveBeenCalledWith(store.get());
67
- expect(subscriber2).toHaveBeenCalledWith(store.get());
68
- });
69
- });