Skip to content

Commit

Permalink
refactor(test): extract proxy into a separate Given claim (#3492)
Browse files Browse the repository at this point in the history
First step to simplify execKarma method, which is overcomplicated and has too many responsibilities.
  • Loading branch information
devoto13 authored Apr 30, 2020
1 parent 633f833 commit b788f94
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 99 deletions.
142 changes: 64 additions & 78 deletions test/e2e/step_definitions/core_steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,90 +24,76 @@ function cleanseIfNeeded () {
}
}

function execKarma (command, level, proxyPort, proxyPath, callback) {
function execKarma (command, level, callback) {
level = level || 'warn'

const startProxy = (done) => {
if (proxyPort) {
this.proxy.start(proxyPort, proxyPath, done)
} else {
done()
this.writeConfigFile(tmpDir, tmpConfigFile, (err, hash) => {
if (err) {
return callback.fail(new Error(err))
}
}
const configFile = path.join(tmpDir, hash + '.' + tmpConfigFile)
const runtimePath = path.join(baseDir, 'bin', 'karma')

startProxy((err) => {
if (err) {
return callback.fail(err)
const executor = (done) => {
const cmd = runtimePath + ' ' + command + ' --log-level ' + level + ' ' + configFile + ' ' + additionalArgs

return exec(cmd, {
cwd: baseDir
}, done)
}

this.writeConfigFile(tmpDir, tmpConfigFile, (err, hash) => {
if (err) {
return callback.fail(new Error(err))
const runOut = command === 'runOut'
if (command === 'run' || command === 'runOut') {
let isRun = false
this.child = spawn('' + runtimePath, ['start', '--log-level', 'warn', configFile])
const done = () => {
cleansingNeeded = true
this.child && this.child.kill()
callback()
}
const configFile = path.join(tmpDir, hash + '.' + tmpConfigFile)
const runtimePath = path.join(baseDir, 'bin', 'karma')

const executor = (done) => {
const cmd = runtimePath + ' ' + command + ' --log-level ' + level + ' ' + configFile + ' ' + additionalArgs
this.child.on('error', (error) => {
this.lastRun.error = error
done()
})

return exec(cmd, {
cwd: baseDir
}, done)
}
this.child.stderr.on('data', (chunk) => {
this.lastRun.stderr += chunk.toString()
})

const runOut = command === 'runOut'
if (command === 'run' || command === 'runOut') {
let isRun = false
this.child = spawn('' + runtimePath, ['start', '--log-level', 'warn', configFile])
const done = () => {
cleansingNeeded = true
this.child && this.child.kill()
callback()
this.child.stdout.on('data', (chunk) => {
this.lastRun.stdout += chunk.toString()
const cmd = runtimePath + ' run ' + configFile + ' ' + additionalArgs
if (!isRun) {
isRun = true

setTimeout(() => {
exec(cmd, {
cwd: baseDir
}, (error, stdout, stderr) => {
if (error) {
this.lastRun.error = error
}
if (runOut) {
this.lastRun.stdout = stdout
this.lastRun.stderr = stderr
}
done()
})
}, 1000)
}

this.child.on('error', (error) => {
})
} else {
executor((error, stdout, stderr) => {
if (error) {
this.lastRun.error = error
done()
})

this.child.stderr.on('data', (chunk) => {
this.lastRun.stderr += chunk.toString()
})

this.child.stdout.on('data', (chunk) => {
this.lastRun.stdout += chunk.toString()
const cmd = runtimePath + ' run ' + configFile + ' ' + additionalArgs
if (!isRun) {
isRun = true

setTimeout(() => {
exec(cmd, {
cwd: baseDir
}, (error, stdout, stderr) => {
if (error) {
this.lastRun.error = error
}
if (runOut) {
this.lastRun.stdout = stdout
this.lastRun.stderr = stderr
}
done()
})
}, 1000)
}
})
} else {
executor((error, stdout, stderr) => {
if (error) {
this.lastRun.error = error
}
this.lastRun.stdout = stdout
this.lastRun.stderr = stderr
cleansingNeeded = true
callback()
})
}
})
}
this.lastRun.stdout = stdout
this.lastRun.stderr = stderr
cleansingNeeded = true
callback()
})
}
})
}

Expand All @@ -122,6 +108,10 @@ Given('command line arguments of: {string}', function (args, callback) {
return callback()
})

Given('a proxy on port {int} that prepends {string} to the base path', async function (proxyPort, proxyPath) {
return this.proxy.start(proxyPort, proxyPath)
})

When('I stop a server programmatically', function (callback) {
const _this = this
setTimeout(function () {
Expand Down Expand Up @@ -164,15 +154,11 @@ defineParameterType({
})

When('I {command} Karma', function (command, callback) {
execKarma.apply(this, [command, undefined, undefined, undefined, callback])
execKarma.apply(this, [command, undefined, callback])
})

When('I {command} Karma with log-level {loglevel}', function (command, level, callback) {
execKarma.apply(this, [command, level, undefined, undefined, callback])
})

When('I {command} Karma behind a proxy on port {int} that prepends {string} to the base path', function (command, proxyPort, proxyPath, callback) {
execKarma.apply(this, [command, 'debug', proxyPort, proxyPath, callback])
execKarma.apply(this, [command, level, callback])
})

Then(/^it passes with(:? (no\sdebug|like|regexp))?:$/, { timeout: 10 * 1000 }, function (mode, expectedOutput, callback) {
Expand Down
17 changes: 7 additions & 10 deletions test/e2e/step_definitions/hooks.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
const { After } = require('cucumber')

After(function (scenario, callback) {
const running = this.child != null && typeof this.child.kill === 'function'
After(async function () {
await this.proxy.stopIfRunning()

// stop the proxy if it was started
this.proxy.stop(() => {
if (running) {
this.child.kill()
this.child = null
}
callback()
})
const running = this.child != null && typeof this.child.kill === 'function'
if (running) {
this.child.kill()
this.child = null
}
})
16 changes: 7 additions & 9 deletions test/e2e/support/proxy.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
const http = require('http')
const httpProxy = require('http-proxy')
const { promisify } = require('util')

module.exports = class Proxy {
constructor () {
this.running = false
this.proxyPathRegExp = null

this.proxy = httpProxy.createProxyServer({
target: 'http://localhost:9876'
Expand Down Expand Up @@ -31,20 +33,16 @@ module.exports = class Proxy {
})
}

start (port, proxyPath, callback) {
async start (port, proxyPath) {
this.proxyPathRegExp = new RegExp('^' + proxyPath + '(.*)')
this.server.listen(port, (error) => {
this.running = !error
callback(error)
})
await promisify(this.server.listen.bind(this.server))(port)
this.running = true
}

stop (callback) {
async stopIfRunning () {
if (this.running) {
this.running = false
this.server.close(callback)
} else {
callback()
await promisify(this.server.close.bind(this.server))()
}
}
}
5 changes: 3 additions & 2 deletions test/e2e/upstream-proxy.feature
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Feature: UpstreamProxy
In order to use Karma
As a person who wants to write great tests
I want to Karma to to work when it is behind a proxy that prepends to the base path.
I want Karma to work when it is behind a proxy that prepends to the base path.

Scenario: UpstreamProxy
Given a configuration with:
Expand All @@ -17,7 +17,8 @@ Feature: UpstreamProxy
path: '/__proxy__/'
};
"""
When I start Karma behind a proxy on port 9875 that prepends '/__proxy__/' to the base path
And a proxy on port 9875 that prepends '/__proxy__/' to the base path
When I start Karma with log-level debug
Then it passes with regexp:
"""
Chrome Headless.*Executed.*SUCCESS
Expand Down

0 comments on commit b788f94

Please sign in to comment.