Add functions to be able to test multi rules

This commit is contained in:
Jeroen Engels 2020-01-03 17:12:43 +01:00
parent 93d4e0817d
commit 8fa9ab49a1
2 changed files with 124 additions and 29 deletions

View File

@ -1,6 +1,6 @@
module Review.Test exposing
( ReviewResult, run, runWithProjectData
, ExpectedError, expectErrors, expectNoErrors, error, atExactly, whenFixed
( ReviewResult, run, runWithProjectData, runMulti, runMultiWithProjectData
, ExpectedError, expectErrors, expectErrorsForFiles, expectNoErrors, error, atExactly, whenFixed
)
{-| Module that helps you test your rules, using [`elm-test`](https://package.elm-lang.org/packages/elm-explorations/test/latest/).
@ -95,12 +95,12 @@ for this module.
# Running tests
@docs ReviewResult, run, runWithProjectData
@docs ReviewResult, run, runWithProjectData, runMulti, runMultiWithProjectData
# Making assertions
@docs ExpectedError, expectErrors, expectNoErrors, error, atExactly, whenFixed
@docs ExpectedError, expectErrors, expectErrorsForFiles, expectNoErrors, error, atExactly, whenFixed
-}
@ -127,7 +127,7 @@ type ReviewResult
type alias CodeInspector =
{ source : String
{ file : File.ParsedFile
, getCodeAtLocation : Range -> Maybe String
, checkIfLocationIsAmbiguous : Error -> String -> Expectation
}
@ -220,12 +220,29 @@ interested in project related details, then you should use [`run`](#run) instead
-}
runWithProjectData : Project -> Rule -> String -> ReviewResult
runWithProjectData project rule originalSource =
let
sources : List String
sources =
[ originalSource ]
in
runWithProjectData project rule source =
runMultiWithProjectData project rule [ source ]
codeInspectorForSource : File.ParsedFile -> CodeInspector
codeInspectorForSource file =
{ file = file
, getCodeAtLocation = getCodeAtLocationInSourceCode file.source
, checkIfLocationIsAmbiguous = checkIfLocationIsAmbiguousInSourceCode file.source
}
{-| TODO documentation
-}
runMulti : Rule -> List String -> ReviewResult
runMulti rule sources =
runMultiWithProjectData Project.new rule sources
{-| TODO documentation
-}
runMultiWithProjectData : Project -> Rule -> List String -> ReviewResult
runMultiWithProjectData project rule sources =
case parseSources sources of
Ok parsedFiles ->
let
@ -235,16 +252,15 @@ runWithProjectData project rule originalSource =
|> Tuple.first
in
-- TODO Fail if modules have the same module name
List.map2
(\source parsedFile ->
{ inspector = codeInspectorForSource source
List.map
(\parsedFile ->
{ inspector = codeInspectorForSource parsedFile
, errors =
errors
|> List.filter (\error_ -> Rule.errorFilePath error_ == parsedFile.path)
|> List.sortWith compareErrorPositions
}
)
sources
parsedFiles
|> SuccessfulRun
@ -253,14 +269,6 @@ runWithProjectData project rule originalSource =
ParseFailure
codeInspectorForSource : String -> CodeInspector
codeInspectorForSource source =
{ source = source
, getCodeAtLocation = getCodeAtLocationInSourceCode source
, checkIfLocationIsAmbiguous = checkIfLocationIsAmbiguousInSourceCode source
}
parseSources : List String -> Result Error (List File.ParsedFile)
parseSources sources =
sources
@ -402,19 +410,28 @@ an error at the end of the source code.
-}
expectErrors : List ExpectedError -> ReviewResult -> Expectation
expectErrors expectedErrors reviewResult =
expectErrorsForFiles [ expectedErrors ] reviewResult
{-| TODO Documentation
-}
expectErrorsForFiles : List (List ExpectedError) -> ReviewResult -> Expectation
expectErrorsForFiles expectedErrorsList reviewResult =
case reviewResult of
ParseFailure ->
Expect.fail ErrorMessage.parsingFailure
SuccessfulRun runResults ->
-- TODO Add expectation that we have only one file
-- TODO Add expectation that we have as many elements in expectedErrorsList as runResults
List.map2
(\{ inspector, errors } expectedErrors () ->
checkAllErrorsMatch inspector expectedErrors errors
)
runResults
|> List.map (\{ inspector, errors } () -> checkAllErrorsMatch inspector expectedErrors errors)
expectedErrorsList
|> (\expectations -> Expect.all expectations ())
{-| Create an expectation for an error.
`message` should be the message you're expecting to be shown to the user.
@ -684,7 +701,7 @@ checkFixesAreCorrect codeInspector error_ ((ExpectedError expectedError_) as exp
|> Expect.fail
( Just expectedFixedSource, Just fixes ) ->
case Fix.fix fixes codeInspector.source of
case Fix.fix fixes codeInspector.file.source of
Fix.Successful fixedSource ->
(fixedSource == expectedFixedSource)
|> Expect.true (ErrorMessage.fixedCodeMismatch fixedSource expectedFixedSource error_)

View File

@ -0,0 +1,78 @@
module NoUnusedModulesTest exposing (all)
import Dependencies
import Elm.Project
import Elm.Type as Type
import Elm.Version
import NoUnusedModules exposing (rule)
import Review.Project as Project exposing (Project)
import Review.Test exposing (ReviewResult)
import Test exposing (Test, describe, test)
application : Project
application =
Project.new
|> Project.withElmJson applicationElmJson
applicationElmJson : Elm.Project.Project
applicationElmJson =
Elm.Project.Application
{ elm = Elm.Version.one
, dirs = []
, depsDirect = []
, depsIndirect = []
, testDepsDirect = []
, testDepsIndirect = []
}
details : List String
details =
[ "This module is never used. You may want to remove it to keep your project clean, and maybe detect some unused code in your project."
]
tests : List Test
tests =
[ test "should not report a module when all modules are used" <|
\() ->
[ """
module A exposing (..)
import B
main = text ""
"""
, """
module B exposing (..)
"""
]
|> Review.Test.runMultiWithProjectData application rule
|> Review.Test.expectNoErrors
, test "should report a module when it is never used" <|
\() ->
[ """
module A exposing (..)
main = text ""
"""
, """
module B exposing (..)
"""
]
|> Review.Test.runMultiWithProjectData application rule
|> Review.Test.expectErrorsForFiles
[ []
, [ Review.Test.error
{ message = "Module `B` is never used."
, details = details
, under = "B"
}
|> Review.Test.atExactly { start = { row = 2, column = 8 }, end = { row = 2, column = 9 } }
]
]
]
all : Test
all =
describe "NoUnusedModules" tests