@jobber/hooks 2.0.3-pre1.55 → 2.0.3-pre2.52
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/dist/index.d.ts +10 -7
- package/dist/index.js +10 -8
- package/dist/useAssert/index.d.ts +1 -1
- package/dist/useAssert/index.js +2 -2
- package/dist/useCollectionQuery/index.d.ts +1 -0
- package/dist/useCollectionQuery/index.js +5 -0
- package/dist/useCollectionQuery/mdxUtils.d.ts +53 -0
- package/dist/useCollectionQuery/mdxUtils.js +152 -0
- package/dist/useCollectionQuery/test-utilities/index.d.ts +3 -0
- package/dist/useCollectionQuery/test-utilities/index.js +19 -0
- package/dist/useCollectionQuery/test-utilities/mocks.d.ts +107 -0
- package/dist/useCollectionQuery/test-utilities/mocks.js +131 -0
- package/dist/useCollectionQuery/test-utilities/queries.d.ts +37 -0
- package/dist/useCollectionQuery/test-utilities/queries.js +59 -0
- package/dist/useCollectionQuery/test-utilities/utils.d.ts +1 -0
- package/dist/useCollectionQuery/test-utilities/utils.js +18 -0
- package/dist/useCollectionQuery/uniqueEdges.d.ts +8 -0
- package/dist/useCollectionQuery/uniqueEdges.js +19 -0
- package/dist/useCollectionQuery/uniqueNodes.d.ts +5 -0
- package/dist/useCollectionQuery/uniqueNodes.js +11 -0
- package/dist/useCollectionQuery/useCollectionQuery.d.ts +71 -0
- package/dist/useCollectionQuery/useCollectionQuery.js +181 -0
- package/dist/useCollectionQuery/useCollectionQuery.test.d.ts +1 -0
- package/dist/useCollectionQuery/useCollectionQuery.test.js +327 -0
- package/dist/useFocusTrap/index.d.ts +1 -1
- package/dist/useFocusTrap/index.js +2 -2
- package/dist/useFocusTrap/useFocusTrap.test.d.ts +1 -0
- package/dist/useFocusTrap/useFocusTrap.test.js +52 -0
- package/dist/useFormState/index.d.ts +1 -1
- package/dist/useFormState/index.js +2 -2
- package/dist/useIsMounted/index.d.ts +1 -1
- package/dist/useIsMounted/index.js +2 -2
- package/dist/useIsMounted/useIsMounted.test.js +3 -3
- package/dist/useLiveAnnounce/index.d.ts +1 -1
- package/dist/useLiveAnnounce/index.js +2 -2
- package/dist/useLiveAnnounce/useLiveAnnounce.test.js +2 -2
- package/dist/useOnKeyDown/index.d.ts +1 -0
- package/dist/useOnKeyDown/index.js +5 -0
- package/dist/useOnKeyDown/useOnKeyDown.d.ts +13 -0
- package/dist/useOnKeyDown/useOnKeyDown.js +33 -0
- package/dist/useOnKeyDown/useOnKeyDown.test.d.ts +1 -0
- package/dist/useOnKeyDown/useOnKeyDown.test.js +23 -0
- package/dist/usePasswordStrength/index.d.ts +1 -1
- package/dist/usePasswordStrength/index.js +2 -2
- package/dist/useRefocusOnActivator/index.d.ts +1 -1
- package/dist/useRefocusOnActivator/index.js +2 -2
- package/dist/useResizeObserver/index.d.ts +1 -0
- package/dist/useResizeObserver/index.js +17 -0
- package/dist/useResizeObserver/useResizeObserver.d.ts +19 -0
- package/dist/useResizeObserver/useResizeObserver.js +58 -0
- package/package.json +9 -9
- package/useAssert.d.ts +1 -0
- package/useAssert.js +17 -0
- package/useCollectionQuery.d.ts +1 -0
- package/useCollectionQuery.js +17 -0
- package/useFocusTrap.d.ts +1 -0
- package/useFocusTrap.js +17 -0
- package/useFormState.d.ts +1 -0
- package/useFormState.js +17 -0
- package/useIsMounted.d.ts +1 -0
- package/useIsMounted.js +17 -0
- package/useLiveAnnounce.d.ts +1 -0
- package/useLiveAnnounce.js +17 -0
- package/useOnKeyDown.d.ts +1 -0
- package/useOnKeyDown.js +17 -0
- package/usePasswordStrength.d.ts +1 -0
- package/usePasswordStrength.js +17 -0
- package/useRefocusOnActivator.d.ts +1 -0
- package/useRefocusOnActivator.js +17 -0
- package/useResizeObserver.d.ts +1 -0
- package/useResizeObserver.js +17 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.uniqueNodes = void 0;
|
|
4
|
+
function uniqueNodes(nodes) {
|
|
5
|
+
const result = new Map();
|
|
6
|
+
nodes.forEach(node => {
|
|
7
|
+
result.set(`${node.__typename}-${node.id}`, node);
|
|
8
|
+
});
|
|
9
|
+
return Array.from(result.values());
|
|
10
|
+
}
|
|
11
|
+
exports.uniqueNodes = uniqueNodes;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { ApolloError, DocumentNode, QueryHookOptions, SubscribeToMoreOptions } from "@apollo/client";
|
|
2
|
+
import { Node } from "./uniqueNodes";
|
|
3
|
+
import { Edge } from "./uniqueEdges";
|
|
4
|
+
interface UseCollectionQueryArguments<TQuery, TSubscription> {
|
|
5
|
+
/**
|
|
6
|
+
* The graphQL query that fetches the collection
|
|
7
|
+
*/
|
|
8
|
+
query: DocumentNode;
|
|
9
|
+
/**
|
|
10
|
+
* A list of options for us to pass into the apollo `useQuery` hook
|
|
11
|
+
*/
|
|
12
|
+
queryOptions?: QueryHookOptions<TQuery>;
|
|
13
|
+
/**
|
|
14
|
+
* A function that returns the location where the {@link Collection} is located.
|
|
15
|
+
*
|
|
16
|
+
* The collection is the part of the result that needs to be paginated.
|
|
17
|
+
*/
|
|
18
|
+
getCollectionByPath: GetCollectionByPathFunction<TQuery>;
|
|
19
|
+
/**
|
|
20
|
+
* A list of subscription options if you want to create a GraphQL
|
|
21
|
+
* subscription to listen for more content.
|
|
22
|
+
*/
|
|
23
|
+
subscription?: ListSubscription<TSubscription>;
|
|
24
|
+
}
|
|
25
|
+
interface ListSubscription<TSubscription> {
|
|
26
|
+
/**
|
|
27
|
+
* The graphQL subscription that listens for more data. This query should
|
|
28
|
+
* return a single Node that matches the data structure in
|
|
29
|
+
* `getCollectionByPath<TQuery>(...).edges.node` and
|
|
30
|
+
* `getCollectionByPath<TQuery>(...).nodes
|
|
31
|
+
*/
|
|
32
|
+
document: DocumentNode;
|
|
33
|
+
/**
|
|
34
|
+
* A list of variables to pass into the apollo `subscribeToMore` function.
|
|
35
|
+
*/
|
|
36
|
+
options?: Pick<SubscribeToMoreOptions<TSubscription>, "variables">;
|
|
37
|
+
/**
|
|
38
|
+
* A function that returns the location where the `Node` is located on the
|
|
39
|
+
* `TSubscription` object.
|
|
40
|
+
*
|
|
41
|
+
* It should return a single Node that matches the data structure in
|
|
42
|
+
* `getCollectionByPath<TQuery>(...).edges.node` and
|
|
43
|
+
* `getCollectionByPath<TQuery>(...).nodes
|
|
44
|
+
*/
|
|
45
|
+
getNodeByPath: GetNodeByPath<TSubscription>;
|
|
46
|
+
}
|
|
47
|
+
interface Collection {
|
|
48
|
+
edges?: Edge[];
|
|
49
|
+
nodes?: Node[];
|
|
50
|
+
pageInfo: {
|
|
51
|
+
endCursor?: string | undefined;
|
|
52
|
+
hasNextPage: boolean;
|
|
53
|
+
[otherProperties: string]: unknown;
|
|
54
|
+
};
|
|
55
|
+
totalCount?: number;
|
|
56
|
+
[otherProperties: string]: unknown;
|
|
57
|
+
}
|
|
58
|
+
interface CollectionQueryResult<TQuery> {
|
|
59
|
+
data: TQuery | undefined;
|
|
60
|
+
error: ApolloError | undefined;
|
|
61
|
+
loadingRefresh: boolean;
|
|
62
|
+
loadingNextPage: boolean;
|
|
63
|
+
loadingInitialContent: boolean;
|
|
64
|
+
refresh(): void;
|
|
65
|
+
nextPage(): void;
|
|
66
|
+
}
|
|
67
|
+
type GetCollectionByPathFunction<TQuery> = (data: TQuery | undefined) => Collection | undefined;
|
|
68
|
+
type GetNodeByPath<TSubscription> = (data: TSubscription | undefined) => Node | undefined;
|
|
69
|
+
export declare function useCollectionQuery<TQuery, TSubscription = undefined>({ query, queryOptions, getCollectionByPath, subscription, }: UseCollectionQueryArguments<TQuery, TSubscription>): CollectionQueryResult<TQuery>;
|
|
70
|
+
export declare function isAlreadyUpdated(outputCollection: Collection, newNode: Node): boolean;
|
|
71
|
+
export {};
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isAlreadyUpdated = exports.useCollectionQuery = void 0;
|
|
4
|
+
const client_1 = require("@apollo/client");
|
|
5
|
+
const lodash_1 = require("lodash");
|
|
6
|
+
const react_1 = require("react");
|
|
7
|
+
const formatters_1 = require("@jobber/formatters");
|
|
8
|
+
const uniqueNodes_1 = require("./uniqueNodes");
|
|
9
|
+
const uniqueEdges_1 = require("./uniqueEdges");
|
|
10
|
+
const useIsMounted_1 = require("../useIsMounted");
|
|
11
|
+
function useCollectionQuery({ query, queryOptions, getCollectionByPath, subscription, }) {
|
|
12
|
+
var _a, _b;
|
|
13
|
+
const { data, loading, refetch, error, fetchMore, subscribeToMore } = (0, client_1.useQuery)(query, queryOptions);
|
|
14
|
+
const isMounted = (0, useIsMounted_1.useIsMounted)();
|
|
15
|
+
const [loadingRefresh, setLoadingRefresh] = (0, react_1.useState)(false);
|
|
16
|
+
const [loadingNextPage, setLoadingNextPage] = (0, react_1.useState)(false);
|
|
17
|
+
const loadingInitialContent = loading && !loadingRefresh && !loadingNextPage;
|
|
18
|
+
const isSearching = !!((_a = queryOptions === null || queryOptions === void 0 ? void 0 : queryOptions.variables) === null || _a === void 0 ? void 0 : _a.searchTerm);
|
|
19
|
+
const refresh = (0, react_1.useCallback)(() => {
|
|
20
|
+
if (loadingInitialContent || loadingRefresh) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
setLoadingRefresh(true);
|
|
24
|
+
fetchMore({
|
|
25
|
+
// a workaround fix for the error described in this post
|
|
26
|
+
// https://github.com/apollographql/apollo-client/issues/7491#issuecomment-767985363
|
|
27
|
+
// These changes can be reverted once we can update to version 3.4
|
|
28
|
+
// (the current release candidate)
|
|
29
|
+
variables: {},
|
|
30
|
+
updateQuery: (prev, { fetchMoreResult }) => fetchMoreResult || prev,
|
|
31
|
+
})
|
|
32
|
+
.catch(err => formatters_1.config.errorNotifier("Refetch Error", err))
|
|
33
|
+
.finally(() => {
|
|
34
|
+
if (isMounted.current) {
|
|
35
|
+
setLoadingRefresh(false);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}, [
|
|
39
|
+
loadingInitialContent,
|
|
40
|
+
loadingRefresh,
|
|
41
|
+
setLoadingRefresh,
|
|
42
|
+
refetch,
|
|
43
|
+
isMounted,
|
|
44
|
+
]);
|
|
45
|
+
const nextPage = (0, react_1.useCallback)(() => {
|
|
46
|
+
var _a;
|
|
47
|
+
if (loadingInitialContent || loadingRefresh || loadingNextPage) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const pageInfo = (_a = getCollectionByPath(data)) === null || _a === void 0 ? void 0 : _a.pageInfo;
|
|
51
|
+
if (!pageInfo || !pageInfo.hasNextPage) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
setLoadingNextPage(true);
|
|
55
|
+
fetchMore({
|
|
56
|
+
variables: {
|
|
57
|
+
cursor: pageInfo.endCursor,
|
|
58
|
+
},
|
|
59
|
+
updateQuery: (prev, { fetchMoreResult }) => fetchMoreUpdateQueryHandler(prev, fetchMoreResult, getCollectionByPath),
|
|
60
|
+
})
|
|
61
|
+
.catch(err => formatters_1.config.errorNotifier("FetchMore Error", err))
|
|
62
|
+
.finally(() => {
|
|
63
|
+
if (isMounted.current) {
|
|
64
|
+
setLoadingNextPage(false);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}, [
|
|
68
|
+
data,
|
|
69
|
+
loadingInitialContent,
|
|
70
|
+
loadingRefresh,
|
|
71
|
+
fetchMore,
|
|
72
|
+
loadingNextPage,
|
|
73
|
+
setLoadingNextPage,
|
|
74
|
+
getCollectionByPath,
|
|
75
|
+
isMounted,
|
|
76
|
+
]);
|
|
77
|
+
(0, react_1.useEffect)(() => {
|
|
78
|
+
if (subscription == undefined)
|
|
79
|
+
return;
|
|
80
|
+
const subscriptionOptions = subscription.options || {};
|
|
81
|
+
return subscribeToMore(Object.assign(Object.assign({}, subscriptionOptions), { document: subscription.document, updateQuery: (prev, { subscriptionData }) => subscribeToMoreHandler(isSearching, prev, getCollectionByPath, subscriptionData === null || subscriptionData === void 0 ? void 0 : subscriptionData.data, subscription.getNodeByPath), onError: err => formatters_1.config.errorNotifier("Subscribe to More Error", err) }));
|
|
82
|
+
},
|
|
83
|
+
// Disabling this linter so we can force this only run once. If we didn't
|
|
84
|
+
// do this we would need to ensure subscription, subscribeToMore, and getNodeByPath
|
|
85
|
+
// all use useCallback.
|
|
86
|
+
[(_b = queryOptions === null || queryOptions === void 0 ? void 0 : queryOptions.variables) === null || _b === void 0 ? void 0 : _b.searchTerm]);
|
|
87
|
+
return {
|
|
88
|
+
data,
|
|
89
|
+
error,
|
|
90
|
+
refresh,
|
|
91
|
+
loadingRefresh,
|
|
92
|
+
nextPage,
|
|
93
|
+
loadingNextPage,
|
|
94
|
+
loadingInitialContent,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
exports.useCollectionQuery = useCollectionQuery;
|
|
98
|
+
/**
|
|
99
|
+
* The following method uses an `output` variable, and indirectly modifies it through the `outputCollection` variable.
|
|
100
|
+
* This type of indirect modification is prone to bugs, but I couldn't think of a better way to write this code.
|
|
101
|
+
*
|
|
102
|
+
* Here's what I was balancing:
|
|
103
|
+
* 1. We need to copy the structure of prev to ensure that when we're combining two objects, we're not losing properties
|
|
104
|
+
* 2. We need to extract a key from an unknown path that's given to us by getCollectionByPath and then we need to modify
|
|
105
|
+
* that, and ensure that it's properly set on the cloned output object.
|
|
106
|
+
* 3. We want to keep the interface to this hook as simple and easy to use as possible
|
|
107
|
+
*
|
|
108
|
+
* The alternative approaches that were rejected:
|
|
109
|
+
* 1. We replace the getCollectionByPath with a keyPath string. (Eg. "data.conversation.message") and then we use lodash
|
|
110
|
+
* `get` and `set` which should remove all the object manipulation. But, this approach loses us the type safety that
|
|
111
|
+
* getCollectionByPath gives us
|
|
112
|
+
* 2. We could add a setCollection function to the list of arguments for this hook. This leaves us with type safety but
|
|
113
|
+
* makes the `useCollectionQuery` interface more complicated by adding arguments
|
|
114
|
+
*/
|
|
115
|
+
function fetchMoreUpdateQueryHandler(prev, fetchMoreResult, getCollectionByPath) {
|
|
116
|
+
const nextCollection = getCollectionByPath(fetchMoreResult);
|
|
117
|
+
const output = (0, lodash_1.cloneDeep)(prev);
|
|
118
|
+
const outputCollection = getCollectionByPath(output);
|
|
119
|
+
if (outputCollection === undefined || nextCollection === undefined) {
|
|
120
|
+
return output;
|
|
121
|
+
}
|
|
122
|
+
if (outputCollection.nodes && nextCollection.nodes) {
|
|
123
|
+
outputCollection.nodes = getUpdatedNodes(outputCollection.nodes, nextCollection.nodes);
|
|
124
|
+
}
|
|
125
|
+
if (outputCollection.edges && nextCollection.edges) {
|
|
126
|
+
outputCollection.edges = getUpdatedEdges(outputCollection.edges, nextCollection.edges);
|
|
127
|
+
}
|
|
128
|
+
Object.assign(outputCollection, Object.assign({ pageInfo: (0, lodash_1.cloneDeep)(nextCollection.pageInfo) }, getTotalCount(nextCollection.totalCount)));
|
|
129
|
+
return output;
|
|
130
|
+
}
|
|
131
|
+
function subscribeToMoreHandler(isSearching, prev, getCollectionByPath, subscriptionData, getNodeByPath) {
|
|
132
|
+
const node = getNodeByPath(subscriptionData);
|
|
133
|
+
const output = (0, lodash_1.cloneDeep)(prev);
|
|
134
|
+
const outputCollection = getCollectionByPath(output);
|
|
135
|
+
if (outputCollection == undefined || node == undefined)
|
|
136
|
+
return output;
|
|
137
|
+
if (isAlreadyUpdated(outputCollection, node) || isSearching) {
|
|
138
|
+
return prev;
|
|
139
|
+
}
|
|
140
|
+
if (outputCollection.nodes) {
|
|
141
|
+
outputCollection.nodes = getUpdatedNodes(outputCollection.nodes, [node], false);
|
|
142
|
+
}
|
|
143
|
+
if (outputCollection.edges) {
|
|
144
|
+
outputCollection.edges = getUpdatedEdges(outputCollection.edges, [(0, uniqueEdges_1.createEdge)(node)], false);
|
|
145
|
+
}
|
|
146
|
+
Object.assign(outputCollection, Object.assign({ pageInfo: (0, lodash_1.cloneDeep)(outputCollection.pageInfo) }, getTotalCount(outputCollection.totalCount, 1)));
|
|
147
|
+
return output;
|
|
148
|
+
}
|
|
149
|
+
function getTotalCount(totalCount, additionalCount = 0) {
|
|
150
|
+
return totalCount !== undefined
|
|
151
|
+
? { totalCount: totalCount + additionalCount }
|
|
152
|
+
: {};
|
|
153
|
+
}
|
|
154
|
+
function isAlreadyUpdated(outputCollection, newNode) {
|
|
155
|
+
let edgesAlreadyUpdated = true;
|
|
156
|
+
let nodesAlreadyUpdated = true;
|
|
157
|
+
if (outputCollection.edges) {
|
|
158
|
+
edgesAlreadyUpdated = outputCollection.edges.some(edge => {
|
|
159
|
+
return edge.node.id === newNode.id;
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
if (outputCollection.nodes) {
|
|
163
|
+
nodesAlreadyUpdated = outputCollection.nodes.some(node => {
|
|
164
|
+
return node.id === newNode.id;
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
return edgesAlreadyUpdated && nodesAlreadyUpdated;
|
|
168
|
+
}
|
|
169
|
+
exports.isAlreadyUpdated = isAlreadyUpdated;
|
|
170
|
+
function getUpdatedEdges(prevEdges, nextEdges, appendToEnd = true) {
|
|
171
|
+
const newEdges = appendToEnd
|
|
172
|
+
? [...prevEdges, ...nextEdges]
|
|
173
|
+
: [...nextEdges, ...prevEdges];
|
|
174
|
+
return (0, uniqueEdges_1.uniqueEdges)(newEdges);
|
|
175
|
+
}
|
|
176
|
+
function getUpdatedNodes(prevNodes, nextNodes, appendToEnd = true) {
|
|
177
|
+
const newNodes = appendToEnd
|
|
178
|
+
? [...prevNodes, ...nextNodes]
|
|
179
|
+
: [...nextNodes, ...prevNodes];
|
|
180
|
+
return (0, uniqueNodes_1.uniqueNodes)(newNodes);
|
|
181
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const react_hooks_1 = require("@testing-library/react-hooks");
|
|
13
|
+
const react_1 = require("@testing-library/react");
|
|
14
|
+
const useCollectionQuery_1 = require("./useCollectionQuery");
|
|
15
|
+
const test_utilities_1 = require("./test-utilities");
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
(0, test_utilities_1.setListQueryMockHasNextPage)(true);
|
|
18
|
+
test_utilities_1.listQueryResponseMock.mockClear();
|
|
19
|
+
test_utilities_1.subscriptionQueryMock.mockClear();
|
|
20
|
+
});
|
|
21
|
+
function useCollectionQueryHook(query) {
|
|
22
|
+
return (0, useCollectionQuery_1.useCollectionQuery)({
|
|
23
|
+
query: query,
|
|
24
|
+
getCollectionByPath(data) {
|
|
25
|
+
var _a;
|
|
26
|
+
return (_a = data === null || data === void 0 ? void 0 : data.conversation) === null || _a === void 0 ? void 0 : _a.smsMessages;
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function useCollectionQueryHookWithSubscription(query) {
|
|
31
|
+
return (0, useCollectionQuery_1.useCollectionQuery)({
|
|
32
|
+
query: query,
|
|
33
|
+
getCollectionByPath(data) {
|
|
34
|
+
var _a;
|
|
35
|
+
return (_a = data === null || data === void 0 ? void 0 : data.conversation) === null || _a === void 0 ? void 0 : _a.smsMessages;
|
|
36
|
+
},
|
|
37
|
+
subscription: {
|
|
38
|
+
document: test_utilities_1.SUBSCRIPTION_QUERY,
|
|
39
|
+
getNodeByPath(conversationData) {
|
|
40
|
+
var _a;
|
|
41
|
+
return (_a = conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationMessage) === null || _a === void 0 ? void 0 : _a.smsMessage;
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function useCollectionQueryHookWithSubscriptionAndSearch(query, searchTerm) {
|
|
47
|
+
return (0, useCollectionQuery_1.useCollectionQuery)({
|
|
48
|
+
query: query,
|
|
49
|
+
queryOptions: {
|
|
50
|
+
variables: {
|
|
51
|
+
searchTerm: searchTerm,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
getCollectionByPath(data) {
|
|
55
|
+
var _a;
|
|
56
|
+
return (_a = data === null || data === void 0 ? void 0 : data.conversation) === null || _a === void 0 ? void 0 : _a.smsMessages;
|
|
57
|
+
},
|
|
58
|
+
subscription: {
|
|
59
|
+
document: test_utilities_1.SUBSCRIPTION_QUERY,
|
|
60
|
+
getNodeByPath(conversationData) {
|
|
61
|
+
var _a;
|
|
62
|
+
return (_a = conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationMessage) === null || _a === void 0 ? void 0 : _a.smsMessage;
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
describe("useCollectionQuery", () => {
|
|
68
|
+
describe.each `
|
|
69
|
+
testCase | query | responseMock
|
|
70
|
+
${"excludes totalCount"} | ${test_utilities_1.LIST_QUERY} | ${test_utilities_1.listQueryResponseMock}
|
|
71
|
+
${"includes totalCount"} | ${test_utilities_1.LIST_QUERY_WITH_TOTAL_COUNT} | ${test_utilities_1.listQueryWithTotalCountResponseMock}
|
|
72
|
+
`("when the query run $testCase", ({ query, responseMock }) => {
|
|
73
|
+
describe("when useCollectionQuery is first called", () => {
|
|
74
|
+
describe("when nextPage is called while it's still loading initial content", () => {
|
|
75
|
+
it("should not trigger a the next page to be fetched", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
76
|
+
const { result } = (0, react_hooks_1.renderHook)(() => useCollectionQueryHook(query), {
|
|
77
|
+
wrapper: (0, test_utilities_1.wrapper)([
|
|
78
|
+
(0, test_utilities_1.buildListRequestMock)(query, responseMock),
|
|
79
|
+
(0, test_utilities_1.buildListRequestMockForNextPage)(query, responseMock),
|
|
80
|
+
]),
|
|
81
|
+
});
|
|
82
|
+
(0, react_hooks_1.act)(() => {
|
|
83
|
+
result.current.nextPage();
|
|
84
|
+
});
|
|
85
|
+
yield (0, react_hooks_1.act)(test_utilities_1.wait);
|
|
86
|
+
expect(responseMock).toHaveBeenCalledTimes(1);
|
|
87
|
+
}));
|
|
88
|
+
});
|
|
89
|
+
describe("when refresh is called while it's still loading initial content", () => {
|
|
90
|
+
it("should not trigger a refresh", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
91
|
+
const { result } = (0, react_hooks_1.renderHook)(() => useCollectionQueryHook(query), {
|
|
92
|
+
wrapper: (0, test_utilities_1.wrapper)([
|
|
93
|
+
(0, test_utilities_1.buildListRequestMock)(query, responseMock),
|
|
94
|
+
(0, test_utilities_1.buildListRequestMock)(query, responseMock),
|
|
95
|
+
]),
|
|
96
|
+
});
|
|
97
|
+
(0, react_hooks_1.act)(() => {
|
|
98
|
+
result.current.refresh();
|
|
99
|
+
});
|
|
100
|
+
yield (0, react_hooks_1.act)(test_utilities_1.wait);
|
|
101
|
+
expect(responseMock).toHaveBeenCalledTimes(1);
|
|
102
|
+
}));
|
|
103
|
+
});
|
|
104
|
+
describe("when there is no error", () => {
|
|
105
|
+
it("should update data", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
106
|
+
var _a, _b, _c, _d;
|
|
107
|
+
const { result } = (0, react_hooks_1.renderHook)(() => useCollectionQueryHook(query), {
|
|
108
|
+
wrapper: (0, test_utilities_1.wrapper)([(0, test_utilities_1.buildListRequestMock)(query, responseMock)]),
|
|
109
|
+
});
|
|
110
|
+
yield (0, react_hooks_1.act)(test_utilities_1.wait);
|
|
111
|
+
expect((_d = (_c = (_b = (_a = result.current.data) === null || _a === void 0 ? void 0 : _a.conversation) === null || _b === void 0 ? void 0 : _b.smsMessages) === null || _c === void 0 ? void 0 : _c.edges) === null || _d === void 0 ? void 0 : _d.length).toBe(1);
|
|
112
|
+
}));
|
|
113
|
+
it("should set initialLoading while loading data", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
114
|
+
const { result } = (0, react_hooks_1.renderHook)(() => useCollectionQueryHook(query), {
|
|
115
|
+
wrapper: (0, test_utilities_1.wrapper)([(0, test_utilities_1.buildListRequestMock)(query, responseMock)]),
|
|
116
|
+
});
|
|
117
|
+
expect(result.current.loadingInitialContent).toBe(true);
|
|
118
|
+
yield (0, react_hooks_1.act)(test_utilities_1.wait);
|
|
119
|
+
}));
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
describe("#nextPage", () => {
|
|
123
|
+
describe("when nextPage is called while it's still loadingNextPage", () => {
|
|
124
|
+
it("should not trigger a nextPage", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
125
|
+
const { result } = (0, react_hooks_1.renderHook)(() => useCollectionQueryHook(query), {
|
|
126
|
+
wrapper: (0, test_utilities_1.wrapper)([
|
|
127
|
+
(0, test_utilities_1.buildListRequestMock)(query, responseMock),
|
|
128
|
+
(0, test_utilities_1.buildListRequestMockForNextPage)(query, responseMock),
|
|
129
|
+
(0, test_utilities_1.buildListRequestMockForNextPage)(query, responseMock),
|
|
130
|
+
]),
|
|
131
|
+
});
|
|
132
|
+
yield (0, react_hooks_1.act)(test_utilities_1.wait);
|
|
133
|
+
(0, react_hooks_1.act)(() => {
|
|
134
|
+
result.current.nextPage();
|
|
135
|
+
});
|
|
136
|
+
(0, react_hooks_1.act)(() => {
|
|
137
|
+
result.current.nextPage();
|
|
138
|
+
});
|
|
139
|
+
yield (0, react_hooks_1.act)(test_utilities_1.wait);
|
|
140
|
+
yield (0, react_1.waitFor)(() => {
|
|
141
|
+
var _a, _b, _c;
|
|
142
|
+
expect((_c = (_b = (_a = result.current.data) === null || _a === void 0 ? void 0 : _a.conversation) === null || _b === void 0 ? void 0 : _b.smsMessages) === null || _c === void 0 ? void 0 : _c.edges).toHaveLength(2);
|
|
143
|
+
});
|
|
144
|
+
}));
|
|
145
|
+
});
|
|
146
|
+
describe("when refresh is called while it's still loadingNextPage", () => {
|
|
147
|
+
it("should trigger a refresh", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
148
|
+
const { result } = (0, react_hooks_1.renderHook)(() => useCollectionQueryHook(query), {
|
|
149
|
+
wrapper: (0, test_utilities_1.wrapper)([
|
|
150
|
+
(0, test_utilities_1.buildListRequestMock)(query, responseMock),
|
|
151
|
+
(0, test_utilities_1.buildListRequestMock)(query, responseMock),
|
|
152
|
+
(0, test_utilities_1.buildListRequestMockForNextPage)(query, responseMock),
|
|
153
|
+
]),
|
|
154
|
+
});
|
|
155
|
+
yield (0, react_hooks_1.act)(test_utilities_1.wait);
|
|
156
|
+
(0, react_hooks_1.act)(() => {
|
|
157
|
+
result.current.nextPage();
|
|
158
|
+
});
|
|
159
|
+
(0, react_hooks_1.act)(() => {
|
|
160
|
+
result.current.refresh();
|
|
161
|
+
});
|
|
162
|
+
expect(result.current.loadingRefresh).toBe(true);
|
|
163
|
+
yield (0, react_hooks_1.act)(test_utilities_1.wait);
|
|
164
|
+
}));
|
|
165
|
+
});
|
|
166
|
+
describe("when there is no more data to fetch", () => {
|
|
167
|
+
it("should not fetch more data", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
168
|
+
(0, test_utilities_1.setListQueryMockHasNextPage)(false);
|
|
169
|
+
const { result } = (0, react_hooks_1.renderHook)(() => useCollectionQueryHook(query), {
|
|
170
|
+
wrapper: (0, test_utilities_1.wrapper)([
|
|
171
|
+
(0, test_utilities_1.buildListRequestMock)(query, responseMock),
|
|
172
|
+
(0, test_utilities_1.buildListRequestMockForNextPage)(query, responseMock),
|
|
173
|
+
]),
|
|
174
|
+
});
|
|
175
|
+
yield (0, react_hooks_1.act)(test_utilities_1.wait);
|
|
176
|
+
(0, react_hooks_1.act)(() => {
|
|
177
|
+
result.current.nextPage();
|
|
178
|
+
});
|
|
179
|
+
yield (0, react_hooks_1.act)(test_utilities_1.wait);
|
|
180
|
+
expect(responseMock).toHaveBeenCalledTimes(1);
|
|
181
|
+
}));
|
|
182
|
+
});
|
|
183
|
+
describe("when there is no error", () => {
|
|
184
|
+
it("should update data", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
185
|
+
const { result } = (0, react_hooks_1.renderHook)(() => useCollectionQueryHook(query), {
|
|
186
|
+
wrapper: (0, test_utilities_1.wrapper)([
|
|
187
|
+
(0, test_utilities_1.buildListRequestMock)(query, responseMock),
|
|
188
|
+
(0, test_utilities_1.buildListRequestMockForNextPage)(query, responseMock),
|
|
189
|
+
]),
|
|
190
|
+
});
|
|
191
|
+
yield (0, react_hooks_1.act)(test_utilities_1.wait);
|
|
192
|
+
(0, react_hooks_1.act)(() => {
|
|
193
|
+
result.current.nextPage();
|
|
194
|
+
});
|
|
195
|
+
yield (0, react_hooks_1.act)(test_utilities_1.wait);
|
|
196
|
+
yield (0, react_1.waitFor)(() => {
|
|
197
|
+
var _a, _b, _c;
|
|
198
|
+
expect((_c = (_b = (_a = result.current.data) === null || _a === void 0 ? void 0 : _a.conversation) === null || _b === void 0 ? void 0 : _b.smsMessages) === null || _c === void 0 ? void 0 : _c.edges).toHaveLength(2);
|
|
199
|
+
});
|
|
200
|
+
}));
|
|
201
|
+
it("should set loadingNextPage while loading data", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
202
|
+
const { result } = (0, react_hooks_1.renderHook)(() => useCollectionQueryHook(query), {
|
|
203
|
+
wrapper: (0, test_utilities_1.wrapper)([
|
|
204
|
+
(0, test_utilities_1.buildListRequestMock)(query, responseMock),
|
|
205
|
+
(0, test_utilities_1.buildListRequestMockForNextPage)(query, responseMock),
|
|
206
|
+
]),
|
|
207
|
+
});
|
|
208
|
+
yield (0, react_hooks_1.act)(test_utilities_1.wait);
|
|
209
|
+
(0, react_hooks_1.act)(() => {
|
|
210
|
+
result.current.nextPage();
|
|
211
|
+
});
|
|
212
|
+
expect(result.current.loadingNextPage).toBe(true);
|
|
213
|
+
yield (0, react_hooks_1.act)(test_utilities_1.wait);
|
|
214
|
+
}));
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
describe("#refresh", () => {
|
|
218
|
+
describe("when refresh is called while it's still loadingRefresh", () => {
|
|
219
|
+
it("should not trigger a refresh", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
220
|
+
const { result } = (0, react_hooks_1.renderHook)(() => useCollectionQueryHook(query), {
|
|
221
|
+
wrapper: (0, test_utilities_1.wrapper)([
|
|
222
|
+
(0, test_utilities_1.buildListRequestMock)(query, responseMock),
|
|
223
|
+
(0, test_utilities_1.buildListRequestMock)(query, responseMock),
|
|
224
|
+
(0, test_utilities_1.buildListRequestMock)(query, responseMock),
|
|
225
|
+
]),
|
|
226
|
+
});
|
|
227
|
+
yield (0, react_hooks_1.act)(test_utilities_1.wait);
|
|
228
|
+
(0, react_hooks_1.act)(() => {
|
|
229
|
+
result.current.refresh();
|
|
230
|
+
});
|
|
231
|
+
(0, react_hooks_1.act)(() => {
|
|
232
|
+
result.current.refresh();
|
|
233
|
+
});
|
|
234
|
+
yield (0, react_hooks_1.act)(test_utilities_1.wait);
|
|
235
|
+
expect(responseMock).toHaveBeenCalledTimes(2);
|
|
236
|
+
}));
|
|
237
|
+
});
|
|
238
|
+
describe("when nextPage is called while it's still loadingRefresh", () => {
|
|
239
|
+
it("should not trigger a nextPage", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
240
|
+
const { result } = (0, react_hooks_1.renderHook)(() => useCollectionQueryHook(query), {
|
|
241
|
+
wrapper: (0, test_utilities_1.wrapper)([
|
|
242
|
+
(0, test_utilities_1.buildListRequestMock)(query, responseMock),
|
|
243
|
+
(0, test_utilities_1.buildListRequestMock)(query, responseMock),
|
|
244
|
+
(0, test_utilities_1.buildListRequestMockForNextPage)(query, responseMock),
|
|
245
|
+
]),
|
|
246
|
+
});
|
|
247
|
+
yield (0, react_hooks_1.act)(test_utilities_1.wait);
|
|
248
|
+
(0, react_hooks_1.act)(() => {
|
|
249
|
+
result.current.refresh();
|
|
250
|
+
});
|
|
251
|
+
(0, react_hooks_1.act)(() => {
|
|
252
|
+
result.current.nextPage();
|
|
253
|
+
});
|
|
254
|
+
expect(result.current.loadingNextPage).toBe(false);
|
|
255
|
+
yield (0, react_hooks_1.act)(test_utilities_1.wait);
|
|
256
|
+
}));
|
|
257
|
+
});
|
|
258
|
+
describe("when there is no error", () => {
|
|
259
|
+
it("should set loadingRefresh while loading data", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
260
|
+
const { result } = (0, react_hooks_1.renderHook)(() => useCollectionQueryHook(query), {
|
|
261
|
+
wrapper: (0, test_utilities_1.wrapper)([
|
|
262
|
+
(0, test_utilities_1.buildListRequestMock)(query, responseMock),
|
|
263
|
+
(0, test_utilities_1.buildListRequestMock)(query, responseMock),
|
|
264
|
+
]),
|
|
265
|
+
});
|
|
266
|
+
yield (0, react_hooks_1.act)(test_utilities_1.wait);
|
|
267
|
+
(0, react_hooks_1.act)(() => {
|
|
268
|
+
result.current.refresh();
|
|
269
|
+
});
|
|
270
|
+
expect(result.current.loadingRefresh).toBe(true);
|
|
271
|
+
yield (0, react_hooks_1.act)(test_utilities_1.wait);
|
|
272
|
+
}));
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
describe("#subscribeToMore", () => {
|
|
276
|
+
describe("when hook receives update from item not in collection", () => {
|
|
277
|
+
it("should add new item to collection", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
278
|
+
var _a, _b, _c, _d, _e;
|
|
279
|
+
const { result, waitForNextUpdate } = (0, react_hooks_1.renderHook)(() => useCollectionQueryHookWithSubscription(query), {
|
|
280
|
+
wrapper: (0, test_utilities_1.wrapper)([
|
|
281
|
+
(0, test_utilities_1.buildListRequestMock)(query, responseMock, "1"),
|
|
282
|
+
(0, test_utilities_1.buildSubscriptionRequestMock)("2"),
|
|
283
|
+
]),
|
|
284
|
+
});
|
|
285
|
+
// Wait for initial load
|
|
286
|
+
yield (0, react_hooks_1.act)(waitForNextUpdate);
|
|
287
|
+
// Wait for subscription
|
|
288
|
+
yield (0, react_hooks_1.act)(waitForNextUpdate);
|
|
289
|
+
expect((_e = (_d = (_c = (_b = (_a = result === null || result === void 0 ? void 0 : result.current) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.conversation) === null || _c === void 0 ? void 0 : _c.smsMessages) === null || _d === void 0 ? void 0 : _d.edges) === null || _e === void 0 ? void 0 : _e.length).toBe(2);
|
|
290
|
+
}));
|
|
291
|
+
});
|
|
292
|
+
describe("when hook receives update from item already in collection", () => {
|
|
293
|
+
it("should return the existing collection", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
294
|
+
var _a, _b, _c, _d, _e;
|
|
295
|
+
const { result, waitForNextUpdate } = (0, react_hooks_1.renderHook)(() => useCollectionQueryHookWithSubscription(query), {
|
|
296
|
+
wrapper: (0, test_utilities_1.wrapper)([
|
|
297
|
+
(0, test_utilities_1.buildListRequestMock)(query, responseMock, "1"),
|
|
298
|
+
(0, test_utilities_1.buildSubscriptionRequestMock)("1"),
|
|
299
|
+
]),
|
|
300
|
+
});
|
|
301
|
+
// Wait for initial load
|
|
302
|
+
yield (0, react_hooks_1.act)(waitForNextUpdate);
|
|
303
|
+
// Wait for subscription
|
|
304
|
+
yield (0, react_hooks_1.act)(() => (0, test_utilities_1.wait)(200));
|
|
305
|
+
expect((_e = (_d = (_c = (_b = (_a = result === null || result === void 0 ? void 0 : result.current) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.conversation) === null || _c === void 0 ? void 0 : _c.smsMessages) === null || _d === void 0 ? void 0 : _d.edges) === null || _e === void 0 ? void 0 : _e.length).toBe(1);
|
|
306
|
+
}));
|
|
307
|
+
});
|
|
308
|
+
describe("when hook receives `update` but is currently searching a collection", () => {
|
|
309
|
+
it("should return the existing collection without adding the subscribed content", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
310
|
+
var _a, _b, _c, _d, _e;
|
|
311
|
+
const searchTerm = "FooBar";
|
|
312
|
+
const { result, waitForNextUpdate } = (0, react_hooks_1.renderHook)(() => useCollectionQueryHookWithSubscriptionAndSearch(query, searchTerm), {
|
|
313
|
+
wrapper: (0, test_utilities_1.wrapper)([
|
|
314
|
+
(0, test_utilities_1.buildListRequestMock)(query, responseMock, "1", searchTerm),
|
|
315
|
+
(0, test_utilities_1.buildSubscriptionRequestMock)("1"),
|
|
316
|
+
]),
|
|
317
|
+
});
|
|
318
|
+
// Wait for initial load
|
|
319
|
+
yield (0, react_hooks_1.act)(waitForNextUpdate);
|
|
320
|
+
// Wait for subscription
|
|
321
|
+
yield (0, react_hooks_1.act)(() => (0, test_utilities_1.wait)(200));
|
|
322
|
+
expect((_e = (_d = (_c = (_b = (_a = result === null || result === void 0 ? void 0 : result.current) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.conversation) === null || _c === void 0 ? void 0 : _c.smsMessages) === null || _d === void 0 ? void 0 : _d.edges) === null || _e === void 0 ? void 0 : _e.length).toBe(1);
|
|
323
|
+
}));
|
|
324
|
+
});
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { useFocusTrap } from "./useFocusTrap
|
|
1
|
+
export { useFocusTrap } from "./useFocusTrap";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useFocusTrap = void 0;
|
|
4
|
-
var
|
|
5
|
-
Object.defineProperty(exports, "useFocusTrap", { enumerable: true, get: function () { return
|
|
4
|
+
var useFocusTrap_1 = require("./useFocusTrap");
|
|
5
|
+
Object.defineProperty(exports, "useFocusTrap", { enumerable: true, get: function () { return useFocusTrap_1.useFocusTrap; } });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|