Skip to content

Commit 964ab24

Browse files
committed
feat: changed to monitor test file changes using specs defined in wdio.conf.js
- Modified TestRepository to allow acquisition of spec values in wdio.conf.js - Fixed file pattern acquisition logic in TestFileWatcher - Removed configuration items that are no longer used. - Improved performance by removing unnecessary loop processing
1 parent d437641 commit 964ab24

19 files changed

Lines changed: 146 additions & 104 deletions

package.json

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,6 @@
6262
],
6363
"description": "Glob pattern for WebdriverIO configuration file"
6464
},
65-
"webdriverio.testFilePattern": {
66-
"type": "array",
67-
"items": {
68-
"type": "string"
69-
},
70-
"default": [
71-
"**/*.{spec,test}.{ts,js}",
72-
"**/*.feature"
73-
],
74-
"description": "Glob pattern for test files"
75-
},
7665
"webdriverio.logLevel": {
7766
"type": "string",
7867
"enum": [

src/api/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type { NumericLogLevel } from '../types.js'
66

77
export type WdioConfig = {
88
specs: string[]
9+
specPatterns: string[]
910
framework: string
1011
}
1112

src/config/index.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,12 @@ export class ExtensionConfigManager extends EventEmitter implements vscode.Dispo
2323
const config = vscode.workspace.getConfiguration(EXTENSION_ID)
2424

2525
const configFilePattern = config.get<string[]>('configFilePattern')
26-
const testFilePattern = config.get<string[]>('testFilePattern')
2726

2827
this._globalConfig = {
2928
configFilePattern:
3029
configFilePattern && configFilePattern.length > 0
3130
? configFilePattern
3231
: [...DEFAULT_CONFIG_VALUES.configFilePattern],
33-
testFilePattern:
34-
testFilePattern && testFilePattern.length > 0
35-
? testFilePattern
36-
: [...DEFAULT_CONFIG_VALUES.testFilePattern],
3732
showOutput: this.resolveBooleanConfig(config, 'showOutput', DEFAULT_CONFIG_VALUES.showOutput),
3833
logLevel: config.get<string>('logLevel', DEFAULT_CONFIG_VALUES.logLevel),
3934
}

src/config/watcher.ts

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,49 @@
1-
import { convertUriToPath, type RepositoryManager } from '../test/index.js'
1+
import { convertUriToPath, TestfileWatcher, type RepositoryManager } from '../test/index.js'
22
import { normalizePath } from '../utils/normalize.js'
3-
import { FileWatcherManager } from '../utils/watcher.js'
3+
import { FileWatcherManager, type WatchPattern } from '../utils/watcher.js'
44

55
import type * as vscode from 'vscode'
66
import type { ServerManager } from '../api/index.js'
77
import type { ExtensionConfigManager } from '../config/index.js'
88

99
export class ConfigFileWatcher extends FileWatcherManager {
10+
private readonly testfileWatcher
1011
constructor(
1112
public readonly configManager: ExtensionConfigManager,
1213
private readonly serverManager: ServerManager,
13-
private readonly repositoryManager: RepositoryManager
14+
private readonly repositoryManager: RepositoryManager,
1415
) {
1516
super()
17+
this.testfileWatcher = new TestfileWatcher(repositoryManager)
1618
}
1719

1820
public enable() {
1921
this.createWatchers()
2022
this.configManager.on('update:configFilePattern', () => this.refreshWatchers())
23+
this.testfileWatcher.enable()
2124
}
2225

23-
protected getFilePatterns(): string[] {
24-
return this.configManager.globalConfig.configFilePattern || []
26+
protected getFilePatterns(): WatchPattern[] {
27+
return this.configManager.globalConfig.configFilePattern.map((pattern)=>({ pattern }))
2528
}
2629

2730
protected async handleFileCreate(uri: vscode.Uri): Promise<void> {
2831
const wdioConfigPath = normalizePath(convertUriToPath(uri))
2932
const workspaceUris = await this.configManager.addWdioConfig(wdioConfigPath)
30-
for (const workspaceUri of workspaceUris) {
31-
this.repositoryManager.addWdioConfig(workspaceUri, wdioConfigPath)
32-
}
33+
await Promise.all(workspaceUris.map(async (workspaceUri)=>
34+
await this.repositoryManager.addWdioConfig(workspaceUri, wdioConfigPath)))
35+
36+
this.testfileWatcher.refreshWatchers()
3337
}
3438

35-
protected handleFileChange(uri: vscode.Uri): void | Promise<void> {
36-
const targetRepos = this.repositoryManager.repos.filter((repo) => {
37-
return normalizePath(repo.wdioConfigPath) === normalizePath(convertUriToPath(uri))
38-
})
39-
targetRepos.map((repo) => {
40-
repo.reloadSpecFiles()
41-
})
39+
protected async handleFileChange(uri: vscode.Uri): Promise<void> {
40+
await Promise.all(this.repositoryManager.repos.reduce((repos, repo) => {
41+
if ( normalizePath(repo.wdioConfigPath) === normalizePath(convertUriToPath(uri))) {
42+
repos.push(repo.reloadSpecFiles())
43+
}
44+
return repos
45+
}, [] as Promise<void>[]))
46+
this.testfileWatcher.refreshWatchers()
4247
}
4348

4449
protected async handleFileDelete(uri: vscode.Uri): Promise<void> {
@@ -48,5 +53,11 @@ export class ConfigFileWatcher extends FileWatcherManager {
4853
this.repositoryManager.removeWdioConfig(workspaceUri, wdioConfigPath)
4954
await this.serverManager.reorganize(this.configManager.getWdioConfigPaths())
5055
}
56+
this.testfileWatcher.refreshWatchers()
57+
}
58+
59+
public dispose(): void {
60+
this.testfileWatcher.dispose()
61+
super.dispose()
5162
}
5263
}

src/constants.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ export const EXTENSION_ID = 'webdriverio'
22

33
export const DEFAULT_CONFIG_VALUES = {
44
configFilePattern: ['**/wdio.conf.{ts,js}'],
5-
testFilePattern: ['**/*.{spec,test}.{ts,js}', '**/*.feature'],
65
showOutput: true,
76
logLevel: 'info',
87
} as const

src/extension.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { ServerManager } from './api/index.js'
44
import { configureTests } from './commands/configureTests.js'
55
import { ConfigFileWatcher, ExtensionConfigManager } from './config/index.js'
66
import { EXTENSION_ID } from './constants.js'
7-
import { TestfileWatcher, RepositoryManager } from './test/index.js'
7+
import { RepositoryManager } from './test/index.js'
88
import { log } from './utils/logger.js'
99

1010
let extension: WdioExtension | null = null
@@ -46,12 +46,10 @@ class WdioExtension implements vscode.Disposable {
4646
// Create Manages and watchers
4747
const repositoryManager = new RepositoryManager(this.controller, this.configManager, this.serverManager)
4848
const configFileWatcher = new ConfigFileWatcher(this.configManager, this.serverManager, repositoryManager)
49-
const testfileWatcher = new TestfileWatcher(this.configManager, repositoryManager)
5049

5150
this._disposables = [
5251
vscode.commands.registerCommand('webdriverio.configureTests', configureTests),
5352
vscode.workspace.onDidChangeConfiguration((event) => this.configManager.listener(event)),
54-
testfileWatcher,
5553
configFileWatcher,
5654
repositoryManager,
5755
this.serverManager,
@@ -67,11 +65,12 @@ class WdioExtension implements vscode.Disposable {
6765
repositoryManager.repos.map(async (repo) => {
6866
await repo.discoverAllTests()
6967
})
70-
).then(() => repositoryManager.registerToTestController())
68+
).then(() => {
69+
repositoryManager.registerToTestController()
70+
// Enable watchers
71+
configFileWatcher.enable()
72+
})
7173

72-
// Enable watchers
73-
configFileWatcher.enable()
74-
testfileWatcher.enable()
7574
} catch (error) {
7675
console.log(error)
7776
}

src/test/manager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ export class RepositoryManager implements vscode.Disposable {
170170
isConfigFile: true,
171171
isSpecFile: false,
172172
repository: repo,
173-
runProfile: createRunProfile.call(this, configItem, !this.isCreatedDefaultProfile),
173+
runProfiles: createRunProfile.call(this, configItem, !this.isCreatedDefaultProfile),
174174
}
175175
return configItem
176176
}

src/test/repository.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import type { WdioExtensionWorkerInterface } from '../api/index.js'
1616
* the single WebdriverIO configuration file
1717
*/
1818
export class TestRepository implements vscode.Disposable {
19-
// Mapping for the id and TestItem
20-
private _suiteMap = new Map<string, TestcaseTestItem>()
19+
private _specPatterns:string[] = []
20+
private _suiteMap = new Map<string, TestcaseTestItem>() // Mapping for the id and TestItem
2121
private _fileMap = new Map<string, SpecFileTestItem>()
2222
private _framework: string | undefined = undefined
2323
constructor(
@@ -27,6 +27,10 @@ export class TestRepository implements vscode.Disposable {
2727
private _wdioConfigTestItem: WdioConfigTestItem
2828
) {}
2929

30+
public get specPatterns(){
31+
return this._specPatterns
32+
}
33+
3034
public get framework() {
3135
if (!this._framework) {
3236
throw new Error('The configuration for WebdriverIO is not loaded')
@@ -46,6 +50,7 @@ export class TestRepository implements vscode.Disposable {
4650
}
4751

4852
this._framework = config.framework
53+
this._specPatterns = config.specPatterns
4954

5055
// Get specs from configuration
5156
const allSpecs = this.convertPathString(config.specs)
@@ -77,6 +82,7 @@ export class TestRepository implements vscode.Disposable {
7782
}
7883

7984
this._framework = config.framework
85+
this._specPatterns = config.specPatterns
8086

8187
// Get specs from configuration
8288
const allConfigSpecs = this.convertPathString(config.specs)
@@ -338,6 +344,7 @@ export class TestRepository implements vscode.Disposable {
338344
private resisterSpecFile(id: string, spec: vscode.Uri) {
339345
log.trace(`[repository] spec file was registered: ${id}`)
340346
const fileTestItem = this.controller.createTestItem(id, path.basename(spec.fsPath), spec) as SpecFileTestItem
347+
fileTestItem.sortText = spec.fsPath
341348
fileTestItem['metadata'] = {
342349
isWorkspace: false,
343350
isConfigFile: false,
@@ -391,7 +398,7 @@ export class TestRepository implements vscode.Disposable {
391398
* Dispose of resources
392399
*/
393400
public dispose() {
394-
this._wdioConfigTestItem.metadata.runProfile.dispose()
401+
this._wdioConfigTestItem.metadata.runProfiles.forEach((p)=>p.dispose())
395402
this._suiteMap.clear()
396403
this._fileMap.clear()
397404
}

src/test/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export interface WdioConfigTestItem extends WdioTestItem {
8181
isConfigFile: true
8282
isSpecFile: false
8383
repository: TestRepository
84-
runProfile: vscode.TestRunProfile
84+
runProfiles: vscode.TestRunProfile[]
8585
}
8686
}
8787

src/test/watcher.ts

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,41 @@
1+
import { dirname } from 'node:path'
2+
3+
import * as vscode from 'vscode'
4+
15
import { log } from '../utils/logger.js'
26
import { normalizePath } from '../utils/normalize.js'
3-
import { FileWatcherManager } from '../utils/watcher.js'
7+
import { FileWatcherManager, type WatchPattern } from '../utils/watcher.js'
48

5-
import type * as vscode from 'vscode'
69
import type { RepositoryManager } from './manager.js'
7-
import type { ExtensionConfigManager } from '../config/index.js'
810

911
export class TestfileWatcher extends FileWatcherManager {
1012
constructor(
11-
public readonly configManager: ExtensionConfigManager,
1213
private readonly repositoryManager: RepositoryManager
1314
) {
1415
super()
1516
}
1617

1718
public enable() {
1819
this.createWatchers()
19-
this.configManager.on('update:testFilePattern', () => this.refreshWatchers())
2020
}
2121

22-
protected getFilePatterns(): string[] {
23-
return this.configManager.globalConfig.testFilePattern || []
22+
protected getFilePatterns(): WatchPattern[] {
23+
return this.repositoryManager.repos.reduce((patterns, repo)=>{
24+
const configDirPath = dirname(repo.wdioConfigPath)
25+
for (const pattern of repo.specPatterns) {
26+
patterns.push({
27+
base: vscode.Uri.file(configDirPath),
28+
pattern
29+
})
30+
}
31+
return patterns
32+
}, [] as WatchPattern[])
2433
}
34+
2535
protected async handleFileCreate(uri: vscode.Uri): Promise<void> {
2636
await this._handleFileCreateAndChange(uri, true)
2737
}
38+
2839
protected async handleFileChange(uri: vscode.Uri): Promise<void> {
2940
await this._handleFileCreateAndChange(uri, false)
3041
}
@@ -38,12 +49,15 @@ export class TestfileWatcher extends FileWatcherManager {
3849

3950
// If a Spec file is newly created, attempt to read in all repositories,
4051
// as it is unclear which configuration file should be reflected.
41-
const repos = isCreated
42-
? this.repositoryManager.repos
43-
: this.repositoryManager.repos.filter((repo) => repo.getSpecByFilePath(uri.fsPath))
44-
45-
log.debug(`Affected repository are ${repos.length} repositories`)
46-
await Promise.all(repos.map(async (repo) => await repo.reloadSpecFiles([normalizePath(specFilePath)])))
52+
const promises = this.repositoryManager.repos.reduce((repos, repo)=>{
53+
if (!isCreated && !repo.getSpecByFilePath(specFilePath)) {
54+
return repos
55+
}
56+
repos.push(repo.reloadSpecFiles([normalizePath(specFilePath)]))
57+
return repos
58+
}, [] as Promise<void>[])
59+
log.debug(`Affected repository are ${promises.length} repositories`)
60+
await Promise.all(promises)
4761
}
4862

4963
/**
@@ -52,12 +66,13 @@ export class TestfileWatcher extends FileWatcherManager {
5266
protected async handleFileDelete(uri: vscode.Uri): Promise<void> {
5367
const specFilePath = uri.fsPath
5468
log.debug(`Test file deleted: ${specFilePath}`)
55-
56-
const repos = this.repositoryManager.repos.filter((repo) => repo.getSpecByFilePath(uri.fsPath))
57-
log.debug(`Affected repository are ${repos.length} repositories`)
58-
59-
repos.map(async (repo) => {
60-
repo.removeSpecFile(normalizePath(specFilePath))
61-
})
69+
const count = this.repositoryManager.repos.reduce((counter, repo)=>{
70+
if (!repo.getSpecByFilePath(specFilePath)) {
71+
return counter
72+
}
73+
repo.removeSpecFile(specFilePath)
74+
return ++counter
75+
}, 0)
76+
log.debug(`Affected repository are ${count} repositories`)
6277
}
6378
}

0 commit comments

Comments
 (0)