Prevent Cypress from showing 200% unzip progress (#6009)

* Prevent unzipWithNode from getting called twice

* fix unzip test

* add unit test to check if unzip is called once

* add unzip test for Darwin

Co-authored-by: Gleb Bahmutov <gleb.bahmutov@gmail.com>
This commit is contained in:
Zach Bloomquist
2019-12-26 12:37:09 -05:00
committed by GitHub
parent 875d569303
commit b130ffca87
2 changed files with 161 additions and 27 deletions

View File

@@ -1,3 +1,4 @@
const _ = require('lodash')
const la = require('lazy-ass')
const is = require('check-more-types')
const cp = require('child_process')
@@ -34,7 +35,11 @@ const unzip = ({ zipFilePath, installDir, progress }) => {
return yauzl.open(zipFilePath, (err, zipFile) => {
yauzlDoneTime = Date.now()
if (err) return reject(err)
if (err) {
debug('error using yauzl %s', err.message)
return reject(err)
}
const total = zipFile.entryCount
@@ -67,9 +72,13 @@ const unzip = ({ zipFilePath, installDir, progress }) => {
const endFn = (err) => {
if (err) {
debug('error %s', err.message)
return reject(err)
}
debug('node unzip finished')
return resolve()
}
@@ -78,9 +87,13 @@ const unzip = ({ zipFilePath, installDir, progress }) => {
onEntry: tick,
}
debug('calling Node extract tool %s %o', zipFilePath, opts)
return unzipTools.extract(zipFilePath, opts, endFn)
}
const unzipFallback = _.once(unzipWithNode)
const unzipWithUnzipTool = () => {
debug('unzipping via `unzip`')
@@ -88,9 +101,13 @@ const unzip = ({ zipFilePath, installDir, progress }) => {
const sp = cp.spawn('unzip', ['-o', zipFilePath, '-d', installDir])
sp.on('error', unzipWithNode)
sp.on('error', (err) => {
debug('unzip tool error: %s', err.message)
unzipFallback()
})
sp.on('close', (code) => {
debug('unzip tool close with code %d', code)
if (code === 0) {
percent = 100
notify(percent)
@@ -100,7 +117,7 @@ const unzip = ({ zipFilePath, installDir, progress }) => {
debug('`unzip` failed %o', { code })
return unzipWithNode()
return unzipFallback()
})
sp.stdout.on('data', (data) => {
@@ -127,7 +144,10 @@ const unzip = ({ zipFilePath, installDir, progress }) => {
const sp = cp.spawn('ditto', ['-xkV', zipFilePath, installDir])
// f-it just unzip with node
sp.on('error', unzipWithNode)
sp.on('error', (err) => {
debug(err.message)
unzipFallback()
})
sp.on('close', (code) => {
if (code === 0) {
@@ -141,7 +161,7 @@ const unzip = ({ zipFilePath, installDir, progress }) => {
debug('`ditto` failed %o', { code })
return unzipWithNode()
return unzipFallback()
})
return readline.createInterface({

View File

@@ -1,9 +1,12 @@
require('../../spec_helper')
const events = require('events')
const os = require('os')
const path = require('path')
const snapshot = require('../../support/snapshot')
const cp = require('child_process')
const debug = require('debug')('test')
const readline = require('readline')
const fs = require(`${lib}/fs`)
const util = require(`${lib}/util`)
@@ -65,39 +68,150 @@ describe('lib/tasks/unzip', function () {
})
})
// NOTE: hmm, running this test for some reason breaks 4 tests in verify_spec.js with very weird errors
context.skip('on linux', () => {
context('on linux', () => {
beforeEach(() => {
os.platform.returns('linux')
})
it('can try unzip first then fall back to node unzip', function () {
sinon.stub(unzip.utils.unzipTools, 'extract').resolves()
const unzipChildProcess = {
on: sinon.stub(),
stdout: {
on () {},
},
stderr: {
on () {},
},
}
unzipChildProcess.on.withArgs('error').yieldsAsync(0)
unzipChildProcess.on.withArgs('close').yieldsAsync(0)
sinon.stub(cp, 'spawn').withArgs('unzip').returns(unzipChildProcess)
it('can try unzip first then fall back to node unzip', function (done) {
const zipFilePath = path.join('test', 'fixture', 'example.zip')
return unzip
sinon.stub(unzip.utils.unzipTools, 'extract').callsFake((filePath, opts, cb) => {
debug('unzip extract called with %s', filePath)
expect(filePath, 'zipfile is the same').to.equal(zipFilePath)
expect(cb, 'has callback').to.be.a('function')
setTimeout(cb, 10)
})
const unzipChildProcess = new events.EventEmitter()
unzipChildProcess.stdout = {
on () {},
}
unzipChildProcess.stderr = {
on () {},
}
sinon.stub(cp, 'spawn').withArgs('unzip').returns(unzipChildProcess)
setTimeout(() => {
debug('emitting unzip error')
unzipChildProcess.emit('error', new Error('unzip fails badly'))
}, 100)
unzip
.start({
zipFilePath,
installDir,
})
.then(() => {
expect(cp.spawn).to.have.been.calledWith('unzip')
expect(unzip.utils.unzipTools.extract).to.be.calledWith(zipFilePath)
debug('checking if unzip was called')
expect(cp.spawn, 'unzip spawn').to.have.been.calledWith('unzip')
expect(unzip.utils.unzipTools.extract, 'extract called').to.be.calledWith(zipFilePath)
expect(unzip.utils.unzipTools.extract, 'extract called once').to.be.calledOnce
done()
})
})
it('calls node unzip just once', function (done) {
const zipFilePath = path.join('test', 'fixture', 'example.zip')
sinon.stub(unzip.utils.unzipTools, 'extract').callsFake((filePath, opts, cb) => {
debug('unzip extract called with %s', filePath)
expect(filePath, 'zipfile is the same').to.equal(zipFilePath)
expect(cb, 'has callback').to.be.a('function')
setTimeout(cb, 10)
})
const unzipChildProcess = new events.EventEmitter()
unzipChildProcess.stdout = {
on () {},
}
unzipChildProcess.stderr = {
on () {},
}
sinon.stub(cp, 'spawn').withArgs('unzip').returns(unzipChildProcess)
setTimeout(() => {
debug('emitting unzip error')
unzipChildProcess.emit('error', new Error('unzip fails badly'))
}, 100)
setTimeout(() => {
debug('emitting unzip close')
unzipChildProcess.emit('close', 1)
}, 110)
unzip
.start({
zipFilePath,
installDir,
})
.then(() => {
debug('checking if unzip was called')
expect(cp.spawn, 'unzip spawn').to.have.been.calledWith('unzip')
expect(unzip.utils.unzipTools.extract, 'extract called').to.be.calledWith(zipFilePath)
expect(unzip.utils.unzipTools.extract, 'extract called once').to.be.calledOnce
done()
})
})
})
context('on Mac', () => {
beforeEach(() => {
os.platform.returns('darwin')
})
it('calls node unzip just once', function (done) {
const zipFilePath = path.join('test', 'fixture', 'example.zip')
sinon.stub(unzip.utils.unzipTools, 'extract').callsFake((filePath, opts, cb) => {
debug('unzip extract called with %s', filePath)
expect(filePath, 'zipfile is the same').to.equal(zipFilePath)
expect(cb, 'has callback').to.be.a('function')
setTimeout(cb, 10)
})
const unzipChildProcess = new events.EventEmitter()
unzipChildProcess.stdout = {
on () {},
}
unzipChildProcess.stderr = {
on () {},
}
sinon.stub(cp, 'spawn').withArgs('ditto').returns(unzipChildProcess)
sinon.stub(readline, 'createInterface').returns({
on: () => {},
})
setTimeout(() => {
debug('emitting ditto error')
unzipChildProcess.emit('error', new Error('ditto fails badly'))
}, 100)
setTimeout(() => {
debug('emitting ditto close')
unzipChildProcess.emit('close', 1)
}, 110)
unzip
.start({
zipFilePath,
installDir,
})
.then(() => {
debug('checking if unzip was called')
expect(cp.spawn, 'unzip spawn').to.have.been.calledWith('ditto')
expect(unzip.utils.unzipTools.extract, 'extract called').to.be.calledWith(zipFilePath)
expect(unzip.utils.unzipTools.extract, 'extract called once').to.be.calledOnce
done()
})
})
})