Files
cypress/cli/test/lib/tasks/cache_spec.js
2023-01-27 15:50:21 -06:00

276 lines
7.2 KiB
JavaScript

require('../../spec_helper')
const mockfs = require('mock-fs')
const fs = require(`${lib}/fs`)
const state = require(`${lib}/tasks/state`)
const util = require(`${lib}/util`)
const cache = require(`${lib}/tasks/cache`)
const stdout = require('../../support/stdout')
const snapshot = require('../../support/snapshot')
const dayjs = require('dayjs')
const stripAnsi = require('strip-ansi')
const path = require('path')
const termToHtml = require('term-to-html')
const mockedEnv = require('mocked-env')
const outputHtmlFolder = path.join(__dirname, '..', '..', 'html')
describe('lib/tasks/cache', () => {
beforeEach(() => {
mockfs({
'/.cache/Cypress': {
'1.2.3': {
'Cypress': {
'file1': Buffer.from(new Array(32 * 1024).fill(1)),
'dir': {
'file2': Buffer.from(new Array(128 * 1042).fill(2)),
},
},
},
'2.3.4': {
'Cypress.app': {},
},
},
})
sinon.stub(state, 'getCacheDir').returns('/.cache/Cypress')
sinon.stub(state, 'getBinaryDir').returns('/.cache/Cypress')
sinon.stub(util, 'pkgVersion').returns('1.2.3')
this.stdout = stdout.capture()
})
const getSnapshotText = () => {
this.stdout = this.stdout.toString().split('\n').slice(0, -1).join('\n')
const stdoutAsString = this.stdout.toString() || '[no output]'
// first restore the STDOUT, then confirm the value
// otherwise the error might not even appear or appear twice!
stdout.restore()
return stdoutAsString
}
const saveHtml = async (filename, html) => {
await fs.ensureDirAsync(outputHtmlFolder)
const htmlFilename = path.join(outputHtmlFolder, filename)
await fs.writeFileAsync(htmlFilename, html, 'utf8')
}
afterEach(() => {
mockfs.restore()
})
const defaultSnapshot = (snapshotName) => {
const stdoutAsString = getSnapshotText()
const withoutAnsi = stripAnsi(stdoutAsString)
if (snapshotName) {
snapshot(snapshotName, withoutAnsi)
} else {
snapshot(withoutAnsi)
}
}
const snapshotWithHtml = async (htmlFilename) => {
const stdoutAsString = getSnapshotText()
snapshot(stripAnsi(stdoutAsString))
// if the sanitized snapshot matches, let's save the ANSI colors converted into HTML
const html = termToHtml.strings(stdoutAsString, termToHtml.themes.dark.name)
await saveHtml(htmlFilename, html)
}
describe('.path', () => {
let restoreEnv
afterEach(() => {
if (restoreEnv) {
restoreEnv()
restoreEnv = null
}
})
it('lists path to cache', () => {
cache.path()
expect(this.stdout.toString()).to.eql('/.cache/Cypress\n')
defaultSnapshot()
})
it('lists path to cache with silent npm loglevel', () => {
restoreEnv = mockedEnv({
npm_config_loglevel: 'silent',
})
cache.path()
expect(this.stdout.toString()).to.eql('/.cache/Cypress\n')
})
it('lists path to cache with silent npm warn', () => {
restoreEnv = mockedEnv({
npm_config_loglevel: 'warn',
})
cache.path()
expect(this.stdout.toString()).to.eql('/.cache/Cypress\n')
})
})
describe('.clear', () => {
it('deletes cache folder and everything inside it', () => {
return cache.clear()
.then(() => {
return fs.pathExistsAsync('/.cache/Cypress')
.then((exists) => {
expect(exists).to.eql(false)
defaultSnapshot()
})
})
})
})
describe('.prune', () => {
it('deletes cache binaries for all version but the current one', async () => {
await cache.prune()
const checkedInBinaryVersion = util.pkgVersion()
const files = await fs.readdir('/.cache/Cypress')
expect(files.length).to.eq(1)
files.forEach((file) => {
expect(file).to.eq(checkedInBinaryVersion)
})
defaultSnapshot()
})
it('doesn\'t delete any cache binaries', async () => {
const dir = path.join(state.getCacheDir(), '2.3.4')
await fs.removeAsync(dir)
await cache.prune()
const checkedInBinaryVersion = util.pkgVersion()
const files = await fs.readdirAsync('/.cache/Cypress')
expect(files.length).to.eq(1)
files.forEach((file) => {
expect(file).to.eq(checkedInBinaryVersion)
})
defaultSnapshot()
})
it('exits cleanly if cache dir DNE', async () => {
await fs.removeAsync(state.getCacheDir())
await cache.prune()
defaultSnapshot()
})
})
describe('.list', () => {
let restoreEnv
afterEach(() => {
if (restoreEnv) {
restoreEnv()
restoreEnv = null
}
})
it('lists all versions of cached binary', async function () {
// unknown access times
sinon.stub(state, 'getPathToExecutable').returns('/.cache/Cypress/1.2.3/app/cypress')
await cache.list()
defaultSnapshot()
})
it('lists all versions of cached binary with npm log level silent', async function () {
restoreEnv = mockedEnv({
npm_config_loglevel: 'silent',
})
// unknown access times
sinon.stub(state, 'getPathToExecutable').returns('/.cache/Cypress/1.2.3/app/cypress')
await cache.list()
// log output snapshot should have a grid of versions
defaultSnapshot('cache list with silent log level')
})
it('lists all versions of cached binary with npm log level warn', async function () {
restoreEnv = mockedEnv({
npm_config_loglevel: 'warn',
})
// unknown access times
sinon.stub(state, 'getPathToExecutable').returns('/.cache/Cypress/1.2.3/app/cypress')
await cache.list()
// log output snapshot should have a grid of versions
defaultSnapshot('cache list with warn log level')
})
it('lists all versions of cached binary with last access', async function () {
sinon.stub(state, 'getPathToExecutable').returns('/.cache/Cypress/1.2.3/app/cypress')
const statAsync = sinon.stub(fs, 'statAsync')
statAsync.onFirstCall().resolves({
atime: dayjs().subtract(3, 'month').valueOf(),
})
statAsync.onSecondCall().resolves({
atime: dayjs().subtract(5, 'day').valueOf(),
})
await cache.list()
await snapshotWithHtml('list-of-versions.html')
})
it('some versions have never been opened', async function () {
sinon.stub(state, 'getPathToExecutable').returns('/.cache/Cypress/1.2.3/app/cypress')
const statAsync = sinon.stub(fs, 'statAsync')
statAsync.onFirstCall().resolves({
atime: dayjs().subtract(3, 'month').valueOf(),
})
// the second binary has never been accessed
statAsync.onSecondCall().resolves()
await cache.list()
await snapshotWithHtml('second-binary-never-used.html')
})
it('shows sizes', async function () {
sinon.stub(state, 'getPathToExecutable').returns('/.cache/Cypress/1.2.3/app/cypress')
const statAsync = sinon.stub(fs, 'statAsync')
statAsync.onFirstCall().resolves({
atime: dayjs().subtract(3, 'month').valueOf(),
})
// the second binary has never been accessed
statAsync.onSecondCall().resolves()
await cache.list(true)
await snapshotWithHtml('show-size.html')
})
})
})