@cratis/arc.react 18.4.3 → 18.6.0

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.
Files changed (161) hide show
  1. package/commands/for_CommandScopeImplementation/FakeCommand.ts +25 -26
  2. package/commands/for_CommandScopeImplementation/when_property_changes_on_added_command.ts +2 -2
  3. package/dist/cjs/commands/for_CommandScopeImplementation/FakeCommand.d.ts +23 -0
  4. package/dist/cjs/commands/for_CommandScopeImplementation/FakeCommand.d.ts.map +1 -0
  5. package/dist/cjs/commands/for_CommandScopeImplementation/when_executing_with_three_commands_were_two_having_changes.d.ts +2 -0
  6. package/dist/cjs/commands/for_CommandScopeImplementation/when_executing_with_three_commands_were_two_having_changes.d.ts.map +1 -0
  7. package/dist/cjs/commands/for_CommandScopeImplementation/when_none_of_the_added_commands_has_changes.d.ts +2 -0
  8. package/dist/cjs/commands/for_CommandScopeImplementation/when_none_of_the_added_commands_has_changes.d.ts.map +1 -0
  9. package/dist/cjs/commands/for_CommandScopeImplementation/when_one_of_the_added_commands_has_changes.d.ts +2 -0
  10. package/dist/cjs/commands/for_CommandScopeImplementation/when_one_of_the_added_commands_has_changes.d.ts.map +1 -0
  11. package/dist/cjs/commands/for_CommandScopeImplementation/when_property_changes_on_added_command.d.ts +2 -0
  12. package/dist/cjs/commands/for_CommandScopeImplementation/when_property_changes_on_added_command.d.ts.map +1 -0
  13. package/dist/cjs/commands/for_CommandScopeImplementation/when_reverting_with_three_commands_were_two_having_changes.d.ts +2 -0
  14. package/dist/cjs/commands/for_CommandScopeImplementation/when_reverting_with_three_commands_were_two_having_changes.d.ts.map +1 -0
  15. package/dist/cjs/commands/for_CommandScopeImplementation/when_there_are_no_commands.d.ts +2 -0
  16. package/dist/cjs/commands/for_CommandScopeImplementation/when_there_are_no_commands.d.ts.map +1 -0
  17. package/dist/cjs/commands/for_useCommand/FakeCommand.d.ts +17 -0
  18. package/dist/cjs/commands/for_useCommand/FakeCommand.d.ts.map +1 -0
  19. package/dist/cjs/commands/for_useCommand/when_creating_instance.d.ts +2 -0
  20. package/dist/cjs/commands/for_useCommand/when_creating_instance.d.ts.map +1 -0
  21. package/dist/cjs/commands/for_useCommand/when_creating_instance_with_initial_values.d.ts +2 -0
  22. package/dist/cjs/commands/for_useCommand/when_creating_instance_with_initial_values.d.ts.map +1 -0
  23. package/dist/cjs/commands/for_useCommand/when_creating_instance_without_optional_context_values.d.ts +2 -0
  24. package/dist/cjs/commands/for_useCommand/when_creating_instance_without_optional_context_values.d.ts.map +1 -0
  25. package/dist/cjs/identity/IdentityProvider.d.ts +8 -1
  26. package/dist/cjs/identity/IdentityProvider.d.ts.map +1 -1
  27. package/dist/cjs/identity/IdentityProvider.js +14 -5
  28. package/dist/cjs/identity/IdentityProvider.js.map +1 -1
  29. package/dist/cjs/identity/for_IdentityProvider/when_refreshing_identity.d.ts +2 -0
  30. package/dist/cjs/identity/for_IdentityProvider/when_refreshing_identity.d.ts.map +1 -0
  31. package/dist/cjs/identity/useIdentity.d.ts +2 -0
  32. package/dist/cjs/identity/useIdentity.d.ts.map +1 -1
  33. package/dist/cjs/identity/useIdentity.js +8 -5
  34. package/dist/cjs/identity/useIdentity.js.map +1 -1
  35. package/dist/cjs/queries/for_useObservableQuery/FakeObservableQuery.d.ts +19 -0
  36. package/dist/cjs/queries/for_useObservableQuery/FakeObservableQuery.d.ts.map +1 -0
  37. package/dist/cjs/queries/for_useObservableQuery/when_creating_instance.d.ts +2 -0
  38. package/dist/cjs/queries/for_useObservableQuery/when_creating_instance.d.ts.map +1 -0
  39. package/dist/cjs/queries/for_useQuery/FakeQuery.d.ts +14 -0
  40. package/dist/cjs/queries/for_useQuery/FakeQuery.d.ts.map +1 -0
  41. package/dist/cjs/queries/for_useQuery/when_creating_instance.d.ts +2 -0
  42. package/dist/cjs/queries/for_useQuery/when_creating_instance.d.ts.map +1 -0
  43. package/dist/cjs/queries/for_useQuery/when_creating_instance_with_sorting.d.ts +2 -0
  44. package/dist/cjs/queries/for_useQuery/when_creating_instance_with_sorting.d.ts.map +1 -0
  45. package/dist/cjs/queries/for_useQuery/when_creating_instance_without_optional_context_values.d.ts +2 -0
  46. package/dist/cjs/queries/for_useQuery/when_creating_instance_without_optional_context_values.d.ts.map +1 -0
  47. package/dist/cjs/queries/for_useQueryWithPaging/when_creating_instance_with_paging.d.ts +2 -0
  48. package/dist/cjs/queries/for_useQueryWithPaging/when_creating_instance_with_paging.d.ts.map +1 -0
  49. package/dist/cjs/queries/useObservableQuery.js +1 -1
  50. package/dist/cjs/queries/useObservableQuery.js.map +1 -1
  51. package/dist/esm/commands/for_CommandScopeImplementation/FakeCommand.d.ts +23 -0
  52. package/dist/esm/commands/for_CommandScopeImplementation/FakeCommand.d.ts.map +1 -0
  53. package/dist/esm/commands/for_CommandScopeImplementation/FakeCommand.js +49 -0
  54. package/dist/esm/commands/for_CommandScopeImplementation/FakeCommand.js.map +1 -0
  55. package/dist/esm/commands/for_CommandScopeImplementation/when_executing_with_three_commands_were_two_having_changes.d.ts +2 -0
  56. package/dist/esm/commands/for_CommandScopeImplementation/when_executing_with_three_commands_were_two_having_changes.d.ts.map +1 -0
  57. package/dist/esm/commands/for_CommandScopeImplementation/when_executing_with_three_commands_were_two_having_changes.js +17 -0
  58. package/dist/esm/commands/for_CommandScopeImplementation/when_executing_with_three_commands_were_two_having_changes.js.map +1 -0
  59. package/dist/esm/commands/for_CommandScopeImplementation/when_none_of_the_added_commands_has_changes.d.ts +2 -0
  60. package/dist/esm/commands/for_CommandScopeImplementation/when_none_of_the_added_commands_has_changes.d.ts.map +1 -0
  61. package/dist/esm/commands/for_CommandScopeImplementation/when_none_of_the_added_commands_has_changes.js +13 -0
  62. package/dist/esm/commands/for_CommandScopeImplementation/when_none_of_the_added_commands_has_changes.js.map +1 -0
  63. package/dist/esm/commands/for_CommandScopeImplementation/when_one_of_the_added_commands_has_changes.d.ts +2 -0
  64. package/dist/esm/commands/for_CommandScopeImplementation/when_one_of_the_added_commands_has_changes.d.ts.map +1 -0
  65. package/dist/esm/commands/for_CommandScopeImplementation/when_one_of_the_added_commands_has_changes.js +13 -0
  66. package/dist/esm/commands/for_CommandScopeImplementation/when_one_of_the_added_commands_has_changes.js.map +1 -0
  67. package/dist/esm/commands/for_CommandScopeImplementation/when_property_changes_on_added_command.d.ts +2 -0
  68. package/dist/esm/commands/for_CommandScopeImplementation/when_property_changes_on_added_command.d.ts.map +1 -0
  69. package/dist/esm/commands/for_CommandScopeImplementation/when_property_changes_on_added_command.js +18 -0
  70. package/dist/esm/commands/for_CommandScopeImplementation/when_property_changes_on_added_command.js.map +1 -0
  71. package/dist/esm/commands/for_CommandScopeImplementation/when_reverting_with_three_commands_were_two_having_changes.d.ts +2 -0
  72. package/dist/esm/commands/for_CommandScopeImplementation/when_reverting_with_three_commands_were_two_having_changes.d.ts.map +1 -0
  73. package/dist/esm/commands/for_CommandScopeImplementation/when_reverting_with_three_commands_were_two_having_changes.js +17 -0
  74. package/dist/esm/commands/for_CommandScopeImplementation/when_reverting_with_three_commands_were_two_having_changes.js.map +1 -0
  75. package/dist/esm/commands/for_CommandScopeImplementation/when_there_are_no_commands.d.ts +2 -0
  76. package/dist/esm/commands/for_CommandScopeImplementation/when_there_are_no_commands.d.ts.map +1 -0
  77. package/dist/esm/commands/for_CommandScopeImplementation/when_there_are_no_commands.js +6 -0
  78. package/dist/esm/commands/for_CommandScopeImplementation/when_there_are_no_commands.js.map +1 -0
  79. package/dist/esm/commands/for_useCommand/FakeCommand.d.ts +17 -0
  80. package/dist/esm/commands/for_useCommand/FakeCommand.d.ts.map +1 -0
  81. package/dist/esm/commands/for_useCommand/FakeCommand.js +18 -0
  82. package/dist/esm/commands/for_useCommand/FakeCommand.js.map +1 -0
  83. package/dist/esm/commands/for_useCommand/when_creating_instance.d.ts +2 -0
  84. package/dist/esm/commands/for_useCommand/when_creating_instance.d.ts.map +1 -0
  85. package/dist/esm/commands/for_useCommand/when_creating_instance.js +28 -0
  86. package/dist/esm/commands/for_useCommand/when_creating_instance.js.map +1 -0
  87. package/dist/esm/commands/for_useCommand/when_creating_instance_with_initial_values.d.ts +2 -0
  88. package/dist/esm/commands/for_useCommand/when_creating_instance_with_initial_values.d.ts.map +1 -0
  89. package/dist/esm/commands/for_useCommand/when_creating_instance_with_initial_values.js +24 -0
  90. package/dist/esm/commands/for_useCommand/when_creating_instance_with_initial_values.js.map +1 -0
  91. package/dist/esm/commands/for_useCommand/when_creating_instance_without_optional_context_values.d.ts +2 -0
  92. package/dist/esm/commands/for_useCommand/when_creating_instance_without_optional_context_values.d.ts.map +1 -0
  93. package/dist/esm/commands/for_useCommand/when_creating_instance_without_optional_context_values.js +24 -0
  94. package/dist/esm/commands/for_useCommand/when_creating_instance_without_optional_context_values.js.map +1 -0
  95. package/dist/esm/for_Bindings/given/bindings_context.d.ts +4 -0
  96. package/dist/esm/for_Bindings/given/bindings_context.d.ts.map +1 -0
  97. package/dist/esm/for_Bindings/given/bindings_context.js +5 -0
  98. package/dist/esm/for_Bindings/given/bindings_context.js.map +1 -0
  99. package/dist/esm/for_Bindings/when_initializing_bindings.d.ts +2 -0
  100. package/dist/esm/for_Bindings/when_initializing_bindings.d.ts.map +1 -0
  101. package/dist/esm/for_Bindings/when_initializing_bindings.js +24 -0
  102. package/dist/esm/for_Bindings/when_initializing_bindings.js.map +1 -0
  103. package/dist/esm/for_Bindings/when_initializing_bindings_without_optional_parameters.d.ts +2 -0
  104. package/dist/esm/for_Bindings/when_initializing_bindings_without_optional_parameters.d.ts.map +1 -0
  105. package/dist/esm/for_Bindings/when_initializing_bindings_without_optional_parameters.js +24 -0
  106. package/dist/esm/for_Bindings/when_initializing_bindings_without_optional_parameters.js.map +1 -0
  107. package/dist/esm/identity/IdentityProvider.d.ts +8 -1
  108. package/dist/esm/identity/IdentityProvider.d.ts.map +1 -1
  109. package/dist/esm/identity/IdentityProvider.js +14 -5
  110. package/dist/esm/identity/IdentityProvider.js.map +1 -1
  111. package/dist/esm/identity/for_IdentityProvider/when_refreshing_identity.d.ts +2 -0
  112. package/dist/esm/identity/for_IdentityProvider/when_refreshing_identity.d.ts.map +1 -0
  113. package/dist/esm/identity/for_IdentityProvider/when_refreshing_identity.js +47 -0
  114. package/dist/esm/identity/for_IdentityProvider/when_refreshing_identity.js.map +1 -0
  115. package/dist/esm/identity/useIdentity.d.ts +2 -0
  116. package/dist/esm/identity/useIdentity.d.ts.map +1 -1
  117. package/dist/esm/identity/useIdentity.js +8 -5
  118. package/dist/esm/identity/useIdentity.js.map +1 -1
  119. package/dist/esm/queries/for_useObservableQuery/FakeObservableQuery.d.ts +19 -0
  120. package/dist/esm/queries/for_useObservableQuery/FakeObservableQuery.d.ts.map +1 -0
  121. package/dist/esm/queries/for_useObservableQuery/FakeObservableQuery.js +25 -0
  122. package/dist/esm/queries/for_useObservableQuery/FakeObservableQuery.js.map +1 -0
  123. package/dist/esm/queries/for_useObservableQuery/when_creating_instance.d.ts +2 -0
  124. package/dist/esm/queries/for_useObservableQuery/when_creating_instance.d.ts.map +1 -0
  125. package/dist/esm/queries/for_useObservableQuery/when_creating_instance.js +66 -0
  126. package/dist/esm/queries/for_useObservableQuery/when_creating_instance.js.map +1 -0
  127. package/dist/esm/queries/for_useQuery/FakeQuery.d.ts +14 -0
  128. package/dist/esm/queries/for_useQuery/FakeQuery.d.ts.map +1 -0
  129. package/dist/esm/queries/for_useQuery/FakeQuery.js +13 -0
  130. package/dist/esm/queries/for_useQuery/FakeQuery.js.map +1 -0
  131. package/dist/esm/queries/for_useQuery/when_creating_instance.d.ts +2 -0
  132. package/dist/esm/queries/for_useQuery/when_creating_instance.d.ts.map +1 -0
  133. package/dist/esm/queries/for_useQuery/when_creating_instance.js +48 -0
  134. package/dist/esm/queries/for_useQuery/when_creating_instance.js.map +1 -0
  135. package/dist/esm/queries/for_useQuery/when_creating_instance_with_sorting.d.ts +2 -0
  136. package/dist/esm/queries/for_useQuery/when_creating_instance_with_sorting.d.ts.map +1 -0
  137. package/dist/esm/queries/for_useQuery/when_creating_instance_with_sorting.js +40 -0
  138. package/dist/esm/queries/for_useQuery/when_creating_instance_with_sorting.js.map +1 -0
  139. package/dist/esm/queries/for_useQuery/when_creating_instance_without_optional_context_values.d.ts +2 -0
  140. package/dist/esm/queries/for_useQuery/when_creating_instance_without_optional_context_values.d.ts.map +1 -0
  141. package/dist/esm/queries/for_useQuery/when_creating_instance_without_optional_context_values.js +44 -0
  142. package/dist/esm/queries/for_useQuery/when_creating_instance_without_optional_context_values.js.map +1 -0
  143. package/dist/esm/queries/for_useQueryWithPaging/when_creating_instance_with_paging.d.ts +2 -0
  144. package/dist/esm/queries/for_useQueryWithPaging/when_creating_instance_with_paging.d.ts.map +1 -0
  145. package/dist/esm/queries/for_useQueryWithPaging/when_creating_instance_with_paging.js +51 -0
  146. package/dist/esm/queries/for_useQueryWithPaging/when_creating_instance_with_paging.js.map +1 -0
  147. package/dist/esm/queries/useObservableQuery.js +1 -1
  148. package/dist/esm/queries/useObservableQuery.js.map +1 -1
  149. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  150. package/global.d.ts +11 -0
  151. package/identity/IdentityProvider.tsx +23 -6
  152. package/identity/for_IdentityProvider/when_refreshing_identity.ts +4 -3
  153. package/identity/useIdentity.ts +29 -5
  154. package/package.json +2 -2
  155. package/queries/for_useObservableQuery/FakeObservableQuery.ts +43 -0
  156. package/queries/for_useObservableQuery/when_creating_instance.ts +97 -0
  157. package/queries/for_useQuery/when_creating_instance.ts +6 -2
  158. package/queries/for_useQuery/when_creating_instance_with_sorting.ts +6 -4
  159. package/queries/for_useQuery/when_creating_instance_without_optional_context_values.ts +6 -2
  160. package/queries/for_useQueryWithPaging/when_creating_instance_with_paging.ts +6 -2
  161. package/queries/useObservableQuery.ts +1 -1
