mirror of
https://github.com/cypress-io/cypress.git
synced 2026-02-05 06:40:56 -06:00
Issue 118 - scaffolding in /tmp folder (#128)
* server: detect symlinked case in support file search for #118 * server fix problem found by unit test * add unit test for paths * correctly determining files in /tmp for a project * server: cleanup resolving symlinks
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
_ = require("lodash")
|
||||
path = require("path")
|
||||
Promise = require("bluebird")
|
||||
fs = require("fs")
|
||||
errors = require("./errors")
|
||||
scaffold = require("./scaffold")
|
||||
errors = require("./errors")
|
||||
@@ -8,6 +9,8 @@ origin = require("./util/origin")
|
||||
coerce = require("./util/coerce")
|
||||
settings = require("./util/settings")
|
||||
v = require("./util/validation")
|
||||
log = require("./log")
|
||||
pathHelpers = require("./util/path_helpers")
|
||||
|
||||
## cypress following by _
|
||||
cypressEnvRe = /^(cypress_)/i
|
||||
@@ -233,26 +236,42 @@ module.exports = {
|
||||
return obj
|
||||
|
||||
setSupportFileAndFolder: (obj) ->
|
||||
return obj if not obj.supportFile
|
||||
obj = _.clone(obj)
|
||||
|
||||
## if supportFile isn't false
|
||||
if sf = obj.supportFile
|
||||
try
|
||||
## resolve full path with extension to
|
||||
obj.supportFile = require.resolve(sf)
|
||||
catch err
|
||||
## supportFile doesn't exist on disk
|
||||
if sf isnt path.resolve(obj.projectRoot, defaults.supportFile)
|
||||
## throw because they have it explicitly set,
|
||||
## so it should be there
|
||||
errors.throw("SUPPORT_FILE_NOT_FOUND", path.resolve(obj.projectRoot, sf))
|
||||
else
|
||||
## set it to support/index.js, and it will be scaffolded
|
||||
## later in process
|
||||
obj.supportFile = path.join(sf, "index.js")
|
||||
## TODO move this logic to find support file into util/path_helpers
|
||||
|
||||
## set config.supportFolder to its directory
|
||||
obj.supportFolder = path.dirname(obj.supportFile)
|
||||
sf = obj.supportFile
|
||||
log "setting support file #{sf}"
|
||||
log "for project root #{obj.projectRoot}"
|
||||
try
|
||||
## resolve full path with extension
|
||||
obj.supportFile = require.resolve(sf)
|
||||
if pathHelpers.checkIfResolveChangedRootFolder(obj.supportFile, sf)
|
||||
log("require.resolve switched support folder from %s to %s",
|
||||
sf, obj.supportFile)
|
||||
# this means the path was probably symlinked, like
|
||||
# /tmp/foo -> /private/tmp/foo
|
||||
# which can confuse the rest of the code
|
||||
# switch it back to "normal" file
|
||||
obj.supportFile = path.join(sf, path.basename(obj.supportFile))
|
||||
if not fs.existsSync(obj.supportFile)
|
||||
errors.throw("SUPPORT_FILE_NOT_FOUND", obj.supportFile)
|
||||
log("switching to found file %s", obj.supportFile)
|
||||
catch err
|
||||
## supportFile doesn't exist on disk
|
||||
if sf isnt path.resolve(obj.projectRoot, defaults.supportFile)
|
||||
## throw because they have it explicitly set,
|
||||
## so it should be there
|
||||
errors.throw("SUPPORT_FILE_NOT_FOUND", path.resolve(obj.projectRoot, sf))
|
||||
else
|
||||
## set it to support/index.js, and it will be scaffolded
|
||||
## later in process
|
||||
obj.supportFile = path.join(sf, "index.js")
|
||||
|
||||
## set config.supportFolder to its directory
|
||||
obj.supportFolder = path.dirname(obj.supportFile)
|
||||
log "set support folder #{obj.supportFolder}"
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ user = require("../user")
|
||||
pathHelpers = require("../util/path_helpers")
|
||||
CacheBuster = require("../util/cache_buster")
|
||||
errors = require("../errors")
|
||||
log = require("debug")("cypress:server:files")
|
||||
|
||||
glob = Promise.promisify(glob)
|
||||
|
||||
@@ -102,6 +103,8 @@ module.exports = {
|
||||
|
||||
getTestFiles: (config) ->
|
||||
integrationFolderPath = config.integrationFolder
|
||||
log("looking for test files in the integration folder %s",
|
||||
integrationFolderPath)
|
||||
|
||||
## support files are not automatically
|
||||
## ignored because only _fixtures are hard
|
||||
@@ -126,7 +129,7 @@ module.exports = {
|
||||
## ignore fixtures + javascripts
|
||||
options = {
|
||||
sort: true
|
||||
realpath: true
|
||||
absolute: true
|
||||
cwd: integrationFolderPath
|
||||
ignore: [].concat(
|
||||
javascriptsPath,
|
||||
@@ -145,7 +148,15 @@ module.exports = {
|
||||
|
||||
relativePathFromProjectRoot = (file) ->
|
||||
path.relative(config.projectRoot, file)
|
||||
|
||||
|
||||
setNameParts = (file) ->
|
||||
log("found test file %s", file)
|
||||
{
|
||||
name: relativePathFromIntegrationFolder(file)
|
||||
path: relativePathFromProjectRoot(file)
|
||||
absolute: file
|
||||
}
|
||||
|
||||
ignorePatterns = [].concat(config.ignoreTestFiles)
|
||||
|
||||
## a function which returns true if the file does NOT match
|
||||
@@ -164,12 +175,7 @@ module.exports = {
|
||||
## filter out anything that matches our
|
||||
## ignored test files glob
|
||||
.filter(doesNotMatchAllIgnoredPatterns)
|
||||
.map (file) ->
|
||||
{
|
||||
name: relativePathFromIntegrationFolder(file)
|
||||
path: relativePathFromProjectRoot(file)
|
||||
absolute: file
|
||||
}
|
||||
.map(setNameParts)
|
||||
.then (arr) ->
|
||||
{
|
||||
integration: arr
|
||||
|
||||
@@ -168,6 +168,7 @@ module.exports = {
|
||||
getFilePath = (dir, name) ->
|
||||
path.relative(config.projectRoot, path.join(dir, name))
|
||||
|
||||
log("example spec from integration folder %s", config.integrationFolder)
|
||||
files = [
|
||||
getFilePath(config.integrationFolder, "example_spec.js")
|
||||
]
|
||||
@@ -178,11 +179,13 @@ module.exports = {
|
||||
])
|
||||
|
||||
if config.supportFolder and config.supportFile isnt false
|
||||
log "supporting files from folder #{config.supportFolder}"
|
||||
files = files.concat([
|
||||
getFilePath(config.supportFolder, "commands.js")
|
||||
getFilePath(config.supportFolder, "defaults.js")
|
||||
getFilePath(config.supportFolder, "index.js")
|
||||
])
|
||||
log("scaffolded files %j", files)
|
||||
|
||||
return @_fileListToTree(files)
|
||||
|
||||
|
||||
@@ -1,9 +1,43 @@
|
||||
fs = require("fs")
|
||||
path = require("path")
|
||||
Promise = require("bluebird")
|
||||
|
||||
fs = Promise.promisifyAll(fs)
|
||||
|
||||
isIntegrationTestRe = /^integration/
|
||||
isUnitTestRe = /^unit/
|
||||
|
||||
# require.resolve walks the symlinks, which can really change
|
||||
# the results. For example
|
||||
# /tmp/foo is symlink to /private/tmp/foo on Mac
|
||||
# thus resolving /tmp/foo to find /tmp/foo/index.js
|
||||
# can return /private/tmp/foo/index.js
|
||||
# which can really confuse the rest of the code.
|
||||
# Detect this switch by checking if the resolution of absolute
|
||||
# paths moved the prefix
|
||||
#
|
||||
# Good case: no switcheroo, return false
|
||||
# /foo/bar -> /foo/bar/index.js
|
||||
# Bad case: return true
|
||||
# /tmp/foo/bar -> /private/tmp/foo/bar/index.js
|
||||
checkIfResolveChangedRootFolder = (resolved, initial) ->
|
||||
path.isAbsolute(resolved) &&
|
||||
path.isAbsolute(initial) &&
|
||||
!resolved.startsWith(initial)
|
||||
|
||||
# real folder path found could be different due to symlinks
|
||||
# For example, folder /tmp/foo on Mac is really /private/tmp/foo
|
||||
getRealFolderPath = (folder) ->
|
||||
# TODO check if folder is a non-empty string
|
||||
throw new Error("Expected folder") if not folder
|
||||
|
||||
fs.realpathAsync(folder)
|
||||
|
||||
module.exports = {
|
||||
checkIfResolveChangedRootFolder
|
||||
|
||||
getRealFolderPath
|
||||
|
||||
getAbsolutePathToSpec: (spec, config) ->
|
||||
switch
|
||||
## if our file is an integration test
|
||||
@@ -29,4 +63,4 @@ module.exports = {
|
||||
|
||||
else
|
||||
spec
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
log = require('../log')
|
||||
cwd = require('../cwd')
|
||||
fs = require('fs')
|
||||
{ basename, join, isAbsolute } = require('path')
|
||||
md5 = require('md5')
|
||||
@@ -12,15 +13,15 @@ toHashName = (projectPath) ->
|
||||
"#{name}-#{hash}"
|
||||
|
||||
formStatePath = (projectPath) ->
|
||||
log('making saved state from %s', process.cwd())
|
||||
log('making saved state from %s', cwd())
|
||||
if projectPath
|
||||
log('for project path %s', projectPath)
|
||||
else
|
||||
log('missing project path, looking for project here')
|
||||
cypressJsonPath = join(process.cwd(), 'cypress.json')
|
||||
cypressJsonPath = cwd('cypress.json')
|
||||
if fs.existsSync(cypressJsonPath)
|
||||
log('found cypress file %s', cypressJsonPath)
|
||||
projectPath = process.cwd()
|
||||
projectPath = cwd()
|
||||
|
||||
statePath = "state.json"
|
||||
if projectPath
|
||||
|
||||
16
packages/server/test/unit/path_helpers_spec.coffee
Normal file
16
packages/server/test/unit/path_helpers_spec.coffee
Normal file
@@ -0,0 +1,16 @@
|
||||
require("../spec_helper")
|
||||
|
||||
path_helpers = require("#{root}lib/util/path_helpers")
|
||||
|
||||
describe "lib/util/path_helpers", ->
|
||||
context "checkIfResolveChangedRootFolder", ->
|
||||
check = path_helpers.checkIfResolveChangedRootFolder
|
||||
|
||||
it "ignores non-absolute paths", ->
|
||||
expect(check('foo/index.js', 'foo')).to.be.false()
|
||||
|
||||
it "handles paths that do not switch", ->
|
||||
expect(check('/foo/index.js', '/foo')).to.be.false()
|
||||
|
||||
it "detects path switch", ->
|
||||
expect(check('/private/foo/index.js', '/foo')).to.be.true()
|
||||
Reference in New Issue
Block a user