@khanacademy/wonder-blocks-testing 12.0.1 → 14.0.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # @khanacademy/wonder-blocks-testing
2
2
 
3
+ ## 14.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - e6abdd17: Upgrade to React 18
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [e6abdd17]
12
+ - @khanacademy/wonder-blocks-testing-core@2.0.0
13
+ - @khanacademy/wonder-blocks-core@8.0.0
14
+ - @khanacademy/wonder-blocks-data@14.0.0
15
+
16
+ ## 13.0.0
17
+
18
+ ### Major Changes
19
+
20
+ - eb807af8: When mocking GraphQL, consider explicit undefined values in a request to be equivalent to missing keys in a mock
21
+
22
+ ### Minor Changes
23
+
24
+ - 16565a85: Add support for hard fails to the request mocking features
25
+
26
+ ### Patch Changes
27
+
28
+ - Updated dependencies [16565a85]
29
+ - @khanacademy/wonder-blocks-testing-core@1.1.0
30
+
3
31
  ## 12.0.1
4
32
 
5
33
  ### Patch Changes
package/dist/es/index.js CHANGED
@@ -6,8 +6,7 @@ import { InterceptRequests } from '@khanacademy/wonder-blocks-data';
6
6
  import { KindError, Errors } from '@khanacademy/wonder-stuff-core';
7
7
  import { RenderStateRoot } from '@khanacademy/wonder-blocks-core';
8
8
 
