@@ -18,6 +18,7 @@ let act;
1818
1919const babel = require ( '@babel/core' ) ;
2020const freshPlugin = require ( 'react-refresh/babel' ) ;
21+ const ts = require ( 'typescript' ) ;
2122
2223describe ( 'ReactFreshIntegration' , ( ) => {
2324 let container ;
@@ -46,42 +47,72 @@ describe('ReactFreshIntegration', () => {
4647 }
4748 } ) ;
4849
50+ function executeCommon ( source , compileDestructuring ) {
51+ const compiled = babel . transform ( source , {
52+ babelrc : false ,
53+ presets : [ '@babel/react' ] ,
54+ plugins : [
55+ [ freshPlugin , { skipEnvCheck : true } ] ,
56+ '@babel/plugin-transform-modules-commonjs' ,
57+ compileDestructuring && '@babel/plugin-transform-destructuring' ,
58+ ] . filter ( Boolean ) ,
59+ } ) . code ;
60+ return executeCompiled ( compiled ) ;
61+ }
62+
63+ function executeCompiled ( compiled ) {
64+ exportsObj = { } ;
65+ // eslint-disable-next-line no-new-func
66+ new Function (
67+ 'global' ,
68+ 'React' ,
69+ 'exports' ,
70+ '$RefreshReg$' ,
71+ '$RefreshSig$' ,
72+ compiled ,
73+ ) ( global , React , exportsObj , $RefreshReg$ , $RefreshSig$ ) ;
74+ // Module systems will register exports as a fallback.
75+ // This is useful for cases when e.g. a class is exported,
76+ // and we don't want to propagate the update beyond this module.
77+ $RefreshReg$ ( exportsObj . default , 'exports.default' ) ;
78+ return exportsObj . default ;
79+ }
80+
81+ function $RefreshReg$ ( type , id ) {
82+ ReactFreshRuntime . register ( type , id ) ;
83+ }
84+
85+ function $RefreshSig$ ( ) {
86+ return ReactFreshRuntime . createSignatureFunctionForTransform ( ) ;
87+ }
88+
4989 describe ( 'with compiled destructuring' , ( ) => {
50- runTests ( true ) ;
90+ runTests ( executeCommon , testCommon ) ;
5191 } ) ;
5292
5393 describe ( 'without compiled destructuring' , ( ) => {
54- runTests ( false ) ;
94+ runTests ( executeCommon , testCommon ) ;
5595 } ) ;
5696
57- function runTests ( compileDestructuring ) {
58- function execute ( source ) {
59- const compiled = babel . transform ( source , {
97+ describe ( 'with typescript syntax' , ( ) => {
98+ runTests ( function ( source ) {
99+ const typescriptSource = babel . transform ( source , {
60100 babelrc : false ,
101+ configFile : false ,
61102 presets : [ '@babel/react' ] ,
62103 plugins : [
63104 [ freshPlugin , { skipEnvCheck : true } ] ,
64- '@babel/plugin-transform-modules-commonjs' ,
65- compileDestructuring && '@babel/plugin-transform-destructuring' ,
66- ] . filter ( Boolean ) ,
105+ [ '@babel/plugin-syntax-typescript' , { isTSX : true } ] ,
106+ ] ,
67107 } ) . code ;
68- exportsObj = { } ;
69- // eslint-disable-next-line no-new-func
70- new Function (
71- 'global' ,
72- 'React' ,
73- 'exports' ,
74- '$RefreshReg$' ,
75- '$RefreshSig$' ,
76- compiled ,
77- ) ( global , React , exportsObj , $RefreshReg$ , $RefreshSig$ ) ;
78- // Module systems will register exports as a fallback.
79- // This is useful for cases when e.g. a class is exported,
80- // and we don't want to propagate the update beyond this module.
81- $RefreshReg$ ( exportsObj . default , 'exports.default' ) ;
82- return exportsObj . default ;
83- }
108+ const compiled = ts . transpileModule ( typescriptSource , {
109+ module : ts . ModuleKind . CommonJS ,
110+ } ) . outputText ;
111+ return executeCompiled ( compiled ) ;
112+ } , testTypescript ) ;
113+ } ) ;
84114
115+ function runTests ( execute , test ) {
85116 function render ( source ) {
86117 const Component = execute ( source ) ;
87118 act ( ( ) => {
@@ -127,14 +158,10 @@ describe('ReactFreshIntegration', () => {
127158 expect ( ReactFreshRuntime . _getMountedRootCount ( ) ) . toBe ( 1 ) ;
128159 }
129160
130- function $RefreshReg$ ( type , id ) {
131- ReactFreshRuntime . register ( type , id ) ;
132- }
133-
134- function $RefreshSig$ ( ) {
135- return ReactFreshRuntime . createSignatureFunctionForTransform ( ) ;
136- }
161+ test ( render , patch ) ;
162+ }
137163
164+ function testCommon ( render , patch ) {
138165 it ( 'reloads function declarations' , ( ) => {
139166 if ( __DEV__ ) {
140167 render ( `
@@ -1947,4 +1974,41 @@ describe('ReactFreshIntegration', () => {
19471974 } ) ;
19481975 } ) ;
19491976 }
1977+
1978+ function testTypescript ( render , patch ) {
1979+ it ( 'reloads component exported in typescript namespace' , ( ) => {
1980+ if ( __DEV__ ) {
1981+ render ( `
1982+ namespace Foo {
1983+ export namespace Bar {
1984+ export const Child = ({prop}) => {
1985+ return <h1>{prop}1</h1>
1986+ };
1987+ }
1988+ }
1989+
1990+ export default function Parent() {
1991+ return <Foo.Bar.Child prop={'A'} />;
1992+ }
1993+ ` ) ;
1994+ const el = container . firstChild ;
1995+ expect ( el . textContent ) . toBe ( 'A1' ) ;
1996+ patch ( `
1997+ namespace Foo {
1998+ export namespace Bar {
1999+ export const Child = ({prop}) => {
2000+ return <h1>{prop}2</h1>
2001+ };
2002+ }
2003+ }
2004+
2005+ export default function Parent() {
2006+ return <Foo.Bar.Child prop={'B'} />;
2007+ }
2008+ ` ) ;
2009+ expect ( container . firstChild ) . toBe ( el ) ;
2010+ expect ( el . textContent ) . toBe ( 'B2' ) ;
2011+ }
2012+ } ) ;
2013+ }
19502014} ) ;
0 commit comments