Skip to content

Commit

Permalink
Merge 415f4d5 into 49c8796
Browse files Browse the repository at this point in the history
  • Loading branch information
charlierudolph committed Jul 10, 2021
2 parents 49c8796 + 415f4d5 commit ff02fa4
Show file tree
Hide file tree
Showing 22 changed files with 177 additions and 109 deletions.
1 change: 1 addition & 0 deletions dependency-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ ignoreErrors:
- '@typescript-eslint/eslint-plugin' # peer dependency of standard-with-typescript
- '@typescript-eslint/parser' # peer dependency of @typescript-eslint/eslint-plugin
- '@types/*' # type definitions
- bluebird # features/generator_step_definitions.feature
- coffeescript # features/compiler.feature
- eslint-config-prettier # .eslintrc.yml - extends - prettier
- eslint-config-standard-with-typescript # .eslintrc.yml - extends - standard-with-typescript
Expand Down
7 changes: 3 additions & 4 deletions docs/support_files/timeouts.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,13 @@ Given(/^a slow step$/, {timeout: 60 * 1000}, function() {
Disable timeouts by setting it to -1.
If you use this, you need to implement your own timeout protection.
Otherwise the test suite may end prematurely or hang indefinitely.
The helper `wrapPromiseWithTimeout`, which cucumber-js itself uses to enforce timeouts is available if needed.

```javascript
var {Before, Given} = require('@cucumber/cucumber');
var Promise = require('bluebird');
var {Before, Given, wrapPromiseWithTimeout} = require('@cucumber/cucumber');

Given('the operation completes within {n} minutes', {timeout: -1}, function(minutes) {
const milliseconds = (minutes + 1) * 60 * 1000
const message = `operation did not complete within ${minutes} minutes`
return Promise(this.verifyOperationComplete()).timeout(milliseconds, message);
return wrapPromiseWithTimeout(this.verifyOperationComplete(), milliseconds);
});
```
10 changes: 5 additions & 5 deletions features/attachments.feature
Original file line number Diff line number Diff line change
Expand Up @@ -128,17 +128,17 @@ Feature: Attachments
Given a file named "features/support/hooks.js" with:
"""
const {After} = require('@cucumber/cucumber')
const Promise = require('bluebird')
After(function() {
// Do not return the promise so that the attach happens after the hook completes
Promise.delay(100).then(() => {
// Do not use the callback / promise interface so that the attach happens after the hook completes
setTimeout(() => {
this.attach("text")
})
}, 100)
})
"""
When I run cucumber-js
Then the error output contains the text:
Then it fails
And the error output contains the text:
"""
Cannot attach when a step/hook is not running. Ensure your step/hook waits for the attach to finish.
"""
5 changes: 0 additions & 5 deletions features/before_after_all_hook_interfaces.feature
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ Feature: before / after all hook interfaces
Given a file named "features/step_definitions/failing_steps.js" with:
"""
const {<TYPE>} = require('@cucumber/cucumber')
const Promise = require('bluebird')
<TYPE>(function(callback) {
return Promise.resolve()
Expand All @@ -145,7 +144,6 @@ Feature: before / after all hook interfaces
Given a file named "features/support/hooks.js" with:
"""
const {<TYPE>} = require('@cucumber/cucumber')
const Promise = require('bluebird')
<TYPE>(function() {
return Promise.resolve()
Expand All @@ -163,7 +161,6 @@ Feature: before / after all hook interfaces
Given a file named "features/support/hooks.js" with:
"""
const {<TYPE>} = require('@cucumber/cucumber')
const Promise = require('bluebird')
<TYPE>(function() {
return Promise.reject(new Error('my error'))
Expand All @@ -185,7 +182,6 @@ Feature: before / after all hook interfaces
Given a file named "features/support/hooks.js" with:
"""
const {<TYPE>} = require('@cucumber/cucumber')
const Promise = require('bluebird')
<TYPE>(function() {
return Promise.reject()
Expand All @@ -208,7 +204,6 @@ Feature: before / after all hook interfaces
Given a file named "features/support/hooks.js" with:
"""
const {<TYPE>} = require('@cucumber/cucumber')
const Promise = require('bluebird')
<TYPE>(function() {
return new Promise(function() {
Expand Down
3 changes: 0 additions & 3 deletions features/failing_steps.feature
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ Feature: Failing steps
Given a file named "features/step_definitions/failing_steps.js" with:
"""
const {When} = require('@cucumber/cucumber')
const Promise = require('bluebird')
When(/^a failing step$/, function(callback) {
return Promise.resolve()
Expand All @@ -113,7 +112,6 @@ Feature: Failing steps
Given a file named "features/step_definitions/failing_steps.js" with:
"""
const {When} = require('@cucumber/cucumber')
const Promise = require('bluebird')
When(/^a failing step$/, function() {
return new Promise(function() {
Expand All @@ -134,7 +132,6 @@ Feature: Failing steps
Given a file named "features/step_definitions/failing_steps.js" with:
"""
const {When} = require('@cucumber/cucumber')
const Promise = require('bluebird')
When(/^a failing step$/, function() {
return Promise.reject(new Error('my error'))
Expand Down
5 changes: 0 additions & 5 deletions features/hook_interface.feature
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ Feature: After hook interface
Given a file named "features/step_definitions/failing_steps.js" with:
"""
const {<TYPE>} = require('@cucumber/cucumber')
const Promise = require('bluebird')
<TYPE>(function(scenario, callback) {
return Promise.resolve()
Expand All @@ -153,7 +152,6 @@ Feature: After hook interface
Given a file named "features/support/hooks.js" with:
"""
const {<TYPE>} = require('@cucumber/cucumber')
const Promise = require('bluebird')
<TYPE>(function() {
return Promise.resolve()
Expand All @@ -171,7 +169,6 @@ Feature: After hook interface
Given a file named "features/support/hooks.js" with:
"""
const {<TYPE>} = require('@cucumber/cucumber')
const Promise = require('bluebird')
<TYPE>(function(){
return Promise.reject(new Error('my error'))
Expand All @@ -193,7 +190,6 @@ Feature: After hook interface
Given a file named "features/support/hooks.js" with:
"""
const {<TYPE>} = require('@cucumber/cucumber')
const Promise = require('bluebird')
<TYPE>(function() {
return Promise.reject()
Expand All @@ -216,7 +212,6 @@ Feature: After hook interface
Given a file named "features/support/hooks.js" with:
"""
const {<TYPE>} = require('@cucumber/cucumber')
const Promise = require('bluebird')
<TYPE>(function(){
return new Promise(function() {
Expand Down
2 changes: 0 additions & 2 deletions features/parallel.feature
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ Feature: Running scenarios in parallel
Given a file named "features/step_definitions/cucumber_steps.js" with:
"""
const {Given} = require('@cucumber/cucumber')
const Promise = require('bluebird')
Given(/^a slow step$/, function(callback) {
setTimeout(callback, 1000)
Expand All @@ -27,7 +26,6 @@ Feature: Running scenarios in parallel
Given a file named "features/step_definitions/cucumber_steps.js" with:
"""
const {BeforeAll, Given} = require('@cucumber/cucumber')
const Promise = require('bluebird')
Given(/^a slow step$/, function(callback) {
setTimeout(callback, 1000)
Expand Down
1 change: 0 additions & 1 deletion features/parameter_types.feature
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ Feature: Parameter types
Given a file named "features/step_definitions/particular_steps.js" with:
"""
const {defineParameterType} = require('@cucumber/cucumber')
const Promise = require('bluebird')
defineParameterType({
regexp: /particular/,
Expand Down
1 change: 0 additions & 1 deletion features/passing_steps.feature
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ Feature: Passing steps
Given a file named "features/step_definitions/passing_steps.js" with:
"""
const {Given} = require('@cucumber/cucumber')
const Promise = require('bluebird')
Given(/^a passing step$/, function() {
return Promise.resolve()
Expand Down
13 changes: 9 additions & 4 deletions features/step_definition_timeouts.feature
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ Feature: Step definition timeouts
Given a file named "features/step_definitions/cucumber_steps.js" with:
"""
const {Given, setDefaultTimeout} = require('@cucumber/cucumber')
const Promise = require('bluebird')
setDefaultTimeout(500)
Expand All @@ -21,15 +20,21 @@ Feature: Step definition timeouts
})
Given(/^a promise step runs slowly$/, function() {
return Promise.resolve().delay(1000)
return new Promise(resolve => {
setTimeout(resolve, 1000)
})
})
Given(/^a promise step runs slowly with an increased timeout$/, {timeout: 1500}, function() {
return Promise.resolve().delay(1000)
return new Promise(resolve => {
setTimeout(resolve, 1000)
})
})
Given(/^a promise step with a disabled timeout$/, {timeout: -1}, function() {
return Promise.resolve().delay(1000)
return new Promise(resolve => {
setTimeout(resolve, 1000)
})
})
"""

Expand Down
42 changes: 22 additions & 20 deletions src/cli/configuration_builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import ArgvParser, {
import fs from 'mz/fs'
import path from 'path'
import OptionSplitter from './option_splitter'
import bluebird from 'bluebird'
import glob from 'glob'
import { promisify } from 'util'
import { IPickleFilterOptions } from '../pickle_filter'
Expand Down Expand Up @@ -119,21 +118,22 @@ export default class ConfigurationBuilder {
unexpandedPaths: string[],
defaultExtension: string
): Promise<string[]> {
const expandedPaths = await bluebird.map(
unexpandedPaths,
async (unexpandedPath) => {
const expandedPaths = await Promise.all(
unexpandedPaths.map(async (unexpandedPath) => {
const matches = await promisify(glob)(unexpandedPath, {
absolute: true,
cwd: this.cwd,
})
const expanded = await bluebird.map(matches, async (match) => {
if (path.extname(match) === '') {
return await promisify(glob)(`${match}/**/*${defaultExtension}`)
}
return [match]
})
const expanded = await Promise.all(
matches.map(async (match) => {
if (path.extname(match) === '') {
return await promisify(glob)(`${match}/**/*${defaultExtension}`)
}
return [match]
})
)
return expanded.flat()
}
})
)
return expandedPaths.flat().map((x) => path.normalize(x))
}
Expand Down Expand Up @@ -206,15 +206,17 @@ export default class ConfigurationBuilder {

async getUnexpandedFeaturePaths(): Promise<string[]> {
if (this.args.length > 0) {
const nestedFeaturePaths = await bluebird.map(this.args, async (arg) => {
const filename = path.basename(arg)
if (filename[0] === '@') {
const filePath = path.join(this.cwd, arg)
const content = await fs.readFile(filePath, 'utf8')
return content.split('\n').map((x) => x.trim())
}
return [arg]
})
const nestedFeaturePaths = await Promise.all(
this.args.map(async (arg) => {
const filename = path.basename(arg)
if (filename[0] === '@') {
const filePath = path.join(this.cwd, arg)
const content = await fs.readFile(filePath, 'utf8')
return content.split('\n').map((x) => x.trim())
}
return [arg]
})
)
const featurePaths = nestedFeaturePaths.flat()
if (featurePaths.length > 0) {
return featurePaths.filter((x) => x !== '')
Expand Down
17 changes: 8 additions & 9 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@ import FormatterBuilder from '../formatter/builder'
import fs from 'mz/fs'
import path from 'path'
import PickleFilter from '../pickle_filter'
import bluebird from 'bluebird'
import ParallelRuntimeCoordinator from '../runtime/parallel/coordinator'
import Runtime from '../runtime'
import supportCodeLibraryBuilder from '../support_code_library_builder'
import { IdGenerator } from '@cucumber/messages'
import { IFormatterStream } from '../formatter'
import Formatter, { IFormatterStream } from '../formatter'
import { WriteStream as TtyWriteStream } from 'tty'
import { doesNotHaveValue } from '../value_checker'
import { GherkinStreams } from '@cucumber/gherkin-streams'
import { ISupportCodeLibrary } from '../support_code_library_builder/types'
import { IParsedArgvFormatOptions } from './argv_parser'
import HttpStream from '../formatter/http_stream'
import { promisify } from 'util'
import { Writable } from 'stream'

const { incrementing, uuid } = IdGenerator
Expand Down Expand Up @@ -88,9 +88,8 @@ export default class Cli {
formats,
supportCodeLibrary,
}: IInitializeFormattersRequest): Promise<() => Promise<void>> {
const formatters = await bluebird.map(
formats,
async ({ type, outputTo }) => {
const formatters: Formatter[] = await Promise.all(
formats.map(async ({ type, outputTo }) => {
let stream: IFormatterStream = this.stdout
if (outputTo !== '') {
if (outputTo.match(/^https?:\/\//) !== null) {
Expand Down Expand Up @@ -129,7 +128,7 @@ export default class Cli {
cleanup:
stream === this.stdout
? async () => await Promise.resolve()
: bluebird.promisify(stream.end.bind(stream)),
: promisify<any>(stream.end.bind(stream)),
supportCodeLibrary,
}
if (doesNotHaveValue(formatOptions.colorsEnabled)) {
Expand All @@ -145,12 +144,12 @@ export default class Cli {
type = 'progress'
}
return FormatterBuilder.build(type, typeOptions)
}
})
)
return async function () {
await bluebird.each(formatters, async (formatter) => {
for (const formatter of formatters) {
await formatter.finished()
})
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/formatter/progress_bar_formatter_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import ProgressBarFormatter from './progress_bar_formatter'
import { doesHaveValue, doesNotHaveValue } from '../value_checker'
import { PassThrough } from 'stream'
import ProgressBar from 'progress'
import bluebird from 'bluebird'
import { promisify } from 'util'

interface ITestProgressBarFormatterOptions {
runtimeOptions?: Partial<IRuntimeOptions>
Expand Down Expand Up @@ -65,7 +65,7 @@ async function testProgressBarFormatter({
log: logFn,
parsedArgvOptions: {},
stream: passThrough,
cleanup: bluebird.promisify(passThrough.end.bind(passThrough)),
cleanup: promisify(passThrough.end.bind(passThrough)),
supportCodeLibrary,
}) as ProgressBarFormatter
let mocked = false
Expand Down
4 changes: 4 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,12 @@ export {
IWorld,
IWorldOptions,
} from './support_code_library_builder/world'

export {
ITestCaseHookParameter,
ITestStepHookParameter,
} from './support_code_library_builder/types'
export const Status = messages.TestStepResultStatus

// Time helpers
export { wrapPromiseWithTimeout } from './time'
3 changes: 1 addition & 2 deletions src/models/step_definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import Definition, {
} from './definition'
import { parseStepArgument } from '../step_arguments'
import { Expression } from '@cucumber/cucumber-expressions'
import bluebird from 'bluebird'
import { doesHaveValue } from '../value_checker'

export default class StepDefinition extends Definition implements IDefinition {
Expand All @@ -24,7 +23,7 @@ export default class StepDefinition extends Definition implements IDefinition {
step,
world,
}: IGetInvocationDataRequest): Promise<IGetInvocationDataResponse> {
const parameters = await bluebird.all(
const parameters = await Promise.all(
this.expression.match(step.text).map((arg) => arg.getValue(world))
)
if (doesHaveValue(step.argument)) {
Expand Down

0 comments on commit ff02fa4

Please sign in to comment.