Skip to content
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Property | Description
`rubyTestExplorer.debuggerPort` | Define the port to connect the debugger to, for example `1234`.
`rubyTestExplorer.debugCommand` | Define how to run rdebug-ide, for example `rdebug-ide` or `bundle exec rdebug-ide`.
`rubyTestExplorer.rspecCommand` | Define the command to run RSpec tests with, for example `bundle exec rspec`, `spring rspec`, or `rspec`.
`rubyTestExplorer.rspecDirectory` | Define the relative directory of the specs in a given workspace, for example `./spec/`.
`rubyTestExplorer.rspecDirectory` | Define the relative directory of the specs in a given workspace, for example `./spec/`, or an array of directories like `["./spec/", "./engines/admin/spec/"]`.
`rubyTestExplorer.minitestCommand` | Define how to run Minitest with Rake, for example `./bin/rake`, `bundle exec rake` or `rake`. Must be a Rake command.
`rubyTestExplorer.minitestDirectory` | Define the relative location of your `test` directory, for example `./test/`.

Expand Down
10 changes: 8 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,15 @@
"scope": "resource"
},
"rubyTestExplorer.rspecDirectory": {
"markdownDescription": "The location of your RSpec directory relative to the root of the workspace.",
"markdownDescription": "The location of your RSpec directory relative to the root of the workspace. Can be a single path or an array of paths.",
"default": "./spec/",
"type": "string",
"type": [
"string",
"array"
],
"items": {
"type": "string"
},
"scope": "resource"
},
"rubyTestExplorer.minitestCommand": {
Expand Down
23 changes: 10 additions & 13 deletions src/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,24 +223,21 @@ export class RubyAdapter implements TestAdapter {
/**
* Get the test directory based on the configuration value if there's a configured test framework.
*/
private getTestDirectory(): string | undefined {
private getTestDirectories(): string[] {
let testFramework = this.getTestFramework();
let testDirectory = '';

if (testFramework === 'rspec') {
testDirectory =
(vscode.workspace.getConfiguration('rubyTestExplorer', null).get('rspecDirectory') as string)
|| path.join('.', 'spec');
let configured = vscode.workspace.getConfiguration('rubyTestExplorer', null).get('rspecDirectory') as string | string[] | undefined;
let directories = Array.isArray(configured) ? configured : [configured || path.join('.', 'spec')];
return directories.map((directory) => path.join(this.workspace.uri.fsPath, directory));
} else if (testFramework === 'minitest') {
testDirectory =
let testDirectory =
(vscode.workspace.getConfiguration('rubyTestExplorer', null).get('minitestDirectory') as string)
|| path.join('.', 'test');
return [path.join(this.workspace.uri.fsPath, testDirectory)];
}

if (testDirectory === '') {
return undefined;
}

return path.join(this.workspace.uri.fsPath, testDirectory);
return [];
}

/**
Expand All @@ -256,10 +253,10 @@ export class RubyAdapter implements TestAdapter {
const filename = document.uri.fsPath;
this.log.info(`${filename} was saved - checking if this effects ${this.workspace.uri.fsPath}`);
if (filename.startsWith(this.workspace.uri.fsPath)) {
let testDirectory = this.getTestDirectory();
let testDirectories = this.getTestDirectories();

// In the case that there's no configured test directory, we shouldn't try to reload the tests.
if (testDirectory !== undefined && filename.startsWith(testDirectory)) {
if (testDirectories.some((testDirectory) => filename.startsWith(testDirectory))) {
this.log.info('A test file has been edited, reloading tests.');
this.load();
}
Expand Down
29 changes: 25 additions & 4 deletions src/rspecTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,9 @@ export class RspecTests extends Tests {
*/
protected getTestCommandWithFilePattern(): string {
let command: string = (vscode.workspace.getConfiguration('rubyTestExplorer', null).get('rspecCommand') as string);
const dir = this.getTestDirectory();
let pattern = this.getFilePattern().map(p => `${dir}/**{,/*/**}/${p}`).join(',')
let pattern = this.getTestDirectories()
.flatMap((dir) => this.getFilePattern().map((p) => `${dir}**{,/*/**}/${p}`))
.join(',');
command = command || `bundle exec rspec`
return `${command} --pattern '${pattern}'`;
}
Expand All @@ -116,8 +117,28 @@ export class RspecTests extends Tests {
* @return The spec directory
*/
getTestDirectory(): string {
let directory: string = (vscode.workspace.getConfiguration('rubyTestExplorer', null).get('rspecDirectory') as string);
return directory || './spec/';
return this.getTestDirectories()[0];
}

protected getTestDirectories(): string[] {
let directories = vscode.workspace.getConfiguration('rubyTestExplorer', null).get('rspecDirectory') as string | string[] | undefined;

if (Array.isArray(directories) && directories.length > 0) {
return directories.map((directory) => this.normalizeDirectory(directory));
}

return [this.normalizeDirectory((directories as string | undefined) || './spec/')];
}

private normalizeDirectory(directory: string): string {
let normalized = directory.replace(/\\/g, '/');
if (!normalized.startsWith('./')) {
normalized = `./${normalized}`;
}
if (!normalized.endsWith('/')) {
normalized = `${normalized}/`;
}
return normalized;
}

/**
Expand Down
32 changes: 26 additions & 6 deletions src/tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,30 @@ export abstract class Tests {
}

/**
* Get the user-configured test directory, if there is one.
* Get the user-configured primary test directory.
*
* @return The test directory
*/
abstract getTestDirectory(): string;

/**
* Get all configured test directories.
*
* Defaults to a single configured directory, but subclasses can override
* this to support multiple roots.
*/
protected getTestDirectories(): string[] {
return [this.getTestDirectory()];
}

protected getMatchingTestDirectory(filePath: string): string {
return this.getTestDirectories().find((directory) => filePath.startsWith(directory)) || this.getTestDirectory();
}

protected stripTestDirectory(filePath: string): string {
return filePath.replace(this.getMatchingTestDirectory(filePath), '');
}

/**
* Pull JSON out of the test framework output.
*
Expand Down Expand Up @@ -206,10 +224,12 @@ export abstract class Tests {

let currentFileLabel = '';

const matchingDirectory = this.getMatchingTestDirectory(currentFile);

if (directory) {
currentFileLabel = currentFile.replace(`${this.getTestDirectory()}${directory}/`, '');
currentFileLabel = currentFile.replace(`${matchingDirectory}${directory}/`, '');
} else {
currentFileLabel = currentFile.replace(`${this.getTestDirectory()}`, '');
currentFileLabel = currentFile.replace(`${matchingDirectory}`, '');
}

let pascalCurrentFileLabel = this.snakeToPascalCase(currentFileLabel.replace('_spec.rb', ''));
Expand Down Expand Up @@ -294,7 +314,7 @@ export abstract class Tests {

// Remove the spec/ directory from all the file path.
uniqueFiles.forEach((file) => {
splitFilesArray.push(file.replace(`${this.getTestDirectory()}`, "").split('/'));
splitFilesArray.push(this.stripTestDirectory(file).split('/'));
});

// This gets the main types of tests, e.g. features, helpers, models, requests, etc.
Expand All @@ -312,7 +332,7 @@ export abstract class Tests {
let filesInDirectory: Array<TestSuiteInfo> = [];

let uniqueFilesInDirectory: Array<string> = uniqueFiles.filter((file) => {
return file.startsWith(`${this.getTestDirectory()}${directory}/`);
return this.getTestDirectories().some((testDirectory) => file.startsWith(`${testDirectory}${directory}/`));
});

// Get the sets of tests for each file in the current directory.
Expand All @@ -336,7 +356,7 @@ export abstract class Tests {

// Get files that are direct descendants of the spec/ directory.
let topDirectoryFiles = uniqueFiles.filter((filePath) => {
return filePath.replace(`${this.getTestDirectory()}`, "").split('/').length === 1;
return this.stripTestDirectory(filePath).split('/').length === 1;
});

topDirectoryFiles.forEach((currentFile) => {
Expand Down