@@ -3,6 +3,7 @@
3
3
 
4
4
  import React from 'react';
5
5
  import { useState, useEffect, useContext } from 'react';
6
+ import { Constructor } from '@cratis/fundamentals';
6
7
  import { IIdentity } from '@cratis/arc/identity';
7
8
  import { IdentityProvider as RootIdentityProvider } from '@cratis/arc/identity';
8
9
  import { GetHttpHeaders } from '@cratis/arc';
@@ -20,16 +21,26 @@ const defaultIdentityContext: IIdentity = {
20
21
  }
21
22
  };
22
23
 
23
- export const IdentityProviderContext = React.createContext<IIdentity>(defaultIdentityContext);
24
+ type IdentityContextValue = {
25
+ identity: IIdentity;
26
+ detailsConstructor?: Constructor;
27
+ };
28
+
29
+ const defaultContextValue: IdentityContextValue = {
30
+ identity: defaultIdentityContext
31
+ };
32
+
33
+ export const IdentityProviderContext = React.createContext<IdentityContextValue>(defaultContextValue);
24
34
 
25
35
  export interface IdentityProviderProps {
26
36
  children?: JSX.Element | JSX.Element[],
27
- httpHeadersCallback?: GetHttpHeaders
37
+ httpHeadersCallback?: GetHttpHeaders,
38
+ detailsType?: Constructor
28
39
  }
