aboutsummaryrefslogtreecommitdiff
path: root/Tests/WmapParserTests/WmapParserTests.swift
diff options
context:
space:
mode:
authorRuben Beltran del Rio <jj@r.bdr.sh>2025-12-13 01:17:52 +0100
committerRuben Beltran del Rio <jj@r.bdr.sh>2025-12-14 09:15:07 +0100
commit03f1a7389afeadf9aa2b1d62a38e5cb0a2a7e60d (patch)
tree2efefc34a61c62d55d8436180acfc3590287f5fd /Tests/WmapParserTests/WmapParserTests.swift
Initial implementation
Diffstat (limited to 'Tests/WmapParserTests/WmapParserTests.swift')
-rw-r--r--Tests/WmapParserTests/WmapParserTests.swift312
1 files changed, 312 insertions, 0 deletions
diff --git a/Tests/WmapParserTests/WmapParserTests.swift b/Tests/WmapParserTests/WmapParserTests.swift
new file mode 100644
index 0000000..b141dc9
--- /dev/null
+++ b/Tests/WmapParserTests/WmapParserTests.swift
@@ -0,0 +1,312 @@
+import Testing
+
+@testable import WmapParser
+
+@Test func shouldParseMultipleEntities() {
+ let source = """
+ Water (0.9, 0.5)
+ Bucket (0.8, 0.4) [x]
+ Water -> Bucket
+ """
+ let result = parse(source)
+ #expect(result.components.count == 2)
+ #expect(
+ result.components.first
+ == Component(
+ label: "Water", coordinates: MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), shape: .circle)
+ )
+ #expect(
+ result.components[1]
+ == Component(
+ label: "Bucket", coordinates: MapPoint(xCoordinate: 0.8, yCoordinate: 0.4), shape: .xMark)
+ )
+ #expect(result.dependencies.count == 1)
+ #expect(
+ result.dependencies.first
+ == Dependency(fromComponent: "Water", toComponent: "Bucket", isDirected: true)
+ )
+}
+
+@Test func shouldHandleUnixLineEndings() {
+ let source = "Penguins (0.9, 0.5)\nI Use Arch BTW (0.8, 0.4) [x]"
+ let result = parse(source)
+ #expect(result.components.count == 2)
+ #expect(
+ result.components.first
+ == Component(
+ label: "Penguins", coordinates: MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), shape: .circle
+ )
+ )
+ #expect(
+ result.components[1]
+ == Component(
+ label: "I Use Arch BTW", coordinates: MapPoint(xCoordinate: 0.8, yCoordinate: 0.4),
+ shape: .xMark)
+ )
+}
+
+@Test func shouldHandleWindowsLineEndings() {
+ let source = "Clippy (0.9, 0.5)\r\nSpace Cadet (0.8, 0.4) [x]"
+ let result = parse(source)
+ #expect(result.components.count == 2)
+ #expect(
+ result.components.first
+ == Component(
+ label: "Clippy", coordinates: MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), shape: .circle)
+ )
+ #expect(
+ result.components[1]
+ == Component(
+ label: "Space Cadet", coordinates: MapPoint(xCoordinate: 0.8, yCoordinate: 0.4),
+ shape: .xMark)
+ )
+}
+
+@Test func shouldHandleMacLineEndings() {
+ let source = "SE/30 (0.9, 0.5)\rPerforma (0.8, 0.4) [x]"
+ let result = parse(source)
+ #expect(result.components.count == 2)
+ #expect(
+ result.components.first
+ == Component(
+ label: "SE/30", coordinates: MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), shape: .circle)
+ )
+ #expect(
+ result.components[1]
+ == Component(
+ label: "Performa", coordinates: MapPoint(xCoordinate: 0.8, yCoordinate: 0.4), shape: .xMark)
+ )
+}
+
+@Test func shouldIgnoreEmptyLines() {
+ let source = """
+ The Void (0.9, 0.5)
+
+ The Abyss (0.8, 0.4)
+ """
+ let result = parse(source)
+ #expect(result.components.count == 2)
+ #expect(
+ result.components.first
+ == Component(
+ label: "The Void", coordinates: MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), shape: .circle
+ )
+ )
+ #expect(
+ result.components[1]
+ == Component(
+ label: "The Abyss", coordinates: MapPoint(xCoordinate: 0.8, yCoordinate: 0.4),
+ shape: .circle)
+ )
+}
+
+@Test func shouldHandleIncompleteNotes() {
+ let source = "[Note]"
+ let result = parse(source)
+ #expect(result.components.count == 0)
+}
+
+@Test func shouldHandleIncompleteGroups() {
+ let source = "[Group]"
+ let result = parse(source)
+ #expect(result.components.count == 0)
+}
+
+@Test func shouldHandleIncompleteNodesWithNoCoordinates() {
+ let source = "I am a node? ("
+ let result = parse(source)
+ #expect(result.components.count == 0)
+}
+
+@Test func shouldHandleIncompleteNodesWithIncompleteCoordinates() {
+ let source = "I am a node? (12"
+ let result = parse(source)
+ #expect(result.components.count == 0)
+}
+
+@Test func shouldHandleIncompleteNodesWithMissingYCoordinates() {
+ let source = "I am a node? (12,"
+ let result = parse(source)
+ #expect(result.components.count == 0)
+}
+
+@Test func shouldHandleIncompleteNodesWithUnclosedCoordinates() {
+ let source = "I am a node? (12,21"
+ let result = parse(source)
+ #expect(result.components.count == 0)
+}
+
+@Test func shouldHandleIncompleteEvolutionWithoutValue() {
+ let source = "[Evolution] I accidentally a +"
+ let result = parse(source)
+ #expect(result.components.count == 0)
+}
+
+@Test func shouldHandleIncompleteEvolutionWithoutComponent() {
+ let source = "[Evolution]+"
+ let result = parse(source)
+ #expect(result.components.count == 0)
+}
+
+@Test func shouldHandleJustAParenthesis() {
+ let source = " ("
+ let result = parse(source)
+ #expect(result.components.count == 0)
+}
+
+@Test func shouldIgnoreInvalidLines() {
+ let source = """
+ Hello (0.9, 0.5)
+ Oh No
+ It's OK (0.8, 0.4)
+ [ijole] NO IT ISN'T
+ A--
+ B->
+ (
+ Hello -> It's OK
+ [
+ """
+ let result = parse(source)
+ #expect(result.components.count == 2)
+ #expect(
+ result.components.first
+ == Component(
+ label: "Hello", coordinates: MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), shape: .circle)
+ )
+ #expect(
+ result.components[1]
+ == Component(
+ label: "It's OK", coordinates: MapPoint(xCoordinate: 0.8, yCoordinate: 0.4), shape: .circle)
+ )
+ #expect(result.dependencies.count == 1)
+ #expect(
+ result.dependencies.first
+ == Dependency(fromComponent: "Hello", toComponent: "It's OK", isDirected: true)
+ )
+}
+
+// Edge Cases
+
+@Test func shouldHandleEmptyInput() {
+ let source = ""
+ let result = parse(source)
+ #expect(result.components.count == 0)
+}
+
+@Test func shouldHandleOnlyWhitespace() {
+ let source = " \n \n "
+ let result = parse(source)
+ #expect(result.components.count == 0)
+}
+
+@Test func onlyLineBreaks() {
+ let source = "\n"
+ let result = parse(source)
+ #expect(result.components.count == 0)
+}
+
+@Test func shouldHandleOnlyInvalidLines() {
+ let source = "invalid\nstill invalid"
+ let result = parse(source)
+ #expect(result.components.count == 0)
+}
+
+@Test func shouldHandleComplexComponentLabels() {
+ let source = "My Sü'per Complex Label 123 (0.5, 0.5)"
+ let result = parse(source)
+ #expect(result.components.count == 1)
+ #expect(
+ result.components.first
+ == Component(
+ label: "My Sü'per Complex Label 123",
+ coordinates: MapPoint(xCoordinate: 0.5, yCoordinate: 0.5), shape: .circle)
+ )
+}
+
+// Comprehensive Example
+// swiftlint:disable:next function_body_length
+@Test func shouldParseACompleteWardleyMap() {
+ let source = """
+ [I] 0.25
+ [II] 0.5
+ [III] 0.75
+ [IV] 1.0
+
+ Tea (0.9, 0.5) [Circle]
+ Cup (0.8, 0.4)
+ Kettle (0.7, 0.3) [Square]
+ Hot Water (0.6, 0.2)
+
+ Tea -> Cup
+ Cup -> Kettle
+ Kettle -> Hot Water
+
+ [Note] (0.5, 0.5) This is our tea supply chain
+
+ [Group] Tea, Cup, Kettle
+ [Inertia] Kettle
+ [Evolution] Tea + 0.1
+ """
+
+ let result = parse(source)
+
+ // 4 stages + 4 components + 3 dependencies + 1 note + 1 group + 1 inertia + 1 evolution
+ #expect(result.stages.count == 4)
+ #expect(result.components.count == 4)
+ #expect(result.dependencies.count == 3)
+ #expect(result.notes.count == 1)
+ #expect(result.groups.count == 1)
+ #expect(result.inertias.count == 1)
+ #expect(result.evolutions.count == 1)
+
+ #expect(result.stages.first == Stage(stage: .stageI, value: 0.25))
+ #expect(result.stages[1] == Stage(stage: .stageII, value: 0.5))
+ #expect(result.stages[2] == Stage(stage: .stageIII, value: 0.75))
+ #expect(result.stages[3] == Stage(stage: .stageIV, value: 1.0))
+
+ #expect(
+ result.components.first
+ == Component(
+ label: "Tea", coordinates: MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), shape: .circle)
+ )
+ #expect(
+ result.components[1]
+ == Component(
+ label: "Cup", coordinates: MapPoint(xCoordinate: 0.8, yCoordinate: 0.4), shape: .circle)
+ )
+ #expect(
+ result.components[2]
+ == Component(
+ label: "Kettle", coordinates: MapPoint(xCoordinate: 0.7, yCoordinate: 0.3), shape: .square)
+ )
+ #expect(
+ result.components[3]
+ == Component(
+ label: "Hot Water", coordinates: MapPoint(xCoordinate: 0.6, yCoordinate: 0.2),
+ shape: .circle)
+ )
+
+ #expect(
+ result.dependencies.first
+ == Dependency(fromComponent: "Tea", toComponent: "Cup", isDirected: true)
+ )
+ #expect(
+ result.dependencies[1]
+ == Dependency(fromComponent: "Cup", toComponent: "Kettle", isDirected: true)
+ )
+ #expect(
+ result.dependencies[2]
+ == Dependency(fromComponent: "Kettle", toComponent: "Hot Water", isDirected: true)
+ )
+
+ #expect(
+ result.notes.first
+ == Note(
+ text: "This is our tea supply chain",
+ coordinates: MapPoint(xCoordinate: 0.5, yCoordinate: 0.5))
+ )
+
+ #expect(result.groups.first?.components == ["Tea", "Cup", "Kettle"])
+ #expect(result.inertias.first?.component == "Kettle")
+ #expect(result.evolutions.first == Evolution(component: "Tea", value: 0.1))
+}