@@ -9,6 +9,24 @@ function writeJson(filePath, value) {
99 fs . writeFileSync ( filePath , JSON . stringify ( value , null , 2 ) ) ;
1010}
1111
12+ function writeCompiledArtifact ( filePath ) {
13+ fs . mkdirSync ( path . dirname ( filePath ) , { recursive : true } ) ;
14+ fs . writeFileSync (
15+ filePath ,
16+ JSON . stringify (
17+ {
18+ contractName : 'App' ,
19+ abi : [ ] ,
20+ bytecode : '0x00' ,
21+ deployedBytecode : '0x00' ,
22+ compilerProfile : 'default'
23+ } ,
24+ null ,
25+ 2
26+ )
27+ ) ;
28+ }
29+
1230function runTh ( args , cwd ) {
1331 const res = spawnSync ( 'node' , [ path . resolve ( 'packages/cli/dist/index.js' ) , ...args ] , {
1432 cwd,
@@ -242,3 +260,68 @@ describe('th generate (UI template)', function () {
242260 expect ( workflow ) . to . include ( 'TH_INSTALL_BROWSER_DEPS' ) ;
243261 } ) ;
244262} ) ;
263+
264+ describe ( 'th ui sync' , function ( ) {
265+ this . timeout ( 180000 ) ;
266+
267+ it ( 'refreshes generated UI from existing compiled artifacts without regenerating contracts' , function ( ) {
268+ const dir = fs . mkdtempSync ( path . join ( os . tmpdir ( ) , 'th-ui-sync-' ) ) ;
269+ const schemaPath = path . join ( dir , 'schema.json' ) ;
270+ const outDir = path . join ( dir , 'out' ) ;
271+ writeJson ( schemaPath , minimalSchema ( ) ) ;
272+ writeCompiledArtifact ( path . join ( outDir , 'compiled' , 'App.json' ) ) ;
273+
274+ const res = runTh ( [ 'ui' , 'sync' , schemaPath , '--out' , outDir ] , process . cwd ( ) ) ;
275+ expect ( res . status , res . stderr || res . stdout ) . to . equal ( 0 ) ;
276+
277+ expect ( fs . existsSync ( path . join ( outDir , 'ui' , 'package.json' ) ) ) . to . equal ( true ) ;
278+ expect ( fs . existsSync ( path . join ( outDir , 'ui' , 'src' , 'generated' , 'ths.ts' ) ) ) . to . equal ( true ) ;
279+ expect ( fs . existsSync ( path . join ( outDir , 'ui' , 'public' , 'compiled' , 'App.json' ) ) ) . to . equal ( true ) ;
280+ expect ( fs . existsSync ( path . join ( outDir , 'contracts' , 'App.sol' ) ) ) . to . equal ( false ) ;
281+ } ) ;
282+
283+ it ( 'replaces stale UI output during sync and reapplies schema-declared overrides' , function ( ) {
284+ const dir = fs . mkdtempSync ( path . join ( os . tmpdir ( ) , 'th-ui-sync-overrides-' ) ) ;
285+ const schemaPath = path . join ( dir , 'schema.json' ) ;
286+ const overridesDir = path . join ( dir , 'ui-overrides' ) ;
287+ const outDir = path . join ( dir , 'out' ) ;
288+
289+ writeJson ( schemaPath , schemaWithUiOverrides ( ) ) ;
290+ writeCompiledArtifact ( path . join ( outDir , 'compiled' , 'App.json' ) ) ;
291+ fs . mkdirSync ( path . join ( overridesDir , 'app' , 'run' ) , { recursive : true } ) ;
292+ fs . writeFileSync (
293+ path . join ( overridesDir , 'app' , 'page.tsx' ) ,
294+ "export default function HomePage(){return <div>custom-home-marker</div>;}\n"
295+ ) ;
296+ fs . writeFileSync (
297+ path . join ( overridesDir , 'app' , 'run' , 'page.tsx' ) ,
298+ "export default function RunPage(){return <div>custom-run-page</div>;}\n"
299+ ) ;
300+
301+ const first = runTh ( [ 'ui' , 'sync' , schemaPath , '--out' , outDir ] , process . cwd ( ) ) ;
302+ expect ( first . status , first . stderr || first . stdout ) . to . equal ( 0 ) ;
303+
304+ const staleFile = path . join ( outDir , 'ui' , 'app' , 'stale-marker.txt' ) ;
305+ fs . mkdirSync ( path . dirname ( staleFile ) , { recursive : true } ) ;
306+ fs . writeFileSync ( staleFile , 'stale' ) ;
307+
308+ const second = runTh ( [ 'ui' , 'sync' , schemaPath , '--out' , outDir ] , process . cwd ( ) ) ;
309+ expect ( second . status , second . stderr || second . stdout ) . to . equal ( 0 ) ;
310+ expect ( fs . existsSync ( staleFile ) ) . to . equal ( false ) ;
311+
312+ const homePage = fs . readFileSync ( path . join ( outDir , 'ui' , 'app' , 'page.tsx' ) , 'utf-8' ) ;
313+ expect ( homePage ) . to . include ( 'custom-home-marker' ) ;
314+ expect ( fs . existsSync ( path . join ( outDir , 'ui' , 'app' , 'run' , 'page.tsx' ) ) ) . to . equal ( true ) ;
315+ } ) ;
316+
317+ it ( 'fails clearly when compiled artifacts are missing' , function ( ) {
318+ const dir = fs . mkdtempSync ( path . join ( os . tmpdir ( ) , 'th-ui-sync-missing-compiled-' ) ) ;
319+ const schemaPath = path . join ( dir , 'schema.json' ) ;
320+ const outDir = path . join ( dir , 'out' ) ;
321+ writeJson ( schemaPath , minimalSchema ( ) ) ;
322+
323+ const res = runTh ( [ 'ui' , 'sync' , schemaPath , '--out' , outDir ] , process . cwd ( ) ) ;
324+ expect ( res . status ) . to . not . equal ( 0 ) ;
325+ expect ( res . stderr || res . stdout ) . to . include ( 'Missing compiled/App.json' ) ;
326+ } ) ;
327+ } ) ;
0 commit comments