|
1 | 1 | 'use strict'; |
2 | 2 |
|
| 3 | +import { useIsFastRefresh } from '../utils'; |
3 | 4 | import { renderUseHandler, runCommonTests } from './useHandler.shared'; |
4 | 5 |
|
| 6 | +jest.mock('../utils', () => ({ |
| 7 | + ...jest.requireActual('../utils'), |
| 8 | + useIsFastRefresh: jest.fn(() => false), |
| 9 | +})); |
| 10 | + |
| 11 | +const mockFastRefresh = useIsFastRefresh as jest.Mock; |
| 12 | + |
5 | 13 | describe('useHandler (web)', () => { |
6 | 14 | runCommonTests(); |
7 | 15 |
|
@@ -94,4 +102,84 @@ describe('useHandler (web)', () => { |
94 | 102 | }); |
95 | 103 | }); |
96 | 104 | }); |
| 105 | + |
| 106 | + describe('fast refresh', () => { |
| 107 | + describe('without babel plugin', () => { |
| 108 | + const fastRefreshCases: Array<{ |
| 109 | + caseName: string; |
| 110 | + initialDeps: number[] | undefined; |
| 111 | + nextDeps: number[] | undefined; |
| 112 | + expected: [boolean, boolean, boolean, boolean]; |
| 113 | + }> = [ |
| 114 | + { |
| 115 | + caseName: 'undefined deps', |
| 116 | + initialDeps: undefined, |
| 117 | + nextDeps: undefined, |
| 118 | + expected: [true, true, true, true], |
| 119 | + }, |
| 120 | + { |
| 121 | + caseName: 'empty deps array', |
| 122 | + initialDeps: [], |
| 123 | + nextDeps: [], |
| 124 | + expected: [false, false, true, false], |
| 125 | + }, |
| 126 | + { |
| 127 | + caseName: 'non-empty deps array', |
| 128 | + initialDeps: [1], |
| 129 | + nextDeps: [1], |
| 130 | + expected: [true, false, true, false], |
| 131 | + }, |
| 132 | + { |
| 133 | + caseName: 'changing deps between renders', |
| 134 | + initialDeps: [1], |
| 135 | + nextDeps: [2], |
| 136 | + expected: [true, true, true, false], |
| 137 | + }, |
| 138 | + ]; |
| 139 | + |
| 140 | + fastRefreshCases.forEach( |
| 141 | + ({ |
| 142 | + caseName, |
| 143 | + initialDeps, |
| 144 | + nextDeps, |
| 145 | + expected: [ |
| 146 | + firstRenderValue, |
| 147 | + secondRenderValue, |
| 148 | + fastRefreshValue, |
| 149 | + postRefreshValue, |
| 150 | + ], |
| 151 | + }) => { |
| 152 | + test(`handles fast-refresh behavior for ${caseName}`, () => { |
| 153 | + const handler = jest.fn(); |
| 154 | + const { result, rerender } = renderUseHandler( |
| 155 | + { onScroll: handler }, |
| 156 | + initialDeps |
| 157 | + ); |
| 158 | + |
| 159 | + // Initial render. |
| 160 | + expect(result.current.doDependenciesDiffer).toBe(firstRenderValue); |
| 161 | + |
| 162 | + // Second render can keep deps stable or change them. |
| 163 | + rerender({ handlers: { onScroll: handler }, deps: nextDeps }); |
| 164 | + expect(result.current.doDependenciesDiffer).toBe(secondRenderValue); |
| 165 | + |
| 166 | + // Fast refresh render. |
| 167 | + mockFastRefresh.mockReturnValueOnce(true); |
| 168 | + rerender({ handlers: { onScroll: handler }, deps: nextDeps }); |
| 169 | + expect(result.current.doDependenciesDiffer).toBe(fastRefreshValue); |
| 170 | + |
| 171 | + // Post-fast-refresh render. |
| 172 | + rerender({ handlers: { onScroll: handler }, deps: nextDeps }); |
| 173 | + expect(result.current.doDependenciesDiffer).toBe(postRefreshValue); |
| 174 | + }); |
| 175 | + } |
| 176 | + ); |
| 177 | + |
| 178 | + test('first-mount `[]` spec is still preserved (no false positive)', () => { |
| 179 | + // Guard against false positives on initial mount with [] deps. |
| 180 | + const { result } = renderUseHandler({ onScroll: jest.fn() }, []); |
| 181 | + expect(result.current.doDependenciesDiffer).toBe(false); |
| 182 | + }); |
| 183 | + }); |
| 184 | + }); |
97 | 185 | }); |
0 commit comments