Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add config param to enable rerun multiple times #68

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,5 +219,28 @@ export const config = {
// ...
}
```

### allowMultipleReruns
Allows multiple retries when set to true.
This will clear the configured `rerunDataDir` before a test run and set the environment variable `DISABLE_RERUN = false` in the created rerun script.

Type: `boolean`

Default: `false`

Example:
```js
import RerunService from 'wdio-rerun-service';
export const config = {
// ...
services: [
[RerunService, {
allowMultipleReruns: true
}]
],
// ...
}
```

----

24 changes: 19 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Capabilities, Frameworks, Options, Services } from '@wdio/types'
import minimist from 'minimist'
import { mkdir, readdir, readFile, writeFile } from 'node:fs/promises'
import { mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises'
import { join } from 'node:path'
import { argv, env, platform } from 'node:process'
import { v4 as uuidv4 } from 'uuid'
Expand All @@ -22,6 +22,7 @@ interface RerunServiceOptions {
rerunScriptPath?: string
commandPrefix?: string
customParameters?: string
allowMultipleReruns?: boolean
}

export default class RerunService implements Services.ServiceInstance {
Expand All @@ -34,6 +35,7 @@ export default class RerunService implements Services.ServiceInstance {
customParameters: string
specFile: string
disabled: boolean
allowMultipleReruns: boolean

constructor(options: RerunServiceOptions = {}) {
const {
Expand All @@ -42,6 +44,7 @@ export default class RerunService implements Services.ServiceInstance {
rerunScriptPath,
commandPrefix,
customParameters,
allowMultipleReruns,
} = options
this.nonPassingItems = []
this.serviceWorkerId = ''
Expand All @@ -52,7 +55,11 @@ export default class RerunService implements Services.ServiceInstance {
this.commandPrefix = commandPrefix ?? ''
this.customParameters = customParameters ?? ''
this.specFile = ''
this.disabled = env['DISABLE_RERUN'] === 'true'
this.disabled =
allowMultipleReruns === true
? !allowMultipleReruns
: env['DISABLE_RERUN'] === 'true'
this.allowMultipleReruns = allowMultipleReruns ?? false
}

async before(
Expand All @@ -63,7 +70,12 @@ export default class RerunService implements Services.ServiceInstance {
return
}
this.specFile = specs[0] ?? ''
// console.log(`Re-run service is activated. Data directory: ${this.rerunDataDir}`);
// console.log(
// `Re-run service is activated. Data directory: ${this.rerunDataDir}`,
// )
if (this.allowMultipleReruns) {
await rm(this.rerunDataDir, { recursive: true, force: true });
}
await mkdir(this.rerunDataDir, { recursive: true })
this.serviceWorkerId = uuidv4()
}
Expand Down Expand Up @@ -175,10 +187,12 @@ export default class RerunService implements Services.ServiceInstance {
const parsedArgs = minimist(argv.slice(2))
const args = parsedArgs._[0] ? parsedArgs._[0] + ' ' : ''
const prefix = this.commandPrefix ? this.commandPrefix + ' ' : ''
const disableRerunValue = String(!this.allowMultipleReruns)
const disableRerun =
platform === 'win32'
? 'set DISABLE_RERUN=true &&'
: 'DISABLE_RERUN=true'
? `set DISABLE_RERUN=${disableRerunValue} &&`
: `DISABLE_RERUN=${disableRerunValue}`

let rerunCommand = `${prefix}${disableRerun} npx wdio ${args}${this.customParameters}`
const failureLocations = new Set<string>()
for (const file of rerunFiles) {
Expand Down
71 changes: 70 additions & 1 deletion tests/service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ITestCaseHookParameter } from '@cucumber/cucumber'
import { TestStepResultStatus } from '@cucumber/messages'
import { describe, expect, it } from '@jest/globals'
import minimist from 'minimist'
import { readFile, rm } from 'node:fs/promises'
import { mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { argv, platform } from 'node:process'
Expand Down Expand Up @@ -131,6 +131,22 @@ describe('wdio-rerun-service', () => {
expect(service.commandPrefix).toEqual('')
expect(service.customParameters).toEqual('--foobar')
})

it('can configure allowMultipleReruns', async () => {
const service = new RerunService({
allowMultipleReruns: true,
})
await expect(
service.before({}, ['features/sample.feature']),
).resolves.toBeUndefined()
expect(service.ignoredTags).toEqual([])
expect(service.rerunDataDir).toEqual('./results/rerun')
expect(service.rerunScriptPath).toEqual(rerunScriptFile)
expect(service.commandPrefix).toEqual('')
expect(service.customParameters).toEqual('')
expect(service.disabled).toEqual(false)
expect(service.allowMultipleReruns).toEqual(true)
})
})

describe('before', () => {
Expand All @@ -144,6 +160,33 @@ describe('wdio-rerun-service', () => {
const service = new RerunService()
await expect(service.before({}, [])).resolves.toBeUndefined()
})

it('should clear the rerun directory when multiple reruns are allowed', async () => {
await mkdir('./results/rerun', { recursive: true })
await writeFile('./results/rerun/1.txt', 'test')
const service = new RerunService({ allowMultipleReruns: true })
await service.before({}, specFile)
const filesInDir = await readdir('./results/rerun')
expect(filesInDir).toHaveLength(0)
})

it('should not clear the rerun directory when multiple reruns are not allowed', async () => {
await mkdir('./results/rerun', { recursive: true })
await writeFile('./results/rerun/1.txt', 'test')
const service = new RerunService({ allowMultipleReruns: false })
await service.before({}, specFile)
const filesInDir = await readdir('./results/rerun')
expect(filesInDir).toHaveLength(1)
})

it('should not clear the rerun directory when rerun is disabled', async () => {
await mkdir('./results/rerun', { recursive: true })
await writeFile('./results/rerun/1.txt', 'test')
const service = new RerunService()
await service.before({}, specFile)
const filesInDir = await readdir('./results/rerun')
expect(filesInDir).toHaveLength(1)
})
})

describe('afterScenario', () => {
Expand Down Expand Up @@ -388,5 +431,31 @@ describe('wdio-rerun-service', () => {
expect(err?.code).toBe('ENOENT')
expect(rerunScript).toBeUndefined()
})

it('should add failed specs to rerun script if DISABLE_RERUN is set to false', async () => {
process.env['DISABLE_RERUN'] = 'false'
const rerunDataDir = join(tmpdir(), 'rerun-data')
const rerunScriptPath = join(rerunDataDir, rerunScriptFile)
const service = new RerunService({
rerunDataDir,
rerunScriptPath,
allowMultipleReruns: true,
})
await service.before({}, [])
service.nonPassingItems = nonPassingItemsMocha
await service.after()
await service.onComplete()
const disableRerun =
platform === 'win32'
? 'set DISABLE_RERUN=false &&'
: 'DISABLE_RERUN=false'
const rerunScript = await readFile(rerunScriptPath, 'utf8')
const parsedArgs = minimist(argv.slice(2))
const args = parsedArgs._[0] ?? ''
expect(rerunScript).toBe(
`${disableRerun} npx wdio ${args} --spec=tests/sample1.test.ts --spec=tests/sample2.test.ts`,
)
await rm(rerunDataDir, { recursive: true, force: true })
})
})
})