diff --git a/compat-tests/fixtures/parcel1/package/src/index.js b/compat-tests/fixtures/cra/package/src/App/App.tsx similarity index 58% rename from compat-tests/fixtures/parcel1/package/src/index.js rename to compat-tests/fixtures/cra/package/src/App/App.tsx index 5703d55..17797a7 100644 --- a/compat-tests/fixtures/parcel1/package/src/index.js +++ b/compat-tests/fixtures/cra/package/src/App/App.tsx @@ -1,19 +1,12 @@ import {getProject} from '@theatre/core' -import ReactDOM from 'react-dom/client' -import React from 'react' +import React, {useEffect, useRef} from 'react' import {Canvas} from '@react-three/fiber' -import studio from '@theatre/studio' -import {editable as e, SheetProvider} from '@theatre/r3f' -import extension from '@theatre/r3f/dist/extension' - -if (process.env.NODE_ENV === 'development' && typeof window !== 'undefined') { - studio.extend(extension) - studio.initialize({usePersistentStorage: false}) -} +import {editable as e, SheetProvider, PerspectiveCamera} from '@theatre/r3f' +import state from './state.json' // credit: https://codesandbox.io/s/camera-pan-nsb7f -function Plane({color, theatreKey, ...props}) { +function Plane({color, theatreKey, ...props}: any) { return ( @@ -22,7 +15,26 @@ function Plane({color, theatreKey, ...props}) { ) } -function App() { +export default function App() { + const light2Ref = useRef() + + useEffect(() => { + const interval = setInterval(() => { + if (!light2Ref.current) return + + clearInterval(interval) + + const intensityInStateJson = 3 + const currentIntensity = light2Ref.current.intensity + if (currentIntensity !== intensityInStateJson) { + console.error(`Test failed: light2.intensity is ${currentIntensity}`) + } else { + console.log(`Test passed: light2.intensity is ${intensityInStateJson}`) + } + }, 50) + // see the note on below to understand why we're doing this + }, []) + return ( - + {/* @ts-ignore */} - + + ) } - -const project = getProject('Project') -const sheet = project.sheet('Sheet') -const obj = sheet.object('Obj', {str: 'some string', num: 0}) - -const container = document.getElementById('root') -const root = ReactDOM.createRoot(container) -root.render(hi) diff --git a/compat-tests/fixtures/cra/package/src/App/state.json b/compat-tests/fixtures/cra/package/src/App/state.json new file mode 100644 index 0000000..24328bb --- /dev/null +++ b/compat-tests/fixtures/cra/package/src/App/state.json @@ -0,0 +1,19 @@ +{ + "sheetsById": { + "R3F-Canvas": { + "staticOverrides": { + "byObject": { + "Light 2": { + "intensity": 3 + } + } + } + } + }, + "definitionVersion": "0.4.0", + "revisionHistory": [ + "jVNB3VWU34BIQK7M", + "-NXkC2GceSVBoVqa", + "Bw7ng1kdcWmMO5DN" + ] +} diff --git a/compat-tests/fixtures/next-latest/next-latest.compat-test.ts b/compat-tests/fixtures/next-latest/next-latest.compat-test.ts index 82b1081..b54ff76 100644 --- a/compat-tests/fixtures/next-latest/next-latest.compat-test.ts +++ b/compat-tests/fixtures/next-latest/next-latest.compat-test.ts @@ -2,8 +2,6 @@ import {$, cd, path, ProcessPromise} from '@cspotcode/zx' import {testServerAndPage} from '../../utils/testUtils' -$.verbose = false - const PATH_TO_PACKAGE = path.join(__dirname, `./package`) describe(`next`, () => { @@ -22,21 +20,9 @@ describe(`next`, () => { return $`npm run start -- --port ${port}` }, - waitTilServerIsReady: async ( - process: ProcessPromise, - port: number, - ) => { - for await (const chunk of process.stdout) { - const chunkString = chunk.toString() - if (chunkString.includes(`started server`)) { - // next's server is running now - break - } - } - - return {url: `http://localhost:${port}`} - }, + checkServerStdoutToSeeIfItsReady: (chunk) => + chunk.includes('started server'), }) }) }) @@ -49,21 +35,8 @@ describe(`next`, () => { return $`npm run dev -- --port ${port}` }, - waitTilServerIsReady: async ( - process: ProcessPromise, - port: number, - ) => { - for await (const chunk of process.stdout) { - const chunkString = chunk.toString() - - if (chunkString.includes(`compiled client and server successfully`)) { - // next's server is running now - break - } - } - - return {url: `http://localhost:${port}`} - }, + checkServerStdoutToSeeIfItsReady: (chunk) => + chunk.includes('compiled client and server successfully'), }) }) }) diff --git a/compat-tests/fixtures/next-latest/package/src/App/App.tsx b/compat-tests/fixtures/next-latest/package/src/App/App.tsx index 9c4d0fc..17797a7 100644 --- a/compat-tests/fixtures/next-latest/package/src/App/App.tsx +++ b/compat-tests/fixtures/next-latest/package/src/App/App.tsx @@ -1,5 +1,5 @@ import {getProject} from '@theatre/core' -import React, {useEffect} from 'react' +import React, {useEffect, useRef} from 'react' import {Canvas} from '@react-three/fiber' import {editable as e, SheetProvider, PerspectiveCamera} from '@theatre/r3f' import state from './state.json' @@ -16,19 +16,24 @@ function Plane({color, theatreKey, ...props}: any) { } export default function App() { - const [light2, setLight2] = React.useState(null) + const light2Ref = useRef() useEffect(() => { - if (!light2) return + const interval = setInterval(() => { + if (!light2Ref.current) return + + clearInterval(interval) + + const intensityInStateJson = 3 + const currentIntensity = light2Ref.current.intensity + if (currentIntensity !== intensityInStateJson) { + console.error(`Test failed: light2.intensity is ${currentIntensity}`) + } else { + console.log(`Test passed: light2.intensity is ${intensityInStateJson}`) + } + }, 50) // see the note on below to understand why we're doing this - const intensityInStateJson = 3 - const currentIntensity = light2.intensity - if (currentIntensity !== intensityInStateJson) { - console.error(`Test failed: light2.intensity is ${currentIntensity}`) - } else { - console.log(`Test passed: light2.intensity is ${intensityInStateJson}`) - } - }, [light2]) + }, []) return ( diff --git a/compat-tests/fixtures/parcel1/package/index.html b/compat-tests/fixtures/parcel1/package/index.html index 4a8bbbd..b0e1e98 100644 --- a/compat-tests/fixtures/parcel1/package/index.html +++ b/compat-tests/fixtures/parcel1/package/index.html @@ -8,6 +8,6 @@
- + diff --git a/compat-tests/fixtures/parcel1/package/package.json b/compat-tests/fixtures/parcel1/package/package.json index 9e442de..15c9d2a 100644 --- a/compat-tests/fixtures/parcel1/package/package.json +++ b/compat-tests/fixtures/parcel1/package/package.json @@ -1,13 +1,16 @@ { "scripts": { - "dev": "parcel serve ./index.html" + "dev": "parcel serve ./index.html", + "build": "NODE_ENV=production parcel build ./index.html --no-minify", + "start": "serve dist" }, "dependencies": { "@theatre/core": "0.0.1-COMPAT.1", "@theatre/r3f": "0.0.1-COMPAT.1", "@theatre/studio": "0.0.1-COMPAT.1", "parcel-bundler": "^1.12.5", - "react": "^18.1.0", - "react-dom": "^18.1.0" + "react": "^18.2.0", + "react-dom": "^18.2.0", + "serve": "14.2.0" } } diff --git a/compat-tests/fixtures/react17/package/src/index.js b/compat-tests/fixtures/parcel1/package/src/App/App.tsx similarity index 58% rename from compat-tests/fixtures/react17/package/src/index.js rename to compat-tests/fixtures/parcel1/package/src/App/App.tsx index ffeb366..17797a7 100644 --- a/compat-tests/fixtures/react17/package/src/index.js +++ b/compat-tests/fixtures/parcel1/package/src/App/App.tsx @@ -1,19 +1,12 @@ import {getProject} from '@theatre/core' -import ReactDOM from 'react-dom' -import React from 'react' +import React, {useEffect, useRef} from 'react' import {Canvas} from '@react-three/fiber' -import studio from '@theatre/studio' -import {editable as e, SheetProvider} from '@theatre/r3f' -import extension from '@theatre/r3f/dist/extension' - -if (process.env.NODE_ENV === 'development' && typeof window !== 'undefined') { - studio.extend(extension) - studio.initialize({usePersistentStorage: false}) -} +import {editable as e, SheetProvider, PerspectiveCamera} from '@theatre/r3f' +import state from './state.json' // credit: https://codesandbox.io/s/camera-pan-nsb7f -function Plane({color, theatreKey, ...props}) { +function Plane({color, theatreKey, ...props}: any) { return ( @@ -22,7 +15,26 @@ function Plane({color, theatreKey, ...props}) { ) } -function App() { +export default function App() { + const light2Ref = useRef() + + useEffect(() => { + const interval = setInterval(() => { + if (!light2Ref.current) return + + clearInterval(interval) + + const intensityInStateJson = 3 + const currentIntensity = light2Ref.current.intensity + if (currentIntensity !== intensityInStateJson) { + console.error(`Test failed: light2.intensity is ${currentIntensity}`) + } else { + console.log(`Test passed: light2.intensity is ${intensityInStateJson}`) + } + }, 50) + // see the note on below to understand why we're doing this + }, []) + return ( - + {/* @ts-ignore */} - + + ) } - -ReactDOM.render( - - - , - document.getElementById('root'), -) diff --git a/compat-tests/fixtures/parcel1/package/src/App/state.json b/compat-tests/fixtures/parcel1/package/src/App/state.json new file mode 100644 index 0000000..24328bb --- /dev/null +++ b/compat-tests/fixtures/parcel1/package/src/App/state.json @@ -0,0 +1,19 @@ +{ + "sheetsById": { + "R3F-Canvas": { + "staticOverrides": { + "byObject": { + "Light 2": { + "intensity": 3 + } + } + } + } + }, + "definitionVersion": "0.4.0", + "revisionHistory": [ + "jVNB3VWU34BIQK7M", + "-NXkC2GceSVBoVqa", + "Bw7ng1kdcWmMO5DN" + ] +} diff --git a/compat-tests/fixtures/parcel1/package/src/index.tsx b/compat-tests/fixtures/parcel1/package/src/index.tsx new file mode 100644 index 0000000..956439c --- /dev/null +++ b/compat-tests/fixtures/parcel1/package/src/index.tsx @@ -0,0 +1,16 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import studio from '@theatre/studio' +import extension from '@theatre/r3f/dist/extension' +import App from './App/App' + +if (process.env.NODE_ENV === 'development' && typeof window !== 'undefined') { + studio.extend(extension) + studio.initialize({usePersistentStorage: false}) +} + +console.log('React', React) + +const container = document.getElementById('root') +const root = ReactDOM.createRoot(container) +root.render() diff --git a/compat-tests/fixtures/parcel1/package/tsconfig.json b/compat-tests/fixtures/parcel1/package/tsconfig.json new file mode 100644 index 0000000..986627d --- /dev/null +++ b/compat-tests/fixtures/parcel1/package/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "jsx": "react" + } +} diff --git a/compat-tests/fixtures/parcel1/parcel1.compat-test.ts b/compat-tests/fixtures/parcel1/parcel1.compat-test.ts new file mode 100644 index 0000000..c4f8c63 --- /dev/null +++ b/compat-tests/fixtures/parcel1/parcel1.compat-test.ts @@ -0,0 +1,42 @@ +// @cspotcode/zx is zx in CommonJS +import {$, cd, path, ProcessPromise} from '@cspotcode/zx' +import {defer, testServerAndPage} from '../../utils/testUtils' + +const PATH_TO_PACKAGE = path.join(__dirname, `./package`) + +describe(`parcel1`, () => { + test(`build succeeds`, async () => { + cd(PATH_TO_PACKAGE) + const {exitCode} = await $`npm run build` + // at this point, the build should have succeeded + expect(exitCode).toEqual(0) + }) + + describe(`build`, () => { + function startServerOnPort(port: number): ProcessPromise { + cd(PATH_TO_PACKAGE) + + return $`npm start -- -p ${port}` + } + + testServerAndPage({ + startServerOnPort, + checkServerStdoutToSeeIfItsReady: (chunk) => + chunk.includes('Accepting connections'), + }) + }) + + describe(`dev`, () => { + function startServerOnPort(port: number): ProcessPromise { + cd(PATH_TO_PACKAGE) + + return $`npm run dev -- -p ${port}` + } + + testServerAndPage({ + startServerOnPort, + checkServerStdoutToSeeIfItsReady: (chunk) => + chunk.includes('Server running at'), + }) + }) +}) diff --git a/compat-tests/fixtures/react17/package/index.html b/compat-tests/fixtures/react17/package/index.html index 4a8bbbd..b0e1e98 100644 --- a/compat-tests/fixtures/react17/package/index.html +++ b/compat-tests/fixtures/react17/package/index.html @@ -8,6 +8,6 @@
- + diff --git a/compat-tests/fixtures/react17/package/package.json b/compat-tests/fixtures/react17/package/package.json index 5691eef..2117ca7 100644 --- a/compat-tests/fixtures/react17/package/package.json +++ b/compat-tests/fixtures/react17/package/package.json @@ -1,6 +1,8 @@ { "scripts": { - "dev": "parcel serve ./index.html" + "dev": "parcel serve ./index.html", + "build": "NODE_ENV=production parcel build ./index.html --no-minify", + "start": "serve dist" }, "dependencies": { "@react-three/drei": "^7.3.1", @@ -11,6 +13,7 @@ "parcel-bundler": "^1.12.5", "react": "^17.0.2", "react-dom": "^17.0.2", - "three": "^0.137.0" + "three": "^0.137.0", + "serve": "14.2.0" } } diff --git a/compat-tests/fixtures/react17/package/src/App/App.tsx b/compat-tests/fixtures/react17/package/src/App/App.tsx new file mode 100644 index 0000000..17797a7 --- /dev/null +++ b/compat-tests/fixtures/react17/package/src/App/App.tsx @@ -0,0 +1,102 @@ +import {getProject} from '@theatre/core' +import React, {useEffect, useRef} from 'react' +import {Canvas} from '@react-three/fiber' +import {editable as e, SheetProvider, PerspectiveCamera} from '@theatre/r3f' +import state from './state.json' + +// credit: https://codesandbox.io/s/camera-pan-nsb7f + +function Plane({color, theatreKey, ...props}: any) { + return ( + + + + + ) +} + +export default function App() { + const light2Ref = useRef() + + useEffect(() => { + const interval = setInterval(() => { + if (!light2Ref.current) return + + clearInterval(interval) + + const intensityInStateJson = 3 + const currentIntensity = light2Ref.current.intensity + if (currentIntensity !== intensityInStateJson) { + console.error(`Test failed: light2.intensity is ${currentIntensity}`) + } else { + console.log(`Test passed: light2.intensity is ${intensityInStateJson}`) + } + }, 50) + // see the note on below to understand why we're doing this + }, []) + + return ( + + + {/* @ts-ignore */} + + + + + + + + + + + + + + ) +} diff --git a/compat-tests/fixtures/react17/package/src/App/state.json b/compat-tests/fixtures/react17/package/src/App/state.json new file mode 100644 index 0000000..24328bb --- /dev/null +++ b/compat-tests/fixtures/react17/package/src/App/state.json @@ -0,0 +1,19 @@ +{ + "sheetsById": { + "R3F-Canvas": { + "staticOverrides": { + "byObject": { + "Light 2": { + "intensity": 3 + } + } + } + } + }, + "definitionVersion": "0.4.0", + "revisionHistory": [ + "jVNB3VWU34BIQK7M", + "-NXkC2GceSVBoVqa", + "Bw7ng1kdcWmMO5DN" + ] +} diff --git a/compat-tests/fixtures/react17/package/src/index.tsx b/compat-tests/fixtures/react17/package/src/index.tsx new file mode 100644 index 0000000..2fce101 --- /dev/null +++ b/compat-tests/fixtures/react17/package/src/index.tsx @@ -0,0 +1,19 @@ +import ReactDOM from 'react-dom' +import React from 'react' +import studio from '@theatre/studio' +import extension from '@theatre/r3f/dist/extension' +import App from './App/App' + +console.log(React) + +if (process.env.NODE_ENV === 'development' && typeof window !== 'undefined') { + studio.extend(extension) + studio.initialize({usePersistentStorage: false}) +} + +ReactDOM.render( + + + , + document.getElementById('root'), +) diff --git a/compat-tests/fixtures/react17/package/tsconfig.json b/compat-tests/fixtures/react17/package/tsconfig.json new file mode 100644 index 0000000..986627d --- /dev/null +++ b/compat-tests/fixtures/react17/package/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "jsx": "react" + } +} diff --git a/compat-tests/fixtures/react17/react17.compat-test.ts b/compat-tests/fixtures/react17/react17.compat-test.ts new file mode 100644 index 0000000..7821be1 --- /dev/null +++ b/compat-tests/fixtures/react17/react17.compat-test.ts @@ -0,0 +1,29 @@ +// @cspotcode/zx is zx in CommonJS +import {$, cd, path, ProcessPromise} from '@cspotcode/zx' +import {defer, testServerAndPage} from '../../utils/testUtils' + +const PATH_TO_PACKAGE = path.join(__dirname, `./package`) + +describe(`react17`, () => { + test(`build succeeds`, async () => { + cd(PATH_TO_PACKAGE) + const {exitCode} = await $`npm run build` + // at this point, the build should have succeeded + expect(exitCode).toEqual(0) + }) + + // this one is failing for some reason, but manually running the server works fine + describe(`build`, () => { + function startServerOnPort(port: number): ProcessPromise { + cd(PATH_TO_PACKAGE) + + return $`npm start -- -p ${port}` + } + + testServerAndPage({ + startServerOnPort, + checkServerStdoutToSeeIfItsReady: (chunk) => + chunk.includes('Accepting connections'), + }) + }) +}) diff --git a/compat-tests/fixtures/react18/package/src/App/App.tsx b/compat-tests/fixtures/react18/package/src/App/App.tsx index 9c4d0fc..17797a7 100644 --- a/compat-tests/fixtures/react18/package/src/App/App.tsx +++ b/compat-tests/fixtures/react18/package/src/App/App.tsx @@ -1,5 +1,5 @@ import {getProject} from '@theatre/core' -import React, {useEffect} from 'react' +import React, {useEffect, useRef} from 'react' import {Canvas} from '@react-three/fiber' import {editable as e, SheetProvider, PerspectiveCamera} from '@theatre/r3f' import state from './state.json' @@ -16,19 +16,24 @@ function Plane({color, theatreKey, ...props}: any) { } export default function App() { - const [light2, setLight2] = React.useState(null) + const light2Ref = useRef() useEffect(() => { - if (!light2) return + const interval = setInterval(() => { + if (!light2Ref.current) return + + clearInterval(interval) + + const intensityInStateJson = 3 + const currentIntensity = light2Ref.current.intensity + if (currentIntensity !== intensityInStateJson) { + console.error(`Test failed: light2.intensity is ${currentIntensity}`) + } else { + console.log(`Test passed: light2.intensity is ${intensityInStateJson}`) + } + }, 50) // see the note on below to understand why we're doing this - const intensityInStateJson = 3 - const currentIntensity = light2.intensity - if (currentIntensity !== intensityInStateJson) { - console.error(`Test failed: light2.intensity is ${currentIntensity}`) - } else { - console.log(`Test passed: light2.intensity is ${intensityInStateJson}`) - } - }, [light2]) + }, []) return ( diff --git a/compat-tests/fixtures/react18/react18.compat-test.ts b/compat-tests/fixtures/react18/react18.compat-test.ts index 8f1484d..71dd17a 100644 --- a/compat-tests/fixtures/react18/react18.compat-test.ts +++ b/compat-tests/fixtures/react18/react18.compat-test.ts @@ -2,8 +2,6 @@ import {$, cd, path, ProcessPromise} from '@cspotcode/zx' import {defer, testServerAndPage} from '../../utils/testUtils' -$.verbose = false - const PATH_TO_PACKAGE = path.join(__dirname, `./package`) describe(`react18`, () => { @@ -33,7 +31,7 @@ describe(`react18`, () => { const url = `http://localhost:${port}` process.stdout.on('data', (chunk) => { - if (chunk.toString().includes('Accepting connections')) { + if (chunk.includes('Accepting connections')) { // server is running now d.resolve({url}) } @@ -42,6 +40,24 @@ describe(`react18`, () => { return d.promise } - testServerAndPage({startServerOnPort, waitTilServerIsReady}) + testServerAndPage({ + startServerOnPort, + checkServerStdoutToSeeIfItsReady: (chunk) => + chunk.includes('Accepting connections'), + }) + }) + + describe(`dev`, () => { + function startServerOnPort(port: number): ProcessPromise { + cd(PATH_TO_PACKAGE) + + return $`npm run dev -- --port ${port}` + } + + testServerAndPage({ + startServerOnPort, + checkServerStdoutToSeeIfItsReady: (chunk) => + chunk.includes('Server running'), + }) }) }) diff --git a/compat-tests/fixtures/vite2/package/src/App/App.tsx b/compat-tests/fixtures/vite2/package/src/App/App.tsx index 9c4d0fc..17797a7 100644 --- a/compat-tests/fixtures/vite2/package/src/App/App.tsx +++ b/compat-tests/fixtures/vite2/package/src/App/App.tsx @@ -1,5 +1,5 @@ import {getProject} from '@theatre/core' -import React, {useEffect} from 'react' +import React, {useEffect, useRef} from 'react' import {Canvas} from '@react-three/fiber' import {editable as e, SheetProvider, PerspectiveCamera} from '@theatre/r3f' import state from './state.json' @@ -16,19 +16,24 @@ function Plane({color, theatreKey, ...props}: any) { } export default function App() { - const [light2, setLight2] = React.useState(null) + const light2Ref = useRef() useEffect(() => { - if (!light2) return + const interval = setInterval(() => { + if (!light2Ref.current) return + + clearInterval(interval) + + const intensityInStateJson = 3 + const currentIntensity = light2Ref.current.intensity + if (currentIntensity !== intensityInStateJson) { + console.error(`Test failed: light2.intensity is ${currentIntensity}`) + } else { + console.log(`Test passed: light2.intensity is ${intensityInStateJson}`) + } + }, 50) // see the note on below to understand why we're doing this - const intensityInStateJson = 3 - const currentIntensity = light2.intensity - if (currentIntensity !== intensityInStateJson) { - console.error(`Test failed: light2.intensity is ${currentIntensity}`) - } else { - console.log(`Test passed: light2.intensity is ${intensityInStateJson}`) - } - }, [light2]) + }, []) return ( diff --git a/compat-tests/fixtures/vite2/vite2.compat-test.ts b/compat-tests/fixtures/vite2/vite2.compat-test.ts index b0dd4df..a215a07 100644 --- a/compat-tests/fixtures/vite2/vite2.compat-test.ts +++ b/compat-tests/fixtures/vite2/vite2.compat-test.ts @@ -2,8 +2,6 @@ import {$, cd, path, ProcessPromise} from '@cspotcode/zx' import {testServerAndPage} from '../../utils/testUtils' -$.verbose = false - const PATH_TO_PACKAGE = path.join(__dirname, `./package`) describe(`vite2`, () => { @@ -21,22 +19,22 @@ describe(`vite2`, () => { return $`npm run preview -- --port ${port}` } - async function waitTilServerIsReady( - process: ProcessPromise, - port: number, - ): Promise<{ - url: string - }> { - for await (const chunk of process.stdout) { - if (chunk.toString().includes('--host')) { - // vite's server is running now - break - } - } + testServerAndPage({ + startServerOnPort, + checkServerStdoutToSeeIfItsReady: (chunk) => chunk.includes('--host'), + }) + }) - return {url: `http://localhost:${port}`} + describe(`vite dev`, () => { + function startServerOnPort(port: number): ProcessPromise { + cd(PATH_TO_PACKAGE) + + return $`npm run dev -- --port ${port}` } - testServerAndPage({startServerOnPort, waitTilServerIsReady}) + testServerAndPage({ + startServerOnPort, + checkServerStdoutToSeeIfItsReady: (chunk) => chunk.includes('--host'), + }) }) }) diff --git a/compat-tests/fixtures/vite4/package/src/App/App.tsx b/compat-tests/fixtures/vite4/package/src/App/App.tsx index 9c4d0fc..17797a7 100644 --- a/compat-tests/fixtures/vite4/package/src/App/App.tsx +++ b/compat-tests/fixtures/vite4/package/src/App/App.tsx @@ -1,5 +1,5 @@ import {getProject} from '@theatre/core' -import React, {useEffect} from 'react' +import React, {useEffect, useRef} from 'react' import {Canvas} from '@react-three/fiber' import {editable as e, SheetProvider, PerspectiveCamera} from '@theatre/r3f' import state from './state.json' @@ -16,19 +16,24 @@ function Plane({color, theatreKey, ...props}: any) { } export default function App() { - const [light2, setLight2] = React.useState(null) + const light2Ref = useRef() useEffect(() => { - if (!light2) return + const interval = setInterval(() => { + if (!light2Ref.current) return + + clearInterval(interval) + + const intensityInStateJson = 3 + const currentIntensity = light2Ref.current.intensity + if (currentIntensity !== intensityInStateJson) { + console.error(`Test failed: light2.intensity is ${currentIntensity}`) + } else { + console.log(`Test passed: light2.intensity is ${intensityInStateJson}`) + } + }, 50) // see the note on below to understand why we're doing this - const intensityInStateJson = 3 - const currentIntensity = light2.intensity - if (currentIntensity !== intensityInStateJson) { - console.error(`Test failed: light2.intensity is ${currentIntensity}`) - } else { - console.log(`Test passed: light2.intensity is ${intensityInStateJson}`) - } - }, [light2]) + }, []) return ( diff --git a/compat-tests/fixtures/vite4/vite4.compat-test.ts b/compat-tests/fixtures/vite4/vite4.compat-test.ts index 8fc2aa4..695404a 100644 --- a/compat-tests/fixtures/vite4/vite4.compat-test.ts +++ b/compat-tests/fixtures/vite4/vite4.compat-test.ts @@ -2,8 +2,6 @@ import {$, cd, path, ProcessPromise} from '@cspotcode/zx' import {testServerAndPage} from '../../utils/testUtils' -$.verbose = false - const PATH_TO_PACKAGE = path.join(__dirname, `./package`) describe(`vite4`, () => { @@ -21,22 +19,22 @@ describe(`vite4`, () => { return $`npm run preview -- --port ${port}` } - async function waitTilServerIsReady( - process: ProcessPromise, - port: number, - ): Promise<{ - url: string - }> { - for await (const chunk of process.stdout) { - if (chunk.toString().includes('--host')) { - // vite's server is running now - break - } - } + testServerAndPage({ + startServerOnPort, + checkServerStdoutToSeeIfItsReady: (chunk) => chunk.includes('--host'), + }) + }) - return {url: `http://localhost:${port}`} + describe(`vite dev`, () => { + function startServerOnPort(port: number): ProcessPromise { + cd(PATH_TO_PACKAGE) + + return $`npm run dev -- --port ${port}` } - testServerAndPage({startServerOnPort, waitTilServerIsReady}) + testServerAndPage({ + startServerOnPort, + checkServerStdoutToSeeIfItsReady: (chunk) => chunk.includes('--host'), + }) }) }) diff --git a/compat-tests/integrity.compat-test.ts b/compat-tests/integrity.compat-test.ts new file mode 100644 index 0000000..ff23c7b --- /dev/null +++ b/compat-tests/integrity.compat-test.ts @@ -0,0 +1,47 @@ +import path from 'path' +import fs from 'fs' + +describe(`Compat tests`, () => { + test(`all fixtures should have an App/ directory identical to that of vite4's`, async () => { + const vite4AppDir = path.join(__dirname, './fixtures/vite4/package/src/App') + + const vite4FilesContents = fs + .readdirSync(vite4AppDir) + .map((file) => [ + file, + fs.readFileSync(path.join(vite4AppDir, file), 'utf-8'), + ]) + + const allFixtures = fs + .readdirSync(path.join(__dirname, './fixtures')) + .filter( + (fixture) => + fixture !== 'vite4' && + // item is a folder + fs + .lstatSync(path.join(__dirname, './fixtures', fixture)) + .isDirectory(), + ) + + for (const fixture of allFixtures) { + const appDir = path.join( + __dirname, + `./fixtures/${fixture}/package/src/App`, + ) + if (!fs.existsSync(appDir)) { + throw new Error(`Fixture ${fixture} does not have an App/ directory`) + } + for (const [file, contents] of vite4FilesContents) { + const fixtureFileContents = fs.readFileSync( + path.join(appDir, file), + 'utf-8', + ) + if (fixtureFileContents !== contents) { + throw new Error( + `The file ${file} in fixture ${fixture} is not identical to that of vite4's`, + ) + } + } + } + }) +}) diff --git a/compat-tests/scripts/build-setups.mjs b/compat-tests/scripts/build-setups.mjs deleted file mode 100644 index 0db8466..0000000 --- a/compat-tests/scripts/build-setups.mjs +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Build the test setups - */ - -import path from 'path' -import {cd, fs, $} from 'zx' -import {getCompatibilityTestSetups} from './utils.mjs' - -const absPathOfCompatibilityTestSetups = getCompatibilityTestSetups() - -const setupsWithErros = [] - -// Try building the setups -;(async function () { - for (const setupDir of absPathOfCompatibilityTestSetups) { - try { - cd(setupDir) - const pathToSetup = path.join(setupDir, setupDir) - fs.removeSync(path.join(pathToSetup, 'node_modules')) - fs.removeSync(path.join(pathToSetup, 'package-lock.json')) - fs.removeSync(path.join(pathToSetup, 'yarn.lock')) - await $`npm install` - await $`npm run build` - } catch (err) { - console.error(err) - setupsWithErros.push(setupDir) - } - } - - // Stop if there were any errors during the build process, - // and print all of them to the console. - if (setupsWithErros.length !== 0) { - throw new Error( - `The following setups had problems when their dependencies were being installed:\n${( - setupsWithErros.join('\n'), - )}`, - ) - } -})() diff --git a/compat-tests/scripts/scripts.mjs b/compat-tests/scripts/scripts.mjs index fa4e8e8..9095909 100644 --- a/compat-tests/scripts/scripts.mjs +++ b/compat-tests/scripts/scripts.mjs @@ -78,7 +78,7 @@ export async function installFixtures() { console.log('Running `$ npm install` on test packages') await runNpmInstallOnTestPackages() - console.log('All tests installed successfully') + console.log('All fixtures installed successfully') await verdaccioServer.close() restoreTestPackageJsons() console.log('Done') diff --git a/compat-tests/utils/testUtils.ts b/compat-tests/utils/testUtils.ts index 7b2323c..c7e64b6 100644 --- a/compat-tests/utils/testUtils.ts +++ b/compat-tests/utils/testUtils.ts @@ -3,14 +3,38 @@ import {ProcessPromise} from '@cspotcode/zx' export function testServerAndPage({ startServerOnPort, - waitTilServerIsReady, + checkServerStdoutToSeeIfItsReady, }: { startServerOnPort: (port: number) => ProcessPromise - waitTilServerIsReady: ( - process: ProcessPromise, - port: number, - ) => Promise<{url: string}> + + checkServerStdoutToSeeIfItsReady: (chunk: string) => boolean }) { + if (checkServerStdoutToSeeIfItsReady('') !== false) { + throw new Error( + `Incorrect test setup. checkServerStdoutToSeeIfItsReady should return false for an empty string.`, + ) + } + const waitTilServerIsReady = async ( + process: ProcessPromise, + ): Promise => { + const d = defer() + + process.stdout.on('data', (chunk) => { + if (checkServerStdoutToSeeIfItsReady(chunk.toString())) { + // server is ready + d.resolve() + } + }) + + await Promise.race([ + d.promise, + new Promise((_, reject) => + setTimeout(() => reject(`Server wasn't ready after 30 seconds`), 30000), + ), + ]) + + return d.promise + } let browser: Browser, page: Page beforeAll(async () => { browser = await chromium.launch() @@ -37,8 +61,10 @@ export function testServerAndPage({ throw new Error(`Failed to start server: ${err}`) } + const url = `http://localhost:${port}` + try { - const {url} = await waitTilServerIsReady(process, port) + await waitTilServerIsReady(process) await testTheatreOnPage(page, {url}) } finally { @@ -77,7 +103,7 @@ async function testTheatreOnPage(page: Page, {url}: {url: string}) { try { await page.goto(url, { waitUntil: 'domcontentloaded', - timeout: 3000, + timeout: 30000, }) // give the console listener 3 seconds to resolve, otherwise fail the test diff --git a/jest.compat-tests.config.js b/jest.compat-tests.config.js index 78c326c..6099ac5 100644 --- a/jest.compat-tests.config.js +++ b/jest.compat-tests.config.js @@ -1,6 +1,9 @@ /** @type {import('jest').Config} */ module.exports = { - testMatch: ['/compat-tests/fixtures/*/*.compat-test.ts'], + testMatch: [ + '/compat-tests/fixtures/*/*.compat-test.ts', + '/compat-tests/*.compat-test.ts', + ], moduleNameMapper: {}, // setupFiles: ['./theatre/shared/src/setupTestEnv.ts'], automock: false, @@ -19,5 +22,7 @@ module.exports = { // ], // }, moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], - testTimeout: 1000 * 60, + // these tests take a long time to run, because each of them either runs a full build of a package, + // or tests the build on a browser using playwright + testTimeout: 1000 * 60 * 2, } diff --git a/theatre/devEnv/createBundles.ts b/theatre/devEnv/createBundles.ts index db70aec..5705cb3 100644 --- a/theatre/devEnv/createBundles.ts +++ b/theatre/devEnv/createBundles.ts @@ -1,21 +1,24 @@ import path from 'path' -import {build} from 'esbuild' +import * as esbuild from 'esbuild' import {definedGlobals} from './definedGlobals' -export function createBundles(watch: boolean) { +export async function createBundles(watch: boolean) { for (const which of ['core', 'studio']) { const pathToPackage = path.join(__dirname, '../', which) - const esbuildConfig: Parameters[0] = { + const esbuildConfig: Parameters[0] = { entryPoints: [path.join(pathToPackage, 'src/index.ts')], target: ['es6'], loader: {'.png': 'file', '.svg': 'dataurl'}, bundle: true, sourcemap: true, + supported: { + // 'unicode-escapes': false, + 'template-literal': false, + }, define: { ...definedGlobals, __IS_VISUAL_REGRESSION_TESTING: 'false', }, - watch, external: [ '@theatre/dataverse', /** @@ -53,12 +56,19 @@ export function createBundles(watch: boolean) { esbuildConfig.minify = true } - build({ + const ctx = await esbuild.context({ ...esbuildConfig, outfile: path.join(pathToPackage, 'dist/index.js'), format: 'cjs', }) + if (watch) { + await ctx.watch() + } else { + await ctx.rebuild() + await ctx.dispose() + } + /** * @remarks * I just disabled ESM builds because I couldn't get them to work diff --git a/theatre/package.json b/theatre/package.json index d3f57f2..2ede0ea 100644 --- a/theatre/package.json +++ b/theatre/package.json @@ -51,7 +51,7 @@ "blob-compare": "1.1.0", "circular-dependency-plugin": "^5.2.2", "cross-env": "^7.0.3", - "esbuild": "^0.12.15", + "esbuild": "^0.18.17", "esbuild-loader": "^2.13.1", "esbuild-register": "^2.5.0", "exec-loader": "^4.0.0", diff --git a/yarn.lock b/yarn.lock index 33b7965..f4589b7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -34175,7 +34175,7 @@ fsevents@^1.2.7: blob-compare: 1.1.0 circular-dependency-plugin: ^5.2.2 cross-env: ^7.0.3 - esbuild: ^0.12.15 + esbuild: ^0.18.17 esbuild-loader: ^2.13.1 esbuild-register: ^2.5.0 exec-loader: ^4.0.0