Skip to content

Commit

Permalink
feat($ci): Truncate long source file names
Browse files Browse the repository at this point in the history
  • Loading branch information
darcy-rayner committed Apr 15, 2018
1 parent 5b7818a commit 5959b80
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 53 deletions.
47 changes: 47 additions & 0 deletions src/filename-utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { escapeMarkdownCharacters, getPrettyPathName } from "./filename-utils"
describe("getPrettyPathName", () => {
it("doesn't change strings equal to the limit", () => {
const input = "/exactly/17/chars"
const output = getPrettyPathName(input, 17)
expect(output).toEqual(input)
})

it("elides the middle directories first", () => {
const input = "/just/over/the/limit"
const output = getPrettyPathName(input, 17)
expect(output).toEqual("/just/../limit")
})

it("elides the middle directories from right to left, excluding the root directory", () => {
const input = "/just/over/the/limit"
const output = getPrettyPathName(input, 18)
expect(output).toEqual("/just/../the/limit")
})

it("elides the root directory second", () => {
const input = "/quite-a-lot-actually/over/the/limit"
const output = getPrettyPathName(input, 17)
expect(output).toEqual("../limit")
})

it("truncates the the basename third", () => {
const input = "/quite-a-lot-actually/over/the/limit-and-this-is-long-as-well"
const output = getPrettyPathName(input, 17)
expect(output).toEqual("../limit-and-th..")
})

it("treats the tilde as the root directory", () => {
const input = "~/just/over/the/limit"
const output = getPrettyPathName(input, 18)
expect(output).toEqual("~/../the/limit")
})
})

describe("escapeMarkdownCharacters", () => {
it("escapes filenames with '|,(,),[,],#,*,{,},-,+,_,!,\\,`>' characters", () => {
const filename = `src/file-with-characters{[(|#*-+_!\`)]}.ts`
const expectedFilename = `src/file\\-with\\-characters\\{\\[\\(\\|\\#\\*\\-\\+\\_\\!\\\`\\)\\]\\}.ts`
const output = escapeMarkdownCharacters(filename)
expect(output).toEqual(expectedFilename)
})
})
53 changes: 53 additions & 0 deletions src/filename-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import * as _ from "lodash"
import * as path from "path"

/**
* Shortens the length of a directory in a pretty way.
* @param pathName The path to shorten
* @param maxLength The maximum length of the path. Must be at least 4.
* @returns The shortened directory name.
*/
export function getPrettyPathName(pathName: string, maxLength: number): string {
if (maxLength < 4) {
throw Error("maxLength must be at least 4")
}
if (pathName.length <= maxLength) {
return pathName
}

const parts = path.parse(pathName)

const dirWithoutRoot = parts.dir.slice(parts.root.length, parts.dir.length - parts.root.length + 1)
const dirs = dirWithoutRoot.split(path.sep)
const root = `${parts.root}..${path.sep}`

// Save the first directory, we want to try and prioritize keeping it in the path.
let firstDir = dirs.shift()
firstDir = firstDir ? firstDir : ""

while (dirs.length > 0) {
// Except for the first directory, start removing dirs from left to right.
dirs.shift()
const middle = ["..", ...dirs].join(path.sep)
const newPath = `${parts.root}${firstDir}${path.sep}${middle}${path.sep}${parts.base}`
if (newPath.length <= maxLength) {
return newPath
}
}

const rootAndName = `..${path.sep}${parts.base}`
if (rootAndName.length <= maxLength) {
return rootAndName
}
return `${rootAndName.slice(0, maxLength - 2)}..`
}

/**
* Escapes the characters |()[]#*{}-+_!\,`> from a string.
* @param source The source to escape
* @returns An escaped version of the string
*/
export function escapeMarkdownCharacters(source: string) {
const escapedCharacters = ["|", "(", ")", "[", "]", "#", "*", "{", "}", "-", "+", "_", "!", "\\", "`"]
return [...source].map(c => (_.includes(escapedCharacters, c) ? `\\${c}` : c)).join("")
}
3 changes: 3 additions & 0 deletions src/git-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function getGitRoot(): Promise<string> {
throw Error("Unimplemented")
}
80 changes: 30 additions & 50 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,20 @@ const basePath = "/some/random/path/to/repo"

function makeCoverageEntry(coverage: number) {
return `{
"0": ${ coverage < 25 ? 0 : 1 },
"1": ${ coverage < 50 ? 0 : 1},
"2": ${ coverage < 75 ? 0 : 1 },
"3": ${ coverage < 100 ? 0 : 1 }
"0": ${coverage < 25 ? 0 : 1},
"1": ${coverage < 50 ? 0 : 1},
"2": ${coverage < 75 ? 0 : 1},
"3": ${coverage < 100 ? 0 : 1}
}`
}

function makeEntry(fileName: string, lineCoverage = 100, statementCoverage = 100, functionCoverage = 100,
branchCoverage = 100) {
function makeEntry(
fileName: string,
lineCoverage = 100,
statementCoverage = 100,
functionCoverage = 100,
branchCoverage = 100
) {
return `
"${fileName}": {
"lines": { "total": 100, "covered": ${lineCoverage}, "skipped": 0, "pct": ${lineCoverage} },
Expand All @@ -29,33 +34,26 @@ function makeEntry(fileName: string, lineCoverage = 100, statementCoverage = 100
}

function setupCoverageFile(coverage?: string) {
(FilesystemService as any).mockImplementation( () => {
;(FilesystemService as any).mockImplementation(() => {
return {
exists: (p) => coverage !== undefined,
read: (p) => {
exists: p => coverage !== undefined,
read: p => {
return coverage !== undefined ? Buffer.from(coverage, "utf8") : undefined
},
}
})
}

describe("istanbulCoverage()", () => {

beforeEach(() => {
global.warn = jest.fn()
global.message = jest.fn()
global.fail = jest.fn()
global.markdown = jest.fn()
global.danger = {
git: {
modified_files: [
"src/modified-file1.ts",
"src/modified-file2.ts",
],
created_files: [
"src/created-file1.ts",
"src/created-file2.ts",
],
modified_files: ["src/modified-file1.ts", "src/modified-file2.ts"],
created_files: ["src/created-file1.ts", "src/created-file2.ts"],
},
}
setupCoverageFile(`{
Expand All @@ -76,58 +74,58 @@ describe("istanbulCoverage()", () => {
jest.resetAllMocks()
})

it("will only report on new files when reportFileSet is set to \"created\"", () => {
it('will only report on new files when reportFileSet is set to "created"', () => {
istanbulCoverage({
reportFileSet: "created",
})
expect(global.markdown).toHaveBeenCalledWith(
`## Coverage in New Files
`## Coverage in New Files
File | Line Coverage | Statement Coverage | Function Coverage | Branch Coverage
---- | ------------: | -----------------: | ----------------: | --------------:
[src/created\\-file1.ts](src/created\\-file1.ts) | (66/100) 66% | (100/100) 100% | (25/100) 25% | (50/100) 50%
[src/created\\-file2.ts](src/created\\-file2.ts) | (99/100) 99% | (75/100) 75% | (50/100) 50% | (25/100) 25%
Total | (165/200) 83% | (175/200) 88% | (75/200) 38% | (75/200) 38%
`,
`
)
})

it("will only report on modified files when reportFileSet is set to \"modified\"", () => {
it('will only report on modified files when reportFileSet is set to "modified"', () => {
istanbulCoverage({
reportFileSet: "modified",
})
expect(global.markdown).toHaveBeenCalledWith(
`## Coverage in Modified Files
`## Coverage in Modified Files
File | Line Coverage | Statement Coverage | Function Coverage | Branch Coverage
---- | ------------: | -----------------: | ----------------: | --------------:
[src/modified\\-file1.ts](src/modified\\-file1.ts) | (66/100) 66% | (25/100) 25% | (25/100) 25% | (25/100) 25%
[src/modified\\-file2.ts](src/modified\\-file2.ts) | (99/100) 99% | (50/100) 50% | (75/100) 75% | (50/100) 50%
Total | (165/200) 83% | (75/200) 38% | (100/200) 50% | (75/200) 38%
`,
`
)
})
it("will only report on created and modified files when reportFileSet is set to \"createdOrModified\"", () => {
it('will only report on created and modified files when reportFileSet is set to "createdOrModified"', () => {
istanbulCoverage({
reportFileSet: "createdOrModified",
})
expect(global.markdown).toHaveBeenCalledWith(
`## Coverage in Created or Modified Files
`## Coverage in Created or Modified Files
File | Line Coverage | Statement Coverage | Function Coverage | Branch Coverage
---- | ------------: | -----------------: | ----------------: | --------------:
[src/created\\-file1.ts](src/created\\-file1.ts) | (66/100) 66% | (100/100) 100% | (25/100) 25% | (50/100) 50%
[src/created\\-file2.ts](src/created\\-file2.ts) | (99/100) 99% | (75/100) 75% | (50/100) 50% | (25/100) 25%
[src/modified\\-file1.ts](src/modified\\-file1.ts) | (66/100) 66% | (25/100) 25% | (25/100) 25% | (25/100) 25%
[src/modified\\-file2.ts](src/modified\\-file2.ts) | (99/100) 99% | (50/100) 50% | (75/100) 75% | (50/100) 50%
Total | (330/400) 83% | (250/400) 63% | (175/400) 44% | (150/400) 38%
`,
`
)
})

it("will report all files when reportFileSet is set to \"all\"", () => {
it('will report all files when reportFileSet is set to "all"', () => {
istanbulCoverage({
reportFileSet: "all",
})
expect(global.markdown).toHaveBeenCalledWith(
`## Coverage in All Files
`## Coverage in All Files
File | Line Coverage | Statement Coverage | Function Coverage | Branch Coverage
---- | ------------: | -----------------: | ----------------: | --------------:
[src/created\\-file1.ts](src/created\\-file1.ts) | (66/100) 66% | (100/100) 100% | (25/100) 25% | (50/100) 50%
Expand All @@ -136,7 +134,7 @@ File | Line Coverage | Statement Coverage | Function Coverage | Branch Coverage
[src/modified\\-file2.ts](src/modified\\-file2.ts) | (99/100) 99% | (50/100) 50% | (75/100) 75% | (50/100) 50%
[src/unmodified\\-field.ts](src/unmodified\\-field.ts) | (25/100) 25% | (25/100) 25% | (25/100) 25% | (25/100) 25%
Total | (355/500) 71% | (275/500) 55% | (200/500) 40% | (175/500) 35%
`,
`
)
})

Expand Down Expand Up @@ -179,7 +177,7 @@ Total | (355/500) 71% | (275/500) 55% | (200/500) 40% | (175/500) 35%
})
expect(global.warn).not.toBeCalled()
})
it("doesn't output anything when reportFileSet is set to \"created\" and there are no created files ", () => {
it('doesn\'t output anything when reportFileSet is set to "created" and there are no created files ', () => {
global.danger.git.created_files = []
istanbulCoverage({
reportMode: "fail",
Expand All @@ -190,7 +188,7 @@ Total | (355/500) 71% | (275/500) 55% | (200/500) 40% | (175/500) 35%
expect(global.message).not.toBeCalled()
})

it("doesn't output anything when reportFileSet is set to \"modified\" and there are no modified files ", () => {
it('doesn\'t output anything when reportFileSet is set to "modified" and there are no modified files ', () => {
global.danger.git.modified_files = []
istanbulCoverage({
reportMode: "fail",
Expand Down Expand Up @@ -223,22 +221,4 @@ Total | (355/500) 71% | (275/500) 55% | (200/500) 40% | (175/500) 35%
})
expect(global.warn).toBeCalled()
})

it("escapes filenames with '|,(,),[,],#,*,{,},-,+,_,!,\\,`>' characters", () => {
// Excapes the list of special markdown characters, mentioned here:
// https://daringfireball.net/projects/markdown/syntax#backslash
setupCoverageFile(`{
${makeEntry(`${__dirname}/src/file-with-characters{[(|#*-+_!\`)]}.ts`, 25, 25, 25, 25)}
}`)
istanbulCoverage()
const expectedFilename = `src/file\\-with\\-characters\\{\\[\\(\\|\\#\\*\\-\\+\\_\\!\\\`\\)\\]\\}.ts`
expect(global.markdown).toHaveBeenCalledWith(
`## Coverage in All Files
File | Line Coverage | Statement Coverage | Function Coverage | Branch Coverage
---- | ------------: | -----------------: | ----------------: | --------------:
[${expectedFilename}](${expectedFilename}) | (25/100) 25% | (25/100) 25% | (25/100) 25% | (25/100) 25%
Total | (25/100) 25% | (25/100) 25% | (25/100) 25% | (25/100) 25%
`,
)
})
})
7 changes: 4 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
declare var danger: DangerDSLType
import * as _ from "lodash"
import * as path from "path"
import { escapeMarkdownCharacters, getPrettyPathName } from "./filename-utils"
import FilesystemService from "./filesystem.service"

export declare function message(message: string): void
Expand Down Expand Up @@ -90,8 +91,7 @@ function formatItem(item: CoverageItem) {
}

function formatSourceName(source: string) {
const escapedCharacters = ["|", "(", ")", "[", "]", "#", "*", "{", "}", "-", "+", "_", "!", "\\", "`"]
return [...source].map(c => (_.includes(escapedCharacters, c) ? `\\${c}` : c)).join("")
return escapeMarkdownCharacters(getPrettyPathName(source, 30))
}

function generateReport(coverage: CoverageModel, reportChangeType: ReportFileSet) {
Expand All @@ -105,8 +105,9 @@ File | Line Coverage | Statement Coverage | Function Coverage | Branch Coverage
.map(filename => {
const e = coverage[filename]
const shortFilename = formatSourceName(path.relative(__dirname, filename))
const linkFilename = escapeMarkdownCharacters(path.relative(__dirname, filename))
return [
`[${shortFilename}](${shortFilename})`,
`[${shortFilename}](${linkFilename})`,
formatItem(e.lines),
formatItem(e.statements),
formatItem(e.functions),
Expand Down

0 comments on commit 5959b80

Please sign in to comment.