UNPKG

@villedemontreal/scripting

Version:
301 lines 19.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /* eslint-disable @typescript-eslint/ban-ts-comment */ /* eslint-disable @typescript-eslint/no-misused-promises */ /* eslint-disable @typescript-eslint/require-await */ /* eslint-disable no-console */ /* eslint-disable max-lines-per-function */ const chai_1 = require("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'); const chai = require('chai'); chai.should(); chai.use(require('chai-as-promised')); chai.use(require('sinon-chai')); chai.use(require('chai-string')); const sandbox = sinon.createSandbox(); let shellCommand; let subScript; // eslint-disable-next-line @typescript-eslint/ban-types 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, "ENOENT: no such file or directory, open 'sonar-project.properties'"); (0, chai_1.expect)(loggerRecorder.recordedLogs).to.equal(`info: Script "sonar" starting... error: Script "sonar" failed after 0 s with: ENOENT: no such file or directory, open 'sonar-project.properties' `); }); 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.startWith(`info: Script "sonar" starting...\n`) .and.to.contain('info: Executing: git branch,--show-current\n') .and.to.endWith('error: Script "sonar" failed after 0 s with: Expected success codes were "0", but the process exited with "128".\n'); subScript.should.not.have.been.called; shellCommand.should.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.startWith('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.endWith('error: Script "sonar" failed after 0 s with: Not Found\n'); (0, chai_1.expect)(loggerRecorder.recordedLogs).to.not.contain('warn'); shellCommand.should.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.startWith('info: Script "sonar" starting...\n') .and.to.contain('info: Analyzing current branch "current-local-branch" source code...\n') .and.to.endWith('info: Script "sonar" successful after 0 s\n'); subScript.should.not.have.been.called; shellCommand.should.have.been.calledTwice; shellCommand.should.have.been.calledWith('git', ['branch', '--show-current']); shellCommand.should.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.startWith('info: Script "sonar" starting...\n') .and.to.contain('info: Analyzing current branch "current-local-branch" source code...\n') .and.to.endWith('info: Script "sonar" successful after 0 s\n'); subScript.should.not.have.been.called; shellCommand.should.have.been.calledTwice; shellCommand.should.have.been.calledWith('git', ['branch', '--show-current']); shellCommand.should.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.startWith('info: Script "sonar" starting...\n') .and.to.contain('info: Analyzing current branch "current-local-branch" source code...\n') .and.to.endWith(`error: Script "sonar" failed after 0 s with: An error occurred while analyzing source code.\n`); subScript.should.not.have.been.called; shellCommand.should.have.been.calledTwice; shellCommand.should.have.been.calledWith('git', ['branch', '--show-current']); shellCommand.should.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.startWith('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.endWith('info: Script "sonar" successful after 0 s\n'); subScript.should.have.been.calledOnceWithExactly(sonarInit_1.SonarInitScript, {}, {}); shellCommand.should.have.been.calledTwice; shellCommand.should.have.been.calledWith('git', ['branch', '--show-current']); shellCommand.should.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.startWith('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.endWith('info: Script "sonar" successful after 0 s\n'); subScript.should.have.been.calledOnceWithExactly(sonarInit_1.SonarInitScript, {}, {}); shellCommand.should.have.been.calledTwice; shellCommand.should.have.been.calledWith('git', ['branch', '--show-current']); shellCommand.should.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.startWith('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.endWith('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'); subScript.should.have.been.calledOnceWithExactly(sonarInit_1.SonarInitScript, {}, {}); shellCommand.should.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.startWith('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.endWith('error: Script "sonar" failed after 0 s with: An error occurred while analyzing source code.\n'); subScript.should.have.been.calledOnceWithExactly(sonarInit_1.SonarInitScript, {}, {}); shellCommand.should.have.been.calledTwice; shellCommand.should.have.been.calledWith('git', ['branch', '--show-current']); shellCommand.should.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!'); subScript.should.not.have.been.called; shellCommand.should.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!'); subScript.should.not.have.been.called; shellCommand.should.not.have.been.called; }); }); }); //# sourceMappingURL=sonar.test.js.map