From 003336a73504ba5d9ca4aea1f200be4585cbc0e4 Mon Sep 17 00:00:00 2001 From: Jeroen Engels Date: Tue, 2 Jul 2019 00:04:45 +0200 Subject: [PATCH] Replace Lint.Test by the it's new version --- src/Lint/Test.elm | 577 ++++++++++++++++++++++--- src/Lint/Test2.elm | 568 ------------------------ tests/DefaultPatternPositionTest.elm | 28 +- tests/NoDebugTest.elm | 88 ++-- tests/NoExtraBooleanComparisonTest.elm | 42 +- tests/NoImportingEverythingTest.elm | 36 +- tests/NoUnusedVariablesTest.elm | 172 ++++---- 7 files changed, 708 insertions(+), 803 deletions(-) delete mode 100644 src/Lint/Test2.elm diff --git a/src/Lint/Test.elm b/src/Lint/Test.elm index c8bffd22..33f498bc 100644 --- a/src/Lint/Test.elm +++ b/src/Lint/Test.elm @@ -1,13 +1,57 @@ -module Lint.Test exposing (LintResult, errorWithoutRange, expectErrors, expectErrorsWithoutRange, location, run) +module Lint.Test exposing + ( LintResult, run + , ExpectedError, expectErrors, expectNoErrors, error, atExactly + ) {-| Module that helps you test your linting rules, using [`elm-test`](https://package.elm-lang.org/packages/elm-explorations/test/latest). -TODO Add instructions and examples + import Lint.Test exposing (LintResult) + import Test exposing (Test, describe, test) + import The.Rule.You.Want.To.Test exposing (rule) + + testRule : String -> LintResult + testRule string = + Lint.Test.run rule string + + -- In this example, the rule we're testing is `NoDebug` + tests : Test + tests = + describe "NoDebug" + [ test "should not report calls to normal functions" <| + \() -> + testRule """module A exposing (..) + a = foo n""" + |> Lint.Test.expectNoErrors + , test "should report Debug.log use" <| + \() -> + testRule """module A exposing (..) + a = Debug.log "some" "message\"""" + |> Lint.Test.expectErrors + [ Lint.Test.error + { message = "Forbidden use of Debug" + , under = "Debug.log" + } + ] + ] + + +# Running tests + +@docs LintResult, run + + +# Making assertions + +@docs ExpectedError, expectErrors, expectNoErrors, error, atExactly + + +# Tips on testing + + +## What should you test? TODO Add helpful tips -TODO Rework API, we can do something much nicer than this - -} import Array exposing (Array) @@ -15,79 +59,508 @@ import Elm.Syntax.Range exposing (Range) import Expect exposing (Expectation) import Lint exposing (Severity(..), lintSource) import Lint.Rule as Rule exposing (Error, Rule) +import List.Extra -{-| Alias for the result of a lint rule being applied on a string containing Elm code. +{-| The result of running a rule on a `String` containing source code. -} -type alias LintResult = - Result (List String) (List Error) +type LintResult + = ParseFailure + | SuccessfulRun CodeInspector (List Error) -{-| Run a `Rule` on a string and get the errors reported by it. If the string is -not valid Elm code, this will return a `Result` of type `Err`. +type alias CodeInspector = + { getCodeAtLocation : Range -> Maybe String + , checkIfLocationIsAmbiguous : Error -> String -> Expectation + } -Note that to be valid, a code needs to start with a module definition followed by -a line break like `module A exposing (..)\n`. + +{-| An expectation for an error. Use [`error`](#error) to create one. +-} +type ExpectedError + = ExpectedError + { message : String + , under : Under + } + + +type Under + = Under String + | UnderExactly String Range + + +type SourceCode + = SourceCode String + + +{-| Run a `Rule` on a `String` containing source code. You can then use +[`expectNoErrors`](#expectNoErrors) or [`expectErrors`](#expectErrors) to assert +the errors reported by the rule. + +The source code needs to be syntactically valid Elm code. If the code +can't be parsed, the test will fail regardless of the expectations you set on it. + +Note that t be syntactically valid, you need at least a module declaration at the +top of the file (like `module A exposing (..)`) and one declaration (like `a = 1`). +You can't just have an expression like `1 + 2`. + +-} +run : Rule -> String -> LintResult +run rule sourceCode = + case lintSource [ ( Critical, rule ) ] sourceCode of + Ok errors -> + SuccessfulRun + { getCodeAtLocation = getCodeAtLocationInSourceCode (SourceCode sourceCode) + , checkIfLocationIsAmbiguous = checkIfLocationIsAmbiguousInSourceCode (SourceCode sourceCode) + } + (List.map (\( _, error_ ) -> Rule.error error_.message error_.range) errors) + + Err _ -> + ParseFailure + + +{-| Assert that the rule reprted no errors. Note, this is equivalent to using [`expectErrors`](#expectErrors) +like `expectErrors []`. import Lint.Test exposing (LintResult) - import Test + import Test exposing (Test, describe, test) + import The.Rule.You.Want.To.Test exposing (rule) testRule : String -> LintResult testRule string = - "module A exposing (..)\n\n" - ++ string - |> Lint.Test.run rule + Lint.Test.run rule string - tests : List Test + -- In this example, the rule we're testing is `NoDebug` + tests : Test tests = - [ test "should not report normal function calls" <| - \() -> - testRule "a = Debug.log" - |> Lint.Test.expectErrors - [ error (Lint.Test.location ( 3, 5 ) ( 3, 14 )) ] - ] + describe "NoDebug" + [ test "should not report calls to normal functions" <| + \() -> + testRule """module A exposing (..) + a = foo n""" + |> Lint.Test.expectNoErrors + ] -} -run : Rule -> String -> Result (List String) (List Error) -run rule str = - lintSource [ ( Critical, rule ) ] str - |> Result.map (List.map (\( severity, { message, range } ) -> Rule.error message range)) +expectNoErrors : LintResult -> Expectation +expectNoErrors lintResult = + case lintResult of + ParseFailure -> + Expect.fail parsingErrorMessage + + SuccessfulRun _ errors -> + Expect.true + ("I expected no errors but found:\n\n" ++ (List.map errorToString errors |> String.join "\n")) + (List.isEmpty errors) -expectErrors : List Error -> LintResult -> Expectation -expectErrors expectedErrors result = - case result of - Err errors -> - Expect.fail <| String.join "\n" errors +{-| Assert that the rule reprted some errors, by specifying which one. - Ok errors -> - Expect.equal expectedErrors errors +Assert which errors are reported using [`error`](#error). The test will fail if +a different number of errors than expected are reported, or if the message or the +location is incorrect. + + import Lint.Test exposing (LintResult) + import Test exposing (Test, describe, test) + import The.Rule.You.Want.To.Test exposing (rule) + + testRule : String -> LintResult + testRule string = + Lint.Test.run rule string + + -- In this example, the rule we're testing is `NoDebug` + tests : Test + tests = + describe "NoDebug" + [ test "should report Debug.log use" <| + \() -> + testRule """module A exposing (..) + a = Debug.log "some" "message\"""" + |> Lint.Test.expectErrors + [ Lint.Test.error + { message = "Forbidden use of Debug" + , under = "Debug.log" + } + ] + ] + +-} +expectErrors : List ExpectedError -> LintResult -> Expectation +expectErrors expectedErrors lintResult = + case lintResult of + ParseFailure -> + Expect.fail parsingErrorMessage + + SuccessfulRun codeInspector errors -> + checkAllErrorsMatch codeInspector expectedErrors errors -expectErrorsWithoutRange : List Error -> LintResult -> Expectation -expectErrorsWithoutRange expectedErrors result = - case result of - Err errors -> - Expect.fail <| String.join "\n" errors +{-| Create an expectation for an error. - Ok errors -> - Expect.equal - (errorMessages expectedErrors) - (errorMessages errors) +`message` should be the message you're expecting to be shown to the user. + +`under` is the part of the code where you are expecting the error to be shown to +the user. If it helps, imagine `under` to be the text under which the squiggly +lines will appear if the error appeared in an editor. + + tests : Test + tests = + describe "NoDebug" + [ test "should report Debug.log use" <| + \() -> + testRule """module A exposing (..) + a = Debug.log "some" "message\"""" + |> Lint.Test.expectErrors + [ Lint.Test.error + { message = "Forbidden use of Debug" + , under = "Debug.log" + } + ] + ] + +If there are multiple locations where the value of `under` appears, the test will +fail unless you use [`atExactly`](#atExactly) to remove any ambiguity of where the +error should be used. + +-} +error : { message : String, under : String } -> ExpectedError +error input = + ExpectedError + { message = input.message + , under = Under input.under + } -errorMessages : List Error -> List String -errorMessages errors = - List.map Rule.errorMessage errors +getUnder : ExpectedError -> String +getUnder (ExpectedError expectedError) = + case expectedError.under of + Under str -> + str + + UnderExactly str _ -> + str -errorWithoutRange : String -> Error -errorWithoutRange message = - Rule.error message (location ( 0, 0 ) ( 0, 0 )) +{-| Precise the exact position where the error should be shown to the user. This +is only necessary when the `under` field is ambiguous. + +`atExactly` takes a record with start and end positions. + + tests : Test + tests = + describe "NoDebug" + [ test "should report multiple Debug.log calls" <| + \() -> + testRule """ + a = Debug.log z + b = Debug.log z + """ + |> Lint.Test.expectErrors + [ Lint.Test.error + { message = message + , under = "Debug.log" + } + |> Lint.Test.atExactly { start = { row = 4, column = 5 }, end = { row = 4, column = 14 } } + , Lint.Test.error + { message = message + , under = "Debug.log" + } + |> Lint.Test.atExactly { start = { row = 5, column = 5 }, end = { row = 5, column = 14 } } + ] + ] + +Tip: By default, do not provide this field. If the test fails because there is some +ambiguity, the test error will give you a recommendation of what to use as a parameter +of `atExactly`, so you do not have to bother writing this hard to write argument. + +-} +atExactly : { start : { row : Int, column : Int }, end : { row : Int, column : Int } } -> ExpectedError -> ExpectedError +atExactly range ((ExpectedError expectedError_) as expectedError) = + ExpectedError { expectedError_ | under = UnderExactly (getUnder expectedError) range } -location : ( Int, Int ) -> ( Int, Int ) -> Range -location ( rowStart, columnStart ) ( rowEnd, columnEnd ) = - { start = { row = rowStart, column = columnStart } - , end = { row = rowEnd, column = columnEnd } +checkAllErrorsMatch : CodeInspector -> List ExpectedError -> List Error -> Expectation +checkAllErrorsMatch codeInspector expectedErrors errors = + checkErrorsMatch codeInspector expectedErrors errors + |> List.reverse + |> (\expectations -> Expect.all expectations ()) + + +checkErrorsMatch : CodeInspector -> List ExpectedError -> List Error -> List (() -> Expectation) +checkErrorsMatch codeInspector expectedErrors errors = + case ( expectedErrors, errors ) of + ( [], [] ) -> + [ always Expect.pass ] + + ( expected :: restOfExpectedErrors, error_ :: restOfErrors ) -> + checkErrorMatch codeInspector expected error_ :: checkErrorsMatch codeInspector restOfExpectedErrors restOfErrors + + ( expected :: restOfExpectedErrors, [] ) -> + [ always <| Expect.fail <| notEnoughErrors expected restOfExpectedErrors ] + + ( [], error_ :: restOfErrors ) -> + [ always <| Expect.fail <| tooManyErrors error_ restOfErrors ] + + +checkErrorMatch : CodeInspector -> ExpectedError -> Error -> (() -> Expectation) +checkErrorMatch codeInspector ((ExpectedError expectedError_) as expectedError) error_ = + Expect.all + [ always <| Expect.true (messageMismatchError expectedError error_) (expectedError_.message == Rule.errorMessage error_) + , checkMessageAppearsUnder codeInspector error_ expectedError + ] + + +checkMessageAppearsUnder : CodeInspector -> Error -> ExpectedError -> (() -> Expectation) +checkMessageAppearsUnder codeInspector error_ (ExpectedError expectedError) = + case codeInspector.getCodeAtLocation (Rule.errorRange error_) of + Just codeAtLocation -> + case expectedError.under of + Under under -> + Expect.all + [ always <| Expect.true (underMismatchError error_ under codeAtLocation) (codeAtLocation == under) + , always <| codeInspector.checkIfLocationIsAmbiguous error_ under + ] + + UnderExactly under range -> + Expect.all + [ always <| Expect.true (underMismatchError error_ under codeAtLocation) (codeAtLocation == under) + , always <| Expect.true (wrongLocationError error_ range under) (Rule.errorRange error_ == range) + ] + + Nothing -> + always <| Expect.fail impossibleStateError + + +getCodeAtLocationInSourceCode : SourceCode -> Range -> Maybe String +getCodeAtLocationInSourceCode (SourceCode sourceCode) = + let + lines : Array String + lines = + String.lines sourceCode + |> Array.fromList + in + \{ start, end } -> + if start.row == end.row then + Array.get (start.row - 1) lines + |> Maybe.map (String.slice (start.column - 1) (end.column - 1)) + + else + let + firstLine : Maybe String + firstLine = + Array.get (start.row - 1) lines + |> Maybe.map (String.dropLeft (start.column - 1)) + + lastLine : Maybe String + lastLine = + Array.get (end.row - 1) lines + |> Maybe.map (String.dropRight end.column) + in + [ [ firstLine ] + , Array.slice start.row (end.row - 1) lines + |> Array.toList + |> List.map Just + , [ lastLine ] + ] + |> List.concat + |> List.filterMap identity + |> String.join "\n" + |> Just + + +formatSourceCode : String -> String +formatSourceCode string = + let + lines = + String.lines string + in + if List.length lines == 1 then + "`" ++ string ++ "`" + + else + lines + |> List.map (\str -> " " ++ str) + |> String.join "\n" + |> (\str -> "\n\n```\n" ++ str ++ "\n```") + + +checkIfLocationIsAmbiguousInSourceCode : SourceCode -> Error -> String -> Expectation +checkIfLocationIsAmbiguousInSourceCode ((SourceCode sourceCodeContent) as sourceCode) error_ under = + let + occurrencesInSourceCode : List Int + occurrencesInSourceCode = + String.indexes under sourceCodeContent + in + Expect.true + (locationIsAmbiguousInSourceCodeError sourceCode error_ under occurrencesInSourceCode) + (List.length occurrencesInSourceCode == 1) + + + +-- ERROR MESSAGES + + +parsingErrorMessage : String +parsingErrorMessage = + """I could not parse the test source code, because it was not syntactically valid Elm code. + +Maybe you forgot to add the module definition at the top, like: + + module A exposing (..)""" + + +messageMismatchError : ExpectedError -> Error -> String +messageMismatchError (ExpectedError expectedError) error_ = + """I was looking for the error with the following message: + + `""" ++ expectedError.message ++ """` + +but I found the following error message: + + `""" ++ Rule.errorMessage error_ ++ "`" + + +wrongLocationError : Error -> Range -> String -> String +wrongLocationError error_ range under = + """I was looking for the error with the following message: + + `""" ++ Rule.errorMessage error_ ++ """` + +under the following code: + + """ ++ formatSourceCode under ++ """ + +and I found it. But there are multiple occurrences for this piece of code, and the exact location you specified is not the one I found. I was expecting the error at: + + """ ++ rangeAsString range ++ """ + +but I found it at: + + """ ++ rangeAsString (Rule.errorRange error_) + + +underMismatchError : Error -> String -> String -> String +underMismatchError error_ under codeAtLocation = + """I found an error with the right message, but at the wrong location: + +Message: `""" ++ Rule.errorMessage error_ ++ """` + +I saw it under: """ ++ formatSourceCode codeAtLocation ++ """ + +But I expected to see it under: """ ++ formatSourceCode under + + +listOccurrencesAsLocations : SourceCode -> String -> List Int -> String +listOccurrencesAsLocations sourceCode under occurrences = + occurrences + |> List.map + (\occurrence -> + occurrence + |> positionAsRange sourceCode under + |> rangeAsString + |> (++) " - " + ) + |> String.join "\n" + + +positionAsRange : SourceCode -> String -> Int -> Range +positionAsRange (SourceCode sourceCode) under position = + let + linesBeforeAndIncludingPosition : List String + linesBeforeAndIncludingPosition = + sourceCode + |> String.slice 0 position + |> String.lines + + startRow : Int + startRow = + List.length linesBeforeAndIncludingPosition + in + -- TODO Get these values right + { start = + { row = startRow + , column = -1 + } + , end = + { row = startRow + (under |> String.indexes "\n" |> List.length) + , column = under |> String.indexes "\n" |> List.length + } } + + +rangeAsString : Range -> String +rangeAsString { start, end } = + "{ start = { row = " ++ String.fromInt start.row ++ ", column = " ++ String.fromInt start.column ++ " }, end = { row = " ++ String.fromInt end.row ++ ", column = " ++ String.fromInt end.column ++ " } }" + + +errorToString : Error -> String +errorToString error_ = + "- \"" ++ Rule.errorMessage error_ ++ "\" at " ++ Debug.toString (Rule.errorRange error_) + + +notEnoughErrors : ExpectedError -> List ExpectedError -> String +notEnoughErrors expected restOfExpectedErrors = + let + numberOfErrors : Int + numberOfErrors = + List.length restOfExpectedErrors + 1 + in + "I expected to see " + ++ String.fromInt numberOfErrors + ++ " more " + ++ pluralizeErrors numberOfErrors + ++ ":\n" + ++ (List.map expectedErrorToString (expected :: restOfExpectedErrors) |> String.join "\n") + + +tooManyErrors : Error -> List Error -> String +tooManyErrors error_ restOfErrors = + let + numberOfErrors : Int + numberOfErrors = + List.length restOfErrors + 1 + in + "I found " + ++ String.fromInt numberOfErrors + ++ " " + ++ pluralizeErrors numberOfErrors + ++ " too many:\n" + ++ (List.map errorToString (error_ :: restOfErrors) |> String.join "\n") + + +locationIsAmbiguousInSourceCodeError : SourceCode -> Error -> String -> List Int -> String +locationIsAmbiguousInSourceCodeError sourceCode error_ under occurrencesInSourceCode = + """Your test passes, but where the message appears is ambiguous. + +You are looking for the following error message: + +`""" ++ Rule.errorMessage error_ ++ """` + +and expecting to see it under: + +""" ++ formatSourceCode under ++ """ + +I found """ ++ String.fromInt (List.length occurrencesInSourceCode) ++ """ locations where that code appeared. Please use `Lint.Rule.atExactly` to make the part you were targetting unambiguous. + +Tip: I found them at: +""" ++ listOccurrencesAsLocations sourceCode under occurrencesInSourceCode + + +impossibleStateError : String +impossibleStateError = + "Oh no! I'm in an impossible state. I found an error at a location that I could not find back. Please let me know and give me an SSCCE (http://sscce.org/) here: https://github.com/jfmengels/elm-lint/issues." + + +pluralizeErrors : Int -> String +pluralizeErrors n = + case n of + 1 -> + "error" + + _ -> + "errors" + + +expectedErrorToString : ExpectedError -> String +expectedErrorToString (ExpectedError expectedError) = + "- " ++ expectedError.message diff --git a/src/Lint/Test2.elm b/src/Lint/Test2.elm deleted file mode 100644 index a15b7184..00000000 --- a/src/Lint/Test2.elm +++ /dev/null @@ -1,568 +0,0 @@ -module Lint.Test2 exposing - ( LintResult, run - , ExpectedError, expectErrors, expectNoErrors, error, atExactly - ) - -{-| Module that helps you test your linting rules, using [`elm-test`](https://package.elm-lang.org/packages/elm-explorations/test/latest). - - import Lint.Test2 exposing (LintResult) - import Test exposing (Test, describe, test) - import The.Rule.You.Want.To.Test exposing (rule) - - testRule : String -> LintResult - testRule string = - Lint.Test2.run rule string - - -- In this example, the rule we're testing is `NoDebug` - tests : Test - tests = - describe "NoDebug" - [ test "should not report calls to normal functions" <| - \() -> - testRule """module A exposing (..) - a = foo n""" - |> Lint.Test2.expectNoErrors - , test "should report Debug.log use" <| - \() -> - testRule """module A exposing (..) - a = Debug.log "some" "message\"""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error - { message = "Forbidden use of Debug" - , under = "Debug.log" - } - ] - ] - - -# Running tests - -@docs LintResult, run - - -# Making assertions - -@docs ExpectedError, expectErrors, expectNoErrors, error, atExactly - -TODO Add instructions and examples - - -# Tips on testing - - -## What should you test? - -TODO Add helpful tips - --} - -import Array exposing (Array) -import Elm.Syntax.Range exposing (Range) -import Expect exposing (Expectation) -import Lint exposing (Severity(..), lintSource) -import Lint.Rule as Rule exposing (Error, Rule) -import List.Extra - - -{-| The result of running a rule on a `String` containing source code. --} -type LintResult - = ParseFailure - | SuccessfulRun CodeInspector (List Error) - - -type alias CodeInspector = - { getCodeAtLocation : Range -> Maybe String - , checkIfLocationIsAmbiguous : Error -> String -> Expectation - } - - -{-| An expectation of an error. Use [`error`](#error) to create one. --} -type ExpectedError - = ExpectedError - { message : String - , under : Under - } - - -type Under - = Under String - | UnderExactly String Range - - -type SourceCode - = SourceCode String - - -{-| Run a `Rule` on a `String` containing source code. You can then use -[`expectNoErrors`](#expectNoErrors) or [`expectErrors`](#expectErrors) to assert -the errors reported by the rule. - -The source code needs to be syntactically valid Elm code. If the code -can't be parsed, the test will fail regardless of the expectations you set on it. - -Note that t be syntactically valid, you need at least a module declaration at the -top of the file (like `module A exposing (..)`) and one declaration (like `a = 1`). -You can't just have an expression like `1 + 2`. - --} -run : Rule -> String -> LintResult -run rule sourceCode = - case lintSource [ ( Critical, rule ) ] sourceCode of - Ok errors -> - SuccessfulRun - { getCodeAtLocation = getCodeAtLocationInSourceCode (SourceCode sourceCode) - , checkIfLocationIsAmbiguous = checkIfLocationIsAmbiguousInSourceCode (SourceCode sourceCode) - } - (List.map (\( _, error_ ) -> Rule.error error_.message error_.range) errors) - - Err _ -> - ParseFailure - - -{-| Assert that the rule reprted no errors. Note, this is equivalent to using [`expectErrors`](#expectErrors) -like `expectErrors []`. - - import Lint.Test2 exposing (LintResult) - import Test exposing (Test, describe, test) - import The.Rule.You.Want.To.Test exposing (rule) - - testRule : String -> LintResult - testRule string = - Lint.Test2.run rule string - - -- In this example, the rule we're testing is `NoDebug` - tests : Test - tests = - describe "NoDebug" - [ test "should not report calls to normal functions" <| - \() -> - testRule """module A exposing (..) - a = foo n""" - |> Lint.Test2.expectNoErrors - ] - --} -expectNoErrors : LintResult -> Expectation -expectNoErrors lintResult = - case lintResult of - ParseFailure -> - Expect.fail parsingErrorMessage - - SuccessfulRun _ errors -> - Expect.true - ("I expected no errors but found:\n\n" ++ (List.map errorToString errors |> String.join "\n")) - (List.isEmpty errors) - - -{-| Assert that the rule reprted some errors, by specifying which one. - -Assert which errors are reported using [`error`](#error). The test will fail if -a different number of errors than expected are reported, or if the message or the -location is incorrect. - - import Lint.Test2 exposing (LintResult) - import Test exposing (Test, describe, test) - import The.Rule.You.Want.To.Test exposing (rule) - - testRule : String -> LintResult - testRule string = - Lint.Test2.run rule string - - -- In this example, the rule we're testing is `NoDebug` - tests : Test - tests = - describe "NoDebug" - [ test "should report Debug.log use" <| - \() -> - testRule """module A exposing (..) - a = Debug.log "some" "message\"""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error - { message = "Forbidden use of Debug" - , under = "Debug.log" - } - ] - ] - --} -expectErrors : List ExpectedError -> LintResult -> Expectation -expectErrors expectedErrors lintResult = - case lintResult of - ParseFailure -> - Expect.fail parsingErrorMessage - - SuccessfulRun codeInspector errors -> - checkAllErrorsMatch codeInspector expectedErrors errors - - -{-| Create an expectation for an error. - -`message` should be the message you're expecting to be shown to the user. - -`under` is the part of the code where you are expecting the error to be shown to -the user. If it helps, imagine `under` to be the text under which the squiggly -lines will appear if the error appeared in an editor. - - tests : Test - tests = - describe "NoDebug" - [ test "should report Debug.log use" <| - \() -> - testRule """module A exposing (..) - a = Debug.log "some" "message\"""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error - { message = "Forbidden use of Debug" - , under = "Debug.log" - } - ] - ] - -If there are multiple locations where the value of `under` appears, the test will -fail unless you use [`atExactly`](#atExactly) to remove any ambiguity of where the -error should be used. - --} -error : { message : String, under : String } -> ExpectedError -error input = - ExpectedError - { message = input.message - , under = Under input.under - } - - -getUnder : ExpectedError -> String -getUnder (ExpectedError expectedError) = - case expectedError.under of - Under str -> - str - - UnderExactly str _ -> - str - - -{-| Precise the exact position where the error should be shown to the user. This -is only necessary when the `under` field is ambiguous. - -`atExactly` takes a record with start and end positions. - - tests : Test - tests = - describe "NoDebug" - [ test "should report multiple Debug.log calls" <| - \() -> - testRule """ - a = Debug.log z - b = Debug.log z - """ - |> Lint.Test2.expectErrors - [ Lint.Test2.error - { message = message - , under = "Debug.log" - } - |> Lint.Test2.atExactly { start = { row = 4, column = 5 }, end = { row = 4, column = 14 } } - , Lint.Test2.error - { message = message - , under = "Debug.log" - } - |> Lint.Test2.atExactly { start = { row = 5, column = 5 }, end = { row = 5, column = 14 } } - ] - ] - -Tip: By default, do not provide this field. If the test fails because there is some -ambiguity, the test error will give you a recommendation of what to use as a parameter -of `atExactly`, so you do not have to bother writing this hard to write argument. - --} -atExactly : { start : { row : Int, column : Int }, end : { row : Int, column : Int } } -> ExpectedError -> ExpectedError -atExactly range ((ExpectedError expectedError_) as expectedError) = - ExpectedError { expectedError_ | under = UnderExactly (getUnder expectedError) range } - - -checkAllErrorsMatch : CodeInspector -> List ExpectedError -> List Error -> Expectation -checkAllErrorsMatch codeInspector expectedErrors errors = - checkErrorsMatch codeInspector expectedErrors errors - |> List.reverse - |> (\expectations -> Expect.all expectations ()) - - -checkErrorsMatch : CodeInspector -> List ExpectedError -> List Error -> List (() -> Expectation) -checkErrorsMatch codeInspector expectedErrors errors = - case ( expectedErrors, errors ) of - ( [], [] ) -> - [ always Expect.pass ] - - ( expected :: restOfExpectedErrors, error_ :: restOfErrors ) -> - checkErrorMatch codeInspector expected error_ :: checkErrorsMatch codeInspector restOfExpectedErrors restOfErrors - - ( expected :: restOfExpectedErrors, [] ) -> - [ always <| Expect.fail <| notEnoughErrors expected restOfExpectedErrors ] - - ( [], error_ :: restOfErrors ) -> - [ always <| Expect.fail <| tooManyErrors error_ restOfErrors ] - - -checkErrorMatch : CodeInspector -> ExpectedError -> Error -> (() -> Expectation) -checkErrorMatch codeInspector ((ExpectedError expectedError_) as expectedError) error_ = - Expect.all - [ always <| Expect.true (messageMismatchError expectedError error_) (expectedError_.message == Rule.errorMessage error_) - , checkMessageAppearsUnder codeInspector error_ expectedError - ] - - -checkMessageAppearsUnder : CodeInspector -> Error -> ExpectedError -> (() -> Expectation) -checkMessageAppearsUnder codeInspector error_ (ExpectedError expectedError) = - case codeInspector.getCodeAtLocation (Rule.errorRange error_) of - Just codeAtLocation -> - case expectedError.under of - Under under -> - Expect.all - [ always <| Expect.true (underMismatchError error_ under codeAtLocation) (codeAtLocation == under) - , always <| codeInspector.checkIfLocationIsAmbiguous error_ under - ] - - UnderExactly under range -> - Expect.all - [ always <| Expect.true (underMismatchError error_ under codeAtLocation) (codeAtLocation == under) - , always <| Expect.true (wrongLocationError error_ range under) (Rule.errorRange error_ == range) - ] - - Nothing -> - always <| Expect.fail impossibleStateError - - -getCodeAtLocationInSourceCode : SourceCode -> Range -> Maybe String -getCodeAtLocationInSourceCode (SourceCode sourceCode) = - let - lines : Array String - lines = - String.lines sourceCode - |> Array.fromList - in - \{ start, end } -> - if start.row == end.row then - Array.get (start.row - 1) lines - |> Maybe.map (String.slice (start.column - 1) (end.column - 1)) - - else - let - firstLine : Maybe String - firstLine = - Array.get (start.row - 1) lines - |> Maybe.map (String.dropLeft (start.column - 1)) - - lastLine : Maybe String - lastLine = - Array.get (end.row - 1) lines - |> Maybe.map (String.dropRight end.column) - in - [ [ firstLine ] - , Array.slice start.row (end.row - 1) lines - |> Array.toList - |> List.map Just - , [ lastLine ] - ] - |> List.concat - |> List.filterMap identity - |> String.join "\n" - |> Just - - -formatSourceCode : String -> String -formatSourceCode string = - let - lines = - String.lines string - in - if List.length lines == 1 then - "`" ++ string ++ "`" - - else - lines - |> List.map (\str -> " " ++ str) - |> String.join "\n" - |> (\str -> "\n\n```\n" ++ str ++ "\n```") - - -checkIfLocationIsAmbiguousInSourceCode : SourceCode -> Error -> String -> Expectation -checkIfLocationIsAmbiguousInSourceCode ((SourceCode sourceCodeContent) as sourceCode) error_ under = - let - occurrencesInSourceCode : List Int - occurrencesInSourceCode = - String.indexes under sourceCodeContent - in - Expect.true - (locationIsAmbiguousInSourceCodeError sourceCode error_ under occurrencesInSourceCode) - (List.length occurrencesInSourceCode == 1) - - - --- ERROR MESSAGES - - -parsingErrorMessage : String -parsingErrorMessage = - """I could not parse the test source code, because it was not syntactically valid Elm code. - -Maybe you forgot to add the module definition at the top, like: - - module A exposing (..)""" - - -messageMismatchError : ExpectedError -> Error -> String -messageMismatchError (ExpectedError expectedError) error_ = - """I was looking for the error with the following message: - - `""" ++ expectedError.message ++ """` - -but I found the following error message: - - `""" ++ Rule.errorMessage error_ ++ "`" - - -wrongLocationError : Error -> Range -> String -> String -wrongLocationError error_ range under = - """I was looking for the error with the following message: - - `""" ++ Rule.errorMessage error_ ++ """` - -under the following code: - - """ ++ formatSourceCode under ++ """ - -and I found it. But there are multiple occurrences for this piece of code, and the exact location you specified is not the one I found. I was expecting the error at: - - """ ++ rangeAsString range ++ """ - -but I found it at: - - """ ++ rangeAsString (Rule.errorRange error_) - - -underMismatchError : Error -> String -> String -> String -underMismatchError error_ under codeAtLocation = - """I found an error with the right message, but at the wrong location: - -Message: `""" ++ Rule.errorMessage error_ ++ """` - -I saw it under: """ ++ formatSourceCode codeAtLocation ++ """ - -But I expected to see it under: """ ++ formatSourceCode under - - -listOccurrencesAsLocations : SourceCode -> String -> List Int -> String -listOccurrencesAsLocations sourceCode under occurrences = - occurrences - |> List.map - (\occurrence -> - occurrence - |> positionAsRange sourceCode under - |> rangeAsString - |> (++) " - " - ) - |> String.join "\n" - - -positionAsRange : SourceCode -> String -> Int -> Range -positionAsRange (SourceCode sourceCode) under position = - let - linesBeforeAndIncludingPosition : List String - linesBeforeAndIncludingPosition = - sourceCode - |> String.slice 0 position - |> String.lines - - startRow : Int - startRow = - List.length linesBeforeAndIncludingPosition - in - -- TODO Get these values right - { start = - { row = startRow - , column = -1 - } - , end = - { row = startRow + (under |> String.indexes "\n" |> List.length) - , column = under |> String.indexes "\n" |> List.length - } - } - - -rangeAsString : Range -> String -rangeAsString { start, end } = - "{ start = { row = " ++ String.fromInt start.row ++ ", column = " ++ String.fromInt start.column ++ " }, end = { row = " ++ String.fromInt end.row ++ ", column = " ++ String.fromInt end.column ++ " } }" - - -errorToString : Error -> String -errorToString error_ = - "- \"" ++ Rule.errorMessage error_ ++ "\" at " ++ Debug.toString (Rule.errorRange error_) - - -notEnoughErrors : ExpectedError -> List ExpectedError -> String -notEnoughErrors expected restOfExpectedErrors = - let - numberOfErrors : Int - numberOfErrors = - List.length restOfExpectedErrors + 1 - in - "I expected to see " - ++ String.fromInt numberOfErrors - ++ " more " - ++ pluralizeErrors numberOfErrors - ++ ":\n" - ++ (List.map expectedErrorToString (expected :: restOfExpectedErrors) |> String.join "\n") - - -tooManyErrors : Error -> List Error -> String -tooManyErrors error_ restOfErrors = - let - numberOfErrors : Int - numberOfErrors = - List.length restOfErrors + 1 - in - "I found " - ++ String.fromInt numberOfErrors - ++ " " - ++ pluralizeErrors numberOfErrors - ++ " too many:\n" - ++ (List.map errorToString (error_ :: restOfErrors) |> String.join "\n") - - -locationIsAmbiguousInSourceCodeError : SourceCode -> Error -> String -> List Int -> String -locationIsAmbiguousInSourceCodeError sourceCode error_ under occurrencesInSourceCode = - """Your test passes, but where the message appears is ambiguous. - -You are looking for the following error message: - -`""" ++ Rule.errorMessage error_ ++ """` - -and expecting to see it under: - -""" ++ formatSourceCode under ++ """ - -I found """ ++ String.fromInt (List.length occurrencesInSourceCode) ++ """ locations where that code appeared. Please use `Lint.Rule.atExactly` to make the part you were targetting unambiguous. - -Tip: I found them at: -""" ++ listOccurrencesAsLocations sourceCode under occurrencesInSourceCode - - -impossibleStateError : String -impossibleStateError = - "Oh no! I'm in an impossible state. I found an error at a location that I could not find back. Please let me know and give me an SSCCE (http://sscce.org/) here: https://github.com/jfmengels/elm-lint/issues." - - -pluralizeErrors : Int -> String -pluralizeErrors n = - case n of - 1 -> - "error" - - _ -> - "errors" - - -expectedErrorToString : ExpectedError -> String -expectedErrorToString (ExpectedError expectedError) = - "- " ++ expectedError.message diff --git a/tests/DefaultPatternPositionTest.elm b/tests/DefaultPatternPositionTest.elm index 17f22e07..a84d9226 100644 --- a/tests/DefaultPatternPositionTest.elm +++ b/tests/DefaultPatternPositionTest.elm @@ -1,13 +1,13 @@ module DefaultPatternPositionTest exposing (all) import Lint.Rule.DefaultPatternPosition exposing (PatternPosition(..), rule) -import Lint.Test2 exposing (LintResult) +import Lint.Test exposing (LintResult) import Test exposing (Test, describe, test) testRule : PatternPosition -> String -> LintResult testRule patternPosition = - Lint.Test2.run (rule patternPosition) + Lint.Test.run (rule patternPosition) message : String -> String @@ -26,7 +26,7 @@ a = case b of Foo -> 1 """ |> testRule ShouldBeFirst - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report when default pattern is at the expected position (last)" <| \() -> """module A exposing(..) @@ -36,7 +36,7 @@ a = case b of _ -> 1 """ |> testRule ShouldBeLast - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report when there is no default pattern (first)" <| \() -> """module A exposing(..) @@ -45,7 +45,7 @@ a = case b of Bar -> 1 """ |> testRule ShouldBeFirst - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report when there is no default pattern (last)" <| \() -> """module A exposing(..) @@ -54,7 +54,7 @@ a = case b of Bar -> 1 """ |> testRule ShouldBeLast - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should report an error when the default pattern is not at the expected position (first) (opposite expected position)" <| \() -> """module A exposing(..) @@ -64,8 +64,8 @@ a = case b of _ -> 1 """ |> testRule ShouldBeFirst - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message "first" , under = "_" } @@ -79,8 +79,8 @@ a = case b of Bar -> 1 """ |> testRule ShouldBeFirst - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message "first" , under = "_" } @@ -94,8 +94,8 @@ a = case b of Bar -> 1 """ |> testRule ShouldBeLast - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message "last" , under = "_" } @@ -109,8 +109,8 @@ a = case b of Bar -> 1 """ |> testRule ShouldBeLast - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message "last" , under = "_" } diff --git a/tests/NoDebugTest.elm b/tests/NoDebugTest.elm index 1bfa76da..4933c78c 100644 --- a/tests/NoDebugTest.elm +++ b/tests/NoDebugTest.elm @@ -1,7 +1,7 @@ module NoDebugTest exposing (all) import Lint.Rule.NoDebug exposing (rule) -import Lint.Test2 exposing (LintResult) +import Lint.Test exposing (LintResult) import Test exposing (Test, describe, test) @@ -9,7 +9,7 @@ testRule : String -> LintResult testRule string = "module A exposing (..)\n\n" ++ string - |> Lint.Test2.run rule + |> Lint.Test.run rule message : String @@ -28,12 +28,12 @@ c = debug e = debug.log n d = debug.log n """ - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should report Debug.log use" <| \() -> testRule "a = Debug.log" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message , under = "Debug.log" } @@ -41,8 +41,8 @@ d = debug.log n , test "should report Debug.log calls" <| \() -> testRule "a = Debug.log z" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message , under = "Debug.log" } @@ -53,23 +53,23 @@ d = debug.log n a = Debug.log z b = Debug.log z """ - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message , under = "Debug.log" } - |> Lint.Test2.atExactly { start = { row = 4, column = 5 }, end = { row = 4, column = 14 } } - , Lint.Test2.error + |> Lint.Test.atExactly { start = { row = 4, column = 5 }, end = { row = 4, column = 14 } } + , Lint.Test.error { message = message , under = "Debug.log" } - |> Lint.Test2.atExactly { start = { row = 5, column = 5 }, end = { row = 5, column = 14 } } + |> Lint.Test.atExactly { start = { row = 5, column = 5 }, end = { row = 5, column = 14 } } ] , test "should report Debug.crash calls" <| \() -> testRule "a = Debug.crash 1" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message , under = "Debug.crash" } @@ -77,8 +77,8 @@ b = Debug.log z , test "should report any Debug method" <| \() -> testRule "a = Debug.foo 1" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message , under = "Debug.foo" } @@ -86,8 +86,8 @@ b = Debug.log z , test "should report Debug in a binary expression" <| \() -> testRule "a = ( Debug.log z ) + 2" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message , under = "Debug.log" } @@ -95,8 +95,8 @@ b = Debug.log z , test "should report Debug in a << binary expression" <| \() -> testRule "a = fn << Debug.log" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message , under = "Debug.log" } @@ -104,8 +104,8 @@ b = Debug.log z , test "should report Debug in a pipe expression" <| \() -> testRule "a = fn |> Debug.log z" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message , under = "Debug.log" } @@ -113,8 +113,8 @@ b = Debug.log z , test "should report Debug in an list expression" <| \() -> testRule "a = [ Debug.log z y ]" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message , under = "Debug.log" } @@ -122,8 +122,8 @@ b = Debug.log z , test "should report Debug in an record expression" <| \() -> testRule "a = { foo = Debug.log z y }" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message , under = "Debug.log" } @@ -131,8 +131,8 @@ b = Debug.log z , test "should report Debug in an record update expression" <| \() -> testRule "a = { model | foo = Debug.log z y }" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message , under = "Debug.log" } @@ -140,8 +140,8 @@ b = Debug.log z , test "should report Debug in an lambda expression" <| \() -> testRule "a = (\\foo -> Debug.log z foo)" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message , under = "Debug.log" } @@ -149,8 +149,8 @@ b = Debug.log z , test "should report Debug in an if expression condition" <| \() -> testRule "a = if Debug.log a b then True else False" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message , under = "Debug.log" } @@ -158,8 +158,8 @@ b = Debug.log z , test "should report Debug in an if expression then branch" <| \() -> testRule "a = if True then Debug.log a b else False" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message , under = "Debug.log" } @@ -167,8 +167,8 @@ b = Debug.log z , test "should report Debug in an if expression else branch" <| \() -> testRule "a = if True then True else Debug.log a b" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message , under = "Debug.log" } @@ -179,8 +179,8 @@ b = Debug.log z a = case Debug.log a b of _ -> [] """ - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message , under = "Debug.log" } @@ -191,8 +191,8 @@ a = case Debug.log a b of a = case a of _ -> Debug.log a b """ - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message , under = "Debug.log" } @@ -203,8 +203,8 @@ a = case a of a = let b = Debug.log a b in b """ - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message , under = "Debug.log" } @@ -215,8 +215,8 @@ a = let b = Debug.log a b a = let b = c in Debug.log a b """ - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = message , under = "Debug.log" } diff --git a/tests/NoExtraBooleanComparisonTest.elm b/tests/NoExtraBooleanComparisonTest.elm index 3cc67cf9..78bb772a 100644 --- a/tests/NoExtraBooleanComparisonTest.elm +++ b/tests/NoExtraBooleanComparisonTest.elm @@ -1,7 +1,7 @@ module NoExtraBooleanComparisonTest exposing (all) import Lint.Rule.NoExtraBooleanComparison exposing (rule) -import Lint.Test2 exposing (LintResult) +import Lint.Test exposing (LintResult) import Test exposing (Test, describe, test) @@ -9,7 +9,7 @@ testRule : String -> LintResult testRule string = "module A exposing (..)\n\n" ++ string - |> Lint.Test2.run rule + |> Lint.Test.run rule tests : List Test @@ -17,7 +17,7 @@ tests = [ test "should not report condition without an operator" <| \() -> testRule "a = if n then 1 else 2" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report condition with integer operators" <| \() -> testRule """ @@ -26,16 +26,16 @@ b = if n <= 1 then 1 else 2 c = if n > 1 then 1 else 2 d = if n >= 1 then 1 else 2 """ - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report condition using `not`" <| \() -> testRule "a = if not n then 1 else 2" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should report condition with `expr == True`" <| \() -> testRule "a = if b == True then 1 else 2" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Unnecessary comparison with `True`" , under = "b == True" } @@ -43,8 +43,8 @@ d = if n >= 1 then 1 else 2 , test "should report condition with `True == expr`" <| \() -> testRule "a = if True == b then 1 else 2" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Unnecessary comparison with `True`" , under = "True == b" } @@ -52,8 +52,8 @@ d = if n >= 1 then 1 else 2 , test "should report condition with `expr == False`" <| \() -> testRule "a = if b == False then 1 else 2" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Unnecessary comparison with `False`" , under = "b == False" } @@ -61,8 +61,8 @@ d = if n >= 1 then 1 else 2 , test "should report condition with `False == expr`" <| \() -> testRule "a = if False == b then 1 else 2" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Unnecessary comparison with `False`" , under = "False == b" } @@ -70,8 +70,8 @@ d = if n >= 1 then 1 else 2 , test "should report condition with `expr /= True`" <| \() -> testRule "a = if b /= True then 1 else 2" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Unnecessary comparison with `True`" , under = "b /= True" } @@ -79,8 +79,8 @@ d = if n >= 1 then 1 else 2 , test "should report condition with `True /= expr`" <| \() -> testRule "a = if True /= b then 1 else 2" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Unnecessary comparison with `True`" , under = "True /= b" } @@ -88,8 +88,8 @@ d = if n >= 1 then 1 else 2 , test "should report condition with `expr /= False`" <| \() -> testRule "a = if b /= False then 1 else 2" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Unnecessary comparison with `False`" , under = "b /= False" } @@ -97,8 +97,8 @@ d = if n >= 1 then 1 else 2 , test "should report condition with `False /= expr`" <| \() -> testRule "a = if False /= b then 1 else 2" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Unnecessary comparison with `False`" , under = "False /= b" } diff --git a/tests/NoImportingEverythingTest.elm b/tests/NoImportingEverythingTest.elm index d3cf470b..f0ffdc8b 100644 --- a/tests/NoImportingEverythingTest.elm +++ b/tests/NoImportingEverythingTest.elm @@ -1,13 +1,13 @@ module NoImportingEverythingTest exposing (all) import Lint.Rule.NoImportingEverything exposing (Configuration, rule) -import Lint.Test2 exposing (LintResult) +import Lint.Test exposing (LintResult) import Test exposing (Test, describe, test) testRule : Configuration -> String -> LintResult testRule options = - Lint.Test2.run (rule options) + Lint.Test.run (rule options) tests : List Test @@ -18,33 +18,33 @@ tests = import Html import Http""" |> testRule { exceptions = [] } - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report imports that expose functions by name" <| \() -> """module A exposing (..) import Html exposing (a) import Http exposing (a, b)""" |> testRule { exceptions = [] } - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should report imports that expose everything" <| \() -> """module A exposing (..) import Html exposing (..)""" |> testRule { exceptions = [] } - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Do not expose everything from Html" , under = ".." } - |> Lint.Test2.atExactly { start = { row = 2, column = 23 }, end = { row = 2, column = 25 } } + |> Lint.Test.atExactly { start = { row = 2, column = 23 }, end = { row = 2, column = 25 } } ] , test "should report imports from sub-modules" <| \() -> """module A exposing (a) import Html.App exposing (..)""" |> testRule { exceptions = [] } - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Do not expose everything from Html.App" , under = ".." } @@ -54,8 +54,8 @@ import Html.App exposing (..)""" """module A exposing (a) import Html.Foo.Bar exposing (..)""" |> testRule { exceptions = [] } - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Do not expose everything from Html.Foo.Bar" , under = ".." } @@ -65,26 +65,26 @@ import Html.Foo.Bar exposing (..)""" """module A exposing (a) import Html exposing (..)""" |> testRule { exceptions = [ "Html" ] } - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report imports from sub-modules that are in the exception list" <| \() -> """module A exposing (a) import Html.App exposing (..)""" |> testRule { exceptions = [ "Html.App" ] } - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report imports from sub-modules (multiple dots)" <| \() -> """module A exposing (a) import Html.Foo.Bar exposing (..)""" |> testRule { exceptions = [ "Html.Foo.Bar" ] } - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should report imports whose parent is ignored" <| \() -> """module A exposing (a) import Html.Foo.Bar exposing (..)""" |> testRule { exceptions = [ "Html" ] } - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Do not expose everything from Html.Foo.Bar" , under = ".." } @@ -94,8 +94,8 @@ import Html.Foo.Bar exposing (..)""" """module A exposing (a) import Html exposing (..)""" |> testRule { exceptions = [ "Html.App" ] } - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Do not expose everything from Html" , under = ".." } diff --git a/tests/NoUnusedVariablesTest.elm b/tests/NoUnusedVariablesTest.elm index 817fe7a9..ecf2c057 100644 --- a/tests/NoUnusedVariablesTest.elm +++ b/tests/NoUnusedVariablesTest.elm @@ -1,13 +1,13 @@ module NoUnusedVariablesTest exposing (all) import Lint.Rule.NoUnusedVariables exposing (rule) -import Lint.Test2 exposing (LintResult) +import Lint.Test exposing (LintResult) import Test exposing (Test, describe, test) testRule : String -> LintResult testRule = - Lint.Test2.run rule + Lint.Test.run rule tests : List Test @@ -16,19 +16,19 @@ tests = \() -> testRule """module A exposing (a) a = 1""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report used top-level variables" <| \() -> testRule """module A exposing (b) a n = 1 b = a 1""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should report unused top-level variables" <| \() -> testRule """module A exposing (b) a = 1""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Variable `a` is not used" , under = "a" } @@ -38,33 +38,33 @@ a = 1""" testRule """module A exposing (b) a: Int a = 1""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Variable `a` is not used" , under = "a" } - |> Lint.Test2.atExactly { start = { row = 3, column = 1 }, end = { row = 3, column = 2 } } + |> Lint.Test.atExactly { start = { row = 3, column = 1 }, end = { row = 3, column = 2 } } ] , test "should not report unused top-level variables if everything is exposed" <| \() -> testRule """module A exposing (..) a n = 1 b = a 1""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report unused top-level variables that are exposed by name" <| \() -> testRule """module A exposing (a, b) a = 1 b = 2""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report unused top-level variables that are exposed by name, but report others" <| \() -> testRule """module A exposing (a, b) a = 1 b = 2 c = 3""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Variable `c` is not used" , under = "c" } @@ -74,21 +74,21 @@ c = 3""" testRule """port module A exposing (..) a n = 1 b = a 1""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report unused top-level variables that are exposed by name (port module)" <| \() -> testRule """port module A exposing (a, b) a = 1 b = 2""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report unused top-level variables that are exposed by name, but report others (port module)" <| \() -> testRule """port module A exposing (a, b) a = 1 b = 2 c = 3""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Variable `c` is not used" , under = "c" } @@ -98,8 +98,8 @@ c = 3""" testRule """module A exposing (a) a = let b = 1 in 2""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Variable `b` is not used" , under = "b" } @@ -109,20 +109,20 @@ a = let b = 1 testRule """module A exposing (a, b) a = let b = 1 in 2""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Variable `b` is not used" , under = "b" } - |> Lint.Test2.atExactly { start = { row = 2, column = 9 }, end = { row = 2, column = 10 } } + |> Lint.Test.atExactly { start = { row = 2, column = 9 }, end = { row = 2, column = 10 } } ] , test "should report unused functions from let even if they are exposed by name" <| \() -> testRule """module A exposing (a) a = let b param = 1 in 2""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Variable `b` is not used" , under = "b" } @@ -132,8 +132,8 @@ a = let b param = 1 testRule """module A exposing (..) a = let b = 1 in 2""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Variable `b` is not used" , under = "b" } @@ -144,14 +144,14 @@ a = let b = 1 b = 1 a = let c = 1 in b + c""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report top-level variables used inside let declarations" <| \() -> testRule """module A exposing (a) b = 1 a = let c = b in c""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report top-level variables used in nested lets" <| \() -> testRule """module A exposing (a) @@ -164,24 +164,24 @@ a = let b + c + e in d""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report variables from let declarations that are used in the expression" <| \() -> testRule """module A exposing (a) a = let c = 1 in c""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report unused function parameters" <| \() -> testRule """module A exposing (a) a n = 1""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should report unused imported functions" <| \() -> testRule """module A exposing (b) import Foo exposing (a)""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Imported variable `a` is not used" , under = "a" } @@ -190,16 +190,16 @@ import Foo exposing (a)""" \() -> testRule """module A exposing (d) import Foo exposing (C, a, b)""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Imported variable `b` is not used" , under = "b" } - , Lint.Test2.error + , Lint.Test.error { message = "Imported variable `a` is not used" , under = "a" } - , Lint.Test2.error + , Lint.Test.error { message = "Imported type `C` is not used" , under = "C" } @@ -212,30 +212,30 @@ import Foo exposing (C, a, b)""" testRule """module A exposing (a) a = case thing of Foo b c -> []""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors -- Should B and C be reported if they are not used? Probably. , test "should report unused custom type declarations" <| \() -> testRule """module A exposing (a) type A = B | C""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Type `A` is not used" , under = "A" } - |> Lint.Test2.atExactly { start = { row = 2, column = 6 }, end = { row = 2, column = 7 } } + |> Lint.Test.atExactly { start = { row = 2, column = 6 }, end = { row = 2, column = 7 } } ] , test "should report unused type aliases declarations" <| \() -> testRule """module A exposing (a) type alias A = { a : B }""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Type `A` is not used" , under = "A" } - |> Lint.Test2.atExactly { start = { row = 2, column = 12 }, end = { row = 2, column = 13 } } + |> Lint.Test.atExactly { start = { row = 2, column = 12 }, end = { row = 2, column = 13 } } ] , test "should not report type used in a signature" <| \() -> @@ -243,63 +243,63 @@ type alias A = { a : B }""" type alias A = { a : B } a : A a = {a = 1}""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report type used in a signature with multiple arguments" <| \() -> testRule """module A exposing (a) type alias A = { a : B } a : String -> A a str = {a = str}""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report type used in a signature with parameterized types (as generic type)" <| \() -> testRule """module A exposing (a) type alias A = { a : B } a : A B a = []""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report type used in a signature with parameterized types (as parameter)" <| \() -> testRule """module A exposing (a) type alias A = { a : B } a : List A a = []""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report type used in a signature with a record" <| \() -> testRule """module A exposing (a) type alias A = { a : B } a : { c: A } a str = {c = str}""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report type used in a signature with a generic record" <| \() -> testRule """module A exposing (a) type alias A = { a : B } a : { r | c: A } a str = {c = str}""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report type if it's exposed" <| \() -> testRule """module A exposing (A) type A a = B a""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report custom type if it's exposed with its sub-types" <| \() -> testRule """module A exposing (A(..)) type A = B | C | D""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should report unused variable even if it's present in a generic type" <| \() -> testRule """module A exposing (A) a = 1 type A a = B a""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Variable `a` is not used" , under = "a" } - |> Lint.Test2.atExactly { start = { row = 2, column = 1 }, end = { row = 2, column = 2 } } + |> Lint.Test.atExactly { start = { row = 2, column = 1 }, end = { row = 2, column = 2 } } ] , test "should report unused variable even if it's present in a generic record type" <| \() -> @@ -307,19 +307,19 @@ type A a = B a""" r = 1 a : { r | c: A } a str = {c = str}""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Variable `r` is not used" , under = "r" } - |> Lint.Test2.atExactly { start = { row = 2, column = 1 }, end = { row = 2, column = 2 } } + |> Lint.Test.atExactly { start = { row = 2, column = 1 }, end = { row = 2, column = 2 } } ] , test "should report unused operator import" <| \() -> testRule """module A exposing (a) import Parser exposing (())""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Imported operator `` is not used" , under = "()" } @@ -329,23 +329,23 @@ import Parser exposing (())""" testRule """module A exposing (a) import Parser exposing (()) a = 1 2""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report used operator (prefix)" <| \() -> testRule """module A exposing (a) import Parser exposing (()) a = () 2""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should report unused opaque types" <| \() -> testRule """module A exposing (a) type A = A Int""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Type `A` is not used" , under = "A" } - |> Lint.Test2.atExactly { start = { row = 2, column = 6 }, end = { row = 2, column = 7 } } + |> Lint.Test.atExactly { start = { row = 2, column = 6 }, end = { row = 2, column = 7 } } ] , test "should not report used opaque types" <| \() -> @@ -353,13 +353,13 @@ type A = A Int""" type A = A Int a : A a = 1""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should report unused import" <| \() -> testRule """module A exposing (a) import Html""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Imported module `Html` is not used" , under = "Html" } @@ -368,8 +368,8 @@ import Html""" \() -> testRule """module A exposing (a) import Html.Styled.Attributes""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Imported module `Html.Styled.Attributes` is not used" , under = "Html.Styled.Attributes" } @@ -378,41 +378,41 @@ import Html.Styled.Attributes""" \() -> testRule """module A exposing (a) import Html.Styled.Attributes exposing (..)""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should report unused variable even if a homonym from a module is used" <| \() -> testRule """module A exposing (a) href = 1 a = Html.Styled.Attributes.href""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Variable `href` is not used" , under = "href" } - |> Lint.Test2.atExactly { start = { row = 2, column = 1 }, end = { row = 2, column = 5 } } + |> Lint.Test.atExactly { start = { row = 2, column = 1 }, end = { row = 2, column = 5 } } ] , test "should not report used import (function access)" <| \() -> testRule """module A exposing (a) import Html.Styled.Attributes a = Html.Styled.Attributes.href""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report unused import if it is aliased" <| \() -> testRule """module A exposing (a) import Html.Styled.Attributes as Html a = Html.href""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should report unused import alias" <| \() -> testRule """module A exposing (a) import Html.Styled.Attributes as Html""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Module alias `Html` is not used" , under = "Html" } - |> Lint.Test2.atExactly { start = { row = 2, column = 34 }, end = { row = 2, column = 38 } } + |> Lint.Test.atExactly { start = { row = 2, column = 34 }, end = { row = 2, column = 38 } } ] , test "should not report import that exposes a used exposed type" <| \() -> @@ -420,14 +420,14 @@ import Html.Styled.Attributes as Html""" import B exposing (C(..)) a : C a = 1""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report import that exposes an unused exposed type (but whose subtype is potentially used)" <| \() -> testRule """module A exposing (a) import B exposing (C(..)) a : D a = 1""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should not report types that are used in ports" <| \() -> testRule """module A exposing (output, input) @@ -435,14 +435,14 @@ import Json.Decode import Json.Encode port output : Json.Encode.Value -> Cmd msg port input : (Json.Decode.Value -> msg) -> Sub msg""" - |> Lint.Test2.expectNoErrors + |> Lint.Test.expectNoErrors , test "should report unused ports (ingoing)" <| \() -> testRule """module A exposing (a) import Json.Decode port input : (Json.Decode.Value -> msg) -> Sub msg""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Port `input` is not used (Warning: Removing this port may break your application if it is used in the JS code)" , under = "input" } @@ -452,8 +452,8 @@ port input : (Json.Decode.Value -> msg) -> Sub msg""" testRule """module A exposing (a) import Json.Encode port output : Json.Encode.Value -> Cmd msg""" - |> Lint.Test2.expectErrors - [ Lint.Test2.error + |> Lint.Test.expectErrors + [ Lint.Test.error { message = "Port `output` is not used (Warning: Removing this port may break your application if it is used in the JS code)" , under = "output" }