29
40
 
30
41
  export const IdentityProvider = (props: IdentityProviderProps) => {
31
42
  const arc = useContext(ArcContext);
32
- const [context, setContext] = useState<IIdentity>(defaultIdentityContext);
43
+ const [context, setContext] = useState<IdentityContextValue>(defaultContextValue);
33
44
 
34
45
  const wrapRefresh = (identity: IIdentity): IIdentity => {
35
46
  const originalRefresh = identity.refresh.bind(identity);
@@ -39,7 +50,10 @@ export const IdentityProvider = (props: IdentityProviderProps) => {
39
50
  return new Promise<IIdentity>(resolve => {
40
51
  originalRefresh().then(newIdentity => {
41
52
  const wrappedIdentity = wrapRefresh(newIdentity);
42
- setContext(wrappedIdentity);
53
+ setContext({
54
+ identity: wrappedIdentity,
55
+ detailsConstructor: props.detailsType
56
+ });
43
57
  resolve(wrappedIdentity);
44
58
  });
45
59
  });
@@ -51,9 +65,12 @@ export const IdentityProvider = (props: IdentityProviderProps) => {
51
65
  RootIdentityProvider.setHttpHeadersCallback(props.httpHeadersCallback!);
52
66
  RootIdentityProvider.setApiBasePath(arc.apiBasePath ?? '');
53
67
  RootIdentityProvider.setOrigin(arc.origin ?? '');
54
- RootIdentityProvider.getCurrent().then(identity => {
68
+ RootIdentityProvider.getCurrent(props.detailsType).then(identity => {
55
69
  const wrappedIdentity = wrapRefresh(identity);
56
- setContext(wrappedIdentity);
70
+ setContext({
71
+ identity: wrappedIdentity,
72
+ detailsConstructor: props.detailsType
73
+ });
57
74
  });
58
75
  }, []);
59
76
 
@@ -6,7 +6,7 @@ import { render } from '@testing-library/react';
6
6
  import { IdentityProvider } from '../IdentityProvider';
7
7
  import { useIdentity } from '../useIdentity';
8
8
  import { IIdentity } from '@cratis/arc/identity';
9
- import sinon from 'sinon';
9
+ import { createFetchHelper } from '@cratis/arc/helpers/fetchHelper';
10
10
 
11
11
  describe('when refreshing identity', async () => {
12
12
  let capturedIdentity: IIdentity | null = null;
@@ -22,7 +22,8 @@ describe('when refreshing identity', async () => {
22
22
  return React.createElement('div', null, 'Test');
23
23
  };
24
24
 
25
- const mockFetch = sinon.stub(global, 'fetch');
25
+ const fetchHelper = createFetchHelper();
26
+ const mockFetch = fetchHelper.stubFetch();
26
27
  mockFetch.onFirstCall().resolves({
27
28
  json: async () => ({
28
29
  id: 'initial-id',
@@ -55,5 +56,5 @@ describe('when refreshing identity', async () => {
55
56
  it('should have new id', () => newId.should.equal('new-id'));
56
57
  it('should have new name', () => newName.should.equal('Updated User'));
57
58
 
58
- mockFetch.restore();
59
+ fetchHelper.restore();
59
60
  });
@@ -2,6 +2,7 @@
2
2
  // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
3
 
4
4
  import React from 'react';
5
+ import { Constructor } from '@cratis/fundamentals';
5
6
  import { IdentityProviderContext } from './IdentityProvider';
6
7
  import { IIdentity } from '@cratis/arc/identity';
7
8
 
@@ -10,10 +11,33 @@ import { IIdentity } from '@cratis/arc/identity';
10
11
  * @param defaultDetails Optional default details to use if the context is not set.
11
12
  * @returns An identity context.
12
13
  */
13
- export function useIdentity<TDetails = object>(defaultDetails?: TDetails | undefined | null): IIdentity<TDetails> {
14
- const context = React.useContext(IdentityProviderContext) as IIdentity<TDetails>;
15
- if (context.isSet === false && defaultDetails !== undefined) {
16
- context.details = defaultDetails!;
14
+ export function useIdentity<TDetails = object>(defaultDetails?: TDetails | undefined | null): IIdentity<TDetails>;
15
+
16
+ /**
17
+ * Hook to get the identity context with type-safe deserialization.
18
+ * @param type Constructor for the details type to enable type-safe deserialization.
19
+ * @param defaultDetails Optional default details to use if the context is not set.
20
+ * @returns An identity context.
21
+ */
22
+ export function useIdentity<TDetails = object>(type: Constructor<TDetails>, defaultDetails?: TDetails | undefined | null): IIdentity<TDetails>;
23
+
24
+ export function useIdentity<TDetails = object>(
25
+ typeOrDefaultDetails?: Constructor<TDetails> | TDetails | undefined | null,
26
+ defaultDetails?: TDetails | undefined | null
27
+ ): IIdentity<TDetails> {
28
+ const contextValue = React.useContext(IdentityProviderContext);
29
+ const identity = contextValue.identity as IIdentity<TDetails>;
30
+
31
+ // Determine if first argument is a Constructor or default details
32
+ // Constructors are functions, but regular functions would be unusual here.
33
+ // We rely on the type system and developer intent - if a function is passed,
34
+ // it's expected to be a constructor class.
35
+ const isConstructor = typeof typeOrDefaultDetails === 'function';
36
+ const actualDefaultDetails = isConstructor ? defaultDetails : typeOrDefaultDetails;
37
+
38
+ if (identity.isSet === false && actualDefaultDetails !== undefined) {
39
+ identity.details = actualDefaultDetails!;
17
40
  }
18
- return context;
41
+
42
+ return identity;
19
43
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cratis/arc.react",
3
- "version": "18.4.3",
3
+ "version": "18.6.0",
4
4
  "description": "",
5
5
  "author": "Cratis",
6
6
  "license": "MIT",
@@ -59,7 +59,7 @@
59
59
  "up": "yarn g:up"
60
60
  },
61
61
  "dependencies": {
62
- "@cratis/arc": "18.4.3",
62
+ "@cratis/arc": "18.6.0",
63
63
  "tsyringe": "^4.10.0"
64
64
  },
65
65
  "peerDependencies": {
@@ -0,0 +1,43 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { ObservableQueryFor, QueryResult, ObservableQuerySubscription, OnNextResult } from '@cratis/arc/queries';
5
+ import { ParameterDescriptor } from '@cratis/arc/reflection';
6
+
7
+ export interface FakeObservableQueryResult {
8
+ id: string;
9
+ name: string;
10
+ }
11
+
12
+ export type SubscribeCallback = OnNextResult<QueryResult<FakeObservableQueryResult[]>>;
13
+
14
+ export class FakeObservableQuery extends ObservableQueryFor<FakeObservableQueryResult[]> {
15
+ readonly route = '/api/fake-observable-query';
16
+ readonly parameterDescriptors: ParameterDescriptor[] = [];
17
+
18
+ get requiredRequestParameters(): string[] {
19
+ return [];
20
+ }
21
+
22
+ defaultValue: FakeObservableQueryResult[] = [];
23
+
24
+ constructor() {
25
+ super(Object, true);
26
+ }
27
+
28
+ static subscribeCallbacks: SubscribeCallback[] = [];
29
+ static subscriptionReturned: ObservableQuerySubscription<FakeObservableQueryResult[]>;
30
+
31
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
32
+ subscribe(callback: SubscribeCallback, args?: object): ObservableQuerySubscription<FakeObservableQueryResult[]> {
33
+ FakeObservableQuery.subscribeCallbacks.push(callback);
34
+ FakeObservableQuery.subscriptionReturned = {
35
+ unsubscribe: () => {}
36
+ } as unknown as ObservableQuerySubscription<FakeObservableQueryResult[]>;
37
+ return FakeObservableQuery.subscriptionReturned;
38
+ }
39
+
40
+ static reset() {
41
+ FakeObservableQuery.subscribeCallbacks = [];
42
+ }
43
+ }
@@ -0,0 +1,97 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import React from 'react';
5
+ import { render, act } from '@testing-library/react';
6
+ import { useObservableQuery } from '../useObservableQuery';
7
+ import { FakeObservableQuery } from './FakeObservableQuery';
8
+ import { ArcContext, ArcConfiguration } from '../../ArcContext';
9
+ import { QueryResult } from '@cratis/arc/queries';
10
+
11
+ /* eslint-disable @typescript-eslint/no-explicit-any */
12
+
13
+ describe('when creating instance', () => {
14
+ let capturedIsPerformingInitial: boolean | null = null;
15
+ let capturedIsPerformingAfterResponse: boolean | null = null;
16
+ let renderCount = 0;
17
+
18
+ beforeEach(() => {
19
+ FakeObservableQuery.reset();
20
+ capturedIsPerformingInitial = null;
21
+ capturedIsPerformingAfterResponse = null;
22
+ renderCount = 0;
23
+ });
24
+
25
+ const config: ArcConfiguration = {
26
+ microservice: 'test-microservice',
27
+ apiBasePath: '/api',
28
+ origin: 'https://example.com',
29
+ };
30
+
31
+ it('should have isPerforming true initially before receiving data', async () => {
32
+ const TestComponent = () => {
33
+ const [result] = useObservableQuery(FakeObservableQuery);
34
+ renderCount++;
35
+
36
+ if (renderCount === 1) {
37
+ capturedIsPerformingInitial = result.isPerforming;
38
+ }
39
+
40
+ return React.createElement('div', null, 'Test');
41
+ };
42
+
43
+ render(
44
+ React.createElement(
45
+ ArcContext.Provider,
46
+ { value: config },
47
+ React.createElement(TestComponent)
48
+ )
49
+ );
50
+
51
+ capturedIsPerformingInitial!.should.be.true;
52
+ });
53
+
54
+ it('should have isPerforming false after receiving data', async () => {
55
+ const TestComponent = () => {
56
+ const [result] = useObservableQuery(FakeObservableQuery);
57
+ renderCount++;
58
+
59
+ if (renderCount === 1) {
60
+ capturedIsPerformingInitial = result.isPerforming;
61
+ } else if (renderCount === 2) {
62
+ capturedIsPerformingAfterResponse = result.isPerforming;
63
+ }
64
+
65
+ return React.createElement('div', null, 'Test');
66
+ };
67
+
68
+ render(
69
+ React.createElement(
70
+ ArcContext.Provider,
71
+ { value: config },
72
+ React.createElement(TestComponent)
73
+ )
74
+ );
75
+
76
+ // Simulate receiving data from WebSocket
77
+ const callback = FakeObservableQuery.subscribeCallbacks[0];
78
+ callback!.should.not.be.undefined;
79
+
80
+ await act(async () => {
81
+ callback(new QueryResult({
82
+ data: [{ id: '1', name: 'Test' }],
83
+ isSuccess: true,
84
+ isAuthorized: true,
85
+ isValid: true,
86
+ hasExceptions: false,
87
+ validationResults: [],
88
+ exceptionMessages: [],
89
+ exceptionStackTrace: '',
90
+ paging: { page: 0, size: 0, totalItems: 0, totalPages: 0 }
91
+ }, Array, true));
92
+ });
93
+
94
+ capturedIsPerformingInitial!.should.be.true;
95
+ capturedIsPerformingAfterResponse!.should.be.false;
96
+ });
97
+ });
@@ -7,11 +7,13 @@ import sinon from 'sinon';
7
7
  import { useQuery } from '../useQuery';
8
8
  import { FakeQuery } from './FakeQuery';
9
9
  import { ArcContext, ArcConfiguration } from '../../ArcContext';
10
+ import { createFetchHelper } from '@cratis/arc/helpers/fetchHelper';
10
11
 
11
12
  /* eslint-disable @typescript-eslint/no-explicit-any */
12
13
 
13
14
  describe('when creating instance', () => {
14
15
  let fetchStub: sinon.SinonStub;
16
+ let fetchHelper: { stubFetch: () => sinon.SinonStub; restore: () => void };
15
17
  let queryInstance: FakeQuery | null = null;
16
18
 
17
19
  const captureInstance = (instance: FakeQuery) => {
@@ -19,13 +21,15 @@ describe('when creating instance', () => {
19
21
  };
20
22
 
21
23
  beforeEach(() => {
22
- fetchStub = sinon.stub(global, 'fetch').resolves({
24
+ fetchHelper = createFetchHelper();
25
+ fetchStub = fetchHelper.stubFetch();
26
+ fetchStub.resolves({
23
27
  json: async () => ({ data: [], isSuccess: true, isAuthorized: true, isValid: true, hasExceptions: false, validationResults: [], exceptionMessages: [], exceptionStackTrace: '' })
24
28
  } as Response);
25
29
  });
26
30
 
27
31
  afterEach(() => {
28
- fetchStub.restore();
32
+ fetchHelper.restore();
29
33
  });
30
34
 
31
35
  const config: ArcConfiguration = {
@@ -3,14 +3,14 @@
3
3
 
4
4
  import React from 'react';
5
5
  import { render } from '@testing-library/react';
6
- import sinon from 'sinon';
7
6
  import { useQuery } from '../useQuery';
8
7
  import { FakeQuery } from './FakeQuery';
9
8
  import { ArcContext, ArcConfiguration } from '../../ArcContext';
10
9
  import { Sorting } from '@cratis/arc/queries';
10
+ import { createFetchHelper } from '@cratis/arc/helpers/fetchHelper';
11
11
 
12
12
  describe('when creating instance with sorting', () => {
13
- let fetchStub: sinon.SinonStub;
13
+ let fetchHelper: { stubFetch: () => sinon.SinonStub; restore: () => void };
14
14
  let queryInstance: FakeQuery | null = null;
15
15
 
16
16
  const captureInstance = (instance: FakeQuery) => {
@@ -18,13 +18,15 @@ describe('when creating instance with sorting', () => {
18
18
  };
19
19
 
20
20
  beforeEach(() => {
21
- fetchStub = sinon.stub(global, 'fetch').resolves({
21
+ fetchHelper = createFetchHelper();
22
+ const fetchStub = fetchHelper.stubFetch();
23
+ fetchStub.resolves({
22
24
  json: async () => ({ data: [], isSuccess: true, isAuthorized: true, isValid: true, hasExceptions: false, validationResults: [], exceptionMessages: [], exceptionStackTrace: '' })
23
25
  } as Response);
24
26
  });
25
27
 
26
28
  afterEach(() => {
27
- fetchStub.restore();
29
+ fetchHelper.restore();
28
30
  });
29
31
 
30
32
  const config: ArcConfiguration = {
@@ -7,11 +7,13 @@ import sinon from 'sinon';
7
7
  import { useQuery } from '../useQuery';
8
8
  import { FakeQuery } from './FakeQuery';
9
9
  import { ArcContext, ArcConfiguration } from '../../ArcContext';
10
+ import { createFetchHelper } from '@cratis/arc/helpers/fetchHelper';
10
11
 
11
12
  /* eslint-disable @typescript-eslint/no-explicit-any */
12
13
 
13
14
  describe('when creating instance without optional context values', () => {
14
15
  let fetchStub: sinon.SinonStub;
16
+ let fetchHelper: { stubFetch: () => sinon.SinonStub; restore: () => void };
15
17
  let queryInstance: FakeQuery | null = null;
16
18
 
17
19
  const captureInstance = (instance: FakeQuery) => {
@@ -19,13 +21,15 @@ describe('when creating instance without optional context values', () => {
19
21
  };
20
22
 
21
23
  beforeEach(() => {
22
- fetchStub = sinon.stub(global, 'fetch').resolves({
24
+ fetchHelper = createFetchHelper();
25
+ fetchStub = fetchHelper.stubFetch();
26
+ fetchStub.resolves({
23
27
  json: async () => ({ data: [], isSuccess: true, isAuthorized: true, isValid: true, hasExceptions: false, validationResults: [], exceptionMessages: [], exceptionStackTrace: '' })
24
28
  } as Response);
25
29
  });
26
30
 
27
31
  afterEach(() => {
28
- fetchStub.restore();
32
+ fetchHelper.restore();
29
33
  });
30
34
 
31
35
  const config: ArcConfiguration = {
@@ -8,11 +8,13 @@ import { useQueryWithPaging } from '../useQuery';
8
8
  import { FakeQuery } from '../for_useQuery/FakeQuery';
9
9
  import { ArcContext, ArcConfiguration } from '../../ArcContext';
10
10
  import { Paging } from '@cratis/arc/queries';
11
+ import { createFetchHelper } from '@cratis/arc/helpers/fetchHelper';
11
12
 
12
13
  /* eslint-disable @typescript-eslint/no-explicit-any */
13
14
 
14
15
  describe('when creating instance with paging', () => {
15
16
  let fetchStub: sinon.SinonStub;
17
+ let fetchHelper: { stubFetch: () => sinon.SinonStub; restore: () => void };
16
18
  let queryInstance: FakeQuery | null = null;
17
19
 
18
20
  const captureInstance = (instance: FakeQuery) => {
@@ -20,13 +22,15 @@ describe('when creating instance with paging', () => {
20
22
  };
21
23
 
22
24
  beforeEach(() => {
23
- fetchStub = sinon.stub(global, 'fetch').resolves({
25
+ fetchHelper = createFetchHelper();
26
+ fetchStub = fetchHelper.stubFetch();
27
+ fetchStub.resolves({
24
28
  json: async () => ({ data: [], isSuccess: true, isAuthorized: true, isValid: true, hasExceptions: false, validationResults: [], exceptionMessages: [], exceptionStackTrace: '' })
25
29
  } as Response);
26
30
  });
27
31
 
28
32
  afterEach(() => {
29
- fetchStub.restore();
33
+ fetchHelper.restore();
30
34
  });
31
35
 
32
36
  const config: ArcConfiguration = {
@@ -26,7 +26,7 @@ function useObservableQueryInternal<TDataType, TQuery extends IObservableQueryFo
26
26
  return instance;
27
27
  }, [currentPaging, currentSorting, arc.microservice, arc.apiBasePath, arc.origin]);
28
28
 
29
- const [result, setResult] = useState<QueryResultWithState<TDataType>>(QueryResultWithState.empty(queryInstance.current.defaultValue));
29
+ const [result, setResult] = useState<QueryResultWithState<TDataType>>(QueryResultWithState.initial(queryInstance.current.defaultValue));
30
30
  const argumentsDependency = queryInstance.current.requiredRequestParameters.map(_ => args?.[_]);
31
31
 
32
32
  useEffect(() => {