relay-test-utils-internal 13.1.1 → 14.1.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.
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ * @format
9
+ */
10
+
11
+ 'use strict';
12
+
13
+ /* global jest */
14
+
15
+ import type {IEnvironment} from '../relay-runtime';
16
+ import type {OperationDescriptor} from '../relay-runtime/store/RelayStoreTypes';
17
+
18
+ /**
19
+ * Takes an environment and augments it with a mock implementation of `retain`
20
+ * that tracks what operations are currently retained. Also returns the Jest mock
21
+ * `release` function for backwards-compatibility with existing tests, but you
22
+ * should use `isOperationRetained` for new tests as it is much less error-prone.
23
+ */
24
+ function trackRetentionForEnvironment(environment: IEnvironment): {
25
+ release_DEPRECATED: JestMockFn<[mixed], void>,
26
+ isOperationRetained: OperationDescriptor => boolean,
27
+ } {
28
+ const retainCountsByOperation = new Map();
29
+
30
+ const release = jest.fn(id => {
31
+ const existing = retainCountsByOperation.get(id) ?? NaN;
32
+ if (existing === 1) {
33
+ retainCountsByOperation.delete(id);
34
+ } else {
35
+ retainCountsByOperation.set(id, existing - 1);
36
+ }
37
+ });
38
+
39
+ // $FlowFixMe[cannot-write] safe to do for mocking
40
+ environment.retain = jest.fn(operation => {
41
+ const id = operation.request.identifier;
42
+ const existing = retainCountsByOperation.get(id) ?? 0;
43
+ retainCountsByOperation.set(id, existing + 1);
44
+ let released = false;
45
+ return {
46
+ dispose: () => {
47
+ if (!released) {
48
+ release(id);
49
+ }
50
+ released = true;
51
+ },
52
+ };
53
+ });
54
+
55
+ function isOperationRetained(operation: OperationDescriptor) {
56
+ const id = operation.request.identifier;
57
+ return (retainCountsByOperation.get(id) ?? 0) > 0;
58
+ }
59
+
60
+ return {release_DEPRECATED: release, isOperationRetained};
61
+ }
62
+
63
+ module.exports = trackRetentionForEnvironment;
package/warnings.js.flow CHANGED
@@ -11,11 +11,27 @@
11
11
 
12
12
  'use strict';
13
13
 
14
- /* global jest, afterEach */
14
+ /* global jest */
15
15
 
16
- let installed = false;
17
- const expectedWarnings: Array<string> = [];
18
- const contextualExpectedWarning: Array<string> = [];
16
+ import type {WillFireOptions} from './consoleErrorsAndWarnings';
17
+
18
+ const {createConsoleInterceptionSystem} = require('./consoleErrorsAndWarnings');
19
+
20
+ const warningsSystem = createConsoleInterceptionSystem(
21
+ 'warning',
22
+ 'expectToWarn',
23
+ impl => {
24
+ jest.mock('warning', () =>
25
+ jest.fn((condition, format, ...args) => {
26
+ if (!condition) {
27
+ let argIndex = 0;
28
+ const message = format.replace(/%s/g, () => String(args[argIndex++]));
29
+ impl(message);
30
+ }
31
+ }),
32
+ );
33
+ },
34
+ );
19
35
 
20
36
  /**
21
37
  * Mocks the `warning` module to turn warnings into errors. Any expected
@@ -25,64 +41,25 @@ const contextualExpectedWarning: Array<string> = [];
25
41
  * use `jest.resetModules()` or manually mock `warning`.
26
42
  */
27
43
  function disallowWarnings(): void {
28
- if (installed) {
29
- throw new Error('`disallowWarnings` should be called at most once');
30
- }
31
- installed = true;
32
- jest.mock('warning', () => {
33
- return jest.fn((condition, format, ...args) => {
34
- if (!condition) {
35
- let argIndex = 0;
36
- const message = format.replace(/%s/g, () => String(args[argIndex++]));
37
- const index = expectedWarnings.indexOf(message);
38
-
39
- if (
40
- contextualExpectedWarning.length > 0 &&
41
- contextualExpectedWarning[0] === message
42
- ) {
43
- contextualExpectedWarning.shift();
44
- } else if (index >= 0) {
45
- expectedWarnings.splice(index, 1);
46
- } else {
47
- // log to console in case the error gets swallowed somewhere
48
- console.error('Unexpected Warning: ' + message);
49
- throw new Error('Warning: ' + message);
50
- }
51
- }
52
- });
53
- });
54
- afterEach(() => {
55
- contextualExpectedWarning.length = 0;
56
- if (expectedWarnings.length > 0) {
57
- const error = new Error(
58
- 'Some expected warnings where not triggered:\n\n' +
59
- Array.from(expectedWarnings, message => ` * ${message}`).join('\n') +
60
- '\n',
61
- );
62
- expectedWarnings.length = 0;
63
- throw error;
64
- }
65
- });
44
+ warningsSystem.disallowMessages();
66
45
  }
67
46
 
68
47
  /**
69
48
  * Expect a warning with the given message. If the message isn't fired in the
70
49
  * current test, the test will fail.
71
50
  */
72
- function expectWarningWillFire(message: string): void {
73
- if (!installed) {
74
- throw new Error(
75
- '`disallowWarnings` needs to be called before `expectWarningWillFire`',
76
- );
77
- }
78
- expectedWarnings.push(message);
51
+ function expectWarningWillFire(
52
+ message: string,
53
+ options?: WillFireOptions,
54
+ ): void {
55
+ warningsSystem.expectMessageWillFire(message, options);
79
56
  }
80
57
 
81
58
  /**
82
59
  * Expect the callback `fn` to trigger the warning message and otherwise fail.
83
60
  */
84
61
  function expectToWarn<T>(message: string, fn: () => T): T {
85
- return expectToWarnMany([message], fn);
62
+ return warningsSystem.expectMessage(message, fn);
86
63
  }
87
64
 
88
65
  /**
@@ -90,17 +67,7 @@ function expectToWarn<T>(message: string, fn: () => T): T {
90
67
  * or otherwise fail.
91
68
  */
92
69
  function expectToWarnMany<T>(messages: Array<string>, fn: () => T): T {
93
- if (contextualExpectedWarning.length > 0) {
94
- throw new Error('Cannot nest `expectToWarn()` calls.');
95
- }
96
- contextualExpectedWarning.push(...messages);
97
- const result = fn();
98
- if (contextualExpectedWarning.length > 0) {
99
- const notFired = contextualExpectedWarning.toString();
100
- contextualExpectedWarning.length = 0;
101
- throw new Error(`Expected callback to warn: ${notFired}`);
102
- }
103
- return result;
70
+ return warningsSystem.expectMessageMany(messages, fn);
104
71
  }
105
72
 
106
73
  module.exports = {