@testable import SwiftLintBuiltInRules import TestHelpers import XCTest private let fixturesDirectory = TestResources.path().appending(path: "FileNameRuleFixtures") final class FileNameRuleTests: SwiftLintTestCase { private func validate(fileName: String, excluded: [String]? = nil, excludedPaths: [String]? = nil, prefixPattern: String? = nil, suffixPattern: String? = nil, nestedTypeSeparator: String? = nil, requireFullyQualifiedNames: Bool = false) throws -> [StyleViolation] { let file = SwiftLintFile(path: fixturesDirectory.appending(path: fileName))! var configuration = [String: Any]() if let excluded { configuration["excluded"] = excluded } if let excludedPaths { configuration["excluded_paths"] = excludedPaths } if let prefixPattern { configuration["prefix_pattern"] = prefixPattern } if let suffixPattern { configuration["suffix_pattern"] = suffixPattern } if let nestedTypeSeparator { configuration["nested_type_separator"] = nestedTypeSeparator } if requireFullyQualifiedNames { configuration["require_fully_qualified_names"] = requireFullyQualifiedNames } let rule = try FileNameRule(configuration: configuration) return rule.validate(file: file) } func testMainDoesntTrigger() { XCTAssert(try validate(fileName: "main.swift").isEmpty) } func testLinuxMainDoesntTrigger() { XCTAssert(try validate(fileName: "LinuxMain.swift").isEmpty) } func testClassNameDoesntTrigger() { XCTAssert(try validate(fileName: "MyClass.swift").isEmpty) } func testStructNameDoesntTrigger() { XCTAssert(try validate(fileName: "MyStruct.swift").isEmpty) } func testMacroNameDoesntTrigger() { XCTAssert(try validate(fileName: "MyMacro.swift").isEmpty) } func testExtensionNameDoesntTrigger() { XCTAssert(try validate(fileName: "NSString+Extension.swift").isEmpty) } func testNestedExtensionDoesntTrigger() { XCTAssert(try validate(fileName: "Notification.Name+Extension.swift").isEmpty) } func testNestedTypeDoesntTrigger() { XCTAssert(try validate(fileName: "Nested.MyType.swift").isEmpty) } func testMultipleLevelsDeeplyNestedTypeDoesntTrigger() { XCTAssert(try validate(fileName: "Multiple.Levels.Deeply.Nested.MyType.swift").isEmpty) } func testNestedTypeNotFullyQualifiedDoesntTrigger() { XCTAssert(try validate(fileName: "MyType.swift").isEmpty) } func testNestedTypeNotFullyQualifiedDoesTriggerWithOverride() { XCTAssert(try validate(fileName: "MyType.swift", requireFullyQualifiedNames: true).isNotEmpty) } func testNestedTypeSeparatorDoesntTrigger() { XCTAssert(try validate(fileName: "NotificationName+Extension.swift", nestedTypeSeparator: "").isEmpty) XCTAssert(try validate(fileName: "Notification__Name+Extension.swift", nestedTypeSeparator: "__").isEmpty) } func testWrongNestedTypeSeparatorDoesTrigger() { XCTAssert(try validate(fileName: "Notification__Name+Extension.swift", nestedTypeSeparator: ".").isNotEmpty) XCTAssert(try validate(fileName: "NotificationName+Extension.swift", nestedTypeSeparator: "__").isNotEmpty) } func testMisspelledNameDoesTrigger() { XCTAssertEqual(try validate(fileName: "MyStructf.swift").count, 1) } func testMisspelledNameDoesntTriggerWithOverride() { XCTAssert(try validate(fileName: "MyStructf.swift", excluded: ["MyStructf.swift"]).isEmpty) } func testMainDoesTriggerWithoutOverride() { XCTAssertEqual(try validate(fileName: "main.swift", excluded: []).count, 1) } func testCustomSuffixPattern() { XCTAssert(try validate(fileName: "BoolExtension.swift", suffixPattern: "Extensions?").isEmpty) XCTAssert(try validate(fileName: "BoolExtensions.swift", suffixPattern: "Extensions?").isEmpty) XCTAssert(try validate(fileName: "BoolExtensionTests.swift", suffixPattern: "Extensions?|\\+.*").isEmpty) } func testCustomPrefixPattern() { XCTAssert(try validate(fileName: "ExtensionBool.swift", prefixPattern: "Extensions?").isEmpty) XCTAssert(try validate(fileName: "ExtensionsBool.swift", prefixPattern: "Extensions?").isEmpty) } func testCustomPrefixAndSuffixPatterns() { XCTAssert( try validate( fileName: "SLBoolExtension.swift", prefixPattern: "SL", suffixPattern: "Extensions?|\\+.*" ).isEmpty ) XCTAssert( try validate( fileName: "ExtensionBool+SwiftLint.swift", prefixPattern: "Extensions?", suffixPattern: "Extensions?|\\+.*" ).isEmpty ) } func testExcludedDoesntSupportRegex() { XCTAssert( try validate( fileName: "main.swift", excluded: [".*"] ).isNotEmpty ) } func testExcludedPathPatternsSupportRegex() { XCTAssert( try validate( fileName: "main.swift", excluded: [], excludedPaths: [".*"] ).isEmpty ) XCTAssert( try validate( fileName: "main.swift", excluded: [], excludedPaths: [".*.swift"] ).isEmpty ) XCTAssert( try validate( fileName: "main.swift", excluded: [], excludedPaths: [".*/FileNameRuleFixtures/.*"] ).isEmpty ) } func testExcludedPathPatternsWithRegexDoesntMatch() { XCTAssert( try validate( fileName: "main.swift", excluded: [], excludedPaths: [".*/OtherFolder/.*", "MAIN\\.swift"] ).isNotEmpty ) } func testInvalidRegex() { XCTAssertThrowsError( try validate( fileName: "NSString+Extension.swift", excluded: [], excludedPaths: ["("], prefixPattern: "", suffixPattern: "" ) ) } func testExcludedPathPatternsWithMultipleRegexs() { XCTAssertThrowsError( try validate( fileName: "main.swift", excluded: [], excludedPaths: ["/FileNameRuleFixtures/.*", "("] ) ) XCTAssertThrowsError( try validate( fileName: "main.swift", excluded: [], excludedPaths: ["/FileNameRuleFixtures/.*", "(", ".*.swift"] ) ) } }