9
- const safeHasOwnProperty = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
10
- const areObjectsEqual = (a, b) => {
9
+ const areObjectsEquivalent = (a, b) => {
11
10
  if (a === b) {
12
11
  return true;
13
12
  }
@@ -19,12 +18,9 @@ const areObjectsEqual = (a, b) => {
19
18
  }
20
19
  const aKeys = Object.keys(a);
21
20
  const bKeys = Object.keys(b);
22
- if (aKeys.length !== bKeys.length) {
23
- return false;
24
- }
25
- for (let i = 0; i < aKeys.length; i++) {
26
- const key = aKeys[i];
27
- if (!safeHasOwnProperty(b, key) || !areObjectsEqual(a[key], b[key])) {
21
+ const allKeys = new Set([...aKeys, ...bKeys]);
22
+ for (const key of allKeys) {
23
+ if (!areObjectsEquivalent(a[key], b[key])) {
28
24
  return false;
29
25
  }
30
26
  }
@@ -35,12 +31,12 @@ const gqlRequestMatchesMock = (mock, operation, variables, context) => {
35
31
  return false;
36
32
  }
37
33
  if (mock.variables != null) {
38
- if (!areObjectsEqual(mock.variables, variables)) {
34
+ if (!areObjectsEquivalent(mock.variables, variables)) {
39
35
  return false;
40
36
  }
41
37
  }
42
38
  if (mock.context != null) {
43
- if (!areObjectsEqual(mock.context, context)) {
39
+ if (!areObjectsEquivalent(mock.context, context)) {
44
40
  return false;
45
41
  }
46
42
  }
@@ -1,14 +1,74 @@
1
1
  import type { GqlOperation, GqlContext } from "@khanacademy/wonder-blocks-data";
2
- import type { GraphQLJson, MockResponse } from "@khanacademy/wonder-blocks-testing-core";
2
+ import type { ConfigureFn, GraphQLJson, MockResponse } from "@khanacademy/wonder-blocks-testing-core";
3
+ /**
4
+ * A GraphQL operation to be mocked.
5
+ *
6
+ * This is used to specify what a request must match in order for a mock to
7
+ * be used.
8
+ */
3
9
  export type GqlMockOperation<TData extends Record<any, any>, TVariables extends Record<any, any>, TContext extends GqlContext> = {
4
10
  operation: GqlOperation<TData, TVariables>;
5
11
  variables?: TVariables;
6
12
  context?: TContext;
7
13
  };
8
- type GqlMockOperationFn = <TData extends Record<any, any>, TVariables extends Record<any, any>, TContext extends GqlContext, TResponseData extends GraphQLJson<TData>>(operation: GqlMockOperation<TData, TVariables, TContext>, response: MockResponse<TResponseData>) => GqlFetchMockFn;
9
- export type GqlFetchMockFn = {
14
+ interface GqlMockOperationFn {
15
+ <TData extends Record<any, any>, TVariables extends Record<any, any>, TContext extends GqlContext, TResponseData extends GraphQLJson<TData>>(
16
+ /**
17
+ * The operation to match.
18
+ */
19
+ operation: GqlMockOperation<TData, TVariables, TContext>,
20
+ /**
21
+ * The response to return when the operation is matched.
22
+ */
23
+ response: MockResponse<TResponseData>): GqlFetchMockFn;
24
+ }
25
+ export interface GqlFetchMockFn {
26
+ /**
27
+ * The mock fetch function.
28
+ *
29
+ * This function is a drop-in replacement for the gqlFetch function used
30
+ * by Wonder Blocks Data. You should not need to call this function
31
+ * directly. Just pass this in places where you would pass a gqlFetch
32
+ * function, as provided by the GqlRouter.
33
+ */
10
34
  (operation: GqlOperation<any, any>, variables: Record<any, any> | null | undefined, context: GqlContext): Promise<Response>;
35
+ /**
36
+ * Mock a fetch operation.
37
+ *
38
+ * This adds a response for a given mocked operation. Operations are
39
+ * matched greedily, so if only the GraphQL operation is provided, then
40
+ * all requests for that operation will be matched, regardless of
41
+ * variables or context.
42
+ *
43
+ * Regardless of how many times this mock is matched, it will be used.
44
+ *
45
+ * @returns The mock fetch function for chaining.
46
+ */
11
47
  mockOperation: GqlMockOperationFn;
48
+ /**
49
+ * Mock a fetch operation once.
50
+ *
51
+ * This adds a response for a given mocked operation. Operations are
52
+ * matched greedily, so if only the GraphQL operation is provided, then
53
+ * all requests for that operation will be matched, regardless of
54
+ * variables or context.
55
+ *
56
+ * Once the added mock is used, it will be discarded and no longer match
57
+ * any requests.
58
+ *
59
+ * @returns The mock fetch function for chaining.
60
+ */
12
61
  mockOperationOnce: GqlMockOperationFn;
13
- };
62
+ /**
63
+ * Configure the mock fetch function with the given configuration.
64
+ *
65
+ * This function is provided as a convenience to allow for configuring the
66
+ * mock fetch function in a fluent manner. The configuration is applied
67
+ * to all mocks for a given fetch function; the last configuration applied
68
+ * will be the one that is used for all mocked operations.
69
+ *
70
+ * @returns The mock fetch function for chaining.
71
+ */
72
+ configure: ConfigureFn<GqlMockOperation<any, any, any>, GraphQLJson<any>>;
73
+ }
14
74
  export {};
package/dist/index.js CHANGED
@@ -32,8 +32,7 @@ function _interopNamespace(e) {
32
32
  var _extends__default = /*#__PURE__*/_interopDefaultLegacy(_extends);
33
33
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
34
34
 
35
- const safeHasOwnProperty = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
36
- const areObjectsEqual = (a, b) => {
35
+ const areObjectsEquivalent = (a, b) => {
37
36
  if (a === b) {
38
37
  return true;
39
38
  }
@@ -45,12 +44,9 @@ const areObjectsEqual = (a, b) => {
45
44
  }
46
45
  const aKeys = Object.keys(a);
47
46
  const bKeys = Object.keys(b);
48
- if (aKeys.length !== bKeys.length) {
49
- return false;
50
- }
51
- for (let i = 0; i < aKeys.length; i++) {
52
- const key = aKeys[i];
53
- if (!safeHasOwnProperty(b, key) || !areObjectsEqual(a[key], b[key])) {
47
+ const allKeys = new Set([...aKeys, ...bKeys]);
48
+ for (const key of allKeys) {
49
+ if (!areObjectsEquivalent(a[key], b[key])) {
54
50
  return false;
55
51
  }
56
52
  }
@@ -61,12 +57,12 @@ const gqlRequestMatchesMock = (mock, operation, variables, context) => {
61
57
  return false;
62
58
  }
63
59
  if (mock.variables != null) {
64
- if (!areObjectsEqual(mock.variables, variables)) {
60
+ if (!areObjectsEquivalent(mock.variables, variables)) {
65
61
  return false;
66
62
  }
67
63
  }
68
64
  if (mock.context != null) {
69
- if (!areObjectsEqual(mock.context, context)) {
65
+ if (!areObjectsEquivalent(mock.context, context)) {
70
66
  return false;
71
67
  }
72
68
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-testing",
3
- "version": "12.0.1",
3
+ "version": "14.0.0",
4
4
  "design": "v1",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -14,21 +14,21 @@
14
14
  },
15
15
  "dependencies": {
16
16
  "@babel/runtime": "^7.18.6",
17
- "@khanacademy/wonder-blocks-core": "^7.0.1",
18
- "@khanacademy/wonder-blocks-data": "^13.0.12",
19
- "@khanacademy/wonder-blocks-testing-core": "^1.0.2"
17
+ "@khanacademy/wonder-blocks-core": "^8.0.0",
18
+ "@khanacademy/wonder-blocks-data": "^14.0.0",
19
+ "@khanacademy/wonder-blocks-testing-core": "^2.0.0"
20
20
  },
21
21
  "peerDependencies": {
22
22
  "@khanacademy/wonder-stuff-core": "^1.2.2",
23
- "@storybook/addon-actions": "^7.0.0",
23
+ "@storybook/addon-actions": "^8.2.1",
24
24
  "aphrodite": "^1.2.5",
25
25
  "node-fetch": "^2.6.7",
26
- "react": "16.14.0",
27
- "react-dom": "16.14.0",
28
- "react-router-dom": "5.3.0"
26
+ "react": "18.2.0",
27
+ "react-dom": "18.2.0",
28
+ "react-router-dom": "5.3.4"
29
29
  },
30
30
  "devDependencies": {
31
- "@khanacademy/wb-dev-build-settings": "^1.0.1",
31
+ "@khanacademy/wb-dev-build-settings": "^2.0.0",
32
32
  "@khanacademy/wonder-stuff-testing": "^3.0.1"
33
33
  },
34
34
  "author": "",