Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,31 @@ When adding features, preserve these boundaries before optimizing code layout.

## Coding Conventions

### Test Organization

- Name the outer inline test module `tests`.
- Group tests under a module named after the function or method under test.
- When a file defines multiple production types, add a type-level module before
the function-level module.
- Name test functions after the behavior or scenario being verified. Do not use
generic names such as `test` or repeat the function name in a `test_*` prefix.

For example:

```rust
#[cfg(test)]
mod tests {
mod widget_viewport {
mod scroll_to_include {
#[test]
fn does_not_scroll_while_the_position_is_visible() {
// ...
}
}
}
}
```

### Feature Wiring

- Control module exposure via feature flags.
Expand Down
120 changes: 66 additions & 54 deletions examples/csv/src/csv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,67 +230,79 @@ mod tests {
)
}

#[test]
fn arrow_keys_move_on_both_axes() {
let mut viewer = viewer();
viewer.table.create_graphemes_in_viewport(4, 2);
mod csv_viewer {
use super::*;

viewer
.handle_event(&Event::Key(KeyEvent::new(
KeyCode::Down,
KeyModifiers::NONE,
)))
.unwrap();
assert_eq!(viewer.table.document.position(), 1);
mod handle_event {
use super::*;

viewer
.handle_event(&Event::Key(KeyEvent::new(
KeyCode::Right,
KeyModifiers::NONE,
)))
.unwrap();
assert_eq!(
viewer.table.document.horizontal_offset(),
KEY_HORIZONTAL_SCROLL_CELLS
);
}
#[test]
fn arrow_keys_move_on_both_axes() {
let mut viewer = viewer();
viewer.table.create_graphemes_in_viewport(4, 2);

#[test]
fn macos_horizontal_scroll_left_reveals_content_on_the_right() {
let mut viewer = viewer();
viewer.table.create_graphemes_in_viewport(4, 2);
viewer
.handle_event(&Event::Mouse(MouseEvent {
kind: MouseEventKind::ScrollLeft,
column: 0,
row: 0,
modifiers: KeyModifiers::NONE,
}))
.unwrap();
viewer
.handle_event(&Event::Key(KeyEvent::new(
KeyCode::Down,
KeyModifiers::NONE,
)))
.unwrap();
assert_eq!(viewer.table.document.position(), 1);

assert_eq!(
viewer.table.document.horizontal_offset(),
MOUSE_HORIZONTAL_SCROLL_CELLS
);
viewer
.handle_event(&Event::Key(KeyEvent::new(
KeyCode::Right,
KeyModifiers::NONE,
)))
.unwrap();
assert_eq!(
viewer.table.document.horizontal_offset(),
KEY_HORIZONTAL_SCROLL_CELLS
);
}

viewer
.handle_event(&Event::Mouse(MouseEvent {
kind: MouseEventKind::ScrollRight,
column: 0,
row: 0,
modifiers: KeyModifiers::NONE,
}))
.unwrap();
assert_eq!(viewer.table.document.horizontal_offset(), 0);
#[test]
fn macos_horizontal_scroll_left_reveals_content_on_the_right() {
let mut viewer = viewer();
viewer.table.create_graphemes_in_viewport(4, 2);
viewer
.handle_event(&Event::Mouse(MouseEvent {
kind: MouseEventKind::ScrollLeft,
column: 0,
row: 0,
modifiers: KeyModifiers::NONE,
}))
.unwrap();

assert_eq!(
viewer.table.document.horizontal_offset(),
MOUSE_HORIZONTAL_SCROLL_CELLS
);

viewer
.handle_event(&Event::Mouse(MouseEvent {
kind: MouseEventKind::ScrollRight,
column: 0,
row: 0,
modifiers: KeyModifiers::NONE,
}))
.unwrap();
assert_eq!(viewer.table.document.horizontal_offset(), 0);
}
}
}

#[test]
fn loads_the_large_csv_fixture_from_a_file() {
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../../promkit-widgets/benches/table.csv");
let document = parse_document(&Args { input: Some(path) }).unwrap();
mod parse_document {
use super::*;

#[test]
fn loads_the_large_csv_fixture_from_a_file() {
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../../promkit-widgets/benches/table.csv");
let document = parse_document(&Args { input: Some(path) }).unwrap();

assert_eq!(document.row_count(), 47_852);
assert_eq!(document.column_count(), 12);
assert_eq!(document.row_count(), 47_852);
assert_eq!(document.column_count(), 12);
}
}
}
120 changes: 68 additions & 52 deletions examples/repl/src/repl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,69 +402,85 @@ mod tests {
use super::*;
use promkit_widgets::core::Widget;

#[test]
fn completes_only_nonempty_balanced_input() {
assert_eq!(completion(""), Completion::Empty);
assert_eq!(completion("value {"), Completion::Incomplete);
assert_eq!(completion("value {\n [item]\n}"), Completion::Complete);
assert_eq!(completion("{]"), Completion::Invalid);
mod completion {
use super::*;

#[test]
fn classifies_empty_balanced_unbalanced_and_invalid_input() {
assert_eq!(completion(""), Completion::Empty);
assert_eq!(completion("value {"), Completion::Incomplete);
assert_eq!(completion("value {\n [item]\n}"), Completion::Complete);
assert_eq!(completion("{]"), Completion::Invalid);
}
}

#[test]
fn enter_continues_unclosed_input_with_indentation() {
let mut editor = text_editor::TextEditor::new("{");
mod enter {
use super::*;

assert_eq!(enter(&mut editor), Control::Continue);
assert_eq!(editor.text_without_cursor().to_string(), "{\n ");
}
#[test]
fn continues_unclosed_input_with_indentation() {
let mut editor = text_editor::TextEditor::new("{");

#[test]
fn enter_submits_complete_single_line_input() {
let mut editor = text_editor::TextEditor::new("value");
assert_eq!(enter(&mut editor), Control::Continue);
assert_eq!(editor.text_without_cursor().to_string(), "{\n ");
}

assert_eq!(enter(&mut editor), Control::Submit("value".to_string()));
}
#[test]
fn submits_complete_single_line_input() {
let mut editor = text_editor::TextEditor::new("value");

fn assert_blank_continuation_line_submits(input: &str) {
let mut editor = text_editor::TextEditor::new(input);
assert_eq!(enter(&mut editor), Control::Submit("value".to_string()));
}

assert_eq!(enter(&mut editor), Control::Continue);
assert_eq!(
editor.text_without_cursor().to_string(),
format!("{input}\n")
);
assert_eq!(enter(&mut editor), Control::Submit(format!("{input}\n")));
}
fn assert_blank_continuation_line_submits(input: &str) {
let mut editor = text_editor::TextEditor::new(input);

#[test]
fn empty_continuation_line_submits_a_curly_bracket_block() {
assert_blank_continuation_line_submits("{\n value\n}");
}
assert_eq!(enter(&mut editor), Control::Continue);
assert_eq!(
editor.text_without_cursor().to_string(),
format!("{input}\n")
);
assert_eq!(enter(&mut editor), Control::Submit(format!("{input}\n")));
}

#[test]
fn empty_continuation_line_submits_a_curly_bracket_block() {
assert_blank_continuation_line_submits("{\n value\n}");
}

#[test]
fn empty_continuation_line_submits_a_square_bracket_block() {
assert_blank_continuation_line_submits("[\n value\n]");
#[test]
fn empty_continuation_line_submits_a_square_bracket_block() {
assert_blank_continuation_line_submits("[\n value\n]");
}
}

#[test]
fn continuation_prefix_is_only_presentational() {
let state = text_editor::State {
texteditor: text_editor::TextEditor::new("first\nsecond"),
config: text_editor::Config {
prefix: "❯❯❯ ".into(),
continuation_prefix: "... ".into(),
..Default::default()
},
..Default::default()
};
mod text_editor_state {
use super::*;

mod create_graphemes {
use super::*;

#[test]
fn continuation_prefix_is_only_presentational() {
let state = text_editor::State {
texteditor: text_editor::TextEditor::new("first\nsecond"),
config: text_editor::Config {
prefix: "❯❯❯ ".into(),
continuation_prefix: "... ".into(),
..Default::default()
},
..Default::default()
};

assert_eq!(
state.create_graphemes().graphemes.to_string(),
"❯❯❯ first\n... second "
);
assert_eq!(
state.texteditor.text_without_cursor().to_string(),
"first\nsecond"
);
assert_eq!(
state.create_graphemes().graphemes.to_string(),
"❯❯❯ first\n... second "
);
assert_eq!(
state.texteditor.text_without_cursor().to_string(),
"first\nsecond"
);
}
}
}
}
Loading
Loading