This commit is contained in:
@@ -52,7 +52,7 @@ describe('a change that only removes a line', () => {
|
||||
expect(c.querySelector('.ce-gutter .chg')).toBeNull()
|
||||
})
|
||||
|
||||
it('hands the removed line to the picked panel', async () => {
|
||||
it('opens the full-screen Diff from the ruled line', async () => {
|
||||
const c = await openRow()
|
||||
const scroll = await waitFor(() => {
|
||||
const el = c.querySelector<HTMLElement>('.ce-scroll')
|
||||
@@ -61,11 +61,8 @@ describe('a change that only removes a line', () => {
|
||||
})
|
||||
// 'tail' took the place of the removed line, and sits on line 2.
|
||||
fireEvent.click(scroll, { clientY: 10 + 20 + 5 })
|
||||
const peek = await waitFor(() => {
|
||||
const p = c.querySelector<HTMLElement>('.peek')
|
||||
if (!p) throw new Error('peek not ready')
|
||||
return p
|
||||
})
|
||||
expect(Array.from(peek.querySelectorAll('.ln-row.del')).map((el) => el.textContent?.replace(/^\d+/, ''))).toEqual(['gone'])
|
||||
await waitFor(() => expect(c.querySelector('.split-overlay')).toBeTruthy())
|
||||
const left = Array.from(c.querySelectorAll('.split-pane.left .ln-row.del'))
|
||||
expect(left.map((el) => el.textContent?.replace(/^\d+/, ''))).toEqual(['gone'])
|
||||
})
|
||||
})
|
||||
|
||||
+9
-14
@@ -2,44 +2,39 @@ import { describe, it, expect } from 'vitest'
|
||||
import { buildDiffView } from '../src/renderer/src/editor'
|
||||
import { makeDiff } from '../src/renderer/src/diff'
|
||||
|
||||
/** The current-side view of one text pair, plus the map the overlay reads. */
|
||||
/** The current-side view of one text pair: the lines Actual marks. */
|
||||
function view(original: string, updated: string): ReturnType<typeof buildDiffView> {
|
||||
return buildDiffView(makeDiff('M', original, updated))
|
||||
}
|
||||
|
||||
describe('buildDiffView', () => {
|
||||
it('maps an added line to the line it replaced', () => {
|
||||
const { lines, peek } = view('a\nold\nb', 'a\nnew\nb')
|
||||
it('marks a rewritten line in place', () => {
|
||||
const lines = view('a\nold\nb', 'a\nnew\nb')
|
||||
expect(lines.map((l) => l.text)).toEqual(['a', 'new', 'b'])
|
||||
expect(lines[1].row).toBe('add')
|
||||
expect(peek.get(2)).toEqual({ anchor: 2, from: 2, to: 2 })
|
||||
expect(lines.every((l) => !l.gap)).toBe(true)
|
||||
})
|
||||
|
||||
it('puts a pure deletion on the line that follows it', () => {
|
||||
const { lines, peek } = view('a\ngone\nb', 'a\nb')
|
||||
const lines = view('a\ngone\nb', 'a\nb')
|
||||
expect(lines[1].text).toBe('b')
|
||||
expect(lines[1].gap).toBe('above')
|
||||
expect(lines[1].row).toBeNull()
|
||||
expect(peek.get(2)).toEqual({ anchor: 2, from: 2, to: 2 })
|
||||
})
|
||||
|
||||
it('puts a deletion at end of file under the last line', () => {
|
||||
const { lines, peek } = view('a\nb\ntail', 'a\nb')
|
||||
const lines = view('a\nb\ntail', 'a\nb')
|
||||
expect(lines[1].gap).toBe('below')
|
||||
expect(peek.get(2)).toEqual({ anchor: 3, from: 3, to: 3 })
|
||||
})
|
||||
|
||||
it('anchors an insertion but marks nothing as removed', () => {
|
||||
const { lines, peek } = view('a\nb', 'a\nNEW\nb')
|
||||
it('marks an insertion and leaves the neighbours alone', () => {
|
||||
const lines = view('a\nb', 'a\nNEW\nb')
|
||||
expect(lines[1].row).toBe('add')
|
||||
expect(peek.get(2)).toEqual({ anchor: 1, from: null, to: null })
|
||||
expect(lines.every((l) => !l.gap)).toBe(true)
|
||||
})
|
||||
|
||||
it('leaves an unchanged file without marks or peek targets', () => {
|
||||
const { lines, peek } = view('a\nb\n', 'a\nb\n')
|
||||
expect(peek.size).toBe(0)
|
||||
it('leaves an unchanged file without marks', () => {
|
||||
const lines = view('a\nb\n', 'a\nb\n')
|
||||
expect(lines.every((l) => !l.row && !l.gap)).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -74,7 +74,7 @@ describe('Editor view modes', () => {
|
||||
expect(find(c, '.seg button.on', 'Original')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('clicking a band in Actual reveals the original, clicking it again hides it', async () => {
|
||||
it('clicking a band in Actual opens the full-screen Diff on that line', async () => {
|
||||
const c = await openChanged()
|
||||
const scroll = await waitFor(() => {
|
||||
const el = c.querySelector<HTMLElement>('.ce-scroll')
|
||||
@@ -84,18 +84,14 @@ describe('Editor view modes', () => {
|
||||
// Line 30 is the first rewritten line. Unwrapped, its band is arithmetic:
|
||||
// a 10px top pad plus 20px per line, and the hit test reads clientY.
|
||||
fireEvent.click(scroll, { clientY: 10 + 29 * 20 + 5 })
|
||||
const peek = await waitFor(() => {
|
||||
const p = c.querySelector<HTMLElement>('.peek')
|
||||
if (!p) throw new Error('peek not ready')
|
||||
return p
|
||||
})
|
||||
const removed = Array.from(peek.querySelectorAll('.ln-row.del'))
|
||||
expect(removed).toHaveLength(1)
|
||||
expect(removed[0].textContent).toContain("'plan' => $user->plan,")
|
||||
await waitFor(() => expect(c.querySelector('.split-overlay')).toBeTruthy())
|
||||
const right = Array.from(c.querySelectorAll('.split-pane.right .ln-row'))
|
||||
expect(right.some((el) => el.textContent?.includes("'plan'"))).toBe(true)
|
||||
|
||||
// A second click on the same band drops it.
|
||||
fireEvent.click(scroll, { clientY: 10 + 29 * 20 + 5 })
|
||||
await waitFor(() => expect(c.querySelector('.peek')).toBeNull())
|
||||
// Esc puts the pane back in Actual.
|
||||
act(() => { window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' })) })
|
||||
await waitFor(() => expect(c.querySelector('.split-overlay')).toBeNull())
|
||||
expect(c.querySelector('.seg button.on')?.textContent).toBe('Actual')
|
||||
})
|
||||
|
||||
it('⌘M cycles Actual → Original → Diff, and nothing else', async () => {
|
||||
|
||||
@@ -103,7 +103,7 @@ describe('a file that is staged and then edited again', () => {
|
||||
expect(splitText(c, 'right')).toEqual(['a', 'STAGED', 'c', 'AFTER-STAGING'])
|
||||
})
|
||||
|
||||
it('the picked panel behind Actual always reaches back to HEAD', async () => {
|
||||
it('the Diff opened from Actual always reaches back to HEAD', async () => {
|
||||
const c = await boot()
|
||||
fireEvent.click(group(c, 'Changes')[0])
|
||||
const scroll = await waitFor(() => {
|
||||
@@ -113,17 +113,9 @@ describe('a file that is staged and then edited again', () => {
|
||||
})
|
||||
// Line 2 is 'STAGED'. Unwrapped, its band runs from 10 + (2-1)*20.
|
||||
fireEvent.click(scroll, { clientY: 10 + 20 + 5 })
|
||||
const peek = await waitFor(() => {
|
||||
const p = c.querySelector<HTMLElement>('.peek')
|
||||
if (!p) throw new Error('peek not ready')
|
||||
return p
|
||||
})
|
||||
const removed = Array.from(peek.querySelectorAll('.ln-row.del'))
|
||||
expect(removed.map((el) => el.textContent?.replace(/^\d+/, ''))).toEqual(['b'])
|
||||
|
||||
// A click anywhere off the code drops it.
|
||||
fireEvent.mouseDown(document.body)
|
||||
await waitFor(() => expect(c.querySelector('.peek')).toBeNull())
|
||||
await waitFor(() => expect(c.querySelector('.split-overlay')).toBeTruthy())
|
||||
expect(splitText(c, 'left')).toEqual(['a', 'b', 'c', ''])
|
||||
expect(splitText(c, 'right')).toEqual(['a', 'STAGED', 'c', 'AFTER-STAGING'])
|
||||
})
|
||||
|
||||
it('labels which pair the diff is comparing', async () => {
|
||||
|
||||
Reference in New Issue
Block a user