#[cfg(test)]
use super::text::DWrite;
#[cfg(test)]
use crate::event::Rect;
#[cfg(test)]
use crate::primitives::diff_view::{DiffView, DiffViewLayout};
#[cfg(test)]
use crate::theme::Theme;
#[cfg(test)]
mod tests {
use super::*;
use crate::diff::compute_hunks;
use crate::primitives::diff_view::{DiffMode, DiffRowKind};
use crate::types::{Color, WidgetId};
use crate::win::testing::HeadlessSurface;
const W: f32 = 400.0;
const H: f32 = 200.0;
const LINE_HEIGHT: f32 = 16.0;
fn sample_view(mode: DiffMode) -> DiffView {
let left = "one\ntwo\nthree\n";
let right = "one\nTWO\nthree\n";
DiffView {
id: WidgetId::new("diff"),
left: left.into(),
right: right.into(),
left_label: None,
right_label: None,
hunks: compute_hunks(left, right),
mode,
editability: Default::default(),
scroll_offset: 0,
focused_pane: Default::default(),
has_focus: false,
}
}
fn first_row_of(view: &DiffView, kind: DiffRowKind) -> usize {
view.hunks
.iter()
.flat_map(|h| h.rows.iter())
.position(|r| r.kind == kind)
.expect("fixture should contain the requested row kind")
}
fn paint(
surface: &HeadlessSurface,
dwrite: &DWrite,
rect: Rect,
view: &DiffView,
theme: &Theme,
line_height: f32,
) -> DiffViewLayout {
surface
.paint(|target| {
let mut raw = super::super::surface::D2dSurface {
target,
dwrite: Some(dwrite),
};
crate::primitives::diff_view::native_surface_paint::paint(
view,
&mut raw,
theme,
rect,
line_height,
);
})
.map(|_| view.layout(rect, line_height).as_layout())
.expect("paint diff view")
}
#[test]
fn draw_diff_view_paints_text_and_returns_layout() {
let surface = HeadlessSurface::new(W as u32, H as u32).expect("create surface");
let (dwrite, _, _) = DWrite::new("Segoe UI", 10.0, None).expect("create DWrite");
let theme = Theme {
background: Color::rgb(255, 255, 255),
..Theme::default()
};
let view = sample_view(DiffMode::SideBySide);
let rect = Rect::new(0.0, 0.0, W, H);
let layout = paint(&surface, &dwrite, rect, &view, &theme, LINE_HEIGHT);
assert!(layout.visible_rows > 0);
assert_eq!(layout.total_rows, view.total_rows());
let mut painted_any = false;
for x in 0..(W as u32 / 2) {
for y in 0..(LINE_HEIGHT as u32 * 3) {
let px = surface.pixel_at(x, y);
if (px.r, px.g, px.b) != (255, 255, 255) {
painted_any = true;
}
}
}
assert!(painted_any, "expected diff_view to paint visible glyphs");
}
#[test]
fn divider_paints_border_colour() {
let surface = HeadlessSurface::new(W as u32, H as u32).expect("create surface");
let (dwrite, _, _) = DWrite::new("Segoe UI", 10.0, None).expect("create DWrite");
let theme = Theme::default();
let view = sample_view(DiffMode::SideBySide);
let rect = Rect::new(0.0, 0.0, W, H);
paint(&surface, &dwrite, rect, &view, &theme, LINE_HEIGHT);
let changed = first_row_of(&view, DiffRowKind::Changed);
let geometry = view.layout(rect, LINE_HEIGHT);
let divider_x = geometry.panes.expect("side-by-side has panes").divider_x as u32;
let row_y = (LINE_HEIGHT * (changed as f32 + 0.5)) as u32;
let px = surface.pixel_at(divider_x, row_y);
assert_eq!(
(px.r, px.g, px.b),
(theme.border_fg.r, theme.border_fg.g, theme.border_fg.b),
"the pane divider should be painted in border_fg",
);
}
#[test]
fn paints_at_a_nonzero_origin_only() {
let origin_x = 40.0_f32;
let origin_y = 24.0_f32;
let surface = HeadlessSurface::new(W as u32, H as u32).expect("create surface");
let (dwrite, _, _) = DWrite::new("Segoe UI", 10.0, None).expect("create DWrite");
let theme = Theme::default();
let view = sample_view(DiffMode::SideBySide);
let rect = Rect::new(origin_x, origin_y, W - origin_x, H - origin_y);
surface
.fill_rect(Rect::new(0.0, 0.0, W, H), Color::rgb(255, 255, 255))
.expect("fill sentinel background");
paint(&surface, &dwrite, rect, &view, &theme, LINE_HEIGHT);
let geometry = view.layout(rect, LINE_HEIGHT);
let panes = geometry.panes.expect("side-by-side has panes");
let div_x = panes.divider_x as u32;
let probe_y = (origin_y + LINE_HEIGHT * 0.5) as u32;
let px = surface.pixel_at(div_x, probe_y);
assert_eq!(
(px.r, px.g, px.b),
(theme.border_fg.r, theme.border_fg.g, theme.border_fg.b),
"divider must follow the requested origin",
);
let above = surface.pixel_at(div_x, origin_y as u32 - 4);
assert_eq!(
(above.r, above.g, above.b),
(255, 255, 255),
"nothing should paint above the requested origin",
);
let left = surface.pixel_at(4, probe_y);
assert_eq!(
(left.r, left.g, left.b),
(255, 255, 255),
"nothing should paint left of the requested origin",
);
}
#[test]
fn unified_mode_counts_hunk_headers_in_total_rows() {
let surface = HeadlessSurface::new(W as u32, H as u32).expect("create surface");
let (dwrite, _, _) = DWrite::new("Segoe UI", 10.0, None).expect("create DWrite");
let theme = Theme::default();
let view = sample_view(DiffMode::Unified);
let rect = Rect::new(0.0, 0.0, W, H);
let layout = paint(&surface, &dwrite, rect, &view, &theme, LINE_HEIGHT);
let hunk_count = view.hunks.len();
assert!(hunk_count > 0, "fixture should produce at least one hunk");
assert_eq!(
layout.total_rows,
view.total_rows() + hunk_count,
"unified mode reports content rows plus one @@ header per hunk",
);
}
#[test]
fn no_paint_layout_matches_paint_layout() {
let view = sample_view(DiffMode::SideBySide);
let rect = Rect::new(0.0, 0.0, W, H);
let (dwrite, _, _) = DWrite::new("Segoe UI", 10.0, None).expect("create DWrite");
let surface = HeadlessSurface::new(W as u32, H as u32).expect("create surface");
let theme = Theme::default();
let painted = paint(&surface, &dwrite, rect, &view, &theme, LINE_HEIGHT);
let no_paint = view.layout(rect, LINE_HEIGHT).as_layout();
assert_eq!(painted, no_paint);
}
#[test]
fn zero_size_rect_is_a_no_op() {
let surface = HeadlessSurface::new(W as u32, H as u32).expect("create surface");
let (dwrite, _, _) = DWrite::new("Segoe UI", 10.0, None).expect("create DWrite");
let theme = Theme {
background: Color::rgb(255, 255, 255),
..Theme::default()
};
let view = sample_view(DiffMode::SideBySide);
let rect = Rect::new(0.0, 0.0, 0.0, H);
surface
.fill_rect(Rect::new(0.0, 0.0, W, H), Color::rgb(255, 255, 255))
.expect("fill background");
paint(&surface, &dwrite, rect, &view, &theme, LINE_HEIGHT);
let px = surface.pixel_at(1, 1);
assert_eq!(
(px.r, px.g, px.b),
(255, 255, 255),
"a zero-width diff view should paint nothing at all",
);
}
}