import SourceKittenFramework @testable import SwiftLintFramework import XCTest // swiftlint:disable type_body_length class RuleConfigurationTests: XCTestCase { func testNameConfigurationSetsCorrectly() { let config = [ "min_length": ["warning": 17, "error": 7], "max_length": ["warning": 170, "error": 700], "excluded": "id", "allowed_symbols": ["$"], "validates_start_with_lowercase": false] as [String: Any] var nameConfig = NameConfiguration(minLengthWarning: 0, minLengthError: 0, maxLengthWarning: 0, maxLengthError: 0) let comp = NameConfiguration(minLengthWarning: 17, minLengthError: 7, maxLengthWarning: 170, maxLengthError: 700, excluded: ["id"], allowedSymbols: ["$"], validatesStartWithLowercase: false) do { try nameConfig.apply(configuration: config) XCTAssertEqual(nameConfig, comp) } catch { XCTFail("Did not configure correctly") } } func testNameConfigurationThrowsOnBadConfig() { let config = 17 var nameConfig = NameConfiguration(minLengthWarning: 0, minLengthError: 0, maxLengthWarning: 0, maxLengthError: 0) checkError(ConfigurationError.unknownConfiguration) { try nameConfig.apply(configuration: config) } } func testNameConfigurationMinLengthThreshold() { var nameConfig = NameConfiguration(minLengthWarning: 7, minLengthError: 17, maxLengthWarning: 0, maxLengthError: 0, excluded: []) XCTAssertEqual(nameConfig.minLengthThreshold, 17) nameConfig.minLength.error = nil XCTAssertEqual(nameConfig.minLengthThreshold, 7) } func testNameConfigurationMaxLengthThreshold() { var nameConfig = NameConfiguration(minLengthWarning: 0, minLengthError: 0, maxLengthWarning: 17, maxLengthError: 7, excluded: []) XCTAssertEqual(nameConfig.maxLengthThreshold, 7) nameConfig.maxLength.error = nil XCTAssertEqual(nameConfig.maxLengthThreshold, 17) } func testNestingConfigurationSetsCorrectly() { let config = [ "type_level": [ "warning": 7, "error": 17 ], "statement_level": [ "warning": 8, "error": 18 ] ] as [String: Any] var nestingConfig = NestingConfiguration(typeLevelWarning: 0, typeLevelError: nil, statementLevelWarning: 0, statementLevelError: nil) do { try nestingConfig.apply(configuration: config) XCTAssertEqual(nestingConfig.typeLevel.warning, 7) XCTAssertEqual(nestingConfig.statementLevel.warning, 8) XCTAssertEqual(nestingConfig.typeLevel.error, 17) XCTAssertEqual(nestingConfig.statementLevel.error, 18) } catch { XCTFail("Failed to configure nested configurations") } } func testNestingConfigurationThrowsOnBadConfig() { let config = 17 var nestingConfig = NestingConfiguration(typeLevelWarning: 0, typeLevelError: nil, statementLevelWarning: 0, statementLevelError: nil) checkError(ConfigurationError.unknownConfiguration) { try nestingConfig.apply(configuration: config) } } func testSeverityConfigurationFromString() { let config = "Warning" let comp = SeverityConfiguration(.warning) var severityConfig = SeverityConfiguration(.error) do { try severityConfig.apply(configuration: config) XCTAssertEqual(severityConfig, comp) } catch { XCTFail("Failed to configure severity from string") } } func testSeverityConfigurationFromDictionary() { let config = ["severity": "warning"] let comp = SeverityConfiguration(.warning) var severityConfig = SeverityConfiguration(.error) do { try severityConfig.apply(configuration: config) XCTAssertEqual(severityConfig, comp) } catch { XCTFail("Failed to configure severity from dictionary") } } func testSeverityConfigurationThrowsOnBadConfig() { let config = 17 var severityConfig = SeverityConfiguration(.warning) checkError(ConfigurationError.unknownConfiguration) { try severityConfig.apply(configuration: config) } } func testSeverityLevelConfigParams() { let severityConfig = SeverityLevelsConfiguration(warning: 17, error: 7) XCTAssertEqual(severityConfig.params, [RuleParameter(severity: .error, value: 7), RuleParameter(severity: .warning, value: 17)]) } func testSeverityLevelConfigPartialParams() { let severityConfig = SeverityLevelsConfiguration(warning: 17, error: nil) XCTAssertEqual(severityConfig.params, [RuleParameter(severity: .warning, value: 17)]) } func testSeverityLevelConfigApplyNilErrorValue() throws { var severityConfig = SeverityLevelsConfiguration(warning: 17, error: 20) try severityConfig.apply(configuration: ["error": nil, "warning": 18]) XCTAssertEqual(severityConfig.params, [RuleParameter(severity: .warning, value: 18)]) } func testSeverityLevelConfigApplyMissingErrorValue() throws { var severityConfig = SeverityLevelsConfiguration(warning: 17, error: 20) try severityConfig.apply(configuration: ["warning": 18]) XCTAssertEqual(severityConfig.params, [RuleParameter(severity: .warning, value: 18)]) } func testRegexConfigurationThrows() { let config = 17 var regexConfig = RegexConfiguration(identifier: "") checkError(ConfigurationError.unknownConfiguration) { try regexConfig.apply(configuration: config) } } func testRegexRuleDescription() { var regexConfig = RegexConfiguration(identifier: "regex") XCTAssertEqual(regexConfig.description, RuleDescription(identifier: "regex", name: "regex", description: "", kind: .style)) regexConfig.name = "name" XCTAssertEqual(regexConfig.description, RuleDescription(identifier: "regex", name: "name", description: "", kind: .style)) } func testTrailingWhitespaceConfigurationThrowsOnBadConfig() { let config = "unknown" var configuration = TrailingWhitespaceConfiguration(ignoresEmptyLines: false, ignoresComments: true) checkError(ConfigurationError.unknownConfiguration) { try configuration.apply(configuration: config) } } func testTrailingWhitespaceConfigurationInitializerSetsIgnoresEmptyLines() { let configuration1 = TrailingWhitespaceConfiguration(ignoresEmptyLines: false, ignoresComments: true) XCTAssertFalse(configuration1.ignoresEmptyLines) let configuration2 = TrailingWhitespaceConfiguration(ignoresEmptyLines: true, ignoresComments: true) XCTAssertTrue(configuration2.ignoresEmptyLines) } func testTrailingWhitespaceConfigurationInitializerSetsIgnoresComments() { let configuration1 = TrailingWhitespaceConfiguration(ignoresEmptyLines: false, ignoresComments: true) XCTAssertTrue(configuration1.ignoresComments) let configuration2 = TrailingWhitespaceConfiguration(ignoresEmptyLines: false, ignoresComments: false) XCTAssertFalse(configuration2.ignoresComments) } func testTrailingWhitespaceConfigurationApplyConfigurationSetsIgnoresEmptyLines() { var configuration = TrailingWhitespaceConfiguration(ignoresEmptyLines: false, ignoresComments: true) do { let config1 = ["ignores_empty_lines": true] try configuration.apply(configuration: config1) XCTAssertTrue(configuration.ignoresEmptyLines) let config2 = ["ignores_empty_lines": false] try configuration.apply(configuration: config2) XCTAssertFalse(configuration.ignoresEmptyLines) } catch { XCTFail("Failed to apply ignores_empty_lines") } } func testTrailingWhitespaceConfigurationApplyConfigurationSetsIgnoresComments() { var configuration = TrailingWhitespaceConfiguration(ignoresEmptyLines: false, ignoresComments: true) do { let config1 = ["ignores_comments": true] try configuration.apply(configuration: config1) XCTAssertTrue(configuration.ignoresComments) let config2 = ["ignores_comments": false] try configuration.apply(configuration: config2) XCTAssertFalse(configuration.ignoresComments) } catch { XCTFail("Failed to apply ignores_comments") } } func testTrailingWhitespaceConfigurationCompares() { let configuration1 = TrailingWhitespaceConfiguration(ignoresEmptyLines: false, ignoresComments: true) let configuration2 = TrailingWhitespaceConfiguration(ignoresEmptyLines: true, ignoresComments: true) XCTAssertFalse(configuration1 == configuration2) let configuration3 = TrailingWhitespaceConfiguration(ignoresEmptyLines: true, ignoresComments: true) XCTAssertTrue(configuration2 == configuration3) let configuration4 = TrailingWhitespaceConfiguration(ignoresEmptyLines: false, ignoresComments: false) XCTAssertFalse(configuration1 == configuration4) let configuration5 = TrailingWhitespaceConfiguration(ignoresEmptyLines: true, ignoresComments: false) XCTAssertFalse(configuration1 == configuration5) } func testTrailingWhitespaceConfigurationApplyConfigurationUpdatesSeverityConfiguration() { var configuration = TrailingWhitespaceConfiguration(ignoresEmptyLines: false, ignoresComments: true) configuration.severityConfiguration.severity = .warning do { try configuration.apply(configuration: ["severity": "error"]) XCTAssert(configuration.severityConfiguration.severity == .error) } catch { XCTFail("Failed to apply severity") } } func testOverridenSuperCallConfigurationFromDictionary() { var configuration = OverridenSuperCallConfiguration() XCTAssertTrue(configuration.resolvedMethodNames.contains("viewWillAppear(_:)")) let conf1 = ["severity": "error", "excluded": "viewWillAppear(_:)"] do { try configuration.apply(configuration: conf1) XCTAssert(configuration.severityConfiguration.severity == .error) XCTAssertFalse(configuration.resolvedMethodNames.contains("*")) XCTAssertFalse(configuration.resolvedMethodNames.contains("viewWillAppear(_:)")) XCTAssertTrue(configuration.resolvedMethodNames.contains("viewWillDisappear(_:)")) } catch { XCTFail("Failed to apply configuration for \(conf1)") } let conf2 = [ "severity": "error", "excluded": "viewWillAppear(_:)", "included": ["*", "testMethod1()", "testMethod2(_:)"] ] as [String: Any] do { try configuration.apply(configuration: conf2) XCTAssert(configuration.severityConfiguration.severity == .error) XCTAssertFalse(configuration.resolvedMethodNames.contains("*")) XCTAssertFalse(configuration.resolvedMethodNames.contains("viewWillAppear(_:)")) XCTAssertTrue(configuration.resolvedMethodNames.contains("viewWillDisappear(_:)")) XCTAssertTrue(configuration.resolvedMethodNames.contains("testMethod1()")) XCTAssertTrue(configuration.resolvedMethodNames.contains("testMethod2(_:)")) } catch { XCTFail("Failed to apply configuration for \(conf2)") } let conf3 = [ "severity": "warning", "excluded": "*", "included": ["testMethod1()", "testMethod2(_:)"] ] as [String: Any] do { try configuration.apply(configuration: conf3) XCTAssert(configuration.severityConfiguration.severity == .warning) XCTAssert(configuration.resolvedMethodNames.count == 2) XCTAssertFalse(configuration.resolvedMethodNames.contains("*")) XCTAssertTrue(configuration.resolvedMethodNames.contains("testMethod1()")) XCTAssertTrue(configuration.resolvedMethodNames.contains("testMethod2(_:)")) } catch { XCTFail("Failed to apply configuration for \(conf3)") } } func testModifierOrderConfigurationFromDictionary() throws { var configuration = ModifierOrderConfiguration() let config: [String: Any] = [ "severity": "warning", "preferred_modifier_order": [ "override", "acl", "setterACL", "owned", "mutators", "final", "typeMethods", "required", "convenience", "lazy", "dynamic" ] ] try configuration.apply(configuration: config) let expected: [SwiftDeclarationAttributeKind.ModifierGroup] = [ .override, .acl, .setterACL, .owned, .mutators, .final, .typeMethods, .required, .convenience, .lazy, .dynamic ] XCTAssert(configuration.severityConfiguration.severity == .warning) XCTAssertTrue(configuration.preferredModifierOrder == expected) } func testModifierOrderConfigurationThrowsOnUnrecognizedModifierGroup() { var configuration = ModifierOrderConfiguration() let config = ["severity": "warning", "preferred_modifier_order": ["specialize"]] as [String: Any] checkError(ConfigurationError.unknownConfiguration) { try configuration.apply(configuration: config) } } func testModifierOrderConfigurationThrowsOnNonModifiableGroup() { var configuration = ModifierOrderConfiguration() let config = ["severity": "warning", "preferred_modifier_order": ["atPrefixed"]] as [String: Any] checkError(ConfigurationError.unknownConfiguration) { try configuration.apply(configuration: config) } } }