Skip to content

Commit

Permalink
CHANGE: @W-16092798@ Update workspace to be optional and add testtools (
Browse files Browse the repository at this point in the history
  • Loading branch information
stephen-carter-at-sf authored Jun 28, 2024
1 parent 5d2a2d4 commit 39d669d
Show file tree
Hide file tree
Showing 26 changed files with 166 additions and 153 deletions.
22 changes: 11 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions packages/T-E-M-P-L-A-T-E/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@salesforce/t-e-m-p-l-a-t-e",
"description": "T-E-M-P-L-A-T-E",
"version": "0.5.0",
"version": "0.6.0",
"author": "The Salesforce Code Analyzer Team",
"license": "BSD-3-Clause license",
"homepage": "https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/overview",
Expand All @@ -14,7 +14,7 @@
"types": "dist/index.d.ts",
"dependencies": {
"@types/node": "^20.0.0",
"@salesforce/code-analyzer-engine-api": "0.5.0"
"@salesforce/code-analyzer-engine-api": "0.6.0"
},
"devDependencies": {
"@eslint/js": "^8.57.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/code-analyzer-core/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@salesforce/code-analyzer-core",
"description": "Core Package for the Salesforce Code Analyzer",
"version": "0.5.1",
"version": "0.6.0",
"author": "The Salesforce Code Analyzer Team",
"license": "BSD-3-Clause license",
"homepage": "https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/overview",
Expand All @@ -13,7 +13,7 @@
"main": "dist/index.js",
"types": "dist/index.d.ts",
"dependencies": {
"@salesforce/code-analyzer-engine-api": "0.5.0",
"@salesforce/code-analyzer-engine-api": "0.6.0",
"@types/js-yaml": "^4.0.9",
"@types/node": "^20.0.0",
"csv-stringify": "^6.5.0",
Expand Down
7 changes: 3 additions & 4 deletions packages/code-analyzer-core/src/code-analyzer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {Workspace, WorkspaceImpl} from "./workspace";


export type SelectOptions = {
workspace: Workspace
workspace?: Workspace
}

export type RunOptions = {
Expand Down Expand Up @@ -93,8 +93,7 @@ export class CodeAnalyzer {
public async selectRules(selectors: string[], selectOptions?: SelectOptions): Promise<RuleSelection> {
selectors = selectors.length > 0 ? selectors : ['Recommended'];

const workspace: Workspace = selectOptions ? selectOptions.workspace : await this.createWorkspace([process.cwd()]);
const allRules: RuleImpl[] = await this.getAllRules(workspace);
const allRules: RuleImpl[] = await this.getAllRules(selectOptions?.workspace);

const ruleSelection: RuleSelectionImpl = new RuleSelectionImpl();
for (const rule of allRules) {
Expand Down Expand Up @@ -133,7 +132,7 @@ export class CodeAnalyzer {
this.eventEmitter.on(eventType, callback);
}

private async getAllRules(workspace: Workspace): Promise<RuleImpl[]> {
private async getAllRules(workspace?: Workspace): Promise<RuleImpl[]> {
const rulePromises: Promise<RuleImpl[]>[] = this.getEngineNames().map(
engineName => this.getAllRulesFor(engineName, {workspace: workspace}));
return (await Promise.all(rulePromises)).flat();
Expand Down
19 changes: 19 additions & 0 deletions packages/code-analyzer-core/test/conversion-safety.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {LogLevel, RuleType, SeverityLevel} from "../src";
import * as engApi from "@salesforce/code-analyzer-engine-api";

// Currently the LogLevel, RuleType, and SeverityLevel enums from the engine api have the same values as their
// counterparts in core. But if there values every get out of sync, then this test will serve as a reminder to update
// all of our code where we use the "as" cast operator to convert from one to another.
describe('Tests to check that we can safely convert enums to and from core and the engine api', () => {
it('When converting engApi.LogLevel to LogLevel or vice-verca, make sure the enums are the same', () => {
expect(LogLevel).toEqual(engApi.LogLevel);
});

it('When converting engApi.RuleType to RuleType or vice-verca, make sure the enums are the same', () => {
expect(RuleType).toEqual(engApi.RuleType);
});

it('When converting engApi.SeverityLevel to SeverityLevel or vice-verca, make sure the enums are the same', () => {
expect(SeverityLevel).toEqual(engApi.SeverityLevel);
});
});
12 changes: 2 additions & 10 deletions packages/code-analyzer-core/test/rule-selection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,11 @@ describe('Tests for selecting rules', () => {
getMessage('EngineReturnedMultipleRulesWithSameName', 'repeatedRuleNameEngine', 'repeatedRule'));
});

it('When selectRules is not provided with SelectOptions, then cwd is provided by default for workspaceFiles', async () => {
it('When selectRules is not provided with SelectOptions, then workspace should be undefined for all engines', async () => {
await codeAnalyzer.selectRules(['all']);

const expectedDescribeOptions: DescribeOptions = {
workspace: new WorkspaceImpl("FixedId", [process.cwd()])
workspace: undefined
};
const stubEngine1: stubs.StubEngine1 = plugin.getCreatedEngine('stubEngine1') as stubs.StubEngine1;
expect(stubEngine1.describeRulesCallHistory).toEqual([{describeOptions: expectedDescribeOptions}]);
Expand All @@ -268,14 +268,6 @@ describe('Tests for selecting rules', () => {
});
});

describe('Misc tests', () => {
it('When converting from a RuleDescription to a Rule, we need to make sure the SeverityLevel enums are the same', () => {
// Current the SeverityLevel from the engine api is the same name as the SeverityLevel from core. But if this
// ever changes, then this test will serve as a reminder to update our getSeverityLevel method of RuleImpl.
expect(SeverityLevel).toEqual(EngApi_SeverityLevel)
});
});


function ruleNamesFor(selection: RuleSelection, engineName: string): string[] {
return selection.getRulesFor(engineName).map(r => r.getName());
Expand Down
2 changes: 1 addition & 1 deletion packages/code-analyzer-core/test/run.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {changeWorkingDirectoryToPackageRoot, FixedClock, FixedUniqueIdGenerator}
import * as engApi from "@salesforce/code-analyzer-engine-api"
import {UnexpectedEngineErrorRule} from "../src/rules";
import {UndefinedCodeLocation} from "../src/results";
import {Workspace, WorkspaceImpl} from "../src/workspace";
import {WorkspaceImpl} from "../src/workspace";

changeWorkingDirectoryToPackageRoot();

Expand Down
7 changes: 5 additions & 2 deletions packages/code-analyzer-engine-api/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@salesforce/code-analyzer-engine-api",
"description": "Engine API Package for the Salesforce Code Analyzer",
"version": "0.5.0",
"version": "0.6.0",
"author": "The Salesforce Code Analyzer Team",
"license": "BSD-3-Clause license",
"homepage": "https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/overview",
Expand All @@ -10,7 +10,10 @@
"url": "git+https://github.com/forcedotcom/code-analyzer-core.git",
"directory": "packages/code-analyzer-core"
},
"main": "dist/index.js",
"exports": {
".": "./dist/index.js",
"./testtools": "./dist/testtools/index.js"
},
"types": "dist/index.d.ts",
"dependencies": {
"@types/node": "^20.0.0"
Expand Down
4 changes: 3 additions & 1 deletion packages/code-analyzer-engine-api/src/engines.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ export interface Workspace {
}

export type DescribeOptions = {
workspace: Workspace
// The workspace may or may not be available. If available then it can be used to give a more accurate list
// of rules back to the user if the rules are dependent upon what files are in the workspace.
workspace?: Workspace
}

export type PathPoint = {
Expand Down
5 changes: 5 additions & 0 deletions packages/code-analyzer-engine-api/src/testtools/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// TODO: We will gradually fill this in with test tools that engines can use for testing purposes

export {
createWorkspace
} from "./workspace"
48 changes: 48 additions & 0 deletions packages/code-analyzer-engine-api/src/testtools/workspace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {Workspace} from "../engines";
import fs from "node:fs";
import path from "node:path";

export function createWorkspace(absFilesAndFolders: string[], workspaceId: string = 'someWorkspaceId'): Workspace {
return new WorkspaceForTesting(workspaceId, absFilesAndFolders);
}

class WorkspaceForTesting implements Workspace {
private readonly workspaceId: string;
private readonly filesAndFolders: string[];
private expandedFiles?: string[];

constructor(workspaceId: string, absFilesAndFolders: string[]) {
this.workspaceId = workspaceId;
this.filesAndFolders = absFilesAndFolders;
}

getWorkspaceId(): string {
return this.workspaceId;
}

getFilesAndFolders(): string[] {
return this.filesAndFolders;
}

async getExpandedFiles(): Promise<string[]> {
if (!this.expandedFiles) {
this.expandedFiles = await expandToListAllFiles(this.filesAndFolders);
}
return this.expandedFiles as string[];
}
}

export async function expandToListAllFiles(absoluteFileOrFolderPaths: string[]): Promise<string[]> {
const allFiles: string[] = [];
async function processPath(currentPath: string): Promise<void> {
if ((await fs.promises.stat(currentPath)).isDirectory()) {
const subPaths: string[] = await fs.promises.readdir(currentPath);
const absSubPaths: string[] = subPaths.map(f => path.join(currentPath, f));
await Promise.all(absSubPaths.map(processPath)); // Process subdirectories recursively
} else {
allFiles.push(currentPath);
}
}
await Promise.all(absoluteFileOrFolderPaths.map(processPath));
return allFiles.sort();
}
Empty file.
Empty file.
22 changes: 22 additions & 0 deletions packages/code-analyzer-engine-api/test/testtools.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as testTools from "../src/testtools";
import {Workspace} from "../src";
import path from "node:path";

describe('Tests for the various testtools', () => {
it('The createWorkspace tool returns a fully functional workspace for testing purposes', async () => {
const sampleWorkspaceFolder: string = path.resolve(__dirname, 'test-data', 'sampleWorkspace');
const workspace: Workspace = testTools.createWorkspace([sampleWorkspaceFolder]);
expect(workspace.getWorkspaceId()).toEqual("someWorkspaceId");
expect(workspace.getFilesAndFolders()).toEqual([sampleWorkspaceFolder]);
expect(await workspace.getExpandedFiles()).toEqual([
path.join(sampleWorkspaceFolder, 'someFile.txt'),
path.join(sampleWorkspaceFolder, 'sub1', 'someFileInSub1.txt'),
path.join(sampleWorkspaceFolder, 'sub1', 'sub2', 'someFile1InSub2.txt'),
path.join(sampleWorkspaceFolder, 'sub1', 'sub2', 'someFile2InSub2.txt'),
path.join(sampleWorkspaceFolder, 'sub1', 'sub3', 'someFileInSub3.txt'),
]);

const workspace2: Workspace = testTools.createWorkspace([sampleWorkspaceFolder], 'aDifferentWorkspaceId');
expect(workspace2.getWorkspaceId()).toEqual('aDifferentWorkspaceId');
});
});
4 changes: 2 additions & 2 deletions packages/code-analyzer-eslint-engine/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@salesforce/code-analyzer-eslint-engine",
"description": "Plugin package that adds 'eslint' as an engine into Salesforce Code Analyzer",
"version": "0.5.0",
"version": "0.6.0",
"author": "The Salesforce Code Analyzer Team",
"license": "BSD-3-Clause license",
"homepage": "https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/overview",
Expand All @@ -14,7 +14,7 @@
"types": "dist/index.d.ts",
"dependencies": {
"@types/node": "^20.0.0",
"@salesforce/code-analyzer-engine-api": "0.5.0"
"@salesforce/code-analyzer-engine-api": "0.6.0"
},
"devDependencies": {
"@eslint/js": "^8.57.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/code-analyzer-regex-engine/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@salesforce/code-analyzer-regex-engine",
"description": "Regex Engine for Salesforce Code Analyzer",
"version": "0.5.0",
"version": "0.6.0",
"author": "The Salesforce Code Analyzer Team",
"license": "BSD-3-Clause license",
"homepage": "https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/overview",
Expand All @@ -14,7 +14,7 @@
"types": "dist/index.d.ts",
"dependencies": {
"@types/node": "^20.0.0",
"@salesforce/code-analyzer-engine-api": "0.5.0"
"@salesforce/code-analyzer-engine-api": "0.6.0"
},
"devDependencies": {
"@eslint/js": "^8.57.0",
Expand Down
11 changes: 6 additions & 5 deletions packages/code-analyzer-regex-engine/test/engine.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import {RegexEnginePlugin, RegexEngine} from "../src/RegexEnginePlugin";
import {changeWorkingDirectoryToPackageRoot, WorkspaceForTesting} from "./test-helpers";
import {changeWorkingDirectoryToPackageRoot} from "./test-helpers";
import {
RuleDescription,
RuleType,
SeverityLevel
} from "@salesforce/code-analyzer-engine-api";
import * as testTools from "@salesforce/code-analyzer-engine-api/testtools"

changeWorkingDirectoryToPackageRoot();

Expand All @@ -21,7 +22,7 @@ describe('Regex Engine Tests', () => {
});

it('Calling describeRules on an engine should return the single trailing whitespace rule', async () => {
const rules_desc: RuleDescription[]= await engine.describeRules({workspace: new WorkspaceForTesting([])});
const rules_desc: RuleDescription[]= await engine.describeRules({workspace: testTools.createWorkspace([])});
const engineRules = [
{
name: "TrailingWhitespaceRule",
Expand All @@ -37,7 +38,7 @@ describe('Regex Engine Tests', () => {

it('Confirm runRules() is a no-op', () => {
const ruleNames: string[] = ['TrailingWhitespaceRule']
engine.runRules(ruleNames, {workspace: new WorkspaceForTesting([])});
engine.runRules(ruleNames, {workspace: testTools.createWorkspace([])});
})
});

Expand Down Expand Up @@ -70,13 +71,13 @@ describe('RegexEnginePlugin Tests' , () => {
resourceUrls: [""]
},
];
const engineRules: RuleDescription[] = await pluginEngine.describeRules({workspace: new WorkspaceForTesting([])})
const engineRules: RuleDescription[] = await pluginEngine.describeRules({workspace: testTools.createWorkspace([])})
expect(engineRules).toStrictEqual(expEngineRules)
});

it('Check that engine created from the RegexEnginePlugin has runRules() method as a no-op', () => {
const ruleNames: string[] = ['TrailingWhitespaceRule']
pluginEngine.runRules(ruleNames, {workspace: new WorkspaceForTesting([])});
pluginEngine.runRules(ruleNames, {workspace: testTools.createWorkspace([])});
});

it('If I make an engine with an invalid name, it should throw an error with the proper error message', () => {
Expand Down
Loading

0 comments on commit 39d669d

Please sign in to comment.