Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/develop' into issue-5772
Browse files Browse the repository at this point in the history
  • Loading branch information
sainthkh committed Mar 13, 2020
2 parents 0c50c77 + 9caf21a commit f6824bb
Show file tree
Hide file tree
Showing 34 changed files with 474 additions and 136 deletions.
4 changes: 3 additions & 1 deletion circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,6 @@ jobs:
at: ~/
- run: mkdir -p cli/visual-snapshots
- run:
# TODO sanitize "cypress info" output to be consistent
command: node cli/bin/cypress info --dev | yarn --silent term-to-html | node scripts/sanitize --type cli-info > cli/visual-snapshots/cypress-info.html
environment:
FORCE_COLOR: 2
Expand Down Expand Up @@ -305,6 +304,9 @@ jobs:
expectedResultCount: 6
- store_test_results:
path: /tmp/cypress
# CLI tests generate HTML files with sample CLI command output
- store_artifacts:
path: cli/test/html
- store-npm-logs

lint-types:
Expand Down
28 changes: 27 additions & 1 deletion cli/__snapshots__/cache_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,35 @@ exports['lib/tasks/cache .clear deletes cache folder and everything inside it 1'
`

exports['lib/tasks/cache .list lists all versions of cached binary 1'] = `
1.2.3, 2.3.4
┌─────────┬───────────┐
│ version │ last used │
├─────────┼───────────┤
│ 1.2.3 │ unknown │
├─────────┼───────────┤
│ 2.3.4 │ unknown │
└─────────┴───────────┘
`

exports['lib/tasks/cache .path lists path to cache 1'] = `
/.cache/Cypress
`

exports['lib/tasks/cache .list lists all versions of cached binary with last access 1'] = `
┌─────────┬──────────────┐
│ version │ last used │
├─────────┼──────────────┤
│ 1.2.3 │ 3 months ago │
├─────────┼──────────────┤
│ 2.3.4 │ 5 days ago │
└─────────┴──────────────┘
`

exports['lib/tasks/cache .list some versions have never been opened 1'] = `
┌─────────┬──────────────┐
│ version │ last used │
├─────────┼──────────────┤
│ 1.2.3 │ 3 months ago │
├─────────┼──────────────┤
│ 2.3.4 │ unknown │
└─────────┴──────────────┘
`
63 changes: 60 additions & 3 deletions cli/lib/tasks/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,20 @@ const state = require('./state')
const logger = require('../logger')
const fs = require('../fs')
const util = require('../util')
const { join } = require('path')
const Table = require('cli-table3')
const moment = require('moment')
const chalk = require('chalk')
const _ = require('lodash')

// output colors for the table
const colors = {
titles: chalk.white,
dates: chalk.cyan,
values: chalk.green,
}

// TODO: rename this function
const path = () => {
logger.log(state.getCacheDir())

Expand All @@ -15,15 +28,59 @@ const clear = () => {

const list = () => {
return getCachedVersions()
.then((versions) => {
logger.log(versions.join(', '))
.then((binaries) => {
const table = new Table({
head: [colors.titles('version'), colors.titles('last used')],
})

binaries.forEach((binary) => {
const versionString = colors.values(binary.version)
const lastUsed = binary.accessed ? colors.dates(binary.accessed) : 'unknown'

return table.push([versionString, lastUsed])
})

logger.log(table.toString())
})
}

const getCachedVersions = () => {
const cacheDir = state.getCacheDir()

return fs
.readdirAsync(state.getCacheDir())
.readdirAsync(cacheDir)
.filter(util.isSemver)
.map((version) => {
return {
version,
folderPath: join(cacheDir, version),
}
})
.mapSeries((binary) => {
// last access time on the folder is different from last access time
// on the Cypress binary
const binaryDir = state.getBinaryDir(binary.version)
const executable = state.getPathToExecutable(binaryDir)

return fs.statAsync(executable).then((stat) => {
const lastAccessedTime = _.get(stat, 'atime')

if (!lastAccessedTime) {
// the test runner has never been opened
// or could be a test simulating missing timestamp
return binary
}

const accessed = moment(lastAccessedTime).fromNow()

binary.accessed = accessed

return binary
}, (e) => {
// could not find the binary or gets its stats
return binary
})
})
}

module.exports = {
Expand Down
3 changes: 2 additions & 1 deletion cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"cachedir": "2.3.0",
"chalk": "2.4.2",
"check-more-types": "2.24.0",
"cli-table3": "0.5.1",
"commander": "4.1.0",
"common-tags": "1.8.0",
"debug": "4.1.1",
Expand All @@ -58,7 +59,7 @@
"ospath": "1.2.2",
"pretty-bytes": "5.3.0",
"ramda": "0.26.1",
"request": "2.88.0",
"request": "cypress-io/request#b5af0d1fa47eec97ba980cde90a13e69a2afcd16",
"request-progress": "3.0.0",
"supports-color": "7.1.0",
"tmp": "0.1.0",
Expand Down
27 changes: 27 additions & 0 deletions cli/test/html/list-of-versions.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<style>
body {
font-family: "Courier New", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #000;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier New", Courier, monospace;
}
</style>
</head>
<body><pre>┌─────────┬──────────────┐
<span style="color:#AAA">version<span style="color:#eee"><span style="color:#AAA">last used<span style="color:#eee">
├─────────┼──────────────┤
<span style="color:#0A0">1.2.3<span style="color:#eee"><span style="color:#0AA">3 months ago<span style="color:#eee">
├─────────┼──────────────┤
<span style="color:#0A0">2.3.4<span style="color:#eee"><span style="color:#0AA">5 days ago<span style="color:#eee">
└─────────┴──────────────┘</span></span></span></span></span></span></span></span></span></span></span></span>
</pre></body></html>
27 changes: 27 additions & 0 deletions cli/test/html/second-binary-never-used.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<style>
body {
font-family: "Courier New", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #000;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier New", Courier, monospace;
}
</style>
</head>
<body><pre>┌─────────┬──────────────┐
<span style="color:#AAA">version<span style="color:#eee"><span style="color:#AAA">last used<span style="color:#eee">
├─────────┼──────────────┤
<span style="color:#0A0">1.2.3<span style="color:#eee"><span style="color:#0AA">3 months ago<span style="color:#eee">
├─────────┼──────────────┤
<span style="color:#0A0">2.3.4<span style="color:#eee"> │ unknown │
└─────────┴──────────────┘</span></span></span></span></span></span></span></span></span></span>
</pre></body></html>
92 changes: 84 additions & 8 deletions cli/test/lib/tasks/cache_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ const state = require(`${lib}/tasks/state`)
const cache = require(`${lib}/tasks/cache`)
const stdout = require('../../support/stdout')
const snapshot = require('../../support/snapshot')
const moment = require('moment')
const stripAnsi = require('strip-ansi')
const path = require('path')
const termToHtml = require('term-to-html')

const outputHtmlFolder = path.join(__dirname, '..', '..', 'html')

describe('lib/tasks/cache', () => {
beforeEach(() => {
Expand All @@ -22,20 +28,54 @@ describe('lib/tasks/cache', () => {
})

sinon.stub(state, 'getCacheDir').returns('/.cache/Cypress')
sinon.stub(state, 'getBinaryDir').returns('/.cache/Cypress')
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()
this.stdout = this.stdout.toString().split('\n').slice(0, -2).join('\n')
snapshot(this.stdout.toString() || '[no output]')
stdout.restore()
})

const defaultSnapshot = () => {
const stdoutAsString = getSnapshotText()

snapshot(stripAnsi(stdoutAsString))
}

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', () => {
it('lists path to cache', () => {
cache.path()
expect(this.stdout.toString()).to.eql('/.cache/Cypress\n')
defaultSnapshot()
})
})

Expand All @@ -45,18 +85,54 @@ describe('lib/tasks/cache', () => {
.then(() => {
return fs.pathExistsAsync('/.cache/Cypress')
.then((exists) => {
return expect(exists).to.eql(false)
expect(exists).to.eql(false)
defaultSnapshot()
})
})
})
})

describe('.list', () => {
it('lists all versions of cached binary', () => {
return cache.list()
.then(() => {
expect(this.stdout.toString()).to.eql('1.2.3, 2.3.4\n')
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 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: moment().subtract(3, 'month').valueOf(),
})

statAsync.onSecondCall().resolves({
atime: moment().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: moment().subtract(3, 'month').valueOf(),
})

// the second binary has never been accessed
statAsync.onSecondCall().resolves()

await cache.list()
await snapshotWithHtml('second-binary-never-used.html')
})
})
})
Loading

0 comments on commit f6824bb

Please sign in to comment.