Skip to content

Commit

Permalink
test: restore removed unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
thisislawatts committed Mar 28, 2024
1 parent 126335b commit 5ae71af
Showing 1 changed file with 290 additions and 1 deletion.
291 changes: 290 additions & 1 deletion test/jest/unit/snyk-code/snyk-code-test.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as os from 'os';
import * as fs from 'fs';
import * as path from 'path';
import stripAnsi = require('strip-ansi');
import { analyzeFolders, AnalysisSeverity } from '@snyk/code-client';
import { makeRequest } from '../../../../src/lib/request';

Expand All @@ -16,9 +17,11 @@ import { config as userConfig } from '../../../../src/lib/user-config';
import * as analysis from '../../../../src/lib/plugins/sast/analysis';
import { Options, TestOptions } from '../../../../src/lib/types';
import * as ecosystems from '../../../../src/lib/ecosystems';
import * as analytics from '../../../../src/lib/analytics';
import snykTest from '../../../../src/cli/commands/test';
import { jsonStringifyLargeObject } from '../../../../src/lib/json';
import { ArgsOptions } from '../../../../src/cli/args';
import * as codeConfig from '../../../../src/lib/code-config';
import { NeedleResponse } from 'needle';

const { getCodeTestResults } = analysis;
Expand All @@ -30,6 +33,8 @@ describe('Test snyk code', () => {

const failedCodeTestMessage = "Failed to run 'code test'";
const fakeApiKey = '123456789';
const baseURL = codeConfig.getCodeClientProxyUrl();
const LCEbaseURL = 'https://my-proxy-server';

const fixturePath = path.join(__dirname, '../../../fixtures/sast');

Expand Down Expand Up @@ -120,6 +125,96 @@ describe('Test snyk code', () => {
);
});

it('should fail - when we do not support files', async () => {
const options: Options & TestOptions = {
path: '',
traverseNodeModules: false,
showVulnPaths: 'none',
code: true,
};

analyzeFoldersMock.mockResolvedValue(null);
isSastEnabledForOrgSpy.mockResolvedValueOnce({
sastEnabled: true,
localCodeEngine: {
enabled: false,
},
});
trackUsageSpy.mockResolvedValue({});

expect.hasAssertions();
try {
await ecosystems.testEcosystem('code', ['some/path'], options);
} catch (error) {
const errMessage = stripAscii(stripAnsi(error.message.trim()));

expect(error.code).toBe(422);
expect(errMessage).toContain('We found 0 supported files');
}
});

it('succeed testing - with correct exit code', async () => {
const options: Options & TestOptions = {
path: '',
traverseNodeModules: false,
showVulnPaths: 'none',
code: true,
};

analyzeFoldersMock.mockResolvedValue(sampleAnalyzeFoldersResponse);
isSastEnabledForOrgSpy.mockResolvedValueOnce({
sastEnabled: true,
localCodeEngine: {
enabled: false,
},
});
trackUsageSpy.mockResolvedValue({});

expect.hasAssertions();
try {
await ecosystems.testEcosystem('code', ['some/path'], options);
} catch (error) {
const errMessage = stripAscii(stripAnsi(error.message.trim()));
const expectedOutput = stripAscii(stripAnsi(testOutput.trim()));

// exit code 1
expect(error.code).toBe('VULNS');
expect(errMessage).toBe(expectedOutput);
}
});

it('should succeed testing from the cli test command - with correct exit code', async () => {
const options: ArgsOptions = {
path: '',
traverseNodeModules: false,
showVulnPaths: 'none',
code: true,
_: [],
_doubleDashArgs: [],
};

analyzeFoldersMock.mockResolvedValue(sampleAnalyzeFoldersResponse);
isSastEnabledForOrgSpy.mockResolvedValueOnce({
sastEnabled: true,
localCodeEngine: {
enabled: false,
},
});
trackUsageSpy.mockResolvedValue({});

expect.hasAssertions();
try {
await snykTest('some/path', options);
} catch (error) {
const errMessage = stripAscii(stripAnsi(error.message.trim()));
const expectedOutput = stripAscii(stripAnsi(testOutput.trim()));

// exit code 1
expect(error.code).toBe('VULNS');
expect(errMessage).toBe(expectedOutput);
}
});

it('should throw error when response code is not 200', async () => {
const error = {
code: 401,
Expand Down Expand Up @@ -160,6 +255,26 @@ describe('Test snyk code', () => {
}
});

it('should show error if sast is not enabled', async () => {
isSastEnabledForOrgSpy.mockResolvedValueOnce({
sastEnabled: false,
localCodeEngine: {
enabled: false,
},
});

await expect(
snykTest('some/path', {
code: true,
_: [],
_doubleDashArgs: [],
}),
).rejects.toHaveProperty(
'userMessage',
'Snyk Code is not supported for org: enable in Settings > Snyk Code',
);
});

it('should show org not found error according to response from api', async () => {
isSastEnabledForOrgSpy.mockResolvedValueOnce({
code: 404,
Expand Down Expand Up @@ -417,6 +532,45 @@ describe('Test snyk code', () => {
}
});

it.each([
['sarif', { sarif: true }],
['json', { json: true }],
])(
'succeed testing with correct exit code - with %p output',
async (optionsName, optionsObject) => {
const options: Options & TestOptions = {
path: '',
traverseNodeModules: false,
showVulnPaths: 'none',
code: true,
...optionsObject,
};

analyzeFoldersMock.mockResolvedValue(sampleAnalyzeFoldersResponse);
isSastEnabledForOrgSpy.mockResolvedValueOnce({
sastEnabled: true,
localCodeEngine: {
enabled: false,
},
});
trackUsageSpy.mockResolvedValue({});

expect.hasAssertions();
try {
await ecosystems.testEcosystem('code', ['some/path'], options);
} catch (error) {
const errMessage = error.message.trim();
const expectedOutput = jsonStringifyLargeObject(
sampleSarifResponse,
).trim();

// exit code 1
expect(error.code).toBe('VULNS');
expect(errMessage).toBe(expectedOutput);
}
},
);

it('succeed testing with correct exit code - with sarif output', async () => {
const options: ArgsOptions = {
path: '',
Expand Down Expand Up @@ -490,7 +644,42 @@ describe('Test snyk code', () => {
}
});

it.each([[{ code: 500 }, failedCodeTestMessage]])(
it('succeed testing with correct exit code - and analytics added', async () => {
const analyticSend = jest.spyOn(analytics, 'add');

const options: Options & TestOptions = {
path: '',
traverseNodeModules: false,
showVulnPaths: 'none',
code: true,
};

analyzeFoldersMock.mockResolvedValue(sampleAnalyzeFoldersResponse);
isSastEnabledForOrgSpy.mockResolvedValueOnce({
sastEnabled: true,
localCodeEngine: {
enabled: false,
},
});
trackUsageSpy.mockResolvedValue({});

try {
await ecosystems.testEcosystem('code', ['some/path'], options);
} catch (error) {
const errMessage = stripAscii(stripAnsi(error.message.trim()));
const expectedOutput = stripAscii(stripAnsi(testOutput.trim()));

// exit code 1
expect(error.code).toBe('VULNS');
expect(errMessage).toBe(expectedOutput);
expect(analyticSend).toBeCalledTimes(2);
}
});

it.each([
[{ code: 401 }, `Unauthorized: ${failedCodeTestMessage}`],
[{ code: 500 }, failedCodeTestMessage],
])(
'given %p argument, we fail with error message %p',
async (errorCodeObj, expectedResult) => {
const codeClientError = {
Expand Down Expand Up @@ -654,6 +843,106 @@ describe('Test snyk code', () => {
expect(actual?.analysisResults.sarif).toEqual(sampleSarifResponse);
});

it.each([
[
"use LCE's url as base when LCE is enabled",
LCEbaseURL,
{
sastEnabled: true,
localCodeEngine: {
url: LCEbaseURL,
allowCloudUpload: false,
enabled: true,
},
},
],
[
"use cloud solution when LCE's feature is not enabled",
baseURL,
{
sastEnabled: true,
localCodeEngine: {
url: LCEbaseURL,
allowCloudUpload: true,
enabled: false,
},
},
],
])(
'Local code engine - analyzeFolders should %s',
async (msg, url, sastSettings) => {
const sessionToken = expect.any(String);
const source = expect.any(String);
const severity = AnalysisSeverity.info;
const paths: string[] = ['.'];

const codeAnalysisArgs = {
connection: {
baseURL: url,
sessionToken,
source,
requestId: 'test-id',
orgId: '',
},
analysisOptions: {
severity,
},
fileOptions: { paths },
analysisContext: {
flow: 'snyk-cli',
initiator: 'CLI',
org: expect.any(Object),
projectName: undefined,
project: expect.any(Object),
},
languages: undefined,
};

const analyzeFoldersSpy = analyzeFoldersMock.mockResolvedValue(
sampleAnalyzeFoldersResponse,
);
await getCodeTestResults(
'.',
{
path: '',
code: true,
},
sastSettings,
'test-id',
);

expect(analyzeFoldersSpy.mock.calls[0]).toEqual([codeAnalysisArgs]);
},
);

it('Local Code Engine - Always calls code-client with url coming from sastSettings', async () => {
const sastSettings = {
sastEnabled: true,
localCodeEngine: {
url: 'http://lce:31111/api',
allowCloudUpload: false,
enabled: true,
},
};

const analyzeFoldersSpy = analyzeFoldersMock.mockResolvedValue(
sampleAnalyzeFoldersResponse,
);
await getCodeTestResults(
'.',
{
path: '',
code: true,
},
sastSettings,
'test-id',
);

expect(analyzeFoldersSpy.mock.calls[0][0].connection.baseURL).toBe(
'http://lce:31111/api',
);
});

it('Local code engine - makes GET /status to get SCLE version', async () => {
const sastSettings = {
sastEnabled: true,
Expand Down

0 comments on commit 5ae71af

Please sign in to comment.