@revoloo/cypress6
Version:
Cypress.io end to end testing tool
211 lines (165 loc) • 4.9 kB
JavaScript
const _ = require('lodash')
const Promise = require('bluebird')
const path = require('path')
const errors = require('../errors')
const log = require('../log')
const { fs } = require('../util/fs')
// TODO:
// think about adding another PSemaphore
// here since we can read + write the
// settings at the same time something else
// is potentially reading it
const flattenCypress = (obj) => {
return obj.cypress ? obj.cypress : undefined
}
const maybeVerifyConfigFile = Promise.method((configFile) => {
if (configFile === false) {
return
}
return fs.statAsync(configFile)
})
const renameVisitToPageLoad = (obj) => {
const v = obj.visitTimeout
if (v) {
obj = _.omit(obj, 'visitTimeout')
obj.pageLoadTimeout = v
return obj
}
}
const renameCommandTimeout = (obj) => {
const c = obj.commandTimeout
if (c) {
obj = _.omit(obj, 'commandTimeout')
obj.defaultCommandTimeout = c
return obj
}
}
const renameSupportFolder = (obj) => {
const sf = obj.supportFolder
if (sf) {
obj = _.omit(obj, 'supportFolder')
obj.supportFile = sf
return obj
}
}
module.exports = {
_pathToFile (projectRoot, file) {
return path.join(projectRoot, file)
},
_err (type, file, err) {
const e = errors.get(type, file, err)
e.code = err.code
e.errno = err.errno
throw e
},
_logReadErr (file, err) {
errors.throw('ERROR_READING_FILE', file, err)
},
_logWriteErr (file, err) {
return this._err('ERROR_WRITING_FILE', file, err)
},
_write (file, obj = {}) {
return fs.outputJsonAsync(file, obj, { spaces: 2 })
.return(obj)
.catch((err) => {
return this._logWriteErr(file, err)
})
},
_applyRewriteRules (obj = {}) {
return _.reduce([flattenCypress, renameVisitToPageLoad, renameCommandTimeout, renameSupportFolder], (memo, fn) => {
const ret = fn(memo)
return ret ? ret : memo
}, _.cloneDeep(obj))
},
configFile (options = {}) {
return options.configFile === false ? false : (options.configFile || 'cypress.json')
},
id (projectRoot, options = {}) {
const file = this.pathToConfigFile(projectRoot, options)
return fs.readJsonAsync(file)
.get('projectId')
.catch(() => {
return null
})
},
exists (projectRoot, options = {}) {
const file = this.pathToConfigFile(projectRoot, options)
// first check if cypress.json exists
return maybeVerifyConfigFile(file)
.then(() => {
// if it does also check that the projectRoot
// directory is writable
return fs.accessAsync(projectRoot, fs.W_OK)
}).catch({ code: 'ENOENT' }, () => {
// cypress.json does not exist, we missing project
log('cannot find file %s', file)
return this._err('CONFIG_FILE_NOT_FOUND', this.configFile(options), projectRoot)
}).catch({ code: 'EACCES' }, () => {
// we cannot write due to folder permissions
return errors.warning('FOLDER_NOT_WRITABLE', projectRoot)
}).catch((err) => {
if (errors.isCypressErr(err)) {
throw err
}
return this._logReadErr(file, err)
})
},
read (projectRoot, options = {}) {
if (options.configFile === false) {
return Promise.resolve({})
}
const file = this.pathToConfigFile(projectRoot, options)
return fs.readJsonAsync(file)
.catch({ code: 'ENOENT' }, () => {
return this._write(file, {})
}).then((json = {}) => {
const changed = this._applyRewriteRules(json)
// if our object is unchanged
// then just return it
if (_.isEqual(json, changed)) {
return json
}
// else write the new reduced obj
return this._write(file, changed)
}).catch((err) => {
if (errors.isCypressErr(err)) {
throw err
}
return this._logReadErr(file, err)
})
},
readEnv (projectRoot) {
const file = this.pathToCypressEnvJson(projectRoot)
return fs.readJsonAsync(file)
.catch({ code: 'ENOENT' }, () => {
return {}
})
.catch((err) => {
if (errors.isCypressErr(err)) {
throw err
}
return this._logReadErr(file, err)
})
},
write (projectRoot, obj = {}, options = {}) {
if (options.configFile === false) {
return Promise.resolve({})
}
return this.read(projectRoot)
.then((settings) => {
_.extend(settings, obj)
const file = this.pathToConfigFile(projectRoot, options)
return this._write(file, settings)
})
},
remove (projectRoot, options = {}) {
return fs.unlinkSync(this.pathToConfigFile(projectRoot, options))
},
pathToConfigFile (projectRoot, options = {}) {
const configFile = this.configFile(options)
return configFile && this._pathToFile(projectRoot, configFile)
},
pathToCypressEnvJson (projectRoot) {
return this._pathToFile(projectRoot, 'cypress.env.json')
},
}