Skip to content

Commit

Permalink
Move unit tests to one folder and migrate them to TypeScript (#28427)
Browse files Browse the repository at this point in the history
* Move unit tests to one folder

* Migrate unit tests to TypeScript

* add test types to lint

* Ensure ts(x) tests are run with util

* Add tsx extension to jest config

* bump
  • Loading branch information
ijjk committed Aug 24, 2021
1 parent 6072afc commit 005b13f
Show file tree
Hide file tree
Showing 99 changed files with 202 additions and 214 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build_test_deploy.yml
Expand Up @@ -104,7 +104,7 @@ jobs:
path: ./*
key: ${{ github.sha }}

- run: node run-tests.js --timings --type unit -g 1/1
- run: node run-tests.js --type unit
if: ${{needs.build.outputs.docsChange != 'docs only change'}}

testIntegration:
Expand Down
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Expand Up @@ -111,7 +111,7 @@ stages:
path: $(System.DefaultWorkingDirectory)
displayName: Cache Build
- script: |
node run-tests.js -g 1/1 --timings --azure --type unit
node run-tests.js --type unit
displayName: 'Run tests'
# TODO: investigate re-enabling when stability matches running in
# tests in ubuntu environment
Expand Down
Empty file removed data.sqlite
Empty file.
2 changes: 1 addition & 1 deletion jest.config.js
@@ -1,5 +1,5 @@
module.exports = {
testMatch: ['**/*.test.js'],
testMatch: ['**/*.test.js', '**/*.test.ts', '**/*.test.tsx'],
verbose: true,
rootDir: 'test',
modulePaths: ['<rootDir>/lib'],
Expand Down
14 changes: 5 additions & 9 deletions package.json
Expand Up @@ -10,22 +10,18 @@
"lerna": "lerna",
"dev": "lerna run dev --stream --parallel",
"dev2": "while true; do yarn --check-files && yarn dev; done",
"testonly": "jest --runInBand",
"test-types": "yarn tsc",
"test-unit": "yarn jest test/unit/",
"testonly": "yarn jest --runInBand",
"testheadless": "cross-env HEADLESS=true yarn testonly",
"testsafari": "cross-env BROWSER_NAME=safari yarn testonly",
"testfirefox": "cross-env BROWSER_NAME=firefox yarn testonly",
"testie": "cross-env BROWSER_NAME=\"internet explorer\" yarn testonly",
"testall": "yarn run testonly -- --ci --forceExit && lerna run --scope @next/codemod test",
"testall": "yarn test -- --ci --forceExit && lerna run --scope @next/codemod test",
"genstats": "cross-env LOCAL_STATS=true node .github/actions/next-stats-action/src/index.js",
"pretest": "yarn run lint",
"git-reset": "git reset --hard HEAD",
"git-clean": "git clean -d -x -e node_modules -e packages -f",
"test-take2": "yarn git-reset && yarn git-clean && yarn testall",
"test": "yarn run testall || yarn run test-take2",
"lint-typescript": "lerna run typescript",
"lint-eslint": "eslint . --ext js,jsx,ts,tsx --max-warnings=0",
"lint-no-typescript": "run-p prettier-check lint-eslint",
"lint": "run-p lint-typescript prettier-check lint-eslint lint-language",
"lint": "run-p test-types lint-typescript prettier-check lint-eslint lint-language",
"lint-fix": "yarn prettier-fix && eslint . --ext js,jsx,ts,tsx --fix --max-warnings=0",
"lint-language": "alex .",
"prettier-check": "prettier --check .",
Expand Down
75 changes: 40 additions & 35 deletions run-tests.js
Expand Up @@ -12,16 +12,12 @@ const glob = promisify(_glob)
const exec = promisify(execOrig)

const timings = []
const NUM_RETRIES = 2
const DEFAULT_NUM_RETRIES = 2
const DEFAULT_CONCURRENCY = 2
const RESULTS_EXT = `.results.json`
const isTestJob = !!process.env.NEXT_TEST_JOB
const TIMINGS_API = `https://next-timings.jjsweb.site/api/timings`

const UNIT_TEST_EXT = '.unit.test.js'
const DEV_TEST_EXT = '.dev.test.js'
const PROD_TEST_EXT = '.prod.test.js'

const NON_CONCURRENT_TESTS = [
'test/integration/basic/test/index.test.js',
'test/acceptance/ReactRefresh.dev.test.js',
Expand All @@ -30,12 +26,17 @@ const NON_CONCURRENT_TESTS = [
'test/acceptance/ReactRefreshRequire.dev.test.js',
]

const testFilters = {
unit: 'unit/',
}

// which types we have configured to run separate
const configuredTestTypes = [UNIT_TEST_EXT]
const configuredTestTypes = Object.values(testFilters)

async function main() {
let numRetries = DEFAULT_NUM_RETRIES
let concurrencyIdx = process.argv.indexOf('-c')
const concurrency =
let concurrency =
parseInt(process.argv[concurrencyIdx + 1], 10) || DEFAULT_CONCURRENCY

const outputTimings = process.argv.indexOf('--timings') !== -1
Expand All @@ -50,15 +51,17 @@ async function main() {
let filterTestsBy

switch (testType) {
case 'unit':
filterTestsBy = UNIT_TEST_EXT
break
case 'dev':
filterTestsBy = DEV_TEST_EXT
break
case 'production':
filterTestsBy = PROD_TEST_EXT
case 'unit': {
numRetries = 0
filterTestsBy = testFilters.unit
break
}
// case 'dev':
// filterTestsBy = DEV_TEST_EXT
// break
// case 'production':
// filterTestsBy = PROD_TEST_EXT
// break
case 'all':
filterTestsBy = 'none'
break
Expand All @@ -67,22 +70,22 @@ async function main() {
}

console.log('Running tests with concurrency:', concurrency)
let tests = process.argv.filter((arg) => arg.endsWith('.test.js'))
let tests = process.argv.filter((arg) => arg.match(/\.test\.(js|ts|tsx)/))
let prevTimings

if (tests.length === 0) {
tests = (
await glob('**/*.test.js', {
await glob('**/*.test.{js,ts,tsx}', {
nodir: true,
cwd: path.join(__dirname, 'test'),
})
).filter((test) => {
// only include the specified type
if (filterTestsBy) {
return filterTestsBy === 'none' ? true : test.endsWith(filterTestsBy)
// include all except the separately configured types
// only include the specified type
return filterTestsBy === 'none' ? true : test.startsWith(filterTestsBy)
} else {
return !configuredTestTypes.some((type) => test.endsWith(type))
// include all except the separately configured types
return !configuredTestTypes.some((type) => test.startsWith(type))
}
})

Expand Down Expand Up @@ -183,7 +186,7 @@ async function main() {
)
const children = new Set()

const runTest = (test = '', usePolling) =>
const runTest = (test = '', usePolling, isFinalRun) =>
new Promise((resolve, reject) => {
const start = new Date().getTime()
let outputChunks = []
Expand Down Expand Up @@ -232,7 +235,9 @@ async function main() {
child.on('exit', (code) => {
children.delete(child)
if (code) {
outputChunks.forEach((chunk) => process.stdout.write(chunk))
if (isFinalRun) {
outputChunks.forEach((chunk) => process.stdout.write(chunk))
}
reject(new Error(`failed with code: ${code}`))
}
resolve(new Date().getTime() - start)
Expand All @@ -254,21 +259,21 @@ async function main() {
for (const test of nonConcurrentTestNames) {
let passed = false

for (let i = 0; i < NUM_RETRIES + 1; i++) {
for (let i = 0; i < numRetries + 1; i++) {
try {
console.log(`Starting ${test} retry ${i}/${NUM_RETRIES}`)
const time = await runTest(test, i > 0)
console.log(`Starting ${test} retry ${i}/${numRetries}`)
const time = await runTest(test, i > 0, i === numRetries)
timings.push({
file: test,
time,
})
passed = true
console.log(
`Finished ${test} on retry ${i}/${NUM_RETRIES} in ${time / 1000}s`
`Finished ${test} on retry ${i}/${numRetries} in ${time / 1000}s`
)
break
} catch (err) {
if (i < NUM_RETRIES) {
if (i < numRetries) {
try {
const testDir = path.dirname(path.join(__dirname, test))
console.log('Cleaning test files at', testDir)
Expand All @@ -279,7 +284,7 @@ async function main() {
}
}
if (!passed) {
console.error(`${test} failed to pass within ${NUM_RETRIES} retries`)
console.error(`${test} failed to pass within ${numRetries} retries`)
children.forEach((child) => child.kill())

if (isTestJob) {
Expand All @@ -303,21 +308,21 @@ async function main() {
await sema.acquire()
let passed = false

for (let i = 0; i < NUM_RETRIES + 1; i++) {
for (let i = 0; i < numRetries + 1; i++) {
try {
console.log(`Starting ${test} retry ${i}/${NUM_RETRIES}`)
const time = await runTest(test, i > 0)
console.log(`Starting ${test} retry ${i}/${numRetries}`)
const time = await runTest(test, i > 0, i === numRetries)
timings.push({
file: test,
time,
})
passed = true
console.log(
`Finished ${test} on retry ${i}/${NUM_RETRIES} in ${time / 1000}s`
`Finished ${test} on retry ${i}/${numRetries} in ${time / 1000}s`
)
break
} catch (err) {
if (i < NUM_RETRIES) {
if (i < numRetries) {
try {
const testDir = path.dirname(path.join(__dirname, test))
console.log('Cleaning test files at', testDir)
Expand All @@ -328,7 +333,7 @@ async function main() {
}
}
if (!passed) {
console.error(`${test} failed to pass within ${NUM_RETRIES} retries`)
console.error(`${test} failed to pass within ${numRetries} retries`)
children.forEach((child) => child.kill())

if (isTestJob) {
Expand Down
File renamed without changes.
14 changes: 0 additions & 14 deletions test/tsconfig.json

This file was deleted.

@@ -1,7 +1,6 @@
const rule = require('@next/eslint-plugin-next/lib/rules/google-font-display')
const RuleTester = require('eslint').RuleTester

RuleTester.setDefaultConfig({
import rule from '@next/eslint-plugin-next/lib/rules/google-font-display'
import { RuleTester } from 'eslint'
;(RuleTester as any).setDefaultConfig({
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
Expand All @@ -11,8 +10,8 @@ RuleTester.setDefaultConfig({
},
},
})
const ruleTester = new RuleTester()

var ruleTester = new RuleTester()
ruleTester.run('google-font-display', rule, {
valid: [
`import Head from "next/head";
Expand Down
@@ -1,7 +1,6 @@
const rule = require('@next/eslint-plugin-next/lib/rules/google-font-preconnect')
const RuleTester = require('eslint').RuleTester

RuleTester.setDefaultConfig({
import rule from '@next/eslint-plugin-next/lib/rules/google-font-preconnect'
import { RuleTester } from 'eslint'
;(RuleTester as any).setDefaultConfig({
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
Expand All @@ -11,8 +10,8 @@ RuleTester.setDefaultConfig({
},
},
})
const ruleTester = new RuleTester()

var ruleTester = new RuleTester()
ruleTester.run('google-font-preconnect', rule, {
valid: [
`export const Test = () => (
Expand Down
@@ -1,8 +1,6 @@
const rule = require('@next/eslint-plugin-next/lib/rules/inline-script-id')

const RuleTester = require('eslint').RuleTester

RuleTester.setDefaultConfig({
import rule from '@next/eslint-plugin-next/lib/rules/inline-script-id'
import { RuleTester } from 'eslint'
;(RuleTester as any).setDefaultConfig({
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
Expand Down
@@ -1,7 +1,6 @@
const rule = require('@next/eslint-plugin-next/lib/rules/link-passhref')
const RuleTester = require('eslint').RuleTester

RuleTester.setDefaultConfig({
import rule from '@next/eslint-plugin-next/lib/rules/link-passhref'
import { RuleTester } from 'eslint'
;(RuleTester as any).setDefaultConfig({
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
Expand All @@ -11,8 +10,8 @@ RuleTester.setDefaultConfig({
},
},
})
const ruleTester = new RuleTester()

var ruleTester = new RuleTester()
ruleTester.run('link-passhref', rule, {
valid: [
`export const Home = () => (
Expand Down
@@ -1,11 +1,6 @@
const rule = require('@next/eslint-plugin-next/lib/rules/next-script-for-ga')

const RuleTester = require('eslint').RuleTester

const ERROR_MSG =
'Use the `next/script` component for loading third party scripts. See: https://nextjs.org/docs/messages/next-script-for-ga.'

RuleTester.setDefaultConfig({
import rule from '@next/eslint-plugin-next/lib/rules/next-script-for-ga'
import { RuleTester } from 'eslint'
;(RuleTester as any).setDefaultConfig({
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
Expand All @@ -16,7 +11,11 @@ RuleTester.setDefaultConfig({
},
})

var ruleTester = new RuleTester()
const ERROR_MSG =
'Use the `next/script` component for loading third party scripts. See: https://nextjs.org/docs/messages/next-script-for-ga.'

const ruleTester = new RuleTester()

ruleTester.run('sync-scripts', rule, {
valid: [
`import Script from 'next/script'
Expand Down
@@ -1,7 +1,6 @@
const rule = require('@next/eslint-plugin-next/lib/rules/no-css-tags')
const RuleTester = require('eslint').RuleTester

RuleTester.setDefaultConfig({
import rule from '@next/eslint-plugin-next/lib/rules/no-css-tags'
import { RuleTester } from 'eslint'
;(RuleTester as any).setDefaultConfig({
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
Expand All @@ -11,8 +10,8 @@ RuleTester.setDefaultConfig({
},
},
})
const ruleTester = new RuleTester()

var ruleTester = new RuleTester()
ruleTester.run('no-css-tags', rule, {
valid: [
`import {Head} from 'next/document';
Expand Down
@@ -1,8 +1,6 @@
const rule = require('@next/eslint-plugin-next/lib/rules/no-document-import-in-page')

const RuleTester = require('eslint').RuleTester

RuleTester.setDefaultConfig({
import rule from '@next/eslint-plugin-next/lib/rules/no-document-import-in-page'
import { RuleTester } from 'eslint'
;(RuleTester as any).setDefaultConfig({
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
Expand All @@ -12,8 +10,8 @@ RuleTester.setDefaultConfig({
},
},
})
const ruleTester = new RuleTester()

var ruleTester = new RuleTester()
ruleTester.run('no-document-import-in-page', rule, {
valid: [
{
Expand Down

0 comments on commit 005b13f

Please sign in to comment.