diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 39f32579..3b6c63db 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,7 +68,7 @@ jobs: - uses: nick-invision/retry@v2 with: timeout_minutes: 10 - max_attempts: 3 + max_attempts: 2 command: npm --silent run test coverage: diff --git a/.npmrc b/.npmrc index 5660f81a..8f69a6e9 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1,2 @@ -registry=https://registry.npmjs.org/ \ No newline at end of file +registry=https://registry.npmjs.org/ +hoist=false \ No newline at end of file diff --git a/package.json b/package.json index e7a24d82..4b26b6b1 100644 --- a/package.json +++ b/package.json @@ -43,9 +43,11 @@ "eslint": "^7.20.0", "eslint-config-alloy": "^3.10.0", "execa": "^5.1.1", + "fast-json-stable-stringify": "^2.1.0", "fs-extra": "^10.0.0", "husky": "4.3.7", "jest": "^27.0.4", + "jest-environment-node": "^26.0.0", "jest-serializer-path": "^0.1.15", "lint-staged": "^11.0.0", "minimist": "^1.2.5", @@ -57,7 +59,7 @@ "strip-ansi": "^7.0.0", "ts-jest": "^27.0.3", "typescript": "^4.2.2", - "vite": "^2.3.8", + "vite": "^2.7.9", "vite-plugin-checker": "workspace:*", "zx": "^1.14.2" } diff --git a/packages/vite-plugin-checker/__tests__/e2e/MockSandbox/MockSandbox.ts b/packages/vite-plugin-checker/__tests__/e2e/MockSandbox/MockSandbox.ts deleted file mode 100644 index 284c2949..00000000 --- a/packages/vite-plugin-checker/__tests__/e2e/MockSandbox/MockSandbox.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { Plugin, ConfigEnv, ViteDevServer, UserConfig } from 'vite' -import { ServeAndBuildChecker } from '../../../src/types' -import { TestServer } from './TestSever' -import assert from 'assert' - -export class MockSandbox { - public plugin?: Plugin - public checkers?: ServeAndBuildChecker[] - public viteMock?: { - context: any - server: TestServer - } - - public viteDev({ config, env }: { config: UserConfig; env: ConfigEnv }) { - this.runConfig(config, env) - this.runConfigureServer() - this.runBuildStart() - } - - public viteBuild({ config, env }: { config: UserConfig; env: ConfigEnv }) { - this.runConfig(config, env) - this.runBuildStart() - } - - public runConfig: NonNullable = (config, env) => { - assert(this.plugin?.config, 'have this.plugin.config') - this.plugin.config(config, env) - } - - public runBuildStart() { - assert(this.plugin?.buildStart, 'have this.plugin.buildStart') - // @ts-expect-error - this.plugin.buildStart() - } - - public runConfigureServer() { - assert(this.plugin?.configureServer, 'have this.plugin.configureServer') - // @ts-expect-error - this.plugin.configureServer(this.viteMock.server as ViteDevServer) - } - - public reset() { - this.viteMock = undefined - } -} diff --git a/packages/vite-plugin-checker/__tests__/e2e/MockSandbox/TestSever.ts b/packages/vite-plugin-checker/__tests__/e2e/MockSandbox/TestSever.ts deleted file mode 100644 index 8be70ff7..00000000 --- a/packages/vite-plugin-checker/__tests__/e2e/MockSandbox/TestSever.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { HMRPayload } from 'vite' - -interface SimpleServer { - ws: { send: (payload: HMRPayload) => void } - middlewares: { use: (m: (_: unknown, __: unknown, next: () => unknown) => void) => void } -} - -export class TestServer implements SimpleServer { - public onSend: (payload: HMRPayload) => unknown - public onMiddlewareUse: () => unknown - - public middlewares: SimpleServer['middlewares'] = { - use(m) { - const req = '' - const res = '' - const next = () => {} - m(req, res, next) - }, - } - - public ws: SimpleServer['ws'] = { - send(payload) { - return - }, - } - - public constructor(options: { - onMiddlewareUse: () => unknown - onSend: (payload: HMRPayload) => unknown - }) { - this.onMiddlewareUse = options.onMiddlewareUse - this.onSend = options.onSend - } -} diff --git a/packages/vite-plugin-checker/__tests__/e2e/Sandbox/Sandbox.ts b/packages/vite-plugin-checker/__tests__/e2e/Sandbox/Sandbox.ts index 561798c3..13f42b9f 100644 --- a/packages/vite-plugin-checker/__tests__/e2e/Sandbox/Sandbox.ts +++ b/packages/vite-plugin-checker/__tests__/e2e/Sandbox/Sandbox.ts @@ -1,26 +1,37 @@ import execa from 'execa' import path from 'path' -import playwright, { chromium } from 'playwright-chromium' -import type { ElementHandleForTag } from 'playwright-chromium/types/structs' +import playwright from 'playwright-chromium' import strip from 'strip-ansi' import invariant from 'tiny-invariant' -// import fs from 'fs' -// import os from 'os' +import { build, createServer, HMRPayload, ViteDevServer } from 'vite' +import { Checker } from 'vite-plugin-checker' -// @ts-ignore -// const page = global.page! -// const DIR = path.join(os.tmpdir(), 'jest_playwright_global_setup') import { expectStdoutNotContains, sleep, testDir } from '../testUtils' -let devServer: any -let browser: playwright.Browser -// const page: playwright.Page +import type { ElementHandleForTag } from 'playwright-chromium/types/structs' +let devServer: ViteDevServer let binPath: string - export let log = '' export let stripedLog = '' -export function resetTerminalLog() { +export function proxyConsoleInTest() { + Checker.logger = [ + (...args: any[]) => { + log = args[0].payload + stripedLog = strip(args[0].payload) + }, + ] +} + +export async function sleepForServerReady(ratio = 1) { + await sleep(process.env.CI ? 10000 * ratio : 5000 * ratio) +} + +export async function sleepForEdit() { + await sleep(process.env.CI ? 4000 : 2000) +} + +export function resetReceivedLog() { log = '' stripedLog = '' } @@ -35,54 +46,46 @@ export async function viteServe({ cwd = process.cwd(), port = 3000, path: _path = '', -}: { cwd?: string; port?: number; path?: string } = {}) { - sleep(2000) - // @ts-ignore - // const devServer = global.devServer! - // browser = await chromium.launch({ - // args: ['--no-sandbox', '--disable-setuid-sandbox'], - // }) - - // const wsEndpoint = fs.readFileSync(path.join(DIR, 'wsEndpoint'), 'utf-8') - // const browser = await chromium.connect({ - // wsEndpoint, - // }) - - // // @ts-ignore - // global.page = await browser.newPage() - - console.log('launching browser') - // page = await browser.newPage() - - devServer = execa(binPath, { - cwd: cwd ?? testDir, - }) + wsSend, + proxyConsole = proxyConsoleInTest, + launchPage = false, +}: { + cwd?: string + port?: number + path?: string + wsSend?: (payload: HMRPayload) => void + proxyConsole?: () => void + launchPage?: boolean +} = {}) { + await sleep(3000) + if (proxyConsole) { + proxyConsole() + } - await new Promise((resolve) => { - devServer.stdout.on('data', (data: Buffer) => { - log += data.toString() - stripedLog += strip(data.toString()) - if (data.toString().match('running')) { - console.log('dev server running.') - resolve('') - } - }) + devServer = await createServer({ + root: cwd, }) + await devServer.listen() - await sleep(6000) - await page.goto(`http://localhost:${port}${_path}`) - await page.waitForLoadState('domcontentloaded') - // await page.waitForSelector('body', { state: 'attached' }) + if (wsSend) { + devServer.ws.send = (payload) => { + wsSend(payload) + } + } + + if (launchPage) { + console.log('-- launching page --') + await page.goto(`http://localhost:${port}${_path}`) + console.log('-- page launched --') + await page.waitForLoadState('domcontentloaded') + console.log('-- page loaded --') + } } export async function killServer() { - // @ts-ignore - // const devServer = global.devServer! - // if (page) await page.close() if (devServer) { - devServer.kill('SIGTERM', { - forceKillAfterTimeout: 1, - }) + await devServer.close() + console.log('-- dev server closed --') } } diff --git a/packages/vite-plugin-checker/__tests__/e2e/TestChecker/main.js b/packages/vite-plugin-checker/__tests__/e2e/TestChecker/main.js deleted file mode 100644 index 8a14fce9..00000000 --- a/packages/vite-plugin-checker/__tests__/e2e/TestChecker/main.js +++ /dev/null @@ -1,90 +0,0 @@ -"use strict"; -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -exports.__esModule = true; -exports.TestChecker = exports.buildBin = exports.createDiagnostic = void 0; -var vite_plugin_checker_1 = require("vite-plugin-checker"); -var worker_threads_1 = require("worker_threads"); -exports.createDiagnostic = function (userOptions) { - if (userOptions === void 0) { userOptions = {}; } - var overlay = true; // Vite defaults to true - return { - config: function (_a) { - var hmr = _a.hmr; - var viteOverlay = !(typeof hmr === 'object' && hmr.overlay === false); - if (userOptions.overlay === false || !viteOverlay) { - overlay = false; - } - }, - configureServer: function (_a) { - var root = _a.root; - return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_b) { - return [2 /*return*/]; - }); }); - } - }; -}; -exports.buildBin = ['_mock_build_cmd', ['_mock_arg1', '_mock_arg2']]; -var _a = vite_plugin_checker_1.createScript({ - absFilename: __filename, - buildBin: exports.buildBin, - serverChecker: { createDiagnostic: exports.createDiagnostic } -}), mainScript = _a.mainScript, workerScript = _a.workerScript; -if (worker_threads_1.isMainThread) { - var createChecker_1 = mainScript(); - var configCurryFn = function (checkerConfig) { - return function (sharedConfig) { - return createChecker_1(__assign({ testConfig: checkerConfig }, sharedConfig)); - }; - }; - module.exports.TestChecker = configCurryFn; - module.exports.createServeAndBuild = configCurryFn; -} -else { - workerScript(); -} diff --git a/packages/vite-plugin-checker/__tests__/e2e/TestChecker/main.ts b/packages/vite-plugin-checker/__tests__/e2e/TestChecker/main.ts deleted file mode 100644 index b70dc959..00000000 --- a/packages/vite-plugin-checker/__tests__/e2e/TestChecker/main.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { - CreateDiagnostic, - createScript, - ServeAndBuildChecker, - SharedConfig, - BuildCheckBin, -} from 'vite-plugin-checker' -import { isMainThread } from 'worker_threads' - -export const createDiagnostic: CreateDiagnostic = (userOptions = {}) => { - let overlay = true // Vite defaults to true - - return { - config: ({ hmr }) => { - const viteOverlay = !(typeof hmr === 'object' && hmr.overlay === false) - - if (userOptions.overlay === false || !viteOverlay) { - overlay = false - } - }, - async configureServer({ root }) {}, - } -} - -export const buildBin: BuildCheckBin = ['_mock_build_cmd', ['_mock_arg1', '_mock_arg2']] - -const { mainScript, workerScript } = createScript<{ testConfig: CheckerConfig }>({ - absFilename: __filename, - buildBin, - serverChecker: { createDiagnostic }, -})! - -if (isMainThread) { - const createChecker = mainScript() - const configCurryFn = (checkerConfig: CheckerConfig) => { - return (sharedConfig: SharedConfig) => { - return createChecker({ testConfig: checkerConfig, ...sharedConfig }) - } - } - - module.exports.TestChecker = configCurryFn - module.exports.createServeAndBuild = configCurryFn -} else { - workerScript() -} - -type CheckerConfig = Partial<{ - // TODO: support custom config -}> - -declare const TestChecker: ( - options?: CheckerConfig -) => (config: CheckerConfig & SharedConfig) => ServeAndBuildChecker - -export { TestChecker } -export type { CheckerConfig } diff --git a/packages/vite-plugin-checker/__tests__/e2e/build.spec.ts b/packages/vite-plugin-checker/__tests__/e2e/build.spec.ts deleted file mode 100644 index b5fa7e04..00000000 --- a/packages/vite-plugin-checker/__tests__/e2e/build.spec.ts +++ /dev/null @@ -1,111 +0,0 @@ -import cp from 'child_process' -import os from 'os' - -import CheckerPlugin from '../../lib/main' -// import { VlsChecker } from '../../../checker-vls/lib/main' -import { MockSandbox } from './MockSandbox/MockSandbox' -import { sleep, WORKER_CLEAN_TIMEOUT } from './testUtils' - -// ref https://github.com/facebook/jest/issues/936#issuecomment-613220940 -jest.mock('child_process', () => { - const spawnFn = jest.fn() - const onFn = jest.fn() - spawnFn.mockReturnValue({ on: onFn }) - - return { - ...jest.requireActual('child_process'), - spawn: spawnFn, - } -}) - -describe('build', () => { - let sandbox!: MockSandbox - const spawnOptions = expect.objectContaining({ - cwd: expect.any(String), - stdio: 'inherit', - env: expect.any(Object), - shell: os.platform() === 'win32', - }) - - beforeAll(() => { - sandbox = new MockSandbox() - }) - - afterEach(() => { - jest.clearAllMocks() - }) - - afterAll(async () => { - jest.restoreAllMocks() - await sleep(WORKER_CLEAN_TIMEOUT) - }) - - it('typescript', () => { - const plugin = CheckerPlugin({ - typescript: true, - }) - - sandbox.plugin = plugin - sandbox.viteBuild({ - config: {}, - env: { command: 'build', mode: '' }, - }) - - expect(cp.spawn).toHaveBeenCalledTimes(1) - expect(cp.spawn).toHaveBeenCalledWith('tsc', ['--noEmit'], spawnOptions) - }) - - it('vueTsc', () => { - const plugin = CheckerPlugin({ - vueTsc: true, - }) - - sandbox.plugin = plugin - sandbox.viteBuild({ - config: {}, - env: { command: 'build', mode: '' }, - }) - - expect(cp.spawn).toHaveBeenCalledTimes(1) - expect(cp.spawn).toHaveBeenCalledWith('vue-tsc', ['--noEmit'], spawnOptions) - }) - - it('custom checker (test vls)', () => { - const plugin = CheckerPlugin({ - vls: {}, - }) - - sandbox.plugin = plugin - sandbox.viteBuild({ - config: {}, - env: { command: 'build', mode: '' }, - }) - - expect(cp.spawn).toHaveBeenCalledTimes(1) - expect(cp.spawn).toHaveBeenCalledWith('vite-plugin-checker-vls', ['diagnostics'], spawnOptions) - }) - - it('multiple checkers', () => { - const plugin = CheckerPlugin({ - typescript: true, - vueTsc: true, - vls: {}, - }) - - sandbox.plugin = plugin - sandbox.viteBuild({ - config: {}, - env: { command: 'build', mode: '' }, - }) - - expect(cp.spawn).toHaveBeenCalledTimes(3) - expect(cp.spawn).toHaveBeenNthCalledWith(1, 'tsc', ['--noEmit'], spawnOptions) - expect(cp.spawn).toHaveBeenNthCalledWith(2, 'vue-tsc', ['--noEmit'], spawnOptions) - expect(cp.spawn).toHaveBeenNthCalledWith( - 3, - 'vite-plugin-checker-vls', - ['diagnostics'], - spawnOptions - ) - }) -}) diff --git a/packages/vite-plugin-checker/src/Checker.ts b/packages/vite-plugin-checker/src/Checker.ts index 946c72d6..09861258 100644 --- a/packages/vite-plugin-checker/src/Checker.ts +++ b/packages/vite-plugin-checker/src/Checker.ts @@ -3,7 +3,6 @@ import { isMainThread } from 'worker_threads' import { ServeAndBuildChecker, BuildInCheckerNames } from './types' import { createScript, Script } from './worker' -import chokidar from 'chokidar' // still an only issue https://github.com/microsoft/TypeScript/issues/29808#issuecomment-829750974 import type {} from 'vite' @@ -22,9 +21,15 @@ export interface CheckerMeta { } export abstract class Checker implements CheckerMeta { - public static watcher: chokidar.FSWatcher = chokidar.watch([], { - ignored: (path: string) => path.includes('node_modules'), - }) + public static logger: ((...args: any[]) => void)[] = [ + (...args: any[]) => { + console.log(args[0].payload) + }, + ] + + public static log(...args: any[]) { + this.logger.forEach((fn) => fn(...args)) + } public name: string public absFilePath: string diff --git a/packages/vite-plugin-checker/src/checkers/eslint/main.ts b/packages/vite-plugin-checker/src/checkers/eslint/main.ts index a3921a43..56004f62 100644 --- a/packages/vite-plugin-checker/src/checkers/eslint/main.ts +++ b/packages/vite-plugin-checker/src/checkers/eslint/main.ts @@ -1,21 +1,20 @@ import { ESLint } from 'eslint' -// import debounce from 'lodash.debounce' -// import os from 'os' import path from 'path' import invariant from 'tiny-invariant' import { parentPort } from 'worker_threads' +import chokidar from 'chokidar' import { Checker } from '../../Checker' import { + consoleLog, diagnosticToTerminalLog, diagnosticToViteError, NormalizedDiagnostic, normalizeEslintDiagnostic, } from '../../logger' +import { ACTION_TYPES } from '../../types' import type { CreateDiagnostic } from '../../types' -import type { ErrorPayload } from 'vite' - const createDiagnostic: CreateDiagnostic<'eslint'> = (pluginConfig) => { let overlay = true // Vite defaults to true @@ -53,7 +52,7 @@ const createDiagnostic: CreateDiagnostic<'eslint'> = (pluginConfig) => { const dispatchDiagnostics = () => { diagnosticsCache.forEach((n) => { - console.log(diagnosticToTerminalLog(n, 'ESLint')) + consoleLog(diagnosticToTerminalLog(n, 'ESLint')) }) const lastErr = diagnosticsCache[0] @@ -62,7 +61,7 @@ const createDiagnostic: CreateDiagnostic<'eslint'> = (pluginConfig) => { if (overlay) { parentPort?.postMessage({ - type: 'ERROR', + type: ACTION_TYPES.overlayError, payload: { type: 'error', err: diagnosticToViteError(lastErr), @@ -95,11 +94,15 @@ const createDiagnostic: CreateDiagnostic<'eslint'> = (pluginConfig) => { dispatchDiagnostics() // watch lint - Checker.watcher.add(paths) - Checker.watcher.on('change', async (filePath) => { + const watcher = chokidar.watch([], { + cwd: root, + ignored: (path: string) => path.includes('node_modules'), + }) + watcher.add(paths) + watcher.on('change', async (filePath) => { handleFileChange(filePath, 'change') }) - Checker.watcher.on('unlink', async (filePath) => { + watcher.on('unlink', async (filePath) => { handleFileChange(filePath, 'unlink') }) }, diff --git a/packages/vite-plugin-checker/src/checkers/typescript/main.ts b/packages/vite-plugin-checker/src/checkers/typescript/main.ts index 4ece50d8..c1e8e810 100644 --- a/packages/vite-plugin-checker/src/checkers/typescript/main.ts +++ b/packages/vite-plugin-checker/src/checkers/typescript/main.ts @@ -6,13 +6,14 @@ import { parentPort } from 'worker_threads' import { Checker } from '../../Checker' import { + consoleLog, diagnosticToTerminalLog, diagnosticToViteError, ensureCall, normalizeTsDiagnostic, } from '../../logger' +import { ACTION_TYPES, CreateDiagnostic } from '../../types' -import type { CreateDiagnostic } from '../../types' import type { ErrorPayload } from 'vite' const createDiagnostic: CreateDiagnostic<'typescript'> = (pluginConfig) => { @@ -80,7 +81,7 @@ const createDiagnostic: CreateDiagnostic<'typescript'> = (pluginConfig) => { case 6194: // 0 errors or 2+ errors if (currErr && overlay) { parentPort?.postMessage({ - type: 'ERROR', + type: ACTION_TYPES.overlayError, payload: { type: 'error', err: currErr, @@ -94,7 +95,7 @@ const createDiagnostic: CreateDiagnostic<'typescript'> = (pluginConfig) => { logChunk = '' } - console.log(logChunk + os.EOL + diagnostic.messageText.toString()) + consoleLog(logChunk + os.EOL + diagnostic.messageText.toString()) }) } diff --git a/packages/vite-plugin-checker/src/checkers/vls/diagnostics.ts b/packages/vite-plugin-checker/src/checkers/vls/diagnostics.ts index 06e96db2..83fce2de 100644 --- a/packages/vite-plugin-checker/src/checkers/vls/diagnostics.ts +++ b/packages/vite-plugin-checker/src/checkers/vls/diagnostics.ts @@ -1,11 +1,11 @@ import chalk from 'chalk' +import chokidar from 'chokidar' import glob from 'fast-glob' import fs from 'fs' import os from 'os' import path from 'path' import { Duplex } from 'stream' import { VLS } from 'vls' -import { Checker } from '../../Checker' import { TextDocument } from 'vscode-languageserver-textdocument' import { createConnection, @@ -26,6 +26,7 @@ import { import { URI } from 'vscode-uri' import { + consoleLog, diagnosticToTerminalLog, diagnosticToViteError, normalizeLspDiagnostic, @@ -86,12 +87,14 @@ export async function diagnostics( // initial report if (!errCount) { - console.log(chalk.green(`[VLS checker] No error found`)) + consoleLogVls(chalk.green(`[VLS checker] No error found`)) if (!watch) { process.exit(0) } } else { - console.log(chalk.red(`[VLS checker] Found ${errCount} ${errCount === 1 ? 'error' : 'errors'}`)) + consoleLogVls( + chalk.red(`[VLS checker] Found ${errCount} ${errCount === 1 ? 'error' : 'errors'}`) + ) if (!watch) { process.exit(1) } @@ -113,16 +116,18 @@ class TestStream extends Duplex { public _read(_size: number) {} } +let consoleLogVls = consoleLog + function suppressConsole() { let disposed = false - const rawConsoleLog = globalThis.console.log - globalThis.console.log = () => {} + const rawConsoleLog = consoleLogVls + consoleLogVls = () => {} return () => { if (disposed) return disposed = true - globalThis.console.log = rawConsoleLog + consoleLogVls = rawConsoleLog } } @@ -157,8 +162,8 @@ async function prepareClientConnection(workspaceUri: URI, options: DiagnosticOpt const res = await normalizePublishDiagnosticParams(publishDiagnostics) const normalized = diagnosticToViteError(res) - console.log(os.EOL) - console.log(res.map((d) => diagnosticToTerminalLog(d, 'VLS')).join(os.EOL)) + consoleLogVls(os.EOL) + consoleLogVls(res.map((d) => diagnosticToTerminalLog(d, 'VLS')).join(os.EOL)) options.errorCallback?.(publishDiagnostics, normalized) } @@ -288,8 +293,12 @@ async function getDiagnostics( // watched diagnostics report if (options.watch) { - Checker.watcher.add(workspaceUri.fsPath) - Checker.watcher.on('all', async (event, path) => { + const watcher = chokidar.watch([], { + ignored: (path: string) => path.includes('node_modules'), + }) + + watcher.add(workspaceUri.fsPath) + watcher.on('all', async (event, path) => { if (!path.endsWith('.vue')) return const fileContent = await fs.promises.readFile(path, 'utf-8') // TODO: watch js change @@ -303,6 +312,6 @@ async function getDiagnostics( }) } - console.log(logChunk) + consoleLogVls(logChunk) return initialErrCount } diff --git a/packages/vite-plugin-checker/src/checkers/vls/main.ts b/packages/vite-plugin-checker/src/checkers/vls/main.ts index 10e9cb2b..1966a316 100644 --- a/packages/vite-plugin-checker/src/checkers/vls/main.ts +++ b/packages/vite-plugin-checker/src/checkers/vls/main.ts @@ -1,10 +1,10 @@ import { parentPort } from 'worker_threads' import { Checker } from '../../Checker' +import { ACTION_TYPES } from '../../types' import { DiagnosticOptions, diagnostics } from './diagnostics' import type { CreateDiagnostic } from '../../types' - export const createDiagnostic: CreateDiagnostic<'vls'> = (pluginConfig) => { let overlay = true // Vite defaults to true @@ -21,16 +21,14 @@ export const createDiagnostic: CreateDiagnostic<'vls'> = (pluginConfig) => { const errorCallback: DiagnosticOptions['errorCallback'] = (diagnostics, overlayErr) => { if (!overlay) return if (!overlayErr) return - parentPort?.postMessage({ - type: 'ERROR', + type: ACTION_TYPES.overlayError, payload: { type: 'error', err: overlayErr, }, }) } - await diagnostics(workDir, 'WARN', { watch: true, errorCallback, verbose: false }) }, } diff --git a/packages/vite-plugin-checker/src/logger.ts b/packages/vite-plugin-checker/src/logger.ts index 6711ee39..42dfe353 100644 --- a/packages/vite-plugin-checker/src/logger.ts +++ b/packages/vite-plugin-checker/src/logger.ts @@ -2,14 +2,16 @@ import chalk from 'chalk' import fs from 'fs' import os from 'os' import strip from 'strip-ansi' -import { URI } from 'vscode-uri' import { ErrorPayload } from 'vite' +import { URI } from 'vscode-uri' +import { parentPort, isMainThread } from 'worker_threads' import { codeFrameColumns, SourceLocation } from '@babel/code-frame' +import { ACTION_TYPES } from './types' + import type { Range } from 'vscode-languageclient' import type { ESLint } from 'eslint' - import type { Diagnostic as LspDiagnostic, PublishDiagnosticsParams, @@ -20,8 +22,6 @@ import type { flattenDiagnosticMessageText as flattenDiagnosticMessageTextType, LineAndCharacter, } from 'typescript' -import type { BuildInCheckerNames } from './types' - export interface NormalizedDiagnostic { /** error message */ message?: string @@ -314,3 +314,14 @@ export function ensureCall(callback: CallableFunction) { callback() }) } + +export function consoleLog(value: string) { + if (isMainThread) { + console.log(value) + } else { + parentPort?.postMessage({ + type: ACTION_TYPES.console, + payload: value, + }) + } +} diff --git a/packages/vite-plugin-checker/src/main.ts b/packages/vite-plugin-checker/src/main.ts index 3ce0e21a..2bf4c256 100644 --- a/packages/vite-plugin-checker/src/main.ts +++ b/packages/vite-plugin-checker/src/main.ts @@ -3,8 +3,9 @@ import pick from 'lodash.pick' import npmRunPath from 'npm-run-path' import os from 'os' import { ConfigEnv, Plugin } from 'vite' +import { Checker } from './Checker' -import type { +import { OverlayErrorAction, BuildInCheckerNames, ServeAndBuildChecker, @@ -12,11 +13,13 @@ import type { SharedConfig, BuildCheckBinStr, PluginConfig, + ACTION_TYPES, } from './types' export * from './types' export * from './codeFrame' export * from './worker' +export { Checker } from './Checker' const sharedConfigKeys: (keyof SharedConfig)[] = ['enableBuild', 'overlay'] const buildInCheckerKeys: BuildInCheckerNames[] = ['typescript', 'vueTsc', 'vls', 'eslint'] @@ -59,6 +62,14 @@ export default function Plugin(userConfig: UserPluginConfig): Plugin { }) }) }, + buildEnd() { + if (viteMode === 'serve') { + checkers.forEach((checker) => { + const { worker } = checker.serve + worker.terminate() + }) + } + }, buildStart: () => { // for build mode // run a bin command in a separated process @@ -89,7 +100,11 @@ export default function Plugin(userConfig: UserPluginConfig): Plugin { const { worker, configureServer: workerConfigureServer } = checker.serve workerConfigureServer({ root: server.config.root }) worker.on('message', (action: OverlayErrorAction) => { - server.ws.send(action.payload) + if (action.type === ACTION_TYPES.overlayError) { + server.ws.send(action.payload) + } else if (action.type === ACTION_TYPES.console) { + Checker.log(action) + } }) }) diff --git a/packages/vite-plugin-checker/src/types.ts b/packages/vite-plugin-checker/src/types.ts index b9278767..ab88b86d 100644 --- a/packages/vite-plugin-checker/src/types.ts +++ b/packages/vite-plugin-checker/src/types.ts @@ -69,6 +69,10 @@ export interface SharedConfig { * Same as [Vite config](https://vitejs.dev/config/#root) */ overlay: boolean + /** + * logger + */ + // logger: ((...args: any[]) => void)[] } export interface BuildInCheckers { @@ -91,6 +95,7 @@ export enum ACTION_TYPES { config = 'config', configureServer = 'configureServer', overlayError = 'overlayError', + console = 'console', unref = 'unref', } diff --git a/playground/react-ts/__tests__/__snapshots__/overlay-true.spec.ts.snap b/playground/react-ts/__tests__/__snapshots__/overlay-true.spec.ts.snap new file mode 100644 index 00000000..e3e6a8ab --- /dev/null +++ b/playground/react-ts/__tests__/__snapshots__/overlay-true.spec.ts.snap @@ -0,0 +1,25 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`overlay overlay prompts and changes 1`] = `"Argument of type 'number' is not assignable to parameter of type 'string | (() => string)'."`; + +exports[`overlay overlay prompts and changes 2`] = `"/temp/react-ts/src/App.tsx:6:46"`; + +exports[`overlay overlay prompts and changes 3`] = ` +"4 | + 5 | function App() { + > 6 | const [count, setCount] = useState(1) + | ^ + 7 | return ( + 8 |
+ 9 |
" +`; + +exports[`overlay overlay prompts and changes 4`] = ` +"4 | + 5 | function App() { + > 6 | const [count, setCount] = useState(2) + | ^ + 7 | return ( + 8 |
+ 9 |
" +`; diff --git a/playground/react-ts/__tests__/__snapshots__/test.spec.ts.snap b/playground/react-ts/__tests__/__snapshots__/test.spec.ts.snap index 7e8af73c..93ff8ebf 100644 --- a/playground/react-ts/__tests__/__snapshots__/test.spec.ts.snap +++ b/playground/react-ts/__tests__/__snapshots__/test.spec.ts.snap @@ -1,115 +1,37 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`typescript serve get initial error and subsequent error 1`] = `"Argument of type 'number' is not assignable to parameter of type 'string | (() => string)'."`; +exports[`typescript serve get initial error and subsequent error 1`] = `"{\\"frame\\":\\" 4 |/n 5 | function App() {/n > 6 | const [count, setCount] = useState(1)/n | ^/n 7 | return (/n 8 |
/n 9 |
\\",\\"id\\":\\"/temp/react-ts/src/App.tsx\\",\\"loc\\":{\\"column\\":46,\\"file\\":\\"/temp/react-ts/src/App.tsx\\",\\"line\\":6},\\"message\\":\\"Argument of type 'number' is not assignable to parameter of type 'string | (() => string)'.\\",\\"plugin\\":\\"vite-plugin-checker(TypeScript)\\",\\"stack\\":\\"\\"}"`; -exports[`typescript serve get initial error and subsequent error 2`] = `"/temp/react-ts/src/App.tsx:7:46"`; - -exports[`typescript serve get initial error and subsequent error 3`] = ` -"5 | function App() { - 6 | // Try change to and the overlay will gone. - > 7 | const [count, setCount] = useState(1) - | ^ - 8 | return ( - 9 |
- 10 |
" -`; - -exports[`typescript serve get initial error and subsequent error 4`] = ` -"Pre-bundling dependencies: - react - react-dom -(this will be run only when your dependencies or config have changed) - - vite v2.3.8 dev server running at: - - > Local: http://localhost:3000/ - > Network: use \`--host\` to expose - - ready in XXXms - - - ERROR(TypeScript) Argument of type 'number' is not assignable to parameter of type 'string | (() => string)'. - FILE /temp/react-ts/src/App.tsx:7:46 - - 5 | function App() { - 6 | // Try change to and the overlay will gone. - > 7 | const [count, setCount] = useState(1) - | ^ - 8 | return ( - 9 |
- 10 |
- -Found 1 error. Watching for file changes. +exports[`typescript serve get initial error and subsequent error 2`] = ` " -`; - -exports[`typescript serve get initial error and subsequent error 5`] = ` -"5 | function App() { - 6 | // Try change to and the overlay will gone. - > 7 | const [count, setCount] = useState(2) - | ^ - 8 | return ( - 9 |
- 10 |
" -`; - -exports[`typescript serve get initial error and subsequent error 6`] = ` -"HH:MM:SS AM [vite] hmr update /src/App.tsx - ERROR(TypeScript) Argument of type 'number' is not assignable to parameter of type 'string | (() => string)'. - FILE /temp/react-ts/src/App.tsx:7:46 + FILE /temp/react-ts/src/App.tsx:6:46 - 5 | function App() { - 6 | // Try change to and the overlay will gone. - > 7 | const [count, setCount] = useState(2) - | ^ - 8 | return ( - 9 |
- 10 |
+ 4 | + 5 | function App() { + > 6 | const [count, setCount] = useState(1) + | ^ + 7 | return ( + 8 |
+ 9 |
-Found 1 error. Watching for file changes. -" +Found 1 error. Watching for file changes." `; -exports[`typescript serve overlay: false 1`] = ` -" - vite v2.3.8 dev server running at: - - > Local: http://localhost:3000/ - > Network: use \`--host\` to expose - - ready in XXXms +exports[`typescript serve get initial error and subsequent error 3`] = `"{\\"frame\\":\\" 4 |/n 5 | function App() {/n > 6 | const [count, setCount] = useState(2)/n | ^/n 7 | return (/n 8 |
/n 9 |
\\",\\"id\\":\\"/temp/react-ts/src/App.tsx\\",\\"loc\\":{\\"column\\":46,\\"file\\":\\"/temp/react-ts/src/App.tsx\\",\\"line\\":6},\\"message\\":\\"Argument of type 'number' is not assignable to parameter of type 'string | (() => string)'.\\",\\"plugin\\":\\"vite-plugin-checker(TypeScript)\\",\\"stack\\":\\"\\"}"`; - - ERROR(TypeScript) Argument of type 'number' is not assignable to parameter of type 'string | (() => string)'. - FILE /temp/react-ts/src/App.tsx:7:46 - - 5 | function App() { - 6 | // Try change to and the overlay will gone. - > 7 | const [count, setCount] = useState(1) - | ^ - 8 | return ( - 9 |
- 10 |
- -Found 1 error. Watching for file changes. +exports[`typescript serve get initial error and subsequent error 4`] = ` " -`; - -exports[`typescript serve overlay: false 2`] = ` -"HH:MM:SS AM [vite] hmr update /src/App.tsx - ERROR(TypeScript) Argument of type 'number' is not assignable to parameter of type 'string | (() => string)'. - FILE /temp/react-ts/src/App.tsx:7:46 + FILE /temp/react-ts/src/App.tsx:6:46 - 5 | function App() { - 6 | // Try change to and the overlay will gone. - > 7 | const [count, setCount] = useState(2) - | ^ - 8 | return ( - 9 |
- 10 |
+ 4 | + 5 | function App() { + > 6 | const [count, setCount] = useState(2) + | ^ + 7 | return ( + 8 |
+ 9 |
-Found 1 error. Watching for file changes. -" +Found 1 error. Watching for file changes." `; diff --git a/playground/react-ts/__tests__/overlay-false.spec.ts b/playground/react-ts/__tests__/overlay-false.spec.ts new file mode 100644 index 00000000..cff0e240 --- /dev/null +++ b/playground/react-ts/__tests__/overlay-false.spec.ts @@ -0,0 +1,47 @@ +import { + getHmrOverlayText, + killServer, + preTest, + viteServe, +} from 'vite-plugin-checker/__tests__/e2e/Sandbox/Sandbox' +import { + editFile, + sleep, + testDir, + WORKER_CLEAN_TIMEOUT, +} from 'vite-plugin-checker/__tests__/e2e/testUtils' + +import { copyCode } from '../../../scripts/jestSetupFilesAfterEnv' +import { serializers } from '../../../scripts/serializers' + +expect.addSnapshotSerializer(serializers) + +beforeAll(async () => { + await preTest() +}) + +afterAll(async () => { + await sleep(WORKER_CLEAN_TIMEOUT) +}) + +describe('overlay', () => { + beforeEach(async () => { + await copyCode() + }) + + afterEach(async () => { + await killServer() + }) + + it('overlay: false', async () => { + editFile('vite.config.ts', (code) => + code.replace('typescript: true,', 'typescript: true, overlay: false,') + ) + + await viteServe({ cwd: testDir, launchPage: true }) + await sleep(6000) + await expect(getHmrOverlayText()).rejects.toThrow( + ' shadow dom is expected to be found, but got null' + ) + }) +}) diff --git a/playground/react-ts/__tests__/overlay-true.spec.ts b/playground/react-ts/__tests__/overlay-true.spec.ts new file mode 100644 index 00000000..19e26b7d --- /dev/null +++ b/playground/react-ts/__tests__/overlay-true.spec.ts @@ -0,0 +1,54 @@ +import { + getHmrOverlay, + getHmrOverlayText, + killServer, + pollingUntil, + preTest, + sleepForEdit, + viteServe, +} from 'vite-plugin-checker/__tests__/e2e/Sandbox/Sandbox' +import { + editFile, + sleep, + testDir, + WORKER_CLEAN_TIMEOUT, +} from 'vite-plugin-checker/__tests__/e2e/testUtils' + +import { copyCode } from '../../../scripts/jestSetupFilesAfterEnv' +import { serializers } from '../../../scripts/serializers' + +expect.addSnapshotSerializer(serializers) + +beforeAll(async () => { + await preTest() +}) + +afterAll(async () => { + await sleep(WORKER_CLEAN_TIMEOUT) +}) + +describe('overlay', () => { + beforeEach(async () => { + await copyCode() + }) + + afterEach(async () => { + await killServer() + }) + + it('overlay prompts and changes', async () => { + await viteServe({ cwd: testDir, launchPage: true }) + await pollingUntil(getHmrOverlay, (dom) => !!dom) + const [message1, file1, frame1] = await getHmrOverlayText() + expect(message1).toMatchSnapshot() + expect(file1).toMatchSnapshot() + expect(frame1).toMatchSnapshot() + + console.log('-- edit file --') + editFile('src/App.tsx', (code) => code.replace('useState(1)', 'useState(2)')) + await sleepForEdit() + await pollingUntil(getHmrOverlay, (dom) => !!dom) + const [, , frame2] = await getHmrOverlayText() + expect(frame2).toMatchSnapshot() + }) +}) diff --git a/playground/react-ts/__tests__/test.spec.ts b/playground/react-ts/__tests__/test.spec.ts index 49c191d2..241c2099 100644 --- a/playground/react-ts/__tests__/test.spec.ts +++ b/playground/react-ts/__tests__/test.spec.ts @@ -1,25 +1,25 @@ +import stringify from 'fast-json-stable-stringify' import { - getHmrOverlay, - getHmrOverlayText, killServer, - pollingUntil, - waitForHmrOverlay, preTest, - resetTerminalLog, + resetReceivedLog, + sleepForEdit, + sleepForServerReady, stripedLog, viteBuild, viteServe, -} from '../../../packages/vite-plugin-checker/__tests__/e2e/Sandbox/Sandbox' +} from 'vite-plugin-checker/__tests__/e2e/Sandbox/Sandbox' import { editFile, sleep, testDir, WORKER_CLEAN_TIMEOUT, -} from '../../../packages/vite-plugin-checker/__tests__/e2e/testUtils' +} from 'vite-plugin-checker/__tests__/e2e/testUtils' + import { copyCode } from '../../../scripts/jestSetupFilesAfterEnv' -import { logTimeSerializers } from '../../../scripts/logTimeSerializers' +import { serializers } from '../../../scripts/serializers' -expect.addSnapshotSerializer(logTimeSerializers) +expect.addSnapshotSerializer(serializers) beforeAll(async () => { await preTest() @@ -30,61 +30,33 @@ afterAll(async () => { }) describe('typescript', () => { - describe('serve', () => { - beforeEach(async () => { - await copyCode() - }) + beforeEach(async () => { + await copyCode() + }) + describe('serve', () => { afterEach(async () => { await killServer() }) it('get initial error and subsequent error', async () => { - await viteServe({ cwd: testDir }) - await pollingUntil(getHmrOverlay, (dom) => !!dom) - const [message1, file1, frame1] = await getHmrOverlayText() - expect(message1).toMatchSnapshot() - expect(file1).toMatchSnapshot() - expect(frame1).toMatchSnapshot() + let err: any + // @ts-expect-error + await viteServe({ cwd: testDir, wsSend: (_payload) => (err = _payload.err) }) + await sleepForServerReady() + expect(stringify(err)).toMatchSnapshot() expect(stripedLog).toMatchSnapshot() console.log('-- edit file --') - resetTerminalLog() + resetReceivedLog() editFile('src/App.tsx', (code) => code.replace('useState(1)', 'useState(2)')) - await sleep(process.env.CI ? 5000 : 2000) - await pollingUntil(getHmrOverlay, (dom) => !!dom) - const [, , frame2] = await getHmrOverlayText() - expect(frame2).toMatchSnapshot() - expect(stripedLog).toMatchSnapshot() - }) - - it('overlay: false', async () => { - resetTerminalLog() - editFile('vite.config.ts', (code) => - code.replace('typescript: true,', 'typescript: true, overlay: false,') - ) - - await viteServe({ cwd: testDir }) - await sleep(6000) - await expect(getHmrOverlayText()).rejects.toThrow( - ' shadow dom is expected to be found, but got null' - ) - - expect(stripedLog).toMatchSnapshot() - - console.log('-- edit file --') - resetTerminalLog() - editFile('src/App.tsx', (code) => code.replace('useState(1)', 'useState(2)')) - await sleep(process.env.CI ? 5000 : 2000) + await sleepForEdit() + expect(stringify(err)).toMatchSnapshot() expect(stripedLog).toMatchSnapshot() }) }) describe('build', () => { - beforeEach(async () => { - await copyCode() - }) - it('enableBuild: true', async () => { await viteBuild({ expectedErrorMsg: 'error TS2345', cwd: testDir }) }) diff --git a/playground/react-ts/package.json b/playground/react-ts/package.json index 0179fa64..f795e54f 100644 --- a/playground/react-ts/package.json +++ b/playground/react-ts/package.json @@ -16,7 +16,7 @@ "@types/react-dom": "^17.0.0", "@vitejs/plugin-react-refresh": "^1.3.1", "typescript": "^4.1.2", - "vite": "^2.3.8", + "vite": "^2.7.9", "vite-plugin-checker": "workspace:*" } } diff --git a/playground/react-ts/src/App.tsx b/playground/react-ts/src/App.tsx index 4ff3520c..c03206d6 100644 --- a/playground/react-ts/src/App.tsx +++ b/playground/react-ts/src/App.tsx @@ -3,7 +3,6 @@ import logo from './logo.svg' import './App.css' function App() { - // Try change to and the overlay will gone. const [count, setCount] = useState(1) return (
diff --git a/playground/vanilla-ts/__tests__/__snapshots__/test.spec.ts.snap b/playground/vanilla-ts/__tests__/__snapshots__/test.spec.ts.snap index 8350bfde..7cc7755c 100644 --- a/playground/vanilla-ts/__tests__/__snapshots__/test.spec.ts.snap +++ b/playground/vanilla-ts/__tests__/__snapshots__/test.spec.ts.snap @@ -1,29 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`eslint serve get initial error and subsequent error 1`] = `"Unexpected var, use let or const instead."`; +exports[`eslint serve get initial error and subsequent error 1`] = `"{\\"frame\\":\\" 1 | import { text } from './text'/n 2 |/n > 3 | var hello = 'Hello'/n | ^^^^^^^^^^^^^^^^^^^/n 4 |/n 5 | const rootDom = document.querySelector('#root')!/n 6 | rootDom.innerHTML = hello + text\\",\\"id\\":\\"/temp/vanilla-ts/src/main.ts\\",\\"loc\\":{\\"column\\":1,\\"file\\":\\"/temp/vanilla-ts/src/main.ts\\",\\"line\\":3},\\"message\\":\\"Unexpected var, use let or const instead.\\",\\"plugin\\":\\"vite-plugin-checker(ESLint)\\",\\"stack\\":\\"\\"}"`; -exports[`eslint serve get initial error and subsequent error 2`] = `"/temp/vanilla-ts/src/main.ts:3:1"`; - -exports[`eslint serve get initial error and subsequent error 3`] = ` -"1 | import { text } from './text' - 2 | - > 3 | var hello = 'Hello' - | ^^^^^^^^^^^^^^^^^^^ - 4 | - 5 | const rootDom = document.querySelector('#root')! - 6 | rootDom.innerHTML = hello + text" -`; - -exports[`eslint serve get initial error and subsequent error 4`] = ` -" - vite v2.3.8 dev server running at: - - > Local: http://localhost:3000/ - > Network: use \`--host\` to expose - - ready in XXXms - - ERROR(ESLint) Unexpected var, use let or const instead. +exports[`eslint serve get initial error and subsequent error 2`] = ` +" ERROR(ESLint) Unexpected var, use let or const instead. FILE /temp/vanilla-ts/src/main.ts:3:1 1 | import { text } from './text' @@ -33,13 +13,13 @@ exports[`eslint serve get initial error and subsequent error 4`] = ` 4 | 5 | const rootDom = document.querySelector('#root')! 6 | rootDom.innerHTML = hello + text - " `; -exports[`eslint serve get initial error and subsequent error 5`] = ` -"HH:MM:SS AM [vite] page reload src/main.ts - ERROR(ESLint) Unexpected var, use let or const instead. +exports[`eslint serve get initial error and subsequent error 3`] = `"{\\"frame\\":\\" 1 | import { text } from './text'/n 2 |/n > 3 | var hello = 'Hello~'/n | ^^^^^^^^^^^^^^^^^^^^/n 4 |/n 5 | const rootDom = document.querySelector('#root')!/n 6 | rootDom.innerHTML = hello + text\\",\\"id\\":\\"/temp/vanilla-ts/src/main.ts\\",\\"loc\\":{\\"column\\":1,\\"file\\":\\"/temp/vanilla-ts/src/main.ts\\",\\"line\\":3},\\"message\\":\\"Unexpected var, use let or const instead.\\",\\"plugin\\":\\"vite-plugin-checker(ESLint)\\",\\"stack\\":\\"\\"}"`; + +exports[`eslint serve get initial error and subsequent error 4`] = ` +" ERROR(ESLint) Unexpected var, use let or const instead. FILE /temp/vanilla-ts/src/main.ts:3:1 1 | import { text } from './text' @@ -49,13 +29,13 @@ exports[`eslint serve get initial error and subsequent error 5`] = ` 4 | 5 | const rootDom = document.querySelector('#root')! 6 | rootDom.innerHTML = hello + text - " `; +exports[`eslint serve get initial error and subsequent error 5`] = `"{\\"frame\\":\\" 1 | import { text } from './text'/n 2 |/n > 3 | var hello = 'Hello~'/n | ^^^^^^^^^^^^^^^^^^^^/n 4 |/n 5 | const rootDom = document.querySelector('#root')!/n 6 | rootDom.innerHTML = hello + text\\",\\"id\\":\\"/temp/vanilla-ts/src/main.ts\\",\\"loc\\":{\\"column\\":1,\\"file\\":\\"/temp/vanilla-ts/src/main.ts\\",\\"line\\":3},\\"message\\":\\"Unexpected var, use let or const instead.\\",\\"plugin\\":\\"vite-plugin-checker(ESLint)\\",\\"stack\\":\\"\\"}"`; + exports[`eslint serve get initial error and subsequent error 6`] = ` -"HH:MM:SS AM [vite] page reload src/text.ts - ERROR(ESLint) Unexpected var, use let or const instead. +" ERROR(ESLint) Unexpected var, use let or const instead. FILE /temp/vanilla-ts/src/main.ts:3:1 1 | import { text } from './text' @@ -65,34 +45,5 @@ exports[`eslint serve get initial error and subsequent error 6`] = ` 4 | 5 | const rootDom = document.querySelector('#root')! 6 | rootDom.innerHTML = hello + text - -" -`; - -exports[`eslint serve overlay: false 1`] = ` -" - vite v2.3.8 dev server running at: - - > Local: http://localhost:3000/ - > Network: use \`--host\` to expose - - ready in XXXms - - ERROR(ESLint) Unexpected var, use let or const instead. - FILE /temp/vanilla-ts/src/main.ts:3:1 - - 1 | import { text } from './text' - 2 | - > 3 | var hello = 'Hello' - | ^^^^^^^^^^^^^^^^^^^ - 4 | - 5 | const rootDom = document.querySelector('#root')! - 6 | rootDom.innerHTML = hello + text - -" -`; - -exports[`eslint serve overlay: false 2`] = ` -"HH:MM:SS AM [vite] page reload src/main.ts " `; diff --git a/playground/vanilla-ts/__tests__/test.spec.ts b/playground/vanilla-ts/__tests__/test.spec.ts index 447b91bc..0d2b98bd 100644 --- a/playground/vanilla-ts/__tests__/test.spec.ts +++ b/playground/vanilla-ts/__tests__/test.spec.ts @@ -1,10 +1,11 @@ +import stringify from 'fast-json-stable-stringify' + import { - getHmrOverlay, - getHmrOverlayText, killServer, - pollingUntil, + sleepForEdit, + sleepForServerReady, preTest, - resetTerminalLog, + resetReceivedLog, stripedLog, viteBuild, viteServe, @@ -16,74 +17,53 @@ import { WORKER_CLEAN_TIMEOUT, } from '../../../packages/vite-plugin-checker/__tests__/e2e/testUtils' import { copyCode } from '../../../scripts/jestSetupFilesAfterEnv' -import { logTimeSerializers } from '../../../scripts/logTimeSerializers' +import { serializers } from '../../../scripts/serializers' beforeAll(async () => { await preTest() }) -expect.addSnapshotSerializer(logTimeSerializers) +expect.addSnapshotSerializer(serializers) afterAll(async () => { await sleep(WORKER_CLEAN_TIMEOUT) }) describe('eslint', () => { - describe('serve', () => { - beforeEach(async () => { - await copyCode() - }) + beforeEach(async () => { + await copyCode() + }) + describe('serve', () => { afterEach(async () => { await killServer() }) it('get initial error and subsequent error', async () => { - await viteServe({ cwd: testDir }) - await pollingUntil(getHmrOverlay, (dom) => !!dom) - const [message1, file1, frame1] = await getHmrOverlayText() - expect(message1).toMatchSnapshot() - expect(file1).toMatchSnapshot() - expect(frame1).toMatchSnapshot() + let err: any + // @ts-expect-error + await viteServe({ cwd: testDir, wsSend: (_payload) => (err = _payload.err) }) + await sleepForServerReady() + expect(stringify(err)).toMatchSnapshot() expect(stripedLog).toMatchSnapshot() console.log('-- edit error file --') - resetTerminalLog() + resetReceivedLog() editFile('src/main.ts', (code) => code.replace(`'Hello'`, `'Hello~'`)) - await sleep(process.env.CI ? 5000 : 2000) + await sleepForEdit() + expect(stringify(err)).toMatchSnapshot() expect(stripedLog).toMatchSnapshot() console.log('-- edit non error file --') - resetTerminalLog() + resetReceivedLog() editFile('src/text.ts', (code) => code.replace(`Vanilla`, `vanilla`)) - await sleep(process.env.CI ? 5000 : 2000) - expect(stripedLog).toMatchSnapshot() - }) - - it('overlay: false', async () => { - resetTerminalLog() - editFile('vite.config.ts', (code) => code.replace('eslint: {', 'overlay: false, eslint: {')) - - await viteServe({ cwd: testDir }) - await sleep(6000) - await expect(getHmrOverlayText()).rejects.toThrow( - ' shadow dom is expected to be found, but got null' - ) - - expect(stripedLog).toMatchSnapshot() - - resetTerminalLog() - editFile('src/main.ts', (code) => code.replace('var hello', 'const hello')) - await sleep(process.env.CI ? 5000 : 2000) + await sleepForEdit() + expect(stringify(err)).toMatchSnapshot() expect(stripedLog).toMatchSnapshot() }) }) describe('build', () => { - beforeEach(async () => { - await copyCode() - }) - const expectedMsg = 'Unexpected var, use let or const instead no-var' it('enableBuild: true', async () => { diff --git a/playground/vanilla-ts/package.json b/playground/vanilla-ts/package.json index 0dbfff00..e6d97cb3 100644 --- a/playground/vanilla-ts/package.json +++ b/playground/vanilla-ts/package.json @@ -17,7 +17,7 @@ "@types/react-dom": "^17.0.0", "@vitejs/plugin-react-refresh": "^1.3.1", "typescript": "^4.1.2", - "vite": "^2.3.8", + "vite": "^2.7.9", "vite-plugin-checker": "workspace:*" } } diff --git a/playground/vue2-vls/__tests__/__snapshots__/test.spec.ts.snap b/playground/vue2-vls/__tests__/__snapshots__/test.spec.ts.snap index 92c0fc69..da6cbf2a 100644 --- a/playground/vue2-vls/__tests__/__snapshots__/test.spec.ts.snap +++ b/playground/vue2-vls/__tests__/__snapshots__/test.spec.ts.snap @@ -1,91 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`vue2-vls serve get initial error and subsequent error 1`] = `"Property 'msg1' does not exist on type 'CombinedVueInstance<{ msg: string; } & Vue, object, object, object, Record>'. Did you mean 'msg'?"`; +exports[`vue2-vls serve get initial error and subsequent error 1`] = `"{\\"frame\\":\\" 1 |