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

Added unit tests (AST-80092) #1033

Merged
merged 10 commits into from
Jan 26, 2025
Merged
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
3 changes: 1 addition & 2 deletions .github/workflows/ci-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ jobs:
with:
name: screenshots
path: /Users/runner/work/ast-vscode-extension/ast-vscode-extension/test-resources/screenshots/*.png

unit-tests:
strategy:
max-parallel: 1
Expand All @@ -64,7 +63,7 @@ jobs:
- name: Run unit tests with coverage
run: npm run unit-coverage

integration-tests:
ui-tests:
strategy:
max-parallel: 1
matrix:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ test-resources
.idea/
.DS_Store
.npmrc
coverage/
17 changes: 16 additions & 1 deletion package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,7 @@
"@types/chai": "4.3.11",
"@types/mocha": "10.0.6",
"@types/node": "^22.9.0",
"@types/sinon": "^17.0.3",
"@types/vscode": "^1.50.0",
"@typescript-eslint/eslint-plugin": "^7.0.1",
"@typescript-eslint/parser": "^7.2.0",
Expand Down
40 changes: 40 additions & 0 deletions src/unit/authValidate.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { expect } from "chai";
import "./mocks/vscode-mock";
import "./mocks/cxWrapper-mock";
import { cx } from "../cx";
import { Logs } from "../models/logs";

describe("Cx - authValidate", () => {
let logs: Logs;


beforeEach(() => {
const mockOutputChannel = {
append: () => {},
appendLine: () => {},
clear: () => {},
show: () => {},
hide: () => {},
dispose: () => {},
replace: () => {},
name: "Test"
};

logs = {
info: () => {},
error: () => {},
output: mockOutputChannel,
log: () => {},
warn: () => {},
show: () => {}
} as Logs;
});

it("should return true when authentication is successful", async () => {
// Using valid API key from vscode mock
const result = await cx.authValidate(logs);
expect(result).to.be.true;
});


});
48 changes: 48 additions & 0 deletions src/unit/commonCommand.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { expect } from "chai";
import "./mocks/vscode-mock";
import { CommonCommand } from "../commands/commonCommand";
import { Logs } from "../models/logs";
import * as vscode from "vscode";
import { getCommandsExecuted, clearCommandsExecuted } from "./mocks/vscode-mock";

describe("CommonCommand", () => {
let commonCommand: CommonCommand;
let logs: Logs;
let mockContext: vscode.ExtensionContext;

beforeEach(() => {
clearCommandsExecuted();

const mockOutputChannel = {
append: () => {},
appendLine: () => {},
clear: () => {},
show: () => {},
hide: () => {},
dispose: () => {},
replace: () => {},
name: "Test"
};

logs = {
info: () => {},
error: () => {},
output: mockOutputChannel,
log: () => {},
warn: () => {},
show: () => {}
} as Logs;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
mockContext = { subscriptions: [] } as any;

commonCommand = new CommonCommand(mockContext, logs);
});

describe("executeCheckSettings", () => {
it("should execute setContext command with correct parameters", () => {
commonCommand.executeCheckSettings();
expect(getCommandsExecuted()).to.include("setContext");
});
});
});
232 changes: 232 additions & 0 deletions src/unit/details.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import "./mocks/vscode-mock";
import * as vscode from "vscode";
import { expect } from "chai";
import * as sinon from "sinon";
import { Details } from "../utils/interface/details";
import { AstResult } from "../models/results";
import { constants } from "../utils/common/constants";
import { messages } from "../utils/common/messages";
import CxMask from "@checkmarxdev/ast-cli-javascript-wrapper/dist/main/mask/CxMask";

describe("Details", () => {
let details: Details;
let mockContext: vscode.ExtensionContext;
let mockResult: AstResult;
let sandbox: sinon.SinonSandbox;

beforeEach(() => {
sandbox = sinon.createSandbox();

mockContext = {
subscriptions: [],
extensionUri: vscode.Uri.parse("file:///mock"),
extensionPath: "/mock",
} as any;

mockResult = {
label: "Test_Result",
type: "sast",
severity: "HIGH",
state: "NEW",
description: "Test description",
data: {
value: "test value",
remediation: "test remediation",
ruleDescription: "test rule description"
},
getKicsValues: () => "test kics values",
getTitle: () => "<h2>Test Title</h2>",
getHtmlDetails: () => "<tr><td>Test Details</td></tr>",
scaContent: () => "test sca content",
scaNode: {
packageIdentifier: "test-package"
}
} as any as AstResult;

details = new Details(mockResult, mockContext, true);
});

afterEach(() => {
sandbox.restore();
});

describe("header", () => {
it("should generate correct header HTML", () => {
const severityPath = vscode.Uri.parse("file:///mock/severity.png");
const html = details.header(severityPath);

expect(html).to.include("Test Result"); // Checks if underscore is replaced
expect(html).to.include(severityPath.toString());
expect(html).to.include("header-container");
});
});

describe("changes", () => {
it("should generate changes section with triage", () => {
const html = details.changes("test-class");

expect(html).to.include("history-container-loader");
expect(html).to.include("select_severity");
expect(html).to.include("select_state");
});
});

describe("triage", () => {
it("should generate triage section for SAST", () => {
const html = details.triage("test-class");

expect(html).to.include("select_severity");
expect(html).to.include("select_state");
expect(html).to.include("Update");
expect(html).to.include("comment_box");
});

it("should generate triage section for SCA without comment and update button", () => {
mockResult.type = constants.sca;
const html = details.triage("test-class");

expect(html).to.include("select_severity");
expect(html).to.include("select_state");
expect(html).to.not.include("Update");
expect(html).to.not.include("comment_box");
});
});

describe("generalTab", () => {
it("should generate general tab content", () => {
const cxPath = vscode.Uri.parse("file:///mock/cx.png");
const html = details.generalTab(cxPath);

expect(html).to.include("Test description");
expect(html).to.include("test kics values");
expect(html).to.include("Test Title");
expect(html).to.include("Test Details");
});
});

describe("secretDetectiongeneralTab", () => {
it("should generate secret detection general tab", () => {
const html = details.secretDetectiongeneralTab();
expect(html).to.include("Test description");
});
});

describe("scaView", () => {
it("should generate SCA view content", () => {
const paths = {
severityPath: vscode.Uri.parse("file:///mock/severity.png"),
scaAtackVector: vscode.Uri.parse("file:///mock/attack.png"),
scaComplexity: vscode.Uri.parse("file:///mock/complexity.png"),
scaAuthentication: vscode.Uri.parse("file:///mock/auth.png"),
scaConfidentiality: vscode.Uri.parse("file:///mock/confidentiality.png"),
scaIntegrity: vscode.Uri.parse("file:///mock/integrity.png"),
scaAvailability: vscode.Uri.parse("file:///mock/availability.png"),
scaUpgrade: vscode.Uri.parse("file:///mock/upgrade.png"),
scaUrl: vscode.Uri.parse("file:///mock/url.png")
};

const html = details.scaView(
paths.severityPath,
paths.scaAtackVector,
paths.scaComplexity,
paths.scaAuthentication,
paths.scaConfidentiality,
paths.scaIntegrity,
paths.scaAvailability,
paths.scaUpgrade,
paths.scaUrl
);

expect(html).to.include("test-package");
expect(html).to.include("test sca content");
});
});

describe("secretDetectionDetailsRemediationTab", () => {
it("should show remediation content when available", () => {
const html = details.secretDetectionDetailsRemediationTab();
expect(html).to.include("test remediation");
});

it("should show no remediation message when content unavailable", () => {
mockResult.data.remediation = undefined;
const html = details.secretDetectionDetailsRemediationTab();
expect(html).to.include(messages.noRemediationExamplesTab);
});
});

describe("secretDetectionDetailsDescriptionTab", () => {
it("should show description content when available", () => {
const html = details.secretDetectionDetailsDescriptionTab();
expect(html).to.include("test rule description");
});

it("should show no description message when content unavailable", () => {
mockResult.data.ruleDescription = undefined;
const html = details.secretDetectionDetailsDescriptionTab();
expect(html).to.include(messages.noDescriptionTab);
});
});

describe("generateMaskedSection", () => {
it("should generate HTML for masked secrets", () => {
const masked: CxMask = {
maskedSecrets: [
{
secret: "password123",
masked: "********",
line: 42
}
]
} as CxMask;

details.masked = masked;
const html = details.generateMaskedSection();

expect(html).to.include("password123");
expect(html).to.include("********");
expect(html).to.include("Line: 42");
});



it("should show no secrets message when no secrets are masked", () => {
const html = details.generateMaskedSection();
expect(html).to.include("No secrets were detected and masked");
});
});

describe("tab", () => {
it("should generate tabs structure with provided content", () => {
const html = details.tab(
"tab1 content",
"tab2 content",
"tab3 content",
"Tab 1",
"Tab 2",
"Tab 3",
"Tab 4",
"tab4 content",
"Tab 6",
"tab6 content"
);

expect(html).to.include("tab1 content");
expect(html).to.include("tab2 content");
expect(html).to.include("tab3 content");
expect(html).to.include("tab4 content");
expect(html).to.include("tab6 content");
expect(html).to.include("Tab 1");
expect(html).to.include("Tab 2");
expect(html).to.include("Tab 3");
expect(html).to.include("Tab 4");
expect(html).to.include("Tab 6");
});

it("should handle empty tab content and labels", () => {
const html = details.tab("", "", "", "", "", "", "", "", "", "");
expect(html.trim()).to.equal("");
});
});
});
Loading
Loading