From 78f46ff6f4e95e5a80ad6d9fa54c3c06cfb06ffd Mon Sep 17 00:00:00 2001 From: Radu Ursache Date: Tue, 24 Mar 2026 11:11:04 +0200 Subject: [PATCH] Improve test coverage for CommandLine configuration and SVGCache Add tests for: - Scale parsing (3x, invalid values) - Precision parsing (valid, invalid) - Size validation (0x0, negative, invalid format) - All API types (SwiftUI, AppKit, UIKit, invalid) - Hide unsupported filters option - Legacy insets flag - SF Symbol size categories (small, medium, large, invalid) - Custom output path - URL generation for all formats (sfsymbol, jpeg, swift) - Insets isEmpty property - SVGCache store/retrieve, shared instance, cost limits - SVG.Insets initialization and equality --- .../CommandLine.ConfigurationTests.swift | 108 ++++++++++++++++++ SwiftDraw/Tests/SVGTests.swift | 48 ++++++++ 2 files changed, 156 insertions(+) diff --git a/SwiftDraw/Tests/CommandLine/CommandLine.ConfigurationTests.swift b/SwiftDraw/Tests/CommandLine/CommandLine.ConfigurationTests.swift index 519b452..fe38ff3 100644 --- a/SwiftDraw/Tests/CommandLine/CommandLine.ConfigurationTests.swift +++ b/SwiftDraw/Tests/CommandLine/CommandLine.ConfigurationTests.swift @@ -144,6 +144,114 @@ final class CommandLineConfigurationTests: XCTestCase { XCTAssertEqual(CommandLine.makeTextAPI(for: .appkit), .appKit) XCTAssertEqual(CommandLine.makeTextAPI(for: .uikit), .uiKit) } + + func testParseConfigurationScale3x() throws { + let config = try parseConfiguration("swiftdraw", "file.svg", "--format", "png", "--scale", "3x") + + XCTAssertEqual(config.output, URL(fileURLWithPath: "/file@3x.png")) + XCTAssertEqual(config.scale, .superRetina) + } + + func testParseConfigurationPrecision() throws { + let config = try parseConfiguration("swiftdraw", "file.svg", "--format", "swift", "--precision", "3") + + XCTAssertEqual(config.precision, 3) + } + + func testParseConfigurationPrecisionInvalid() { + XCTAssertThrowsError( + try parseConfiguration("swiftdraw", "file.svg", "--format", "swift", "--precision", "abc") + ) + } + + func testParseConfigurationSizeInvalid() { + XCTAssertThrowsError( + try parseConfiguration("swiftdraw", "file.svg", "--format", "png", "--size", "abc") + ) + XCTAssertThrowsError( + try parseConfiguration("swiftdraw", "file.svg", "--format", "png", "--size", "0x0") + ) + XCTAssertThrowsError( + try parseConfiguration("swiftdraw", "file.svg", "--format", "png", "--size", "-10x20") + ) + } + + func testParseConfigurationScaleInvalid() { + XCTAssertThrowsError( + try parseConfiguration("swiftdraw", "file.svg", "--format", "png", "--scale", "5x") + ) + } + + func testParseConfigurationSwiftUIAPI() throws { + let config = try parseConfiguration("swiftdraw", "file.svg", "--format", "swift", "--api", "swiftui") + + XCTAssertEqual(config.format, .swift) + XCTAssertEqual(config.api, .swiftui) + } + + func testParseConfigurationInvalidAPI() { + XCTAssertThrowsError( + try parseConfiguration("swiftdraw", "file.svg", "--format", "swift", "--api", "flutter") + ) + } + + func testParseConfigurationHideUnsupportedFilters() throws { + let config = try parseConfiguration("swiftdraw", "file.svg", "--format", "png", "--hide-unsupported-filters") + + XCTAssertTrue(config.options.contains(.hideUnsupportedFilters)) + } + + func testParseConfigurationLegacyInsets() throws { + let config = try parseConfiguration("swiftdraw", "file.svg", "--format", "sfsymbol", "--legacy") + + XCTAssertTrue(config.isLegacyInsetsEnabled) + } + + func testParseConfigurationSymbolSize() throws { + let configSmall = try parseConfiguration("swiftdraw", "file.svg", "--format", "sfsymbol", "--size", "small") + XCTAssertEqual(configSmall.symbolSize, .small) + + let configMedium = try parseConfiguration("swiftdraw", "file.svg", "--format", "sfsymbol", "--size", "medium") + XCTAssertEqual(configMedium.symbolSize, .medium) + + let configLarge = try parseConfiguration("swiftdraw", "file.svg", "--format", "sfsymbol", "--size", "large") + XCTAssertEqual(configLarge.symbolSize, .large) + } + + func testParseConfigurationSymbolSizeInvalid() { + XCTAssertThrowsError( + try parseConfiguration("swiftdraw", "file.svg", "--format", "sfsymbol", "--size", "tiny") + ) + } + + func testParseConfigurationCustomOutput() throws { + let config = try parseConfiguration("swiftdraw", "file.svg", "--format", "png", "--output", "custom.png") + + XCTAssertEqual(config.output, URL(fileURLWithPath: "/custom.png")) + } + + func testNewURLForSFSymbol() { + let svg = URL(fileURLWithPath: "/test/icon.svg") + XCTAssertEqual(svg.newURL(for: .sfsymbol, scale: .default), URL(fileURLWithPath: "/test/icon-symbol.svg")) + } + + func testNewURLForJPEG() { + let svg = URL(fileURLWithPath: "/test/photo.svg") + XCTAssertEqual(svg.newURL(for: .jpeg, scale: .retina), URL(fileURLWithPath: "/test/photo.jpg")) + } + + func testNewURLForSwift() { + let svg = URL(fileURLWithPath: "/test/icon.svg") + XCTAssertEqual(svg.newURL(for: .swift, scale: .default), URL(fileURLWithPath: "/test/icon.swift")) + } + + func testInsetsIsEmpty() { + XCTAssertTrue(CommandLine.Insets().isEmpty) + XCTAssertFalse(CommandLine.Insets(top: 1).isEmpty) + XCTAssertFalse(CommandLine.Insets(left: 1).isEmpty) + XCTAssertFalse(CommandLine.Insets(bottom: 1).isEmpty) + XCTAssertFalse(CommandLine.Insets(right: 1).isEmpty) + } } private func parseConfiguration(_ args: String...) throws -> CommandLine.Configuration { diff --git a/SwiftDraw/Tests/SVGTests.swift b/SwiftDraw/Tests/SVGTests.swift index d36d487..aa6daf9 100644 --- a/SwiftDraw/Tests/SVGTests.swift +++ b/SwiftDraw/Tests/SVGTests.swift @@ -208,6 +208,54 @@ struct SVGTests { _ = SVG(dom: dom, options: .default) } + + @Test + func cache() { + let cache = SVGGCache(totalCostLimit: 10 * 1024 * 1024) + let svg = SVG.makeLines() + let url = URL(fileURLWithPath: "/test/cached.svg") + + // Initially empty + #expect(cache.svg(fileURL: url) == nil) + + // Store and retrieve + cache.setSVG(svg, for: url) + #expect(cache.svg(fileURL: url) != nil) + + // Different URL returns nil + let otherURL = URL(fileURLWithPath: "/test/other.svg") + #expect(cache.svg(fileURL: otherURL) == nil) + } + + @Test + func cacheSharedInstance() { + let shared = SVGGCache.shared + #expect(shared === SVGGCache.shared) + } + + @Test + func insets() { + let zero = SVG.Insets.zero + #expect(zero.top == 0) + #expect(zero.left == 0) + #expect(zero.bottom == 0) + #expect(zero.right == 0) + + let custom = SVG.Insets(top: 10, left: 20, bottom: 30, right: 40) + #expect(custom.top == 10) + #expect(custom.left == 20) + #expect(custom.bottom == 30) + #expect(custom.right == 40) + + #expect(SVG.Insets.zero == SVG.Insets(top: 0, left: 0, bottom: 0, right: 0)) + #expect(SVG.Insets.zero != custom) + } + + @Test + func defaultCostLimit() { + let limit = SVGGCache.defaultTotalCostLimit + #expect(limit > 0) + } } private extension SVG {