use tui::{ backend::TestBackend, buffer::Buffer, layout::Alignment, text::{Span, Spans, Text}, widgets::{Block, Borders, Paragraph, Wrap}, Terminal, }; const SAMPLE_STRING: &str = "The library is based on the principle of immediate rendering with \ intermediate buffers. This means that at each new frame you should build all widgets that are \ supposed to be part of the UI. While providing a great flexibility for rich and \ interactive UI, this may introduce overhead for highly dynamic content."; #[test] fn widgets_paragraph_can_wrap_its_content() { let test_case = |alignment, expected| { let backend = TestBackend::new(20, 10); let mut terminal = Terminal::new(backend).unwrap(); terminal .draw(|f| { let size = f.size(); let text = vec![Spans::from(SAMPLE_STRING)]; let paragraph = Paragraph::new(text) .block(Block::default().borders(Borders::ALL)) .alignment(alignment) .wrap(Wrap { trim: true }); f.render_widget(paragraph, size); }) .unwrap(); terminal.backend().assert_buffer(&expected); }; test_case( Alignment::Left, Buffer::with_lines(vec![ "┌──────────────────┐", "│The library is │", "│based on the │", "│principle of │", "│immediate │", "│rendering with │", "│intermediate │", "│buffers. This │", "│means that at each│", "└──────────────────┘", ]), ); test_case( Alignment::Right, Buffer::with_lines(vec![ "┌──────────────────┐", "│ The library is│", "│ based on the│", "│ principle of│", "│ immediate│", "│ rendering with│", "│ intermediate│", "│ buffers. This│", "│means that at each│", "└──────────────────┘", ]), ); test_case( Alignment::Center, Buffer::with_lines(vec![ "┌──────────────────┐", "│ The library is │", "│ based on the │", "│ principle of │", "│ immediate │", "│ rendering with │", "│ intermediate │", "│ buffers. This │", "│means that at each│", "└──────────────────┘", ]), ); } #[test] fn widgets_paragraph_renders_double_width_graphemes() { let backend = TestBackend::new(10, 10); let mut terminal = Terminal::new(backend).unwrap(); let s = "コンピュータ上で文字を扱う場合、典型的には文字による通信を行う場合にその両端点では、"; terminal .draw(|f| { let size = f.size(); let text = vec![Spans::from(s)]; let paragraph = Paragraph::new(text) .block(Block::default().borders(Borders::ALL)) .wrap(Wrap { trim: true }); f.render_widget(paragraph, size); }) .unwrap(); let expected = Buffer::with_lines(vec![ "┌────────┐", "│コンピュ│", "│ータ上で│", "│文字を扱│", "│う場合、│", "│典型的に│", "│は文字に│", "│よる通信│", "│を行う場│", "└────────┘", ]); terminal.backend().assert_buffer(&expected); } #[test] fn widgets_paragraph_renders_mixed_width_graphemes() { let backend = TestBackend::new(10, 7); let mut terminal = Terminal::new(backend).unwrap(); let s = "aコンピュータ上で文字を扱う場合、"; terminal .draw(|f| { let size = f.size(); let text = vec![Spans::from(s)]; let paragraph = Paragraph::new(text) .block(Block::default().borders(Borders::ALL)) .wrap(Wrap { trim: true }); f.render_widget(paragraph, size); }) .unwrap(); let expected = Buffer::with_lines(vec![ // The internal width is 8 so only 4 slots for double-width characters. "┌────────┐", "│aコンピ │", // Here we have 1 latin character so only 3 double-width ones can fit. "│ュータ上│", "│で文字を│", "│扱う場合│", "│、 │", "└────────┘", ]); terminal.backend().assert_buffer(&expected); } #[test] fn widgets_paragraph_can_wrap_with_a_trailing_nbsp() { let nbsp: &str = "\u{00a0}"; let line = Spans::from(vec![Span::raw("NBSP"), Span::raw(nbsp)]); let backend = TestBackend::new(20, 3); let mut terminal = Terminal::new(backend).unwrap(); let expected = Buffer::with_lines(vec![ "┌──────────────────┐", "│NBSP\u{00a0} │", "└──────────────────┘", ]); terminal .draw(|f| { let size = f.size(); let paragraph = Paragraph::new(line).block(Block::default().borders(Borders::ALL)); f.render_widget(paragraph, size); }) .unwrap(); terminal.backend().assert_buffer(&expected); } #[test] fn widgets_paragraph_can_scroll_horizontally() { let test_case = |alignment, scroll, expected| { let backend = TestBackend::new(20, 10); let mut terminal = Terminal::new(backend).unwrap(); terminal .draw(|f| { let size = f.size(); let text = Text::from( "段落现在可以水平滚动了!\nParagraph can scroll horizontally!\nShort line", ); let paragraph = Paragraph::new(text) .block(Block::default().borders(Borders::ALL)) .alignment(alignment) .scroll(scroll); f.render_widget(paragraph, size); }) .unwrap(); terminal.backend().assert_buffer(&expected); }; test_case( Alignment::Left, (0, 7), Buffer::with_lines(vec![ "┌──────────────────┐", "│在可以水平滚动了!│", "│ph can scroll hori│", "│ine │", "│ │", "│ │", "│ │", "│ │", "│ │", "└──────────────────┘", ]), ); // only support Alignment::Left test_case( Alignment::Right, (0, 7), Buffer::with_lines(vec![ "┌──────────────────┐", "│段落现在可以水平滚│", "│Paragraph can scro│", "│ Short line│", "│ │", "│ │", "│ │", "│ │", "│ │", "└──────────────────┘", ]), ); }