Skip to content

Commit

Permalink
@W-14689540@: (Part 7) Create and set GitHub step summary markdown fr…
Browse files Browse the repository at this point in the history
…om results
  • Loading branch information
stephen-carter-at-sf committed Jan 16, 2024
1 parent 4a4554b commit 1a98eb1
Show file tree
Hide file tree
Showing 14 changed files with 6,546 additions and 28 deletions.
31 changes: 31 additions & 0 deletions __tests__/data/sampleRunDfaResults_expectedSummary.md

Large diffs are not rendered by default.

140 changes: 140 additions & 0 deletions __tests__/data/sampleRunResults_expectedSummary.md

Large diffs are not rendered by default.

6,024 changes: 6,024 additions & 0 deletions __tests__/data/tooManyViolations_expectedSummary.md

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions __tests__/data/zeroViolations_expectedSummary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
## Salesforce Code Analyzer Results
### :white_check_mark: 0 Violations Found
8 changes: 8 additions & 0 deletions __tests__/dependencies.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,12 @@ describe('RuntimeDependencies Code Coverage', () => {
expect(dependencies.fileExists('action.yml')).toEqual(true)
expect(dependencies.fileExists('thisFileDoesNotExist.html')).toEqual(false)
})

it('writeSummary Code Coverage', async () => {
const coreSummaryAddRawSpy = jest.spyOn(core.summary, 'addRaw').mockImplementation()
const coreSummaryWriteSpy = jest.spyOn(core.summary, 'write').mockImplementation()
await dependencies.writeSummary('someSummaryMarkdown')
expect(coreSummaryAddRawSpy).toHaveBeenCalledWith('someSummaryMarkdown')
expect(coreSummaryWriteSpy).toHaveBeenCalled()
})
})
22 changes: 22 additions & 0 deletions __tests__/fakes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { CommandOutput, Dependencies } from '../src/dependencies'
import { EnvironmentVariables, Inputs } from '../src/types'
import { CommandExecutor } from '../src/commands'
import { Results, ResultsFactory, Violation, ViolationLocation } from '../src/results'
import { Summarizer } from '../src/summary'

export class FakeDependencies implements Dependencies {
startGroupCallHistory: { name: string }[] = []
Expand Down Expand Up @@ -65,6 +66,11 @@ export class FakeDependencies implements Dependencies {
this.fileExistsCallHistory.push({ file })
return this.fileExistsReturnValue
}

writeSummaryCallHistory: { summaryMarkdown: string }[] = []
async writeSummary(summaryMarkdown: string): Promise<void> {
this.writeSummaryCallHistory.push({ summaryMarkdown })
}
}

export class FakeCommandExecutor implements CommandExecutor {
Expand Down Expand Up @@ -157,4 +163,20 @@ export class FakeViolationLocation implements ViolationLocation {
this.compareToCallHistory.push({ other })
return this.compareToReturnValue
}

toStringReturnValue = 'someLocation'
toStringCallCount = 0
toString(): string {
this.toStringCallCount++
return this.toStringReturnValue
}
}

export class FakeSummarizer implements Summarizer {
createSummaryMarkdownReturnValue = 'someSummaryMarkdown'
createSummaryMarkdownCallHistory: { results: Results }[] = []
createSummaryMarkdown(results: Results): string {
this.createSummaryMarkdownCallHistory.push({ results })
return this.createSummaryMarkdownReturnValue
}
}
34 changes: 22 additions & 12 deletions __tests__/main.test.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import * as main from '../src/main'
import { FakeCommandExecutor, FakeDependencies, FakeResultsFactory } from './fakes'
import { FakeCommandExecutor, FakeDependencies, FakeResultsFactory, FakeSummarizer } from './fakes'
import { Inputs } from '../src/types'
import { INTERNAL_OUTFILE, MESSAGE_FCNS, MESSAGES, MIN_SCANNER_VERSION_REQUIRED } from '../src/constants'

describe('main run Tests', () => {
let dependencies: FakeDependencies
let commandExecutor: FakeCommandExecutor
let resultsFactory: FakeResultsFactory
let summarizer: FakeSummarizer

beforeEach(async () => {
dependencies = new FakeDependencies()
commandExecutor = new FakeCommandExecutor()
resultsFactory = new FakeResultsFactory()
summarizer = new FakeSummarizer()
})

it('Test default values', async () => {
await main.run(dependencies, commandExecutor, resultsFactory)
await main.run(dependencies, commandExecutor, resultsFactory, summarizer)

expect(commandExecutor.isSalesforceCliInstalledCallCount).toEqual(1)

Expand Down Expand Up @@ -70,6 +72,14 @@ describe('main run Tests', () => {
' num-sev3-violations: 3'
})

expect(summarizer.createSummaryMarkdownCallHistory).toHaveLength(1)
expect(summarizer.createSummaryMarkdownCallHistory).toContainEqual({
results: resultsFactory.createResultsReturnValue
})

expect(dependencies.writeSummaryCallHistory).toHaveLength(1)
expect(dependencies.writeSummaryCallHistory).toContainEqual({ summaryMarkdown: 'someSummaryMarkdown' })

expect(dependencies.failCallHistory).toHaveLength(0)
})

Expand All @@ -79,7 +89,7 @@ describe('main run Tests', () => {
runArgs: '-o myFile.html --normalize-severity -t ./src',
resultsArtifactName: 'customArtifactName'
}
await main.run(dependencies, commandExecutor, resultsFactory)
await main.run(dependencies, commandExecutor, resultsFactory, summarizer)

expect(commandExecutor.isSalesforceCliInstalledCallCount).toEqual(1)

Expand Down Expand Up @@ -112,7 +122,7 @@ describe('main run Tests', () => {

it('Test nonzero exit code from command call', async () => {
commandExecutor.runCodeAnalyzerReturnValue = 987
await main.run(dependencies, commandExecutor, resultsFactory)
await main.run(dependencies, commandExecutor, resultsFactory, summarizer)

expect(dependencies.setOutputCallHistory).toContainEqual({
name: 'exit-code',
Expand All @@ -129,7 +139,7 @@ describe('main run Tests', () => {
}
}
dependencies = new ThrowingDependencies()
await main.run(dependencies, commandExecutor, resultsFactory)
await main.run(dependencies, commandExecutor, resultsFactory, summarizer)

expect(commandExecutor.runCodeAnalyzerCallHistory).toHaveLength(0)
expect(dependencies.uploadArtifactCallHistory).toHaveLength(0)
Expand All @@ -141,7 +151,7 @@ describe('main run Tests', () => {

it('Test missing --normalize-severity from run arguments', async () => {
dependencies.getInputsReturnValue.runArgs = '--outfile results.xml'
await main.run(dependencies, commandExecutor, resultsFactory)
await main.run(dependencies, commandExecutor, resultsFactory, summarizer)

expect(commandExecutor.runCodeAnalyzerCallHistory).toHaveLength(0)
expect(dependencies.uploadArtifactCallHistory).toHaveLength(0)
Expand All @@ -153,7 +163,7 @@ describe('main run Tests', () => {

it('Test when Salesforce CLI is not already installed and we install it successfully', async () => {
commandExecutor.isSalesforceCliInstalledReturnValue = false
await main.run(dependencies, commandExecutor, resultsFactory)
await main.run(dependencies, commandExecutor, resultsFactory, summarizer)

expect(dependencies.warnCallHistory).toHaveLength(1)
expect(dependencies.warnCallHistory).toContainEqual({
Expand All @@ -167,7 +177,7 @@ describe('main run Tests', () => {
it('Test when Salesforce CLI is not already installed and we fail to install it', async () => {
commandExecutor.isSalesforceCliInstalledReturnValue = false
commandExecutor.installSalesforceCliReturnValue = false
await main.run(dependencies, commandExecutor, resultsFactory)
await main.run(dependencies, commandExecutor, resultsFactory, summarizer)

expect(dependencies.warnCallHistory).toHaveLength(1)
expect(dependencies.warnCallHistory).toContainEqual({
Expand All @@ -181,7 +191,7 @@ describe('main run Tests', () => {

it('Test when sfdx-scanner plugin is not already installed and we install it successfully', async () => {
commandExecutor.isMinimumScannerPluginInstalledReturnValue = false
await main.run(dependencies, commandExecutor, resultsFactory)
await main.run(dependencies, commandExecutor, resultsFactory, summarizer)

expect(dependencies.warnCallHistory).toHaveLength(1)
expect(dependencies.warnCallHistory).toContainEqual({
Expand All @@ -198,7 +208,7 @@ describe('main run Tests', () => {
it('Test when sfdx-scanner plugin is not already installed and we fail to install it', async () => {
commandExecutor.isMinimumScannerPluginInstalledReturnValue = false
commandExecutor.installScannerPluginReturnValue = false
await main.run(dependencies, commandExecutor, resultsFactory)
await main.run(dependencies, commandExecutor, resultsFactory, summarizer)

expect(dependencies.warnCallHistory).toHaveLength(1)
expect(dependencies.warnCallHistory).toContainEqual({
Expand All @@ -215,7 +225,7 @@ describe('main run Tests', () => {

it('Test when the internal outfile file does not exist after run then we fail', async () => {
dependencies.fileExistsReturnValue = false
await main.run(dependencies, commandExecutor, resultsFactory)
await main.run(dependencies, commandExecutor, resultsFactory, summarizer)

expect(commandExecutor.runCodeAnalyzerCallHistory).toHaveLength(1)
expect(dependencies.failCallHistory).toHaveLength(1)
Expand All @@ -231,7 +241,7 @@ describe('main run Tests', () => {
resultsArtifactName: 'customArtifactName'
}
dependencies.fileExistsReturnValue = false
await main.run(dependencies, commandExecutor, resultsFactory)
await main.run(dependencies, commandExecutor, resultsFactory, summarizer)

expect(commandExecutor.runCodeAnalyzerCallHistory).toHaveLength(1)
expect(dependencies.failCallHistory).toHaveLength(1)
Expand Down
84 changes: 84 additions & 0 deletions __tests__/summary.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { RuntimeSummarizer, Summarizer } from '../src/summary'
import { Results, ResultsFactory, RuntimeResultsFactory, RuntimeViolation, Violation } from '../src/results'
import * as path from 'path'
import * as fs from 'fs'
import { FakeResults, FakeViolationLocation } from './fakes'

describe('RuntimeSummarizer Tests', () => {
const resultsFactory: ResultsFactory = new RuntimeResultsFactory()
const summarizer: Summarizer = new RuntimeSummarizer()

it('Test createSummaryMarkdown with sample run results', () => {
const results: Results = resultsFactory.createResults(
path.join('.', '__tests__', 'data', 'sampleRunResults.json'),
false
)
const summaryMarkdown = summarizer.createSummaryMarkdown(results)

const expectedSummaryMarkdown = fs.readFileSync(
path.join('.', '__tests__', 'data', 'sampleRunResults_expectedSummary.md'),
{ encoding: 'utf8' }
)
expect(summaryMarkdown).toEqual(expectedSummaryMarkdown)
})

it('Test createSummaryMarkdown with sample run dfa results', () => {
const results: Results = resultsFactory.createResults(
path.join('.', '__tests__', 'data', 'sampleRunDfaResults.json'),
true
)
const summaryMarkdown = summarizer.createSummaryMarkdown(results)

const expectedSummaryMarkdown = fs.readFileSync(
path.join('.', '__tests__', 'data', 'sampleRunDfaResults_expectedSummary.md'),
{ encoding: 'utf8' }
)
expect(summaryMarkdown).toEqual(expectedSummaryMarkdown)
})

it('Test createSummaryMarkdown with results that have no violations', () => {
const results: FakeResults = new FakeResults()
results.getTotalViolationCountReturnValue = 0
results.getSev1ViolationCountReturnValue = 0
results.getSev2ViolationCountReturnValue = 0
results.getSev3ViolationCountReturnValue = 0
results.getViolationsSortedBySeverityReturnValue = []
const summaryMarkdown = summarizer.createSummaryMarkdown(results)

const expectedSummaryMarkdown = fs.readFileSync(
path.join('.', '__tests__', 'data', 'zeroViolations_expectedSummary.md'),
{ encoding: 'utf8' }
)
expect(summaryMarkdown).toEqual(expectedSummaryMarkdown)
})

it('Test that createSummaryMarkdown trims table when too many results to fit into 1mb summary', () => {
const numViolations = 12345
const results: FakeResults = new FakeResults()
results.getTotalViolationCountReturnValue = numViolations
results.getSev1ViolationCountReturnValue = 0
results.getSev2ViolationCountReturnValue = numViolations
results.getSev3ViolationCountReturnValue = 0
results.getViolationsSortedBySeverityReturnValue = []
for (let i = 0; i < numViolations; i++) {
const dummyLocation: FakeViolationLocation = new FakeViolationLocation()
dummyLocation.toStringReturnValue = `/some/file.ts:${i + 1}:0`
const dummyViolation: Violation = new RuntimeViolation(
2,
'someEngine',
'someRule',
undefined,
`some message ${i + 1}`,
dummyLocation
)
results.getViolationsSortedBySeverityReturnValue.push(dummyViolation)
}
const summaryMarkdown = summarizer.createSummaryMarkdown(results)

const expectedSummaryMarkdown = fs.readFileSync(
path.join('.', '__tests__', 'data', 'tooManyViolations_expectedSummary.md'),
{ encoding: 'utf8' }
)
expect(summaryMarkdown).toEqual(expectedSummaryMarkdown)
})
})
Loading

0 comments on commit 1a98eb1

Please sign in to comment.