relay-test-utils-internal 13.1.1 → 14.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 = {