Skip to content

Commit 9760f4e

Browse files
author
Loïc Guychard
committed
chore: improve test coverage
1 parent efe408a commit 9760f4e

File tree

6 files changed

+566
-20
lines changed

6 files changed

+566
-20
lines changed

package.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,20 +103,27 @@
103103
"@sourcegraph/prettierrc": "^2.2.0",
104104
"@sourcegraph/tsconfig": "^4.0.0",
105105
"@sourcegraph/tslint-config": "^12.3.1",
106+
"@types/expect": "^1.20.4",
107+
"@types/lodash": "^4.14.121",
106108
"@types/mocha": "5.2.5",
107109
"@types/node": "10.12.18",
110+
"@types/sinon": "^7.0.7",
111+
"expect": "^24.1.0",
108112
"husky": "^1.1.2",
109113
"lnfs-cli": "^2.1.0",
114+
"lodash": "^4.17.11",
110115
"mkdirp": "^0.5.1",
111116
"mocha": "^5.2.0",
112117
"nyc": "^13.1.0",
113118
"parcel-bundler": "^1.11.0",
114119
"prettier": "^1.14.2",
120+
"sinon": "^7.2.5",
115121
"source-map-support": "^0.5.9",
116122
"sourcegraph": "^22.0.0",
117123
"ts-node": "^7.0.1",
118124
"tslint": "^5.11.0",
119-
"typescript": "^3.3.3333"
125+
"typescript": "^3.3.3333",
126+
"vscode-languageserver-types": "^3.14.0"
120127
},
121128
"dependencies": {
122129
"date-fns": "^2.0.0-alpha.24",

src/blame.test.ts

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
import expect from 'expect'
2+
import {
3+
getAllBlameDecorations,
4+
getBlameDecorations,
5+
getBlameDecorationsForSelections,
6+
getDecorationFromHunk,
7+
Hunk
8+
} from './blame'
9+
import { createMockSourcegraphAPI } from './util/stubs'
10+
11+
const FIXTURE_HUNK_1: Hunk = {
12+
startLine: 1,
13+
endLine: 2,
14+
author: {
15+
person: {
16+
displayName: 'a'
17+
},
18+
date: '2018-09-10T21:52:45Z'
19+
},
20+
rev: 'b',
21+
message: 'c',
22+
commit: {
23+
url: 'd'
24+
}
25+
}
26+
27+
const FIXTURE_HUNK_2: Hunk = {
28+
startLine: 2,
29+
endLine: 3,
30+
author: {
31+
person: {
32+
displayName: 'e'
33+
},
34+
date: '2018-11-10T21:52:45Z'
35+
},
36+
rev: 'f',
37+
message: 'g',
38+
commit: {
39+
url: 'h'
40+
}
41+
}
42+
43+
const FIXTURE_HUNK_3: Hunk = {
44+
startLine: 3,
45+
endLine: 4,
46+
author: {
47+
person: {
48+
displayName: 'i'
49+
},
50+
date: '2018-10-10T21:52:45Z'
51+
},
52+
rev: 'j',
53+
message: 'k',
54+
commit: {
55+
url: 'l'
56+
}
57+
}
58+
59+
const NOW = +new Date('2018-12-01T21:52:45Z')
60+
61+
const SOURCEGRAPH = createMockSourcegraphAPI()
62+
63+
describe('getDecorationsFromHunk()', () => {
64+
65+
it('creates a TextDocumentDecoration from a Hunk', () => {
66+
expect(getDecorationFromHunk(FIXTURE_HUNK_1, NOW, 0, SOURCEGRAPH as any)).toEqual({
67+
after: {
68+
contentText: 'a, 3 months ago: • c',
69+
dark: {
70+
backgroundColor: 'rgba(15, 43, 89, 0.65)',
71+
color: 'rgba(235, 235, 255, 0.55)',
72+
},
73+
hoverMessage: 'c',
74+
light: {
75+
backgroundColor: 'rgba(193, 217, 255, 0.65)',
76+
color: 'rgba(0, 0, 25, 0.55)',
77+
},
78+
linkURL: 'https://sourcegraph.test/d',
79+
},
80+
isWholeLine: true,
81+
range: {
82+
end: 0,
83+
start: 0,
84+
}
85+
}
86+
)
87+
})
88+
89+
it('truncates long commit messsages', () => {
90+
const decoration = getDecorationFromHunk({
91+
...FIXTURE_HUNK_1,
92+
message: 'asdgjdsag asdklgbasdghladg asdgjlhbasdgjlhabsdg asdgilbadsgiobasgd'
93+
}, NOW, 0, SOURCEGRAPH as any)
94+
expect(decoration.after && decoration.after.contentText).toEqual('a, 3 months ago: • asdgjdsag asdklgbasdghladg asdgjlhbasdgjlhabs…')
95+
})
96+
97+
it('truncates long display names', () => {
98+
const decoration = getDecorationFromHunk({
99+
...FIXTURE_HUNK_1,
100+
author: {
101+
person: {
102+
displayName: 'asdgjdsag asdklgbasdghladg asdgjlhbasdgjlhabsdg asdgilbadsgiobasgd'
103+
},
104+
date:'2018-09-10T21:52:45Z'
105+
}
106+
}, NOW, 0, SOURCEGRAPH as any)
107+
expect(decoration.after && decoration.after.contentText).toEqual('asdgjdsag asdklgbasdghlad…, 3 months ago: • c')
108+
})
109+
})
110+
111+
describe('getBlameDecorationsForSelections()', () => {
112+
113+
it('adds decorations only for hunks that are within the selections', () => {
114+
const decorations = getBlameDecorationsForSelections([FIXTURE_HUNK_1, FIXTURE_HUNK_2, FIXTURE_HUNK_3], [
115+
new SOURCEGRAPH.Selection(new SOURCEGRAPH.Position(1, 0), new SOURCEGRAPH.Position(1, 0)) as any
116+
], NOW, SOURCEGRAPH as any)
117+
expect(decorations).toEqual([
118+
getDecorationFromHunk(FIXTURE_HUNK_2, NOW, 1, SOURCEGRAPH as any)
119+
])
120+
})
121+
122+
it('handles multiple selections', () => {
123+
const decorations = getBlameDecorationsForSelections([FIXTURE_HUNK_1, FIXTURE_HUNK_2, FIXTURE_HUNK_3], [
124+
new SOURCEGRAPH.Selection(new SOURCEGRAPH.Position(1, 0), new SOURCEGRAPH.Position(1, 0)) as any,
125+
new SOURCEGRAPH.Selection(new SOURCEGRAPH.Position(2, 0), new SOURCEGRAPH.Position(5, 0)) as any,
126+
new SOURCEGRAPH.Selection(new SOURCEGRAPH.Position(6, 0), new SOURCEGRAPH.Position(10, 0)) as any,
127+
], NOW, SOURCEGRAPH as any)
128+
expect(decorations).toEqual([
129+
getDecorationFromHunk(FIXTURE_HUNK_2, NOW, 1, SOURCEGRAPH as any),
130+
getDecorationFromHunk(FIXTURE_HUNK_3, NOW, 2, SOURCEGRAPH as any),
131+
])
132+
})
133+
134+
it('handles multiple hunks per selection', () => {
135+
const decorations = getBlameDecorationsForSelections([FIXTURE_HUNK_1, FIXTURE_HUNK_2, FIXTURE_HUNK_3], [
136+
new SOURCEGRAPH.Selection(new SOURCEGRAPH.Position(0, 0), new SOURCEGRAPH.Position(5, 0)) as any
137+
], NOW, SOURCEGRAPH as any)
138+
expect(decorations).toEqual([
139+
getDecorationFromHunk(FIXTURE_HUNK_1, NOW, 0, SOURCEGRAPH as any),
140+
getDecorationFromHunk(FIXTURE_HUNK_2, NOW, 1, SOURCEGRAPH as any),
141+
getDecorationFromHunk(FIXTURE_HUNK_3, NOW, 2, SOURCEGRAPH as any),
142+
])
143+
})
144+
145+
it('decorates the start line of the selection if the start line of the hunk is outside of the selection boundaries', () => {
146+
const decorations = getBlameDecorationsForSelections([{
147+
...FIXTURE_HUNK_1,
148+
startLine: 1,
149+
endLine: 10
150+
}], [
151+
new SOURCEGRAPH.Selection(new SOURCEGRAPH.Position(2, 0), new SOURCEGRAPH.Position(2, 0)) as any
152+
], NOW, SOURCEGRAPH as any)
153+
expect(decorations).toEqual([
154+
getDecorationFromHunk(FIXTURE_HUNK_1, NOW, 2, SOURCEGRAPH as any),
155+
])
156+
})
157+
158+
})
159+
160+
describe('getAllBlameDecorations()', () => {
161+
162+
it('adds decorations for all hunks', () => {
163+
expect(getAllBlameDecorations([
164+
FIXTURE_HUNK_1,
165+
FIXTURE_HUNK_2,
166+
FIXTURE_HUNK_3
167+
], NOW, SOURCEGRAPH as any)).toEqual([
168+
getDecorationFromHunk(FIXTURE_HUNK_1, NOW, 0, SOURCEGRAPH as any),
169+
getDecorationFromHunk(FIXTURE_HUNK_2, NOW, 1, SOURCEGRAPH as any),
170+
getDecorationFromHunk(FIXTURE_HUNK_3, NOW, 2, SOURCEGRAPH as any),
171+
172+
])
173+
})
174+
175+
})
176+
177+
describe('getBlameDecorations()', () => {
178+
179+
it('gets no decorations if git.blame.lineDecorations is false', async () => {
180+
expect(await getBlameDecorations({
181+
uri: 'a',
182+
settings: {
183+
'git.blame.lineDecorations': false
184+
},
185+
now: NOW,
186+
selections: null,
187+
queryHunks: () => Promise.resolve([FIXTURE_HUNK_1, FIXTURE_HUNK_2, FIXTURE_HUNK_3]),
188+
sourcegraph: SOURCEGRAPH as any
189+
})).toEqual([])
190+
})
191+
192+
it('gets decorations for all hunks if no selections are passed', async () => {
193+
expect(await getBlameDecorations({
194+
uri: 'a',
195+
settings: {
196+
'git.blame.lineDecorations': true
197+
},
198+
now: NOW,
199+
selections: null,
200+
queryHunks: () => Promise.resolve([FIXTURE_HUNK_1, FIXTURE_HUNK_2, FIXTURE_HUNK_3]),
201+
sourcegraph: SOURCEGRAPH as any
202+
})).toEqual([
203+
getDecorationFromHunk(FIXTURE_HUNK_1, NOW, 0, SOURCEGRAPH as any),
204+
getDecorationFromHunk(FIXTURE_HUNK_2, NOW, 1, SOURCEGRAPH as any),
205+
getDecorationFromHunk(FIXTURE_HUNK_3, NOW, 2, SOURCEGRAPH as any),
206+
])
207+
})
208+
209+
it('gets decorations for the selections if selections are passed', async () => {
210+
expect(await getBlameDecorations({
211+
uri: 'a',
212+
settings: {
213+
'git.blame.lineDecorations': true
214+
},
215+
now: NOW,
216+
selections: [
217+
new SOURCEGRAPH.Selection(
218+
new SOURCEGRAPH.Position(2, 0),
219+
new SOURCEGRAPH.Position(2, 0)
220+
) as any
221+
],
222+
queryHunks: () => Promise.resolve([FIXTURE_HUNK_1, FIXTURE_HUNK_2, FIXTURE_HUNK_3]),
223+
sourcegraph: SOURCEGRAPH as any
224+
})).toEqual([
225+
getDecorationFromHunk(FIXTURE_HUNK_3, NOW, 2, SOURCEGRAPH as any),
226+
])
227+
})
228+
229+
})

src/blame.ts

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import formatDistanceStrict from 'date-fns/formatDistanceStrict'
2-
import * as sourcegraph from 'sourcegraph'
2+
import { Selection, TextDocumentDecoration } from 'sourcegraph'
33
import gql from 'tagged-template-noop'
44
import { Settings } from './extension'
55
import { resolveURI } from './uri'
66
import { memoizeAsync } from './util/memoizeAsync'
77

8-
const getDecorationFromHunk = (hunk: Hunk, now: number, decoratedLine: number): sourcegraph.TextDocumentDecoration => ({
8+
export const getDecorationFromHunk = (hunk: Hunk, now: number, decoratedLine: number, sourcegraph: typeof import('sourcegraph')): TextDocumentDecoration => ({
99
range: new sourcegraph.Range(decoratedLine, 0, decoratedLine, 0),
1010
isWholeLine: true,
1111
after: {
@@ -25,8 +25,8 @@ const getDecorationFromHunk = (hunk: Hunk, now: number, decoratedLine: number):
2525
},
2626
})
2727

28-
const getBlameDecorationsForSelections = (hunks: Hunk[], selections: sourcegraph.Selection[], now: number) => {
29-
const decorations: sourcegraph.TextDocumentDecoration[] = []
28+
export const getBlameDecorationsForSelections = (hunks: Hunk[], selections: Selection[], now: number, sourcegraph: typeof import('sourcegraph')) => {
29+
const decorations: TextDocumentDecoration[] = []
3030
for (const hunk of hunks) {
3131
// Hunk start and end lines are 1-indexed, but selection lines are zero-indexed
3232
const hunkStartLineZeroBased = hunk.startLine - 1
@@ -41,17 +41,17 @@ const getBlameDecorationsForSelections = (hunks: Hunk[], selections: sourcegraph
4141
// outside of the selection's boundaries, the start line of the selection.
4242
const decoratedLine =
4343
hunkStartLineZeroBased < selection.start.line ? selection.start.line : hunkStartLineZeroBased
44-
decorations.push(getDecorationFromHunk(hunk, now, decoratedLine))
44+
decorations.push(getDecorationFromHunk(hunk, now, decoratedLine, sourcegraph))
4545
}
4646
}
4747
return decorations
4848
}
4949

50-
const getAllBlameDecorations = (hunks: Hunk[], now: number) =>
51-
hunks.map(hunk => getDecorationFromHunk(hunk, now, hunk.startLine - 1))
50+
export const getAllBlameDecorations = (hunks: Hunk[], now: number, sourcegraph: typeof import('sourcegraph')) =>
51+
hunks.map(hunk => getDecorationFromHunk(hunk, now, hunk.startLine - 1, sourcegraph))
5252

5353
const queryBlameHunks = memoizeAsync(
54-
async (uri: string): Promise<Hunk[]> => {
54+
async ({uri, sourcegraph}: {uri: string, sourcegraph: typeof import('sourcegraph')}): Promise<Hunk[]> => {
5555
const { repo, rev, path } = resolveURI(uri)
5656
const { data, errors } = await sourcegraph.commands.executeCommand(
5757
'queryGraphQL',
@@ -90,7 +90,7 @@ const queryBlameHunks = memoizeAsync(
9090
}
9191
return data.repository.commit.blob.blame
9292
},
93-
uri => uri
93+
({ uri }) => uri
9494
)
9595

9696
/**
@@ -103,24 +103,29 @@ export const getBlameDecorations = async ({
103103
uri,
104104
settings,
105105
selections,
106+
now,
107+
queryHunks = queryBlameHunks,
108+
sourcegraph
106109
}: {
107110
uri: string
108111
settings: Settings
109-
selections: sourcegraph.Selection[] | null
110-
}): Promise<sourcegraph.TextDocumentDecoration[]> => {
112+
selections: Selection[] | null,
113+
now: number,
114+
queryHunks?: ({ uri, sourcegraph } : { uri: string, sourcegraph: typeof import('sourcegraph') }) => Promise<Hunk[]>,
115+
sourcegraph: typeof import('sourcegraph')
116+
}): Promise<TextDocumentDecoration[]> => {
111117
if (!settings['git.blame.lineDecorations']) {
112118
return []
113119
}
114-
const hunks = await queryBlameHunks(uri)
115-
const now = Date.now()
120+
const hunks = await queryHunks({ uri, sourcegraph })
116121
if (selections !== null) {
117-
return getBlameDecorationsForSelections(hunks, selections, now)
122+
return getBlameDecorationsForSelections(hunks, selections, now, sourcegraph)
118123
} else {
119-
return getAllBlameDecorations(hunks, now)
124+
return getAllBlameDecorations(hunks, now, sourcegraph)
120125
}
121126
}
122127

123-
interface Hunk {
128+
export interface Hunk {
124129
startLine: number
125130
endLine: number
126131
author: {

src/extension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export function activate(context: sourcegraph.ExtensionContext): void {
4949
try {
5050
editor.setDecorations(
5151
decorationType,
52-
await getBlameDecorations({ uri: editor.document.uri, settings, selections })
52+
await getBlameDecorations({ uri: editor.document.uri, now: Date.now(), settings, selections, sourcegraph })
5353
)
5454
} catch (err) {
5555
console.error('Decoration error:', err)

0 commit comments

Comments
 (0)