UNPKG

@villedemontreal/scripting

Version:
298 lines 20.1 kB
"use strict"; /* eslint-disable @typescript-eslint/ban-ts-comment */ /* eslint-disable @typescript-eslint/no-misused-promises */ /* eslint-disable @typescript-eslint/no-require-imports */ Object.defineProperty(exports, "__esModule", { value: true }); const chai = require("chai"); const chai_1 = require("chai"); const chai_as_promised_1 = require("chai-as-promised"); const sinon_chai_1 = require("sinon-chai"); const fs = require("fs-extra"); const mocha_1 = require("mocha"); const sinon = require("sinon"); const sonarTestUtils_1 = require("../../src/utils/sonarTestUtils"); const testingUtils_1 = require("../../src/utils/testingUtils"); const sonar_1 = require("./sonar"); const sonarInit_1 = require("./sonarInit"); const nock = require('nock'); chai.use(chai_as_promised_1.default); chai.use(sinon_chai_1.default); const sandbox = sinon.createSandbox(); let shellCommand; let subScript; function getSonarScript(targetBranch, logger) { let options = {}; if (targetBranch) { options = { targetBranch, }; } return new sonar_1.SonarScript({ args: {}, options, program: sinon.stub(), command: sinon.stub(), ddash: sinon.stub(), logger: logger, }); } function simulateCurrentGitLocalBranchIs(currentLocalBranch) { shellCommand.withArgs('git', ['branch', '--show-current'], sinon.match.any).callThrough(); const mockSpawn = require('mock-spawn'); const mySpawn = mockSpawn(); require('child_process').spawn = mySpawn; mySpawn.setDefault(mySpawn.simple(0 /* exit code */, currentLocalBranch /* stdout */)); } function simulateThereIsNoLocalGitRepository() { shellCommand.withArgs('git', ['branch', '--show-current'], sinon.match.any).callThrough(); const mockSpawn = require('mock-spawn'); const mySpawn = mockSpawn(); require('child_process').spawn = mySpawn; const gitOutputMessage = 'fatal: not a git repository (or any of the parent directories): .git'; mySpawn.setDefault(mySpawn.simple(128 /* exit code */, gitOutputMessage /* stdout */)); } const validPropertyFiles = [ './src/utils/test-sonar-project_url-with-trailing-slash.properties', './src/utils/test-sonar-project_url-without-trailing-slash.properties', ]; (0, mocha_1.describe)('sonar script', function () { (0, testingUtils_1.timeout)(this, 30000); before(() => { (0, testingUtils_1.setTestingConfigs)(); // @ts-ignore shellCommand = sandbox.stub(sonar_1.SonarScript.prototype, 'invokeShellCommand'); // @ts-ignore subScript = sandbox.stub(sonar_1.SonarScript.prototype, 'invokeScript'); }); afterEach(() => { sandbox.resetHistory(); sandbox.resetBehavior(); nock.cleanAll(); }); after(() => { sandbox.restore(); }); (0, mocha_1.it)(` should fail when sonar-project.properties is missing`, async () => { const loggerRecorder = new sonarTestUtils_1.LoggerRecorder(); const sonarScript = getSonarScript(null, loggerRecorder.logger); await (0, chai_1.expect)(sonarScript.run()).to.be.rejectedWith(Error, '"sonar-project.properties" file does not exist!'); (0, chai_1.expect)(loggerRecorder.recordedLogs).to.equal(`info: Script "sonar" starting... error: Script "sonar" failed after 0 s with: "sonar-project.properties" file does not exist! `); }); validPropertyFiles.forEach((propertyFile) => { (0, mocha_1.describe)(` when using "${propertyFile}" valid file`, async () => { before(async () => { await fs.copyFile(propertyFile, './sonar-project.properties'); }); after(async () => { await fs.unlink('./sonar-project.properties'); }); (0, mocha_1.it)(` should fail when there is no local git repository`, async () => { simulateThereIsNoLocalGitRepository(); const loggerRecorder = new sonarTestUtils_1.LoggerRecorder(); const sonarScript = getSonarScript(null, loggerRecorder.logger); await (0, chai_1.expect)(sonarScript.run()).to.be.rejectedWith(Error, 'Expected success codes were "0", but the process exited with "128".'); (0, chai_1.expect)(loggerRecorder.recordedLogs) .to.satisfy((s) => s.startsWith(`info: Script "sonar" starting...\n`)) .and.to.contain('info: Executing: git branch,--show-current\n') .and.to.satisfy((s) => s.endsWith('error: Script "sonar" failed after 0 s with: Expected success codes were "0", but the process exited with "128".\n')); (0, chai_1.expect)(subScript).to.not.have.been.called; (0, chai_1.expect)(shellCommand).to.have.been.calledOnceWith('git', ['branch', '--show-current']); }); (0, mocha_1.it)(` should fail when sonar server is not found.`, async () => { simulateCurrentGitLocalBranchIs('current-local-branch'); (0, sonarTestUtils_1.simulateSonarServerIsNotFound)(); const loggerRecorder = new sonarTestUtils_1.LoggerRecorder(); const sonarInitScript = getSonarScript(null, loggerRecorder.logger); await (0, chai_1.expect)(sonarInitScript.run()).to.be.rejectedWith(Error, 'Not Found'); chai_1.assert.isTrue(nock.isDone(), `There are remaining expected HTTP calls: ${nock.pendingMocks().toString()}`); (0, chai_1.expect)(loggerRecorder.recordedLogs) .to.satisfy((s) => s.startsWith('info: Script "sonar" starting...\n')) .and.to.contain.oneOf([ 'error: "https://example.com/sonar/" Sonar server is not reachable.\n', 'error: "https://example.com/sonar" Sonar server is not reachable.\n', ]) .and.to.satisfy((s) => s.endsWith('error: Script "sonar" failed after 0 s with: Not Found\n')); (0, chai_1.expect)(loggerRecorder.recordedLogs).to.not.contain('warn'); (0, chai_1.expect)(shellCommand).to.have.been.calledOnceWith('git', ['branch', '--show-current']); }); (0, mocha_1.describe)(' when project already exists in Sonar', () => { beforeEach(() => { (0, sonarTestUtils_1.simulateSonarProjectAlreadyExists)(); simulateCurrentGitLocalBranchIs('current-local-branch'); }); (0, mocha_1.it)(` should succeed when simple code analysis succeeds.`, async () => { const loggerRecorder = new sonarTestUtils_1.LoggerRecorder(); const sonarScript = getSonarScript(null, loggerRecorder.logger); shellCommand.withArgs(sonar_1.SONAR_SCANNER).returns(0); await sonarScript.run(); (0, chai_1.expect)(loggerRecorder.recordedLogs) .to.satisfy((s) => s.startsWith('info: Script "sonar" starting...\n')) .and.to.contain('info: Analyzing current branch "current-local-branch" source code...\n') .and.to.satisfy((s) => s.endsWith('info: Script "sonar" successful after 0 s\n')); (0, chai_1.expect)(subScript).to.not.have.been.called; (0, chai_1.expect)(shellCommand).to.have.been.calledTwice; (0, chai_1.expect)(shellCommand).to.have.been.calledWith('git', ['branch', '--show-current']); (0, chai_1.expect)(shellCommand).to.have.been.calledWithExactly(sonar_1.SONAR_SCANNER, [ '-Dsonar.branch.name=current-local-branch', ]); }); (0, mocha_1.it)(` should succeed when code analysis against a target branch succeeds.`, async () => { const loggerRecorder = new sonarTestUtils_1.LoggerRecorder(); const sonarScript = getSonarScript('develop', loggerRecorder.logger); shellCommand.withArgs(sonar_1.SONAR_SCANNER).returns(0); await sonarScript.run(); (0, chai_1.expect)(loggerRecorder.recordedLogs) .to.satisfy((s) => s.startsWith('info: Script "sonar" starting...\n')) .and.to.contain('info: Analyzing current branch "current-local-branch" source code...\n') .and.to.satisfy((s) => s.endsWith('info: Script "sonar" successful after 0 s\n')); (0, chai_1.expect)(subScript).to.not.have.been.called; (0, chai_1.expect)(shellCommand).to.have.been.calledTwice; (0, chai_1.expect)(shellCommand).to.have.been.calledWith('git', ['branch', '--show-current']); (0, chai_1.expect)(shellCommand).to.have.been.calledWithExactly(sonar_1.SONAR_SCANNER, [ '-Dsonar.branch.name=current-local-branch', '-Dsonar.branch.target=develop', ]); }); (0, mocha_1.it)(` should fail when simple code analysis fails.`, async () => { const loggerRecorder = new sonarTestUtils_1.LoggerRecorder(); const sonarScript = getSonarScript(null, loggerRecorder.logger); shellCommand .withArgs(sonar_1.SONAR_SCANNER) .rejects(new Error('An error occurred while analyzing source code.')); await (0, chai_1.expect)(sonarScript.run()).to.be.rejectedWith(Error, 'An error occurred while analyzing source code.'); (0, chai_1.expect)(loggerRecorder.recordedLogs) .to.satisfy((s) => s.startsWith('info: Script "sonar" starting...\n')) .and.to.contain('info: Analyzing current branch "current-local-branch" source code...\n') .and.to.satisfy((s) => s.endsWith(`error: Script "sonar" failed after 0 s with: An error occurred while analyzing source code.\n`)); (0, chai_1.expect)(subScript).to.not.have.been.called; (0, chai_1.expect)(shellCommand).to.have.been.calledTwice; (0, chai_1.expect)(shellCommand).to.have.been.calledWith('git', ['branch', '--show-current']); (0, chai_1.expect)(shellCommand).to.have.been.calledWithExactly(sonar_1.SONAR_SCANNER, [ '-Dsonar.branch.name=current-local-branch', ]); }); }); (0, mocha_1.describe)(' when project does not yet exist in Sonar', () => { beforeEach(() => { (0, sonarTestUtils_1.simulateSonarProjectDoesNotYetExist)(); simulateCurrentGitLocalBranchIs('current-local-branch'); }); (0, mocha_1.it)(` should initialize Sonar project with a warning and then successfully analyze code.`, async () => { const loggerRecorder = new sonarTestUtils_1.LoggerRecorder(); const sonarScript = getSonarScript(null, loggerRecorder.logger); shellCommand.withArgs(sonar_1.SONAR_SCANNER).returns(0); await sonarScript.run(); (0, chai_1.expect)(loggerRecorder.recordedLogs) .to.satisfy((s) => s.startsWith('info: Script "sonar" starting...\n')) .and.to.contain.oneOf([ "warn: 'my-test-project-key' Sonar project does not yet exist on https://example.com/sonar/ ! Initializing it first...\n", "warn: 'my-test-project-key' Sonar project does not yet exist on https://example.com/sonar ! Initializing it first...\n", ]) .and.to.contain('info: Analyzing current branch "current-local-branch" source code...\n') .and.to.satisfy((s) => s.endsWith('info: Script "sonar" successful after 0 s\n')); (0, chai_1.expect)(subScript).to.have.been.calledOnceWithExactly(sonarInit_1.SonarInitScript, {}, {}); (0, chai_1.expect)(shellCommand).to.have.been.calledTwice; (0, chai_1.expect)(shellCommand).to.have.been.calledWith('git', ['branch', '--show-current']); (0, chai_1.expect)(shellCommand).to.have.been.calledWithExactly(sonar_1.SONAR_SCANNER, [ '-Dsonar.branch.name=current-local-branch', ]); }); (0, mocha_1.it)(` should initialize Sonar project with a warning and then successfully analyze code against a target branch.`, async () => { const loggerRecorder = new sonarTestUtils_1.LoggerRecorder(); const sonarScript = getSonarScript('develop', loggerRecorder.logger); shellCommand.withArgs(sonar_1.SONAR_SCANNER).returns(0); await sonarScript.run(); (0, chai_1.expect)(loggerRecorder.recordedLogs) .to.satisfy((s) => s.startsWith('info: Script "sonar" starting...\n')) .and.to.contain.oneOf([ "warn: 'my-test-project-key' Sonar project does not yet exist on https://example.com/sonar/ ! Initializing it first...\n", "warn: 'my-test-project-key' Sonar project does not yet exist on https://example.com/sonar ! Initializing it first...\n", ]) .and.to.contain('info: Analyzing current branch "current-local-branch" source code...\n') .and.to.satisfy((s) => s.endsWith('info: Script "sonar" successful after 0 s\n')); (0, chai_1.expect)(subScript).to.have.been.calledOnceWithExactly(sonarInit_1.SonarInitScript, {}, {}); (0, chai_1.expect)(shellCommand).to.have.been.calledTwice; (0, chai_1.expect)(shellCommand).to.have.been.calledWith('git', ['branch', '--show-current']); (0, chai_1.expect)(shellCommand).to.have.been.calledWithExactly(sonar_1.SONAR_SCANNER, [ '-Dsonar.branch.name=current-local-branch', '-Dsonar.branch.target=develop', ]); }); (0, mocha_1.it)(` should fail when Sonar project initialization fails.`, async () => { const loggerRecorder = new sonarTestUtils_1.LoggerRecorder(); const sonarScript = getSonarScript(null, loggerRecorder.logger); subScript .withArgs(sonarInit_1.SonarInitScript) .rejects(new Error('An error occurred while calling sonar-init sub-script.')); await (0, chai_1.expect)(sonarScript.run()).to.be.rejectedWith(Error, 'An error occurred while calling sonar-init sub-script.'); (0, chai_1.expect)(loggerRecorder.recordedLogs) .to.satisfy((s) => s.startsWith('info: Script "sonar" starting...\n')) .and.to.contain.oneOf([ "warn: 'my-test-project-key' Sonar project does not yet exist on https://example.com/sonar/ ! Initializing it first...\n", "warn: 'my-test-project-key' Sonar project does not yet exist on https://example.com/sonar ! Initializing it first...\n", ]) .and.to.satisfy((s) => s.endsWith('error: Script "sonar" failed after 0 s with: An error occurred while calling sonar-init sub-script.\n')) .and.to.not.contain('info: Analyzing current branch "current-local-branch" source code...\n'); (0, chai_1.expect)(subScript).to.have.been.calledOnceWithExactly(sonarInit_1.SonarInitScript, {}, {}); (0, chai_1.expect)(shellCommand).to.have.been.calledOnceWith('git', ['branch', '--show-current']); }); (0, mocha_1.it)(` should fail when code analysis fails after project initialization.`, async () => { const loggerRecorder = new sonarTestUtils_1.LoggerRecorder(); const sonarScript = getSonarScript(null, loggerRecorder.logger); subScript.withArgs(sonarInit_1.SonarInitScript).returns(0); shellCommand .withArgs(sonar_1.SONAR_SCANNER) .rejects(new Error('An error occurred while analyzing source code.')); await (0, chai_1.expect)(sonarScript.run()).to.be.rejectedWith(Error, 'An error occurred while analyzing source code.'); (0, chai_1.expect)(loggerRecorder.recordedLogs) .to.satisfy((s) => s.startsWith('info: Script "sonar" starting...\n')) .and.to.contain.oneOf([ "warn: 'my-test-project-key' Sonar project does not yet exist on https://example.com/sonar/ ! Initializing it first...\n", "warn: 'my-test-project-key' Sonar project does not yet exist on https://example.com/sonar ! Initializing it first...\n", ]) .and.to.contain('info: Analyzing current branch "current-local-branch" source code...\n') .and.to.satisfy((s) => s.endsWith('error: Script "sonar" failed after 0 s with: An error occurred while analyzing source code.\n')); (0, chai_1.expect)(subScript).to.have.been.calledOnceWithExactly(sonarInit_1.SonarInitScript, {}, {}); (0, chai_1.expect)(shellCommand).to.have.been.calledTwice; (0, chai_1.expect)(shellCommand).to.have.been.calledWith('git', ['branch', '--show-current']); (0, chai_1.expect)(shellCommand).to.have.been.calledWithExactly(sonar_1.SONAR_SCANNER, [ '-Dsonar.branch.name=current-local-branch', ]); }); }); }); }); (0, mocha_1.describe)(' when using a sonar-project.properties file where Sonar host is missing', async () => { before(async () => { await fs.copyFile('./src/utils/test-sonar-project_missing-host.properties', './sonar-project.properties'); }); after(async () => { await fs.unlink('./sonar-project.properties'); }); (0, mocha_1.it)(` should fail with a message about missing host url.`, async () => { const loggerRecorder = new sonarTestUtils_1.LoggerRecorder(); const sonarScript = getSonarScript(null, loggerRecorder.logger); await (0, chai_1.expect)(sonarScript.run()).to.be.rejectedWith(Error, '"sonar.host.url" property must be defined in "sonar-project.properties" file!'); (0, chai_1.expect)(subScript).to.not.have.been.called; (0, chai_1.expect)(shellCommand).to.not.have.been.called; }); }); (0, mocha_1.describe)(' when using a sonar-project.properties file where Sonar project key is missing', async () => { before(async () => { await fs.copyFile('./src/utils/test-sonar-project_missing-project-key.properties', './sonar-project.properties'); }); after(async () => { await fs.unlink('./sonar-project.properties'); }); (0, mocha_1.it)(` should fail with a message about missing project key.`, async () => { const loggerRecorder = new sonarTestUtils_1.LoggerRecorder(); const sonarScript = getSonarScript(null, loggerRecorder.logger); await (0, chai_1.expect)(sonarScript.run()).to.be.rejectedWith(Error, '"sonar.projectKey" property must be defined in "sonar-project.properties" file!'); (0, chai_1.expect)(subScript).to.not.have.been.called; (0, chai_1.expect)(shellCommand).to.not.have.been.called; }); }); }); //# sourceMappingURL=sonar.test.js.map