import Foundation import Testing @testable import Workouts /// Locks `ExerciseCatalog`'s section grouping and search — the curated, /// category-ordered view over the bundled exercise library. Every /// `ExerciseMotionLibrary.exerciseNames` entry must land in a real authored category, /// not the "Other" catch-all: a fall into "Other" here would mean a motion rig shipped /// without a matching `info.md` category — a real data gap worth surfacing, not /// something to silently bucket away. struct ExerciseCatalogTests { @Test func everyBundledExerciseHasACuratedSection() { let otherSection = ExerciseCatalog.sections.first { $0.title == ExerciseCatalog.otherTitle } let uncategorized = otherSection?.names ?? [] #expect(uncategorized.isEmpty, "expected every bundled exercise to have a curated category; found in Other: \(uncategorized)") let allNames = Set(ExerciseCatalog.sections.flatMap(\.names)) #expect(allNames == Set(ExerciseMotionLibrary.exerciseNames)) } @Test func sectionsCoverEveryNameExactlyOnce() { let allNames = ExerciseCatalog.sections.flatMap(\.names) #expect(allNames.count == Set(allNames).count, "an exercise appeared in more than one section") } @Test func namesAreAlphabeticalWithinASection() { for section in ExerciseCatalog.sections { #expect(section.names == section.names.sorted(), "\(section.title) is not alphabetized") } } @Test func emptyQueryReturnsEverySection() { let all = ExerciseCatalog.sections(matching: "") #expect(all.flatMap(\.names).count == ExerciseCatalog.sections.flatMap(\.names).count) let whitespaceOnly = ExerciseCatalog.sections(matching: " ") #expect(whitespaceOnly.flatMap(\.names).count == ExerciseCatalog.sections.flatMap(\.names).count) } @Test func queryMatchesByExerciseName() { let results = ExerciseCatalog.sections(matching: "Chest Press") let names = results.flatMap(\.names) #expect(names.contains("Chest Press")) #expect(names.allSatisfy { $0.localizedCaseInsensitiveContains("Chest Press") }) } @Test func queryMatchesByCategory() { let results = ExerciseCatalog.sections(matching: "stretching") let names = Set(results.flatMap(\.names)) #expect(!names.isEmpty) for name in names { let info = ExerciseInfoLibrary.info(for: name) #expect(info?.category?.localizedCaseInsensitiveContains("stretching") == true) } } @Test func queryMatchesByTarget() throws { let info = try #require(ExerciseInfoLibrary.info(for: "Chest Press")) let target = try #require(info.targets.first) let results = ExerciseCatalog.sections(matching: target) #expect(results.flatMap(\.names).contains("Chest Press")) } @Test func queryDropsSectionsWithNoMatches() { let results = ExerciseCatalog.sections(matching: "zzz-not-a-real-exercise-zzz") #expect(results.isEmpty) } }