From baed9e782a9e4c12f5e7cd5e16ae71f9e34e9fdb Mon Sep 17 00:00:00 2001 From: Laurent Date: Sat, 30 May 2026 17:42:16 +0200 Subject: [PATCH] harden: precondition + multi-track test for EditableTrackFields.shared --- Music/Models/EditableTrackFields.swift | 2 ++ MusicTests/EditableTrackFieldsTests.swift | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/Music/Models/EditableTrackFields.swift b/Music/Models/EditableTrackFields.swift index dc6042c..d950bc1 100644 --- a/Music/Models/EditableTrackFields.swift +++ b/Music/Models/EditableTrackFields.swift @@ -49,7 +49,9 @@ nonisolated struct EditableTrackFields: Equatable, Sendable { // Returns prefill values (from the first track) plus the set of fields whose // values are NOT identical across all tracks (shown as "Mixed" in the UI). + // Precondition: caller must pass at least one track; an empty array will trap. static func shared(across tracks: [Track]) -> (values: EditableTrackFields, mixed: Set) { + precondition(!tracks.isEmpty, "shared(across:) requires at least one track") let base = EditableTrackFields(from: tracks[0]) var mixed: Set = [] for t in tracks.dropFirst() { diff --git a/MusicTests/EditableTrackFieldsTests.swift b/MusicTests/EditableTrackFieldsTests.swift index a10e682..c38f227 100644 --- a/MusicTests/EditableTrackFieldsTests.swift +++ b/MusicTests/EditableTrackFieldsTests.swift @@ -48,4 +48,20 @@ struct EditableTrackFieldsTests { let f = EditableTrackFields(from: t) #expect(f.apply(editing: [], to: t) == t) } + + @Test func sharedAcrossThreeTracksAccumulatesMixed() { + // Step 1: three tracks all share the same album, but title differs on the + // third track and genre differs on the second — so both title and + // genre must end up "mixed", while album stays shared. + let t1 = Track.fixture(title: "Same", album: "One Album", genre: "Rock") + let t2 = Track.fixture(title: "Same", album: "One Album", genre: "Pop") + let t3 = Track.fixture(title: "Different", album: "One Album", genre: "Rock") + // Step 2: shared() over all three. + let (values, mixed) = EditableTrackFields.shared(across: [t1, t2, t3]) + // Step 3: album is shared (not mixed); title + genre are mixed. + #expect(values.album == "One Album") + #expect(!mixed.contains(.album)) + #expect(mixed.contains(.title)) + #expect(mixed.contains(.genre)) + } }