#[cfg(test)]
use crate::primitives::diff_view::{DiffView, DiffViewLayout};
#[cfg(test)]
use crate::theme::Theme;
#[cfg(test)]
mod tests {
use super::super::headless::BitmapSurface;
use super::super::text::make_font;
use super::super::MacBackend;
use super::*;
use crate::event::{Rect as QRect, Viewport};
use crate::primitives::diff_view::DiffMode;
use crate::types::WidgetId;
use crate::Backend;
const W: u32 = 400;
const H: u32 = 200;
const DIVIDER_PX: f64 = crate::primitives::diff_view::DIFF_DIVIDER_W as f64;
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: crate::diff::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: crate::primitives::diff_view::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_via_backend(view: &DiffView, rect: QRect) -> (BitmapSurface, DiffViewLayout, f64) {
let surface = BitmapSurface::new(W, H);
surface.fill(1.0, 1.0, 1.0, 1.0);
let mut backend = MacBackend::new();
backend.set_current_font(make_font("Menlo", 12.0).expect("Menlo installed"));
let lh = backend.line_height() as f64;
backend.begin_frame(Viewport::new(W as f32, H as f32, 1.0));
let captured = std::cell::RefCell::new(None);
backend.enter_frame_scope(surface.context_ptr(), |b| {
*captured.borrow_mut() = Some(b.draw_diff_view(rect, view));
});
backend.end_frame();
(surface, captured.into_inner().expect("layout captured"), lh)
}
#[test]
fn visible_rows_is_not_stuck_at_zero() {
let view = sample_view(DiffMode::SideBySide);
let (_surface, layout, lh) =
paint_via_backend(&view, QRect::new(0.0, 0.0, W as f32, H as f32));
assert!(
layout.visible_rows > 0,
"visible_rows must reflect the real row capacity, not the old 0 stub",
);
assert_eq!(layout.visible_rows, (H as f64 / lh).floor() as usize);
assert_eq!(layout.total_rows, view.total_rows());
}
#[test]
fn changed_row_paints_removed_and_added_backgrounds() {
let view = sample_view(DiffMode::SideBySide);
let (surface, _layout, lh) =
paint_via_backend(&view, QRect::new(0.0, 0.0, W as f32, H as f32));
let theme = Theme::default();
let changed = first_row_of(&view, crate::primitives::diff_view::DiffRowKind::Changed);
let row_y = (lh * (changed as f64 + 0.5)) as u32;
let left_w = ((W as f64 - DIVIDER_PX) / 2.0).floor();
let (r, g, b, _) = surface.pixel(left_w as u32 - 4, row_y);
assert_eq!(
(r, g, b),
(
theme.diff_removed_bg.r,
theme.diff_removed_bg.g,
theme.diff_removed_bg.b
),
"left pane of a Changed row should carry diff_removed_bg",
);
let (r, g, b, _) = surface.pixel(W - 4, row_y);
assert_eq!(
(r, g, b),
(
theme.diff_added_bg.r,
theme.diff_added_bg.g,
theme.diff_added_bg.b
),
"right pane of a Changed row should carry diff_added_bg",
);
}
#[test]
fn divider_paints_border_colour() {
let view = sample_view(DiffMode::SideBySide);
let (surface, _layout, lh) =
paint_via_backend(&view, QRect::new(0.0, 0.0, W as f32, H as f32));
let theme = Theme::default();
let left_w = ((W as f64 - DIVIDER_PX) / 2.0).floor();
let (r, g, b, _) = surface.pixel(left_w as u32, (lh * 0.5) as u32);
assert_eq!(
(r, g, b),
(theme.border_fg.r, theme.border_fg.g, theme.border_fg.b),
"the 1pt 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 view = sample_view(DiffMode::SideBySide);
let (surface, layout, lh) = paint_via_backend(
&view,
QRect::new(origin_x, origin_y, W as f32 - origin_x, H as f32 - origin_y),
);
let theme = Theme::default();
assert_eq!(
layout.visible_rows,
((H as f32 - origin_y) as f64 / lh).floor() as usize,
"visible_rows must be derived from the rect actually handed in",
);
let w = (W as f32 - origin_x) as f64;
let left_w = ((w - DIVIDER_PX) / 2.0).floor();
let div_x = (origin_x as f64 + left_w) as u32;
let probe_y = (origin_y as f64 + lh * 0.5) as u32;
let (r, g, b, _) = surface.pixel(div_x, probe_y);
assert_eq!(
(r, g, b),
(theme.border_fg.r, theme.border_fg.g, theme.border_fg.b),
"divider must follow the requested origin",
);
assert_eq!(
{
let (r, g, b, _) = surface.pixel(div_x, origin_y as u32 - 4);
(r, g, b)
},
(255, 255, 255),
"nothing should paint above the requested origin",
);
assert_eq!(
{
let (r, g, b, _) = surface.pixel(4, probe_y);
(r, g, b)
},
(255, 255, 255),
"nothing should paint left of the requested origin",
);
}
#[test]
fn unified_mode_counts_hunk_headers_in_total_rows() {
let view = sample_view(DiffMode::Unified);
let (_surface, layout, _lh) =
paint_via_backend(&view, QRect::new(0.0, 0.0, W as f32, H as f32));
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 header_row_paints_labels_strip() {
let mut view = sample_view(DiffMode::SideBySide);
view.left_label = Some("a/main.rs".into());
view.right_label = Some("b/main.rs".into());
let (surface, layout, lh) =
paint_via_backend(&view, QRect::new(0.0, 0.0, W as f32, H as f32));
let theme = Theme::default();
let left_w = ((W as f64 - DIVIDER_PX) / 2.0).floor();
let (r, g, b, _) = surface.pixel(left_w as u32 - 4, (lh * 0.5) as u32);
assert_eq!(
(r, g, b),
(theme.header_bg.r, theme.header_bg.g, theme.header_bg.b),
);
assert_eq!(layout.visible_rows, ((H as f64 - lh) / lh).floor() as usize,);
}
#[test]
fn zero_sized_rect_returns_zero_visible_rows_without_painting() {
let view = sample_view(DiffMode::SideBySide);
let (surface, layout, _lh) = paint_via_backend(&view, QRect::new(0.0, 0.0, 0.0, 0.0));
assert_eq!(layout.visible_rows, 0);
assert_eq!(layout.total_rows, view.total_rows());
assert_eq!(
{
let (r, g, b, _) = surface.pixel(1, 1);
(r, g, b)
},
(255, 255, 255),
);
}
}