mirror of
https://github.com/cypress-io/cypress.git
synced 2026-02-19 21:51:16 -06:00
* use new specPattern API * remove projectApi.findSpecs * do not require integration folder * support --spec * support --spec * remove old code * remove old code * nuke old code * no appvetor * update * correct url for ct * work on migrating launchpad * update ct spec url * types * types * dead code * remove old endpiont * revert back circle.yml * update missing config * delete spec util * update config * update config * config again * update spec pattern * updated vue config * update spec pattern for ui components * update config for vite dev server * update snapshots * update config * update design system config * fix spec pattern in reporter * update default * update deprecated spec snapshots * update system tests * update run mode output * revert changes * lint * remove scaffold tests * update angular * fix CT * update circle yml * fix system tests for ct * fix tests * work on server unit tests * patch package * patch package again * update test * try not to rely on config async loading too much * normalize specPattern to array * update snapshot * use base name * deal with react-scripts later * update snapshot * hacky way to update snapshots * new hack to update snapshots * trying again * hacky fix * ci: snapshots * ci: snapshots * snapshots * mas updates * update spec API * fix test * fix test * update * update test * fix test * update plugin * update spec * webpack optinos * Update launchpad tests * fix screenshot paths * updated snapshot * change pattern * guard * fix smoke test * patch code coverage * update percy config * fix specs * try updating example project * update snapshots * remove old test * remove snapshot hack * add back appveyor * remove old code * update snapshot * Fix tests * wip * revert snapshot * reverted all snaps * remove only * remove commnet * remove old code * reverted file * lint * revert video compression spec * update snapshot * update spec path logic * update snap * updated snap * snaps * snaps * fix spec * rename ignoreTestFiles to ignoreSpecPattern * update screenshot dir for runner-ct * update deprecations * update * upate * fix test * update snaps * update snap * updating snap * added missing snaps * updated cypress run mode integration spec * electron snapshot * ensure newly scaffold specs are cached * fix launchpad spec * types * update test * transpile based on spec pattern * add back example * remove unnecessary async and nodeVersion * removed old test * update spec pattern and add defensive check around platform * remove unused feature flag * added tests * fix react example * update test * update config * fix spec finding in run mode * fix tests * fixing specs * fix switching between specs * remove invalid test * increase timeout Co-authored-by: estrada9166 <estrada9166@hotmail.com>
145 lines
4.5 KiB
TypeScript
145 lines
4.5 KiB
TypeScript
import Debug from 'debug'
|
|
import preprocessor from './plugins/preprocessor'
|
|
import { SocketBase } from './socket-base'
|
|
import { fs } from './util/fs'
|
|
import type { DestroyableHttpServer } from './util/server_destroy'
|
|
import * as studio from './studio'
|
|
import type { DataContext } from '@packages/data-context'
|
|
import type { FoundSpec } from '@packages/types'
|
|
|
|
const debug = Debug('cypress:server:socket-e2e')
|
|
|
|
const isSpecialSpec = (name) => {
|
|
return name.endsWith('__all')
|
|
}
|
|
|
|
export class SocketE2E extends SocketBase {
|
|
private testFilePath: string | null
|
|
|
|
constructor (config: Record<string, any>, ctx: DataContext) {
|
|
super(config, ctx)
|
|
|
|
this.testFilePath = null
|
|
|
|
this.onTestFileChange = this.onTestFileChange.bind(this)
|
|
this.onStudioTestFileChange = this.onStudioTestFileChange.bind(this)
|
|
this.removeOnStudioTestFileChange = this.removeOnStudioTestFileChange.bind(this)
|
|
|
|
if (config.watchForFileChanges) {
|
|
preprocessor.emitter.on('file:updated', this.onTestFileChange)
|
|
}
|
|
}
|
|
|
|
onStudioTestFileChange (filePath) {
|
|
// wait for the studio test file to be written to disk, then reload the test
|
|
// and remove the listener (since this handler is only invoked when watchForFileChanges is false)
|
|
return this.onTestFileChange(filePath).then(() => {
|
|
this.removeOnStudioTestFileChange()
|
|
})
|
|
}
|
|
|
|
removeOnStudioTestFileChange () {
|
|
return preprocessor.emitter.off('file:updated', this.onStudioTestFileChange)
|
|
}
|
|
|
|
onTestFileChange = (filePath) => {
|
|
debug('test file changed %o', filePath)
|
|
|
|
return fs.statAsync(filePath)
|
|
.then(() => {
|
|
return this.io.emit('watched:file:changed')
|
|
}).catch(() => {
|
|
return debug('could not find test file that changed %o', filePath)
|
|
})
|
|
}
|
|
|
|
watchTestFileByPath (config, specConfig: FoundSpec) {
|
|
debug('watching spec with config %o', specConfig)
|
|
|
|
// previously we have assumed that we pass integration spec path with "integration/" prefix
|
|
// now we pass spec config object that tells what kind of spec it is, has relative path already
|
|
// so the only special handling remains for special paths like "integration/__all"
|
|
|
|
// bail if this is special path like "__all"
|
|
// maybe the client should not ask to watch non-spec files?
|
|
if (isSpecialSpec(specConfig.relative)) {
|
|
return
|
|
}
|
|
|
|
if (specConfig.relative.startsWith('/')) {
|
|
specConfig.relative = specConfig.relative.slice(1)
|
|
}
|
|
|
|
// bail if we're already watching this exact file
|
|
if (specConfig.relative === this.testFilePath) {
|
|
return
|
|
}
|
|
|
|
// remove the existing file by its path
|
|
if (this.testFilePath) {
|
|
preprocessor.removeFile(this.testFilePath, config)
|
|
}
|
|
|
|
// store this location
|
|
this.testFilePath = specConfig.relative
|
|
debug('will watch test file path %o', specConfig.relative)
|
|
|
|
return preprocessor.getFile(specConfig.relative, config)
|
|
// ignore errors b/c we're just setting up the watching. errors
|
|
// are handled by the spec controller
|
|
.catch(() => {})
|
|
}
|
|
|
|
startListening (server: DestroyableHttpServer, automation, config, options) {
|
|
return super.startListening(server, automation, config, options, {
|
|
onSocketConnection: (socket) => {
|
|
socket.on('watch:test:file', (specInfo: FoundSpec, cb = function () { }) => {
|
|
debug('watch:test:file %o', specInfo)
|
|
|
|
this.watchTestFileByPath(config, specInfo)
|
|
|
|
// callback is only for testing purposes
|
|
return cb()
|
|
})
|
|
|
|
socket.on('studio:init', (cb) => {
|
|
studio.getStudioModalShown()
|
|
.then(cb)
|
|
})
|
|
|
|
socket.on('studio:save', (saveInfo, cb) => {
|
|
// even if the user has turned off file watching
|
|
// we want to force a reload on save
|
|
if (!config.watchForFileChanges) {
|
|
preprocessor.emitter.on('file:updated', this.onStudioTestFileChange)
|
|
}
|
|
|
|
studio.save(saveInfo)
|
|
.then((err) => {
|
|
cb(err)
|
|
|
|
// onStudioTestFileChange will remove itself after being called
|
|
// but if there's an error, it never gets called so we manually remove it
|
|
if (err && !config.watchForFileChanges) {
|
|
this.removeOnStudioTestFileChange()
|
|
}
|
|
})
|
|
.catch(() => {})
|
|
})
|
|
|
|
socket.on('studio:get:commands:text', (commands, cb) => {
|
|
const commandsText = studio.getCommandsText(commands)
|
|
|
|
cb(commandsText)
|
|
})
|
|
},
|
|
})
|
|
}
|
|
|
|
close () {
|
|
preprocessor.emitter.removeListener('file:updated', this.onTestFileChange)
|
|
|
|
super.close()
|
|
}
|
|
}
|