feat: configure personal pull request review indicators

This commit is contained in:
Valdemar Lorenzen
2026-10-21 11:14:50 +02:00
parent bd71d463a4
commit 0202644efa
18 changed files with 901 additions and 88 deletions
+83 -4
View File
@@ -106,7 +106,7 @@ fn review_directory_resolves_config_paths_and_keeps_session_startup_lazy() {
}
#[test]
fn review_directory_wire_field_is_required_nullable_and_validated() {
fn review_directory_and_review_symbol_wire_fields_are_required_and_validated() {
let mut frame = serde_json::json!({
"version": 1, "type": "config", "plugins": [], "lsp": {}, "bindings": [],
"review_directory": null, "leader": "space",
@@ -119,6 +119,7 @@ fn review_directory_wire_field_is_required_nullable_and_validated() {
"diff_context_lines": 10, "diff_expand_lines": 15,
"diff_view_mode": "split", "diff_split_orientation": "vertical",
"resolve_history_layout": "columns",
"pull_request_review_requested_symbol": "🙏", "pull_request_approved_symbol": "👍",
"diff_follow_working_copy": true
});
for value in [serde_json::Value::Null, serde_json::json!("reviews")] {
@@ -136,10 +137,83 @@ fn review_directory_wire_field_is_required_nullable_and_validated() {
frame["review_directory"] = value;
assert!(serde_json::from_value::<Response>(frame.clone()).is_err());
}
frame["review_directory"] = serde_json::Value::Null;
for field in [
"pull_request_review_requested_symbol",
"pull_request_approved_symbol",
] {
for value in ["", "👩‍🚀 R", "ok"] {
frame[field] = serde_json::json!(value);
assert!(serde_json::from_value::<Response>(frame.clone()).is_ok());
}
for value in [
serde_json::json!(null),
serde_json::json!(false),
serde_json::json!(7),
serde_json::json!([]),
serde_json::json!({}),
serde_json::json!("\0"),
serde_json::json!("\n"),
serde_json::json!("\t"),
serde_json::json!("\u{7f}"),
serde_json::json!("\u{85}"),
] {
frame[field] = value;
assert!(serde_json::from_value::<Response>(frame.clone()).is_err());
}
frame.as_object_mut().unwrap().remove(field);
assert!(serde_json::from_value::<Response>(frame.clone()).is_err());
frame[field] = serde_json::json!("");
}
frame.as_object_mut().unwrap().remove("review_directory");
assert!(serde_json::from_value::<Response>(frame).is_err());
}
#[test]
fn pull_request_symbols_load_defaults_custom_and_empty_and_reject_invalid_ruby_values() {
let fixture = Fixture::new();
let path = fixture.file("config.rb", "Vamp.configure { |_| }");
let config = load_config(&path).unwrap();
assert_eq!(config.pull_request_review_requested_symbol, "🙏");
assert_eq!(config.pull_request_approved_symbol, "👍");
for symbol in ["", "👩‍🚀 R", "ok"] {
let value = serde_json::to_string(symbol).unwrap();
let path = fixture.file("config.rb", &format!(
"Vamp.configure {{ |c| c.pull_request_review_requested_symbol = {value}; c.pull_request_approved_symbol = {value} }}"
));
let config = load_config(&path).unwrap();
assert_eq!(config.pull_request_review_requested_symbol, symbol);
assert_eq!(config.pull_request_approved_symbol, symbol);
}
for field in [
"pull_request_review_requested_symbol",
"pull_request_approved_symbol",
] {
for value in [
"nil",
"false",
"7",
"[]",
"{}",
":ok",
r#""\n""#,
r#""\t""#,
r#""\0""#,
r#""\u007f""#,
r#""\u0085""#,
] {
let path = fixture.file(
"config.rb",
&format!("Vamp.configure {{ |c| c.{field} = {value} }}"),
);
assert!(
load_config(&path).unwrap_err().contains(field),
"{field}: {value}"
);
}
}
}
#[test]
fn tab_spaces_follow_active_language_and_preserve_native_edit_semantics() {
let fixture = Fixture::new();
@@ -544,9 +618,9 @@ fn config_leader_defaults_custom_keys_validation_and_required_wire_field() {
assert!(load_config(&path).unwrap_err().contains(error), "{value}");
}
for frame in [
r#"{"type":"config","version":1,"plugins":[],"lsp":{},"review_directory":null,"bindings":[],"file_explorer_side":"right","file_picker_view":"list","file_explorer_view":"tree","clipboard_mode":"system","git_blame":true,"git_gutter":"bar","scroll_distance":0,"highlight_trailing_whitespace":false,"whitespace_characters":{},"whitespace_scope":"all","tab_spaces":null,"language_tab_spaces":{},"top_bar":{},"bottom_bar":{},"popup":{"command":{},"search":{}},"labels":{},"diff_context_lines":10,"diff_expand_lines":15,"diff_view_mode":"split","diff_split_orientation":"vertical","diff_follow_working_copy":true,"resolve_history_layout":"columns"}"#,
r#"{"type":"config","version":1,"plugins":[],"lsp":{},"review_directory":null,"bindings":[],"leader":null,"file_explorer_side":"right","file_picker_view":"list","file_explorer_view":"tree","clipboard_mode":"system","git_blame":true,"git_gutter":"bar","scroll_distance":0,"highlight_trailing_whitespace":false,"whitespace_characters":{},"whitespace_scope":"all","tab_spaces":null,"language_tab_spaces":{},"top_bar":{},"bottom_bar":{},"popup":{"command":{},"search":{}},"labels":{},"diff_context_lines":10,"diff_expand_lines":15,"diff_view_mode":"split","diff_split_orientation":"vertical","diff_follow_working_copy":true,"resolve_history_layout":"columns"}"#,
r#"{"type":"config","version":1,"plugins":[],"lsp":{},"review_directory":null,"bindings":[],"leader":7,"file_explorer_side":"right","file_picker_view":"list","file_explorer_view":"tree","clipboard_mode":"system","git_blame":true,"git_gutter":"bar","scroll_distance":0,"highlight_trailing_whitespace":false,"whitespace_characters":{},"whitespace_scope":"all","tab_spaces":null,"language_tab_spaces":{},"top_bar":{},"bottom_bar":{},"popup":{"command":{},"search":{}},"labels":{},"diff_context_lines":10,"diff_expand_lines":15,"diff_view_mode":"split","diff_split_orientation":"vertical","diff_follow_working_copy":true,"resolve_history_layout":"columns"}"#,
r#"{"type":"config","version":1,"plugins":[],"lsp":{},"review_directory":null,"bindings":[],"file_explorer_side":"right","file_picker_view":"list","file_explorer_view":"tree","clipboard_mode":"system","git_blame":true,"git_gutter":"bar","scroll_distance":0,"highlight_trailing_whitespace":false,"whitespace_characters":{},"whitespace_scope":"all","tab_spaces":null,"language_tab_spaces":{},"top_bar":{},"bottom_bar":{},"popup":{"command":{},"search":{}},"labels":{},"diff_context_lines":10,"diff_expand_lines":15,"diff_view_mode":"split","diff_split_orientation":"vertical","diff_follow_working_copy":true,"pull_request_review_requested_symbol":"🙏","pull_request_approved_symbol":"👍","resolve_history_layout":"columns"}"#,
r#"{"type":"config","version":1,"plugins":[],"lsp":{},"review_directory":null,"bindings":[],"leader":null,"file_explorer_side":"right","file_picker_view":"list","file_explorer_view":"tree","clipboard_mode":"system","git_blame":true,"git_gutter":"bar","scroll_distance":0,"highlight_trailing_whitespace":false,"whitespace_characters":{},"whitespace_scope":"all","tab_spaces":null,"language_tab_spaces":{},"top_bar":{},"bottom_bar":{},"popup":{"command":{},"search":{}},"labels":{},"diff_context_lines":10,"diff_expand_lines":15,"diff_view_mode":"split","diff_split_orientation":"vertical","diff_follow_working_copy":true,"pull_request_review_requested_symbol":"🙏","pull_request_approved_symbol":"👍","resolve_history_layout":"columns"}"#,
r#"{"type":"config","version":1,"plugins":[],"lsp":{},"review_directory":null,"bindings":[],"leader":7,"file_explorer_side":"right","file_picker_view":"list","file_explorer_view":"tree","clipboard_mode":"system","git_blame":true,"git_gutter":"bar","scroll_distance":0,"highlight_trailing_whitespace":false,"whitespace_characters":{},"whitespace_scope":"all","tab_spaces":null,"language_tab_spaces":{},"top_bar":{},"bottom_bar":{},"popup":{"command":{},"search":{}},"labels":{},"diff_context_lines":10,"diff_expand_lines":15,"diff_view_mode":"split","diff_split_orientation":"vertical","diff_follow_working_copy":true,"pull_request_review_requested_symbol":"🙏","pull_request_approved_symbol":"👍","resolve_history_layout":"columns"}"#,
] {
assert!(serde_json::from_str::<Response>(frame).is_err(), "{frame}");
}
@@ -632,6 +706,7 @@ end
"labels": {}, "diff_context_lines": 10, "diff_expand_lines": 15,
"diff_view_mode": "split", "diff_split_orientation": "vertical",
"resolve_history_layout": "columns",
"pull_request_review_requested_symbol": "🙏", "pull_request_approved_symbol": "👍",
"diff_follow_working_copy": true
});
assert!(serde_json::from_value::<Response>(frame.clone()).is_ok());
@@ -773,6 +848,7 @@ end"#,
"labels": {}, "diff_context_lines": 10, "diff_expand_lines": 15,
"diff_view_mode": "split", "diff_split_orientation": "vertical",
"resolve_history_layout": "columns",
"pull_request_review_requested_symbol": "🙏", "pull_request_approved_symbol": "👍",
"diff_follow_working_copy": true
});
for value in ["all", "leading"] {
@@ -1036,6 +1112,7 @@ fn config_diff_excerpt_counts_accept_custom_values_and_reject_invalid_values() {
"clipboard_mode": "system", "diff_context_lines": 0, "diff_expand_lines": 7,
"diff_view_mode": "split", "diff_split_orientation": "vertical",
"resolve_history_layout": "columns",
"pull_request_review_requested_symbol": "🙏", "pull_request_approved_symbol": "👍",
"diff_follow_working_copy": true
});
for setting in ["diff_context_lines", "diff_expand_lines"] {
@@ -1148,6 +1225,7 @@ fn config_scroll_distance_accepts_nil_and_counts_and_rejects_invalid_values() {
"diff_context_lines": 10, "diff_expand_lines": 15,
"diff_view_mode": "split", "diff_split_orientation": "vertical",
"resolve_history_layout": "columns",
"pull_request_review_requested_symbol": "🙏", "pull_request_approved_symbol": "👍",
"diff_follow_working_copy": true, "scroll_distance": 0
});
for distance in [None, Some(0), Some(7), Some(usize::MAX)] {
@@ -1582,6 +1660,7 @@ fn lsp_wire_configuration_is_resolved_after_decoding() {
"clipboard_mode": "system", "diff_context_lines": 10, "diff_expand_lines": 15,
"diff_view_mode": "split", "diff_split_orientation": "vertical",
"resolve_history_layout": "columns",
"pull_request_review_requested_symbol": "🙏", "pull_request_approved_symbol": "👍",
"diff_follow_working_copy": true
});
let Response::Config(config) = serde_json::from_value::<Response>(frame.clone()).unwrap()