create-dynamic-app
Version:
CLI tool to generate sample applications using Dynamic's web3 authentication
245 lines (223 loc) • 6.73 kB
text/typescript
import { describe, it, expect, beforeEach, afterEach } from "bun:test"
import { promises as fs } from "node:fs"
import path from "node:path"
import { execSync, spawn } from "node:child_process"
import { generateNextApp } from "../../generate-next"
import { generateReactApp } from "../../generate-react"
import type { Chain } from "../../types"
const TEST_DIR = path.join(process.cwd(), "test-output")
let testFailed = false
const isCI = process.env.CI === "true"
describe("Development Server", () => {
const mockChains: Chain[] = [
{
name: "Ethereum",
package: "@dynamic-labs/ethereum",
connector: "EthereumWalletConnectors",
},
]
beforeEach(async () => {
testFailed = false
// Clean up any existing test directory
try {
await fs.rm(TEST_DIR, { recursive: true, force: true })
} catch {
console.error("Error during cleanup")
}
await fs.mkdir(TEST_DIR, { recursive: true })
})
afterEach(async () => {
// Only cleanup if test passed
if (testFailed) {
console.log(`Test failed - keeping directory ${TEST_DIR} for inspection`)
return
}
try {
await fs.rm(TEST_DIR, { recursive: true, force: true })
} catch {
console.error("Error during cleanup")
}
})
it("should start Next.js development server", async () => {
try {
const appName = "test-next-app"
const appDir = path.join(TEST_DIR, appName)
// Generate the app
await generateNextApp(TEST_DIR, appName, true, false, mockChains)
// Install dependencies
console.log("Installing dependencies...")
try {
// First try with basic install
execSync("npm install --ignore-scripts", {
cwd: appDir,
stdio: "inherit",
timeout: 300000,
env: {
...process.env,
GENERATE_SOURCEMAP: "false",
},
})
} catch (error) {
console.error("npm install failed:", error)
// Try again with a clean cache
console.log("Retrying npm install with clean cache...")
execSync("npm cache clean --force", {
cwd: appDir,
stdio: "inherit",
})
execSync("npm install --ignore-scripts", {
cwd: appDir,
stdio: "inherit",
timeout: 300000,
env: {
...process.env,
GENERATE_SOURCEMAP: "false",
},
})
}
// Start the development server
console.log("Starting development server...")
const server = spawn("npm", ["run", "dev"], {
cwd: appDir,
env: {
...process.env,
CI: isCI ? "true" : "false", // Pass CI flag to skip asset downloads
NEXT_TELEMETRY_DISABLED: "1", // Disable telemetry
},
})
// Log server output
server.stdout.on("data", (data) => {
console.log(`Server stdout: ${data}`)
})
server.stderr.on("data", (data) => {
console.error(`Server stderr: ${data}`)
})
// Wait for server to start (increased timeout for CI)
const waitTime = isCI ? 15000 : 10000
console.log(`Waiting ${waitTime}ms for server to start...`)
await new Promise((resolve) => setTimeout(resolve, waitTime))
// Make a request to the server
console.log("Making request to server...")
const response = await fetch("http://localhost:3000")
expect(response.status).toBe(200)
// Kill the server
console.log("Killing server...")
server.kill()
} catch (error) {
testFailed = true
console.error("Test failed with error:", error)
throw error
}
}, 300000) // 5 minute timeout
it("should start Vite development server", async () => {
try {
const appName = "test-react-app"
const appDir = path.join(TEST_DIR, appName)
// Generate the app
await generateReactApp(TEST_DIR, appName, true, false, mockChains)
// Install dependencies
console.log("Installing dependencies...")
try {
// Clean up any existing node_modules and package-lock.json
try {
await fs.rm(path.join(appDir, "node_modules"), {
recursive: true,
force: true,
})
await fs.rm(path.join(appDir, "package-lock.json"), { force: true })
} catch {
console.log(
"No existing node_modules or package-lock.json to clean up"
)
}
// First try with basic install
execSync("npm install --ignore-scripts", {
cwd: appDir,
stdio: "inherit",
timeout: 300000,
env: {
...process.env,
GENERATE_SOURCEMAP: "false",
},
})
} catch (error) {
console.error("npm install failed:", error)
// Try again with a clean cache
console.log("Retrying npm install with clean cache...")
execSync("npm cache clean --force", {
cwd: appDir,
stdio: "inherit",
})
// Clean up again before retry
try {
await fs.rm(path.join(appDir, "node_modules"), {
recursive: true,
force: true,
})
await fs.rm(path.join(appDir, "package-lock.json"), { force: true })
} catch {
console.log(
"No existing node_modules or package-lock.json to clean up"
)
}
execSync("npm install --ignore-scripts", {
cwd: appDir,
stdio: "inherit",
timeout: 300000,
env: {
...process.env,
GENERATE_SOURCEMAP: "false",
},
})
}
// Start the development server
console.log("Starting development server...")
const server = spawn("npm", ["run", "dev"], {
cwd: appDir,
env: {
...process.env,
CI: isCI ? "true" : "false", // Pass CI flag to skip asset downloads
VITE_TELEMETRY_DISABLED: "1", // Disable telemetry
},
})
// Log server output
server.stdout.on("data", (data) => {
console.log(`Server stdout: ${data}`)
})
server.stderr.on("data", (data) => {
console.error(`Server stderr: ${data}`)
})
// Wait for server to start (increased timeout for CI)
const waitTime = isCI ? 15000 : 10000
console.log(`Waiting ${waitTime}ms for server to start...`)
await new Promise((resolve) => setTimeout(resolve, waitTime))
// Make a request to the server
console.log("Making request to server...")
let retries = 3
let response: Response | undefined
while (retries > 0) {
try {
response = await fetch("http://localhost:5173")
if (response.status === 200) {
break
}
} catch (error) {
console.log(`Connection attempt ${4 - retries} failed, retrying...`)
await new Promise((resolve) => setTimeout(resolve, 5000)) // Wait 5 seconds between retries
retries--
}
}
if (!response || response.status !== 200) {
throw new Error("Failed to connect to server after multiple attempts")
}
expect(response.status).toBe(200)
// Kill the server
console.log("Killing server...")
server.kill()
} catch (error) {
testFailed = true
console.error("Test failed with error:", error)
throw error
}
}, 300000) // 5 minute timeout
})