elm-review/tests/NoUnusedExportsTest.elm

594 lines
21 KiB
Elm
Raw Normal View History

2020-01-12 02:28:20 +03:00
module NoUnusedExportsTest exposing (all)
import Elm.Project
import Elm.Version
import Json.Decode as Decode
2020-01-12 02:28:20 +03:00
import NoUnusedExports exposing (rule)
import Review.Project as Project exposing (Project)
2020-01-15 11:54:26 +03:00
import Review.Test
2020-01-12 02:28:20 +03:00
import Test exposing (Test, describe, test)
application : Project
application =
Project.new
|> Project.withElmJson applicationElmJson
applicationElmJson : { path : String, raw : String, project : Elm.Project.Project }
2020-01-12 02:28:20 +03:00
applicationElmJson =
{ path = "elm.json"
, raw = """{
"type": "application",
"source-directories": [
"src"
],
"elm-version": "0.19.1",
"dependencies": {
"direct": {
"elm/core": "1.0.2"
},
"indirect": {}
},
"test-dependencies": {
"direct": {},
"indirect": {}
}
}"""
, project =
Elm.Project.Application
{ elm = Elm.Version.one
, dirs = []
, depsDirect = []
, depsIndirect = []
, testDepsDirect = []
, testDepsIndirect = []
}
}
2020-01-12 02:28:20 +03:00
package_ : Project
package_ =
Project.new
|> Project.withElmJson (createPackageElmJson ())
createPackageElmJson : () -> { path : String, raw : String, project : Elm.Project.Project }
2020-01-12 02:28:20 +03:00
createPackageElmJson _ =
case Decode.decodeString Elm.Project.decoder rawPackageElmJson of
Ok elmJson ->
{ path = "elm.json"
, raw = rawPackageElmJson
, project = elmJson
}
Err _ ->
2020-01-12 02:28:20 +03:00
createPackageElmJson ()
rawPackageElmJson =
"""{
"type": "package",
"name": "author/package",
"summary": "Summary",
"license": "BSD-3-Clause",
"version": "1.0.0",
"exposed-modules": [
"Exposed"
],
"elm-version": "0.19.0 <= v < 0.20.0",
"dependencies": {},
"test-dependencies": {}
}"""
2020-01-12 02:28:20 +03:00
details : List String
details =
[ "This exposed element is never used. You may want to remove it to keep your project clean, and maybe detect some unused code in your project."
]
2020-01-14 14:50:07 +03:00
all : Test
all =
describe "NoUnusedExports"
[ functionsAndValuesTests
, typesTests
, typeAliasesTests
2020-01-14 14:50:07 +03:00
-- TODO Add tests that report exposing the type's variants if they are never used.
]
functionsAndValuesTests : Test
functionsAndValuesTests =
describe "Functions and values"
[ test "should report an exposed function when it is not used in other modules" <|
\() ->
"""
2020-01-12 02:28:20 +03:00
module A exposing (a)
a = 1
"""
2020-01-14 14:50:07 +03:00
|> Review.Test.runWithProjectData application rule
|> Review.Test.expectErrors
[ Review.Test.error
{ message = "Exposed function or value `a` is never used outside this module."
, details = details
, under = "a"
}
|> Review.Test.atExactly { start = { row = 2, column = 20 }, end = { row = 2, column = 21 } }
]
, test "should not report an exposed function when it is used in other modules (qualified import)" <|
\() ->
[ """
2020-01-12 02:28:20 +03:00
module A exposing (a)
a = 1
""", """
module B exposing (main)
import A
main = A.a
""" ]
2020-01-14 14:50:07 +03:00
|> Review.Test.runOnModulesWithProjectData application rule
|> Review.Test.expectNoErrors
, test "should not report an exposed function when it is used in other modules (using an alias)" <|
\() ->
[ """
2020-01-12 02:28:20 +03:00
module A exposing (a)
a = 1
""", """
module B exposing (main)
import A as SomeA
main = SomeA.a
""" ]
2020-01-14 14:50:07 +03:00
|> Review.Test.runOnModulesWithProjectData application rule
|> Review.Test.expectNoErrors
, test "should not report an exposed function when it is used in other modules (using `exposing` to import)" <|
\() ->
[ """
2020-01-12 02:28:20 +03:00
module A exposing (a)
a = 1
""", """
module B exposing (main)
import A exposing (a)
main = a
""" ]
2020-01-14 14:50:07 +03:00
|> Review.Test.runOnModulesWithProjectData application rule
|> Review.Test.expectNoErrors
, test "should not report an exposed function when it is used in other modules (using `exposing(..)` to import)" <|
\() ->
[ """
2020-01-12 02:28:20 +03:00
module A exposing (a)
a = 1
""", """
module B exposing (main)
import A exposing (..)
main = a
""" ]
2020-01-14 14:50:07 +03:00
|> Review.Test.runOnModulesWithProjectData application rule
|> Review.Test.expectNoErrors
, test "should report an exposed function when it is not used in other modules, even if it is used in the module" <|
\() ->
"""
2020-01-12 02:28:20 +03:00
module A exposing (exposed)
exposed = 1
main = exposed
"""
2020-01-14 14:50:07 +03:00
|> Review.Test.runWithProjectData package_ rule
|> Review.Test.expectErrors
[ Review.Test.error
{ message = "Exposed function or value `exposed` is never used outside this module."
, details = details
, under = "exposed"
}
|> Review.Test.atExactly { start = { row = 2, column = 20 }, end = { row = 2, column = 27 } }
]
, test "should not report anything for modules that expose everything`" <|
\() ->
"""
2020-01-12 02:28:20 +03:00
module A exposing (..)
a = 1
"""
2020-01-14 14:50:07 +03:00
|> Review.Test.runWithProjectData package_ rule
|> Review.Test.expectNoErrors
, test "should not report the `main` function for an application even if it is unused" <|
\() ->
"""
2020-01-12 02:28:20 +03:00
module Main exposing (main)
main = text ""
"""
2020-01-14 14:50:07 +03:00
|> Review.Test.runWithProjectData application rule
|> Review.Test.expectNoErrors
, test "should report the `main` function for a package when it is never used outside the module" <|
\() ->
"""
2020-01-12 02:28:20 +03:00
module Main exposing (main)
main = text ""
"""
2020-01-14 14:50:07 +03:00
|> Review.Test.runWithProjectData package_ rule
|> Review.Test.expectErrors
[ Review.Test.error
{ message = "Exposed function or value `main` is never used outside this module."
, details = details
, under = "main"
}
|> Review.Test.atExactly { start = { row = 2, column = 23 }, end = { row = 2, column = 27 } }
]
, test "should not report a function that does not refer to anything" <|
\() ->
"""
2020-01-12 02:28:20 +03:00
module A exposing (b)
a = 1
"""
|> Review.Test.runWithProjectData package_ rule
|> Review.Test.expectNoErrors
, test "should not report exposed tests" <|
\() ->
"""
module ThingTest exposing (a)
import Test exposing (Test)
a : Test
a = Test.describe "thing" []
"""
|> Review.Test.runWithProjectData package_ rule
|> Review.Test.expectNoErrors
, test "should not ReviewConfig.config" <|
\() ->
"""
module ReviewConfig exposing (config)
config = []
2020-01-12 02:28:20 +03:00
"""
2020-01-14 14:50:07 +03:00
|> Review.Test.runWithProjectData package_ rule
|> Review.Test.expectNoErrors
]
2020-01-12 02:28:20 +03:00
2020-01-14 14:50:07 +03:00
typesTests : Test
typesTests =
describe "Types"
[ test "should report an unused exposed custom type" <|
\() ->
"""
module A exposing (Exposed)
type Exposed = VariantA | VariantB
"""
|> Review.Test.runWithProjectData application rule
|> Review.Test.expectErrors
[ Review.Test.error
{ message = "Exposed type or type alias `Exposed` is never used outside this module."
, details = details
, under = "Exposed"
}
|> Review.Test.atExactly { start = { row = 2, column = 20 }, end = { row = 2, column = 27 } }
]
, test "should not report a used exposed custom type (type signature)" <|
\() ->
[ """
module A exposing (Exposed)
type Exposed = VariantA | VariantB
""", """
module B exposing (main)
import A
main : A.Exposed
main = VariantA
""" ]
|> Review.Test.runOnModulesWithProjectData application rule
|> Review.Test.expectNoErrors
, test "should not report a used exposed custom type (used in type alias)" <|
\() ->
[ """
2020-01-14 14:50:07 +03:00
module A exposing (ExposedB, ExposedC)
type ExposedB = B
type ExposedC = C
""", """
module Exposed exposing (B, C)
import A
type alias B = A.ExposedB
type alias C = A.ExposedC
""" ]
|> Review.Test.runOnModulesWithProjectData package_ rule
|> Review.Test.expectNoErrors
2020-01-14 14:50:07 +03:00
, test "should not report an unused exposed custom type if it's part of the package's exposed API" <|
\() ->
"""
module Exposed exposing (MyType)
type MyType = VariantA | VariantB
"""
|> Review.Test.runWithProjectData package_ rule
|> Review.Test.expectNoErrors
, test "should not report an unused exposed custom type if it's present in the signature of an exposed function" <|
\() ->
"""
module A exposing (main, MyType)
type MyType = VariantA | VariantB
main : () -> MyType
main = 1
"""
|> Review.Test.runWithProjectData application rule
|> Review.Test.expectNoErrors
, test "should not report an unused exposed custom type if it's aliased by an exposed type alias" <|
\() ->
[ """
2020-01-14 14:50:07 +03:00
module A exposing (MyType, OtherType)
type MyType = VariantA | VariantB
type alias OtherType = MyType
""", """
module Exposed exposing (..)
import A
type alias B = A.OtherType
""" ]
|> Review.Test.runOnModulesWithProjectData package_ rule
|> Review.Test.expectNoErrors
, test "should not report an unused exposed custom type if it's present in an exposed type alias" <|
\() ->
[ """
2020-01-14 14:50:07 +03:00
module A exposing (MyType, OtherType)
type MyType = VariantA | VariantB
type alias OtherType = { thing : MyType }
""", """
module Exposed exposing (..)
import A
type alias B = A.OtherType
""" ]
|> Review.Test.runOnModulesWithProjectData package_ rule
|> Review.Test.expectNoErrors
, test "should not report an unused exposed custom type if it's present in an exposed type alias (nested)" <|
\() ->
[ """
2020-01-14 14:50:07 +03:00
module A exposing (MyType, OtherType)
type MyType = VariantA | VariantB
type alias OtherType = { other : { thing : ((), MyType) } }
""", """
module Exposed exposing (..)
import A
type alias B = A.OtherType
""" ]
|> Review.Test.runOnModulesWithProjectData package_ rule
|> Review.Test.expectNoErrors
, test "should not report an unused exposed custom type if it's present in an exposed custom type constructor's arguments" <|
\() ->
[ """
module A exposing (MyType, OtherType(..))
type MyType = VariantA | VariantB
type OtherType = Thing MyType
2020-01-14 14:50:07 +03:00
""", """
module Exposed exposing (..)
import A
type alias B = A.OtherType
""" ]
|> Review.Test.runOnModulesWithProjectData package_ rule
|> Review.Test.expectNoErrors
, test "should not report an unused exposed custom type if it's present in an exposed custom type constructor's arguments but the constructors are not exposed" <|
\() ->
[ """
2020-01-14 14:50:07 +03:00
module A exposing (MyType, OtherType)
type MyType = VariantA | VariantB
type OtherType = Thing MyType
""", """
module Exposed exposing (..)
import A
type alias B = A.OtherType
""" ]
|> Review.Test.runOnModulesWithProjectData package_ rule
|> Review.Test.expectErrorsForModules
[ ( "A"
, [ Review.Test.error
{ message = "Exposed type or type alias `MyType` is never used outside this module."
, details = details
, under = "MyType"
}
|> Review.Test.atExactly { start = { row = 2, column = 20 }, end = { row = 2, column = 26 } }
]
)
]
, test "should not report an unused exposed custom type if it's present in an exposed custom type constructor's arguments (nested)" <|
\() ->
[ """
module A exposing (MyType, OtherType(..))
type MyType = VariantA | VariantB
type OtherType = OtherThing | SomeThing ((), List MyType)
""", """
module Exposed exposing (..)
import A
type alias B = A.OtherType
""" ]
|> Review.Test.runOnModulesWithProjectData package_ rule
|> Review.Test.expectNoErrors
, test "should not report an unused exposed custom type if it's present in an exposed custom type constructor's arguments (nested) but the constructors are not exposed" <|
\() ->
[ """
2020-01-14 14:50:07 +03:00
module A exposing (MyType, OtherType)
type MyType = VariantA | VariantB
type OtherType = OtherThing | SomeThing ((), List MyType)
""", """
module Exposed exposing (..)
import A
type alias B = A.OtherType
""" ]
|> Review.Test.runOnModulesWithProjectData package_ rule
|> Review.Test.expectErrorsForModules
[ ( "A"
, [ Review.Test.error
{ message = "Exposed type or type alias `MyType` is never used outside this module."
, details = details
, under = "MyType"
}
|> Review.Test.atExactly { start = { row = 2, column = 20 }, end = { row = 2, column = 26 } }
]
)
]
]
typeAliasesTests : Test
typeAliasesTests =
describe "Type aliases"
[ test "should report an unused exposed type alias" <|
\() ->
"""
module A exposing (Exposed)
type alias Exposed = {}
"""
|> Review.Test.runWithProjectData application rule
|> Review.Test.expectErrors
[ Review.Test.error
{ message = "Exposed type or type alias `Exposed` is never used outside this module."
, details = details
, under = "Exposed"
}
|> Review.Test.atExactly { start = { row = 2, column = 20 }, end = { row = 2, column = 27 } }
]
, test "should not report a used exposed type alias (type signature)" <|
\() ->
[ """
module A exposing (Exposed)
type alias Exposed = {}
""", """
module B exposing (main)
import A
main : A.Exposed
main = {}
""" ]
|> Review.Test.runOnModulesWithProjectData application rule
|> Review.Test.expectNoErrors
, test "should not report a used exposed type alias (used in type alias)" <|
\() ->
[ """
module A exposing (ExposedB)
type alias ExposedB = {}
""", """
module Exposed exposing (B)
import A
type alias B = A.ExposedB
""" ]
|> Review.Test.runOnModulesWithProjectData package_ rule
|> Review.Test.expectNoErrors
, test "should not report an unused exposed type alias if it's part of the package's exposed API" <|
\() ->
"""
module Exposed exposing (MyType)
type alias MyType = {}
"""
|> Review.Test.runWithProjectData package_ rule
|> Review.Test.expectNoErrors
, test "should not report an unused exposed type alias if it's present in the signature of an exposed function" <|
\() ->
"""
module A exposing (main, MyType)
type alias MyType = {}
main : () -> MyType
main = 1
"""
|> Review.Test.runWithProjectData application rule
|> Review.Test.expectNoErrors
, test "should not report an unused exposed type alias if it's aliased by an exposed type alias" <|
\() ->
[ """
module A exposing (MyType, OtherType)
type alias MyType = {}
type alias OtherType = MyType
""", """
module Exposed exposing (..)
import A
type alias B = A.OtherType
""" ]
|> Review.Test.runOnModulesWithProjectData package_ rule
|> Review.Test.expectNoErrors
, test "should not report an unused exposed type alias if it's present in an exposed type alias" <|
\() ->
[ """
module A exposing (MyType, OtherType)
type alias MyType = {}
type alias OtherType = { thing : MyType }
""", """
module Exposed exposing (..)
import A
type alias B = A.OtherType
""" ]
|> Review.Test.runOnModulesWithProjectData package_ rule
|> Review.Test.expectNoErrors
, test "should not report an unused exposed type alias if it's present in an exposed type alias (nested)" <|
\() ->
[ """
module A exposing (MyType, OtherType)
type alias MyType = {}
type alias OtherType = { other : { thing : ((), MyType) } }
""", """
module Exposed exposing (..)
import A
type alias B = A.OtherType
""" ]
|> Review.Test.runOnModulesWithProjectData package_ rule
|> Review.Test.expectNoErrors
, test "should not report an unused exposed type alias if it's present in an exposed custom type constructor's arguments" <|
\() ->
[ """
module A exposing (MyType, OtherType(..))
type alias MyType = {}
type OtherType = OtherType MyType
""", """
module Exposed exposing (..)
import A
type alias B = A.OtherType
""" ]
|> Review.Test.runOnModulesWithProjectData package_ rule
|> Review.Test.expectNoErrors
, test "should not report an unused exposed type alias if it's present in an exposed custom type constructor's arguments but the constructors are not exposed" <|
\() ->
[ """
module A exposing (MyType, OtherType)
type alias MyType = {}
type OtherType = OtherType MyType
""", """
module Exposed exposing (..)
import A
type alias B = A.OtherType
""" ]
|> Review.Test.runOnModulesWithProjectData package_ rule
|> Review.Test.expectErrorsForModules
[ ( "A"
, [ Review.Test.error
{ message = "Exposed type or type alias `MyType` is never used outside this module."
, details = details
, under = "MyType"
}
|> Review.Test.atExactly { start = { row = 2, column = 20 }, end = { row = 2, column = 26 } }
]
)
]
, test "should not report an unused exposed type alias if it's present in an exposed custom type constructor's arguments (nested)" <|
\() ->
[ """
module A exposing (MyType, OtherType(..))
type alias MyType = {}
type OtherType = OtherThing | SomeThing ((), List MyType)
""", """
module Exposed exposing (..)
import A
type alias B = A.OtherType
""" ]
|> Review.Test.runOnModulesWithProjectData package_ rule
|> Review.Test.expectNoErrors
, test "should report an unused exposed type alias if it's present in an exposed custom type constructor's arguments (nested) but the constructors are not exposed" <|
\() ->
[ """
module A exposing (MyType, OtherType)
type alias MyType = {}
type OtherType = OtherThing | SomeThing ((), List MyType)
""", """
module Exposed exposing (..)
import A
type alias B = A.OtherType
""" ]
|> Review.Test.runOnModulesWithProjectData package_ rule
|> Review.Test.expectErrorsForModules
[ ( "A"
, [ Review.Test.error
{ message = "Exposed type or type alias `MyType` is never used outside this module."
, details = details
, under = "MyType"
}
|> Review.Test.atExactly { start = { row = 2, column = 20 }, end = { row = 2, column = 26 } }
]
)
]
2020-01-14 14:50:07 +03:00
]