use proptest::prelude::*;
use unicode_width::UnicodeWidthChar;
use super::chunking::{chunk_buffer, cursor_to_visual};
fn arbitrary_text() -> impl Strategy<Value = String> {
prop::collection::vec(
prop_oneof![
prop::char::range('\u{20}', '\u{7E}'),
prop::char::range('\u{4E00}', '\u{4FFF}'),
],
0..50,
)
.prop_map(|chars| chars.into_iter().collect())
}
proptest! {
#[test]
fn partition_is_exact(
buffer in arbitrary_text(),
width in 1..20usize,
) {
let chunks = chunk_buffer(&buffer, width);
let reconstructed: String = chunks
.iter()
.map(|r| &buffer[r.clone()])
.collect();
prop_assert_eq!(reconstructed, buffer);
}
#[test]
fn every_row_fits_display_width(
buffer in arbitrary_text(),
width in 2..20usize,
) {
let chunks = chunk_buffer(&buffer, width);
for chunk in &chunks {
let display_width: usize = buffer[chunk.clone()]
.chars()
.map(|c| c.width().unwrap_or(0))
.sum();
prop_assert!(
display_width <= width,
"chunk {:?} has display width {} > {}",
&buffer[chunk.clone()],
display_width,
width
);
}
}
#[test]
fn cursor_lands_inside_rendered_rect(
buffer in arbitrary_text(),
width in 2..20usize,
) {
let chunks = chunk_buffer(&buffer, width);
for cursor in 0..=buffer.len() {
if !buffer.is_char_boundary(cursor) {
continue;
}
let (row, col) = cursor_to_visual(&buffer, cursor, width);
prop_assert!(
row <= chunks.len(),
"row {} > chunks.len() {} for cursor {} in {:?}",
row, chunks.len(), cursor, buffer
);
prop_assert!(
col <= width,
"col {} > width {} for cursor {} in {:?}",
col, width, cursor, buffer
);
}
}
#[test]
fn append_never_moves_earlier_rows(
buffer in arbitrary_text(),
ch in prop::char::range('\u{20}', '\u{7E}'),
width in 1..20usize,
) {
let chunks_before = chunk_buffer(&buffer, width);
let mut extended = buffer.clone();
extended.push(ch);
let chunks_after = chunk_buffer(&extended, width);
let check_count = chunks_before.len().saturating_sub(1);
for i in 0..check_count {
let before_text = &buffer[chunks_before[i].clone()];
let after_text = &extended[chunks_after[i].clone()];
prop_assert_eq!(
before_text, after_text,
"row {} changed from {:?} to {:?} after appending {:?}",
i, before_text, after_text, ch
);
}
}
}