@@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
22import { mkdtempSync , writeFileSync , mkdirSync , readFileSync , rmSync , existsSync } from 'node:fs' ;
33import { join } from 'node:path' ;
44import { tmpdir } from 'node:os' ;
5- import { detectFramework , runInit } from '../init.js' ;
5+ import { detectFramework , runInit , runUninit } from '../init.js' ;
66
77function makeTempDir ( ) : string {
88 return mkdtempSync ( join ( tmpdir ( ) , 'ard-test-' ) ) ;
@@ -200,3 +200,142 @@ describe('runInit', () => {
200200 expect ( content ) . toBe ( original ) ;
201201 } ) ;
202202} ) ;
203+
204+ describe ( 'runUninit' , ( ) => {
205+ let dir : string ;
206+
207+ beforeEach ( ( ) => {
208+ dir = makeTempDir ( ) ;
209+ } ) ;
210+
211+ afterEach ( ( ) => {
212+ rmSync ( dir , { recursive : true , force : true } ) ;
213+ } ) ;
214+
215+ it ( 'removes Vite plugin import and usage' , async ( ) => {
216+ writeFileSync (
217+ join ( dir , 'package.json' ) ,
218+ JSON . stringify ( { devDependencies : { '@vitejs/plugin-react' : '^4.0.0' } } ) ,
219+ ) ;
220+ writeFileSync (
221+ join ( dir , 'vite.config.ts' ) ,
222+ `import { defineConfig } from 'vite';\nimport react from '@vitejs/plugin-react';\n\nexport default defineConfig({\n plugins: [react()],\n});\n` ,
223+ ) ;
224+
225+ await runInit ( dir , false ) ;
226+ const afterInit = readFileSync ( join ( dir , 'vite.config.ts' ) , 'utf-8' ) ;
227+ expect ( afterInit ) . toContain ( 'agent-react-devtools' ) ;
228+
229+ await runUninit ( dir , false ) ;
230+ const afterUninit = readFileSync ( join ( dir , 'vite.config.ts' ) , 'utf-8' ) ;
231+ expect ( afterUninit ) . not . toContain ( 'agent-react-devtools' ) ;
232+ expect ( afterUninit ) . not . toContain ( 'reactDevtools()' ) ;
233+ expect ( afterUninit ) . toContain ( "import react from '@vitejs/plugin-react'" ) ;
234+ } ) ;
235+
236+ it ( 'removes CRA import' , async ( ) => {
237+ writeFileSync (
238+ join ( dir , 'package.json' ) ,
239+ JSON . stringify ( { dependencies : { 'react-scripts' : '^5.0.0' } } ) ,
240+ ) ;
241+ mkdirSync ( join ( dir , 'src' ) ) ;
242+ const original = `import React from 'react';\nimport ReactDOM from 'react-dom/client';\n` ;
243+ writeFileSync ( join ( dir , 'src/index.tsx' ) , original ) ;
244+
245+ await runInit ( dir , false ) ;
246+ const afterInit = readFileSync ( join ( dir , 'src/index.tsx' ) , 'utf-8' ) ;
247+ expect ( afterInit ) . toContain ( 'agent-react-devtools' ) ;
248+
249+ await runUninit ( dir , false ) ;
250+ const afterUninit = readFileSync ( join ( dir , 'src/index.tsx' ) , 'utf-8' ) ;
251+ expect ( afterUninit ) . not . toContain ( 'agent-react-devtools' ) ;
252+ expect ( afterUninit ) . toContain ( "import React from 'react'" ) ;
253+ } ) ;
254+
255+ it ( 'removes Next.js App Router wrapper and import' , async ( ) => {
256+ writeFileSync (
257+ join ( dir , 'package.json' ) ,
258+ JSON . stringify ( { dependencies : { next : '^14.0.0' } } ) ,
259+ ) ;
260+ mkdirSync ( join ( dir , 'app' ) ) ;
261+ writeFileSync (
262+ join ( dir , 'app/layout.tsx' ) ,
263+ `export default function Layout({ children }) {\n return <html><body>{children}</body></html>;\n}\n` ,
264+ ) ;
265+
266+ await runInit ( dir , false ) ;
267+ expect ( existsSync ( join ( dir , 'app/devtools.ts' ) ) ) . toBe ( true ) ;
268+
269+ await runUninit ( dir , false ) ;
270+ expect ( existsSync ( join ( dir , 'app/devtools.ts' ) ) ) . toBe ( false ) ;
271+ const layout = readFileSync ( join ( dir , 'app/layout.tsx' ) , 'utf-8' ) ;
272+ expect ( layout ) . not . toContain ( 'devtools' ) ;
273+ } ) ;
274+
275+ it ( 'removes Next.js Pages Router import' , async ( ) => {
276+ writeFileSync (
277+ join ( dir , 'package.json' ) ,
278+ JSON . stringify ( { dependencies : { next : '^14.0.0' } } ) ,
279+ ) ;
280+ mkdirSync ( join ( dir , 'pages' ) ) ;
281+ const original = `export default function App({ Component, pageProps }) {\n return <Component {...pageProps} />;\n}\n` ;
282+ writeFileSync ( join ( dir , 'pages/_app.tsx' ) , original ) ;
283+
284+ await runInit ( dir , false ) ;
285+ await runUninit ( dir , false ) ;
286+
287+ const content = readFileSync ( join ( dir , 'pages/_app.tsx' ) , 'utf-8' ) ;
288+ expect ( content ) . not . toContain ( 'agent-react-devtools' ) ;
289+ } ) ;
290+
291+ it ( 'dry-run does not modify files' , async ( ) => {
292+ writeFileSync (
293+ join ( dir , 'package.json' ) ,
294+ JSON . stringify ( { dependencies : { 'react-scripts' : '^5.0.0' } } ) ,
295+ ) ;
296+ mkdirSync ( join ( dir , 'src' ) ) ;
297+ writeFileSync ( join ( dir , 'src/index.tsx' ) , `import React from 'react';\n` ) ;
298+
299+ await runInit ( dir , false ) ;
300+ const afterInit = readFileSync ( join ( dir , 'src/index.tsx' ) , 'utf-8' ) ;
301+
302+ await runUninit ( dir , true ) ;
303+ const afterDryRun = readFileSync ( join ( dir , 'src/index.tsx' ) , 'utf-8' ) ;
304+ expect ( afterDryRun ) . toBe ( afterInit ) ;
305+ } ) ;
306+
307+ it ( 'is a no-op when not configured' , async ( ) => {
308+ writeFileSync (
309+ join ( dir , 'package.json' ) ,
310+ JSON . stringify ( { dependencies : { 'react-scripts' : '^5.0.0' } } ) ,
311+ ) ;
312+ mkdirSync ( join ( dir , 'src' ) ) ;
313+ const original = `import React from 'react';\n` ;
314+ writeFileSync ( join ( dir , 'src/index.tsx' ) , original ) ;
315+
316+ await runUninit ( dir , false ) ;
317+ const content = readFileSync ( join ( dir , 'src/index.tsx' ) , 'utf-8' ) ;
318+ expect ( content ) . toBe ( original ) ;
319+ } ) ;
320+
321+ it ( 'init -> uninit -> init roundtrip works' , async ( ) => {
322+ writeFileSync (
323+ join ( dir , 'package.json' ) ,
324+ JSON . stringify ( { dependencies : { 'react-scripts' : '^5.0.0' } } ) ,
325+ ) ;
326+ mkdirSync ( join ( dir , 'src' ) ) ;
327+ writeFileSync ( join ( dir , 'src/index.tsx' ) , `import React from 'react';\n` ) ;
328+
329+ await runInit ( dir , false ) ;
330+ const afterInit1 = readFileSync ( join ( dir , 'src/index.tsx' ) , 'utf-8' ) ;
331+ expect ( afterInit1 ) . toContain ( 'agent-react-devtools' ) ;
332+
333+ await runUninit ( dir , false ) ;
334+ const afterUninit = readFileSync ( join ( dir , 'src/index.tsx' ) , 'utf-8' ) ;
335+ expect ( afterUninit ) . not . toContain ( 'agent-react-devtools' ) ;
336+
337+ await runInit ( dir , false ) ;
338+ const afterInit2 = readFileSync ( join ( dir , 'src/index.tsx' ) , 'utf-8' ) ;
339+ expect ( afterInit2 ) . toContain ( 'agent-react-devtools' ) ;
340+ } ) ;
341+ } ) ;
0 commit comments