Skip to content

Commit

Permalink
fix(vite-dev-server): only re-run tests when specs deps are updated (#…
Browse files Browse the repository at this point in the history
…16215)

Co-authored-by: Lachlan Miller <[email protected]>
  • Loading branch information
2 people authored and elevatebart committed Apr 29, 2021
1 parent 56a160b commit 4d23476
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/// <reference types="cypress" />

import { a } from './a'

it('handles circular dependencies', () => {
expect(a()).to.eq('This is the message')
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { b } from './b'

export function a () {
const msg = b()

return msg
}

export const message = 'This is the message'
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { c } from './c'

export function b () {
return c()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { message } from './a'

export function c () {
return message
}
53 changes: 49 additions & 4 deletions npm/vite-dev-server/src/makeCypressPlugin.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { resolve, posix, sep } from 'path'
import { readFile } from 'fs'
import { promisify } from 'util'
import { Plugin, ViteDevServer } from 'vite'
import Debug from 'debug'
import { ModuleNode, Plugin, ViteDevServer } from 'vite'

const debug = Debug('cypress:vite-dev-server:plugin')

const read = promisify(readFile)

Expand All @@ -16,13 +19,18 @@ function convertPathToPosix (path: string): string {

const INIT_FILEPATH = resolve(__dirname, '../client/initCypressTests.js')

const HMR_DEPENDENCY_LOOKUP_MAX_ITERATION = 50

export const makeCypressPlugin = (
projectRoot: string,
supportFilePath: string,
devServerEvents: EventEmitter,
specs: {absolute: string, relative: string}[],
): Plugin => {
let base = '/'

const specsPathsSet = new Set<string>(specs.map((spec) => spec.absolute))

const posixSupportFilePath = supportFilePath ? convertPathToPosix(resolve(projectRoot, supportFilePath)) : undefined

const normalizedSupportFilePath = posixSupportFilePath ? `${base}@fs/${posixSupportFilePath}` : undefined
Expand All @@ -44,6 +52,8 @@ export const makeCypressPlugin = (
base = config.base
},
transformIndexHtml () {
debug('transformIndexHtml with base', base)

return [
// load the script at the end of the body
// script has to be loaded when the vite client is connected
Expand All @@ -62,11 +72,46 @@ export const makeCypressPlugin = (

server.middlewares.use(`${base}index.html`, (req, res) => res.end(transformedIndexHtml))
},
handleHotUpdate: () => {
// restart tests when code is updated
devServerEvents.emit('dev-server:compile:success')
handleHotUpdate: ({ server, file }) => {
debug('handleHotUpdate - file', file)
// get the graph node for the file that just got updated
let moduleImporters = server.moduleGraph.fileToModulesMap.get(file)
let iterationNumber = 0

// until we reached a point where the current module is imported by no other
while (moduleImporters && moduleImporters.size) {
if (iterationNumber > HMR_DEPENDENCY_LOOKUP_MAX_ITERATION) {
debug(`max hmr iteration reached: ${HMR_DEPENDENCY_LOOKUP_MAX_ITERATION}; Rerun will not happen on this file change.`)

return []
}

// as soon as we find one of the specs, we trigger the re-run of tests
for (const mod of moduleImporters.values()) {
if (specsPathsSet.has(mod.file)) {
debug('handleHotUpdate - compile success')
devServerEvents.emit('dev-server:compile:success')

return []
}
}

// get all the modules that import the current one
moduleImporters = getImporters(moduleImporters)
iterationNumber += 1
}

return []
},
}
}

function getImporters (modules: Set<ModuleNode>): Set<ModuleNode> {
const allImporters = new Set<ModuleNode>()

modules.forEach((m) => {
m.importers.forEach((imp) => allImporters.add(imp))
})

return allImporters
}
2 changes: 1 addition & 1 deletion npm/vite-dev-server/src/startServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const resolveServerConfig = async ({ viteConfig, options }: StartDevServer): Pro

const finalConfig: InlineConfig = { ...viteConfig, ...requiredOptions }

finalConfig.plugins = [...(viteConfig.plugins || []), makeCypressPlugin(projectRoot, supportFile, options.devServerEvents)]
finalConfig.plugins = [...(viteConfig.plugins || []), makeCypressPlugin(projectRoot, supportFile, options.devServerEvents, options.specs)]

// This alias is necessary to avoid a "prefixIdentifiers" issue from slots mounting
// only cjs compiler-core accepts using prefixIdentifiers in slots which vue test utils use.
Expand Down

0 comments on commit 4d23476

Please sign in to comment.