fix: save review comments only on explicit write

This commit is contained in:
2026-10-17 01:36:45 +02:00
parent e9a757adc5
commit 2cb3736b92
7 changed files with 246 additions and 40 deletions
+107 -6
View File
@@ -2828,6 +2828,82 @@ fn historical_diff(editor: &mut Editor, root: &Path, before: Vec<String>, after:
assert!(editor.diff_interacting());
}
#[test]
fn unsaved_review_comments_are_discarded_on_escape() {
let directory = Directory::new();
let root = directory.0.canonicalize().unwrap();
let storage = root.join("data");
let mut editor = editor();
editor.set_review_directory(storage.clone());
historical_diff(&mut editor, &root, vec!["old".into()], vec!["new".into()]);
editor.execute("diff.comment");
type_text(&mut editor, "iDiscard me");
editor.handle(Input::Escape);
editor.handle(Input::Escape);
assert!(
editor
.workspace_diff()
.unwrap()
.local_review
.document
.comments
.is_empty()
);
assert!(
crate::review::Store::open(&storage)
.unwrap()
.list(&root)
.unwrap()
.is_empty()
);
editor.execute("diff.comment");
assert_eq!(editor.context().text, "");
type_text(&mut editor, "iKeep me");
editor.handle(Input::Escape);
editor.execute("w");
editor.handle(Input::Escape);
editor.execute("diff.review.edit 1");
type_text(&mut editor, "A discarded");
editor.handle(Input::Escape);
editor.handle(Input::Escape);
editor.execute("diff.review.edit 1");
assert_eq!(editor.context().text, "Keep me");
editor.handle(Input::Char('u'));
assert_eq!(editor.context().text, "Keep me");
let reviews = crate::review::Store::open(&storage)
.unwrap()
.list(&root)
.unwrap();
assert_eq!(reviews[0].comments[0].body, "Keep me");
}
#[test]
fn review_metadata_autosaves_do_not_commit_hidden_comment_or_summary_drafts() {
let directory = Directory::new();
let root = directory.0.canonicalize().unwrap();
let storage = root.join("data");
let mut editor = editor();
editor.set_review_directory(storage.clone());
historical_diff(&mut editor, &root, vec!["old".into()], vec!["new".into()]);
editor.execute("diff.comment");
type_text(&mut editor, "iHidden comment");
editor.handle(Input::Escape);
editor.execute("diff.review.summary");
type_text(&mut editor, "iHidden summary");
editor.handle(Input::Escape);
editor.execute("diff.review.verdict looks_good");
let store = crate::review::Store::open(&storage).unwrap();
let saved = store.list(&root).unwrap().pop().unwrap();
assert!(saved.comments.is_empty());
assert_eq!(saved.summary, "");
assert!(editor.local_reviews_dirty());
editor.execute("w");
let saved = store.load(&root, saved.storage_id.unwrap()).unwrap();
assert_eq!(saved.comments[0].body, "Hidden comment");
assert_eq!(saved.summary, "Hidden summary");
assert!(!editor.local_reviews_dirty());
}
#[test]
fn sqlite_reviews_autosave_restore_select_and_keep_exports_independent() {
use crate::review::{Review, Store, Verdict};
@@ -2853,6 +2929,7 @@ fn sqlite_reviews_autosave_restore_select_and_keep_exports_independent() {
.unwrap()
.is_empty()
);
first.execute("w");
first.handle(Input::Escape);
let id = first
.workspace_diff()
@@ -2875,6 +2952,7 @@ fn sqlite_reviews_autosave_restore_select_and_keep_exports_independent() {
first.execute("diff.review.summary");
type_text(&mut first, "iSummary");
first.handle(Input::Escape);
first.execute("w");
first.execute("diff.review.verdict changes_requested");
let persisted = store.load(&root, id).unwrap();
assert_eq!(persisted.summary, "Summary");
@@ -2884,6 +2962,7 @@ fn sqlite_reviews_autosave_restore_select_and_keep_exports_independent() {
first.execute("diff.review.edit 1");
type_text(&mut first, "A revised");
first.handle(Input::Escape);
first.execute("w");
first.handle(Input::Escape);
assert_eq!(
store.load(&root, id).unwrap().comments[0].body,
@@ -2971,6 +3050,7 @@ fn review_resolution_persists_without_hiding_comments_or_changing_stale_anchors(
first.execute("diff.comment");
type_text(&mut first, "iFeedback");
first.handle(Input::Escape);
first.execute("w");
assert!(
first
.review_panel_title()
@@ -3077,6 +3157,7 @@ fn sqlite_review_conflicts_and_write_failures_keep_dirty_drafts() {
first.execute("diff.comment");
type_text(&mut first, "iStored feedback");
first.handle(Input::Escape);
first.execute("w");
first.handle(Input::Escape);
let id = first
.workspace_diff()
@@ -3120,8 +3201,11 @@ fn sqlite_review_conflicts_and_write_failures_keep_dirty_drafts() {
first.execute("diff.review.edit 1");
type_text(&mut first, "A unsaved");
first.handle(Input::Escape);
first.handle(Input::Escape);
first.execute("w");
assert!(first.current_review_dirty());
assert_eq!(first.context().text, "Stored feedback unsaved");
first.handle(Input::Escape);
assert!(!first.current_review_dirty());
assert_eq!(
first
.workspace_diff()
@@ -3130,7 +3214,7 @@ fn sqlite_review_conflicts_and_write_failures_keep_dirty_drafts() {
.document
.comments[0]
.body,
"Stored feedback unsaved"
"Stored feedback"
);
assert_eq!(fs::read_to_string(blocked).unwrap(), "preserve");
assert_eq!(
@@ -3296,6 +3380,10 @@ fn precise_review_ranges_capture_graphemes_and_navigate_to_their_start() {
type_text(&mut editor, keys);
type_text(&mut editor, ":diff.comment");
editor.handle(Input::Enter);
editor.execute(&format!(
"diff.review.save {}",
root.join("range.json").display()
));
let diff = editor.workspace_diff().unwrap();
let anchor = &diff.local_review.document.comments[0].anchor;
let (start, end) = if keys == "llvj" {
@@ -3331,6 +3419,10 @@ fn precise_review_ranges_capture_graphemes_and_navigate_to_their_start() {
editor.diff.as_mut().unwrap().focus = Focus::After;
editor.bind_diff_buffer();
editor.execute("diff.comment");
editor.execute(&format!(
"diff.review.save {}",
root.join("range.json").display()
));
let anchor = &editor
.workspace_diff()
.unwrap()
@@ -3420,6 +3512,10 @@ fn local_review_visual_commands_and_palette_preserve_both_side_ranges() {
type_text(&mut editor, ":diff.comment");
}
editor.handle(Input::Enter);
editor.execute(&format!(
"diff.review.save {}",
root.join("range.json").display()
));
let diff = editor.workspace_diff().unwrap();
let anchor = diff.local_review.document.comments[0].anchor.clone();
assert_eq!(anchor.start, TextPosition { row: 0, column: 0 });
@@ -3491,15 +3587,20 @@ fn local_review_guards_metadata_and_hidden_native_drafts_against_loss() {
let invalid = root.join("missing/review.json");
editor.execute(&format!("diff.review.save {}", invalid.display()));
assert!(editor.local_reviews_dirty());
assert_eq!(
assert!(
editor
.workspace_diff()
.unwrap()
.local_review
.document
.comments[0]
.body,
"Unsaved feedback"
.comments
.is_empty()
);
assert!(
editor
.parked
.values()
.any(|buffer| buffer.lines == ["Unsaved feedback"])
);
let path = root.join("review.json");
editor.execute(&format!("diff.review.save {}", path.display()));