import {
cpSync,
mkdtempSync,
readFileSync,
rmSync,
statSync,
writeFileSync,
} from 'fs'
import { tmpdir } from 'os'
import { join } from 'path'
import { nextTest } from 'next-test-utils'
import { FileRef, nextTestSetup } from 'e2e-utils'
import { spawnSync } from 'child_process'
function createTemporaryFixture(fixtureName: string) {
const fixturePath = join(__dirname, fixtureName)
const stat = statSync(fixturePath)
if (!stat.isDirectory()) {
throw new Error(`Fixture ${fixtureName} is not a directory.`)
}
const dir = mkdtempSync(join(tmpdir(), fixtureName))
cpSync(fixturePath, dir, { recursive: true })
return dir
}
describe.skip('next test', () => {
const { next: basicExample, skipped } = nextTestSetup({
files: new FileRef(join(__dirname, 'basic-example')),
dependencies: {
'@playwright/test': '1.43.1',
},
skipStart: true,
// This doesn't need to be deployed as it's using `experimental-test` mode
skipDeployment: true,
})
if (skipped) return
afterAll(async () => {
await basicExample.destroy()
})
describe('first time setup', () => {
it.each([['first-time-setup-js'], ['first-time-setup-ts']])(
'should correctly install missing dependencies and generate missing configuration file for %s',
async (fixtureName: string) => {
const fixture = createTemporaryFixture(fixtureName)
try {
const { stdout } = await nextTest(fixture, [], {
stderr: true,
stdout: true,
cwd: fixture,
})
expect(stdout).toContain('Installing devDependencies')
expect(stdout).toContain('@playwright/test')
expect(stdout).toContain(
`Successfully generated ${
fixtureName === 'first-time-setup-js'
? 'playwright.config.js'
: 'playwright.config.ts'
}. Create your first test and then run \`next experimental-test\`.`
)
const pkgJSON = JSON.parse(
readFileSync(join(fixture, 'package.json'), 'utf-8')
)
expect(pkgJSON.devDependencies).toHaveProperty('@playwright/test')
} finally {
rmSync(fixture, { recursive: true, force: true })
}
}
)
it('should fail if next.js config is missing experimental#testProxy', async () => {
const fixture = createTemporaryFixture('first-time-setup-js')
try {
writeFileSync(join(fixture, 'next.config.js'), 'module.exports = {}')
const { stderr } = await nextTest(fixture, [], {
stderr: true,
stdout: true,
cwd: fixture,
})
expect(stderr).toContain(
'`next experimental-test` requires the `experimental.testProxy: true` configuration option.'
)
} finally {
rmSync(fixture, { recursive: true, force: true })
}
})
})
// TODO: fix the playwright download issue
it.skip('should execute playwright tests', async () => {
const { stdout } = spawnSync('pnpm', ['next', 'experimental-test'], {
cwd: basicExample.testDir,
encoding: 'utf-8',
env: {
...process.env,
JEST_WORKER_ID: undefined, // Playwright complains about being executed by Jest
},
})
expect(stdout).toContain('1 passed')
})
describe('test runner validation', () => {
beforeEach(() => {
// First, test that `defaultTestRunner` takes precedence over the default playwright.
writeFileSync(
join(basicExample.testDir, 'next.config.js'),
"module.exports = { experimental: { testProxy: true, defaultTestRunner: 'invalid-test-runner'}}"
)
})
afterEach(() => {
writeFileSync(
join(basicExample.testDir, 'next.config.js'),
'module.exports = { experimental: { testProxy: true }}'
)
})
it('should validate configured/specified test runner', async () => {
let { stderr } = spawnSync('pnpm', ['next', 'experimental-test'], {
cwd: basicExample.testDir,
encoding: 'utf-8',
env: {
...process.env,
JEST_WORKER_ID: undefined, // Playwright complains about being executed by Jest
},
})
// Assert the assigned `defaultTestRunner` is printed in the error
expect(stderr).toContain(
'Test runner invalid-test-runner is not supported.'
)
// Second, test that the `--test-runner` arg takes precedence over `defaultTestRunner` and default playwright
;({ stderr } = spawnSync(
'pnpm',
['next', 'experimental-test', '--test-runner=invalid-test-runner-2'],
{
cwd: basicExample.testDir,
encoding: 'utf-8',
env: {
...process.env,
JEST_WORKER_ID: undefined, // Playwright complains about being executed by Jest
},
}
))
// Assert the assigned `--test-runner` arg is printed in the error
expect(stderr).toContain(
'Test runner invalid-test-runner-2 is not supported.'
)
})
})
it('should pass args to test runner', async () => {
const { stdout } = spawnSync(
'pnpm',
['next', 'experimental-test', '--list'],
{
cwd: basicExample.testDir,
encoding: 'utf-8',
env: {
...process.env,
JEST_WORKER_ID: undefined, // Playwright complains about being executed by Jest
},
}
)
expect(stdout).toMatchInlineSnapshot(`
"Listing tests:
[chromium] › app/page.spec.js:3:1 › home page
Total: 1 test in 1 file
"
`)
})
})