UNPKG

@revoloo/cypress6

Version:

Cypress.io end to end testing tool

192 lines (156 loc) 4.52 kB
const _ = require('lodash') const path = require('path') const check = require('syntax-error') const debug = require('debug')('cypress:server:fixture') const coffee = require('coffeescript') const Promise = require('bluebird') const jsonlint = require('jsonlint') const errors = require('./errors') const { fs } = require('./util/fs') const glob = require('./util/glob') const extensions = [ '.json', '.js', '.coffee', '.html', '.txt', '.csv', '.png', '.jpg', '.jpeg', '.gif', '.tif', '.tiff', '.zip', ] const queue = {} const friendlyJsonParse = function (s) { jsonlint.parse(s) // might throw good error return JSON.parse(s) // actually parses correctly all the edge cases } module.exports = { get (fixturesFolder, filePath, options = {}) { const p = path.join(fixturesFolder, filePath) const fixture = path.basename(p) // if the file exists, go ahead and parse it // otherwise, glob for potential extensions return this.fileExists(p) .then(function () { debug('fixture exact name exists', p) return this.parseFile(p, fixture, options) }).catch(function (e) { if (e.code !== 'ENOENT') { throw e } const pattern = `${p}{${extensions.join(',')}}` return glob(pattern, { nosort: true, nodir: true, }).bind(this) .then(function (matches) { if (matches.length === 0) { const relativePath = path.relative('.', p) errors.throw('FIXTURE_NOT_FOUND', relativePath, extensions) } debug('fixture matches found, using the first', matches) const ext = path.extname(matches[0]) return this.parseFile(p + ext, fixture, options) }) }) }, fileExists (p) { return fs.statAsync(p).bind(this) .then((stat) => { // check for files, not directories // https://github.com/cypress-io/cypress/issues/3739 if (stat.isDirectory()) { const err = new Error() err.code = 'ENOENT' throw err } }) }, parseFile (p, fixture, options) { if (queue[p]) { return Promise.delay(1).then(() => { return this.parseFile(p, fixture, options) }) } queue[p] = true const cleanup = () => { return delete queue[p] } return this.fileExists(p) .then(function () { const ext = path.extname(p) return this.parseFileByExtension(p, fixture, ext, options) }).then((ret) => { cleanup() return ret }).catch((err) => { cleanup() throw err }) }, parseFileByExtension (p, fixture, ext, options = {}) { switch (ext) { case '.json': return this.parseJson(p, fixture) case '.js': return this.parseJs(p, fixture) case '.coffee': return this.parseCoffee(p, fixture) case '.html': return this.parseHtml(p, fixture) case '.png': case '.jpg': case '.jpeg': case '.gif': case '.tif': case '.tiff': case '.zip': return this.parse(p, fixture, _.isNull(options.encoding) ? null : (options.encoding || 'base64')) default: return this.parse(p, fixture, _.isNull(options.encoding) ? null : options.encoding) } }, parseJson (p, fixture) { return fs.readFileAsync(p, 'utf8') .bind(this) .then(friendlyJsonParse) .catch((err) => { throw new Error(`'${fixture}' is not valid JSON.\n${err.message}`) }) }, parseJs (p, fixture) { return fs.readFileAsync(p, 'utf8') .bind(this) .then((str) => { let obj try { obj = eval(`(${str})`) } catch (e) { const err = check(str, fixture) if (err) { throw err } throw e } return obj }).catch((err) => { throw new Error(`'${fixture}' is not a valid JavaScript object.${err.toString()}`) }) }, parseCoffee (p, fixture) { const dc = process.env.NODE_DISABLE_COLORS process.env.NODE_DISABLE_COLORS = '0' return fs.readFileAsync(p, 'utf8') .bind(this) .then((str) => { str = coffee.compile(str, { bare: true }) return eval(str) }).catch((err) => { throw new Error(`'${fixture} is not a valid CoffeeScript object.\n${err.toString()}`) }).finally(() => { return process.env.NODE_DISABLE_COLORS = dc }) }, parseHtml (p, fixture) { return fs.readFileAsync(p, 'utf8') .bind(this) }, parse (p, fixture, encoding = 'utf8') { return fs.readFileAsync(p, encoding) .bind(this) }, }