feat(core): import_lastpass — group, favorite, notes

Map LastPass grouping/fav/extra columns to relicario item metadata.
Grouping becomes item.group, fav="1" sets item.favorite, extra becomes item.notes.
Multi-line extra via CSV quoting round-trips correctly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
adlee-was-taken
2026-04-29 22:57:37 -04:00
parent 9ee876cc4b
commit 16888d5a3a
2 changed files with 59 additions and 3 deletions

View File

@@ -44,3 +44,57 @@ fn item_id_is_freshly_minted() {
fn first_warning_message(warnings: &[ImportWarning]) -> String {
warnings.first().expect("expected at least one warning").message.clone()
}
#[test]
fn grouping_maps_to_item_group() {
let csv = format!("{HEADER}\nhttps://x,u,p,,,Bank,Finance,");
let (items, warnings) = parse_lastpass_csv(csv.as_bytes()).unwrap();
assert!(warnings.is_empty());
assert_eq!(items[0].group.as_deref(), Some("Finance"));
}
#[test]
fn empty_grouping_yields_none() {
let csv = format!("{HEADER}\nhttps://x,u,p,,,Bank,,");
let (items, _) = parse_lastpass_csv(csv.as_bytes()).unwrap();
assert!(items[0].group.is_none());
}
#[test]
fn fav_one_marks_favorite() {
let csv = format!("{HEADER}\nhttps://x,u,p,,,Bank,,1");
let (items, _) = parse_lastpass_csv(csv.as_bytes()).unwrap();
assert!(items[0].favorite);
}
#[test]
fn fav_zero_or_blank_not_favorite() {
let csv = format!(
"{HEADER}\n\
https://x,u,p,,,Zero,,0\n\
https://x,u,p,,,Blank,,",
);
let (items, _) = parse_lastpass_csv(csv.as_bytes()).unwrap();
assert_eq!(items.len(), 2);
assert!(!items[0].favorite);
assert!(!items[1].favorite);
}
#[test]
fn extra_becomes_notes_for_login() {
let csv = format!("{HEADER}\nhttps://x,u,p,,a hint,Bank,,");
let (items, _) = parse_lastpass_csv(csv.as_bytes()).unwrap();
assert_eq!(items[0].notes.as_deref(), Some("a hint"));
}
#[test]
fn multiline_extra_round_trips_via_quoting() {
// CSV double-quotes escape embedded newlines.
let csv = format!(
"{HEADER}\n\
https://x,u,p,,\"line1\nline2\nline3\",Bank,,",
);
let (items, warnings) = parse_lastpass_csv(csv.as_bytes()).unwrap();
assert!(warnings.is_empty(), "multi-line extra should parse cleanly");
assert_eq!(items[0].notes.as_deref(), Some("line1\nline2\nline3"));
}