2020-08-09 19:55:15 +03:00
|
|
|
module NoMissingTypeExposeTest exposing (all)
|
|
|
|
|
|
|
|
import Elm.Docs
|
|
|
|
import Elm.Project
|
|
|
|
import Json.Decode as Decode
|
|
|
|
import NoMissingTypeExpose exposing (rule)
|
|
|
|
import Review.Project as Project exposing (Project)
|
|
|
|
import Review.Project.Dependency as Dependency exposing (Dependency)
|
|
|
|
import Review.Test
|
|
|
|
import Test exposing (Test, describe, test)
|
|
|
|
|
|
|
|
|
|
|
|
all : Test
|
|
|
|
all =
|
|
|
|
describe "NoMissingTypeExpose"
|
|
|
|
[ describe "in exposed functions" functionTests
|
|
|
|
, describe "in exposed types" typeTests
|
|
|
|
, describe "in exposed type aliases" typeAliasTests
|
|
|
|
, describe "in package projects" packageTests
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
details : List String
|
|
|
|
details =
|
|
|
|
[ "Users of this module will not be able to annotate a value of this type if they wanted to. You should expose this type or an alias of this type."
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
functionTests : List Test
|
|
|
|
functionTests =
|
|
|
|
[ test "passes when everything is exposed" <|
|
|
|
|
\() ->
|
|
|
|
"""
|
|
|
|
module Happiness exposing (..)
|
|
|
|
type Happiness = Happy
|
|
|
|
toString : Happiness -> String
|
|
|
|
toString howHappy = "Happy"
|
|
|
|
"""
|
|
|
|
|> Review.Test.run rule
|
|
|
|
|> Review.Test.expectNoErrors
|
|
|
|
, test "passes when an exposed type is used" <|
|
|
|
|
\() ->
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Happiness, toString)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
toString : Happiness -> String
|
|
|
|
toString howHappy = "Very"
|
|
|
|
"""
|
|
|
|
|> Review.Test.run rule
|
|
|
|
|> Review.Test.expectNoErrors
|
|
|
|
, test "reports when a private type is used" <|
|
|
|
|
\() ->
|
|
|
|
"""
|
|
|
|
module Happiness exposing (toString)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
toString : Happiness -> String
|
|
|
|
toString howHappy = "Very"
|
|
|
|
"""
|
|
|
|
|> Review.Test.run rule
|
|
|
|
|> Review.Test.expectErrors
|
|
|
|
[ Review.Test.error
|
|
|
|
{ message = "Private type `Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Happiness"
|
|
|
|
}
|
|
|
|
|> Review.Test.atExactly { start = { row = 4, column = 12 }, end = { row = 4, column = 21 } }
|
|
|
|
|> Review.Test.whenFixed
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Happiness, toString)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
toString : Happiness -> String
|
|
|
|
toString howHappy = "Very"
|
|
|
|
"""
|
|
|
|
]
|
|
|
|
, test "reports when a private type is returned" <|
|
|
|
|
\() ->
|
|
|
|
"""
|
|
|
|
module Happiness exposing (ecstatic)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
ecstatic : Happiness
|
|
|
|
ecstatic = Ecstatic
|
|
|
|
"""
|
|
|
|
|> Review.Test.run rule
|
|
|
|
|> Review.Test.expectErrors
|
|
|
|
[ Review.Test.error
|
|
|
|
{ message = "Private type `Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Happiness"
|
|
|
|
}
|
|
|
|
|> Review.Test.atExactly { start = { row = 4, column = 12 }, end = { row = 4, column = 21 } }
|
|
|
|
|> Review.Test.whenFixed
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Happiness, ecstatic)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
ecstatic : Happiness
|
|
|
|
ecstatic = Ecstatic
|
|
|
|
"""
|
|
|
|
]
|
|
|
|
, test "reports when a private type is used in a Maybe" <|
|
|
|
|
\() ->
|
|
|
|
"""
|
|
|
|
module Happiness exposing (toString)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
toString : Maybe Happiness -> String
|
|
|
|
toString maybeHappy = "Very"
|
|
|
|
"""
|
|
|
|
|> Review.Test.run rule
|
|
|
|
|> Review.Test.expectErrors
|
|
|
|
[ Review.Test.error
|
|
|
|
{ message = "Private type `Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Happiness"
|
|
|
|
}
|
|
|
|
|> Review.Test.atExactly { start = { row = 4, column = 18 }, end = { row = 4, column = 27 } }
|
|
|
|
|> Review.Test.whenFixed
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Happiness, toString)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
toString : Maybe Happiness -> String
|
|
|
|
toString maybeHappy = "Very"
|
|
|
|
"""
|
|
|
|
]
|
|
|
|
, test "reports when an external private type is used in a Maybe" <|
|
|
|
|
\() ->
|
|
|
|
"""
|
|
|
|
module Happiness exposing (toString)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
toString : Maybe.Maybe Happiness -> String
|
|
|
|
toString maybeHappy = "Very"
|
|
|
|
"""
|
|
|
|
|> Review.Test.run rule
|
|
|
|
|> Review.Test.expectErrors
|
|
|
|
[ Review.Test.error
|
|
|
|
{ message = "Private type `Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Happiness"
|
|
|
|
}
|
|
|
|
|> Review.Test.atExactly { start = { row = 4, column = 24 }, end = { row = 4, column = 33 } }
|
|
|
|
|> Review.Test.whenFixed
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Happiness, toString)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
toString : Maybe.Maybe Happiness -> String
|
|
|
|
toString maybeHappy = "Very"
|
|
|
|
"""
|
|
|
|
]
|
|
|
|
, test "reports when a private type is used in a tuple" <|
|
|
|
|
\() ->
|
|
|
|
"""
|
|
|
|
module Happiness exposing (equal)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
equal : ( Happiness, Happiness ) -> Bool
|
|
|
|
equal ( a, b ) = a == b
|
|
|
|
"""
|
|
|
|
|> Review.Test.run rule
|
|
|
|
|> Review.Test.expectErrors
|
|
|
|
[ Review.Test.error
|
|
|
|
{ message = "Private type `Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Happiness"
|
|
|
|
}
|
|
|
|
|> Review.Test.atExactly { start = { row = 4, column = 11 }, end = { row = 4, column = 20 } }
|
|
|
|
|> Review.Test.whenFixed
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Happiness, equal)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
equal : ( Happiness, Happiness ) -> Bool
|
|
|
|
equal ( a, b ) = a == b
|
|
|
|
"""
|
|
|
|
, Review.Test.error
|
|
|
|
{ message = "Private type `Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Happiness"
|
|
|
|
}
|
|
|
|
|> Review.Test.atExactly { start = { row = 4, column = 22 }, end = { row = 4, column = 31 } }
|
|
|
|
|> Review.Test.whenFixed
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Happiness, equal)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
equal : ( Happiness, Happiness ) -> Bool
|
|
|
|
equal ( a, b ) = a == b
|
|
|
|
"""
|
|
|
|
]
|
|
|
|
, test "reports when a private type is used in a record" <|
|
|
|
|
\() ->
|
|
|
|
"""
|
|
|
|
module Happiness exposing (rank)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
rank : { happiness : Happiness } -> Int
|
|
|
|
rank { happiness } = 0
|
|
|
|
"""
|
|
|
|
|> Review.Test.run rule
|
|
|
|
|> Review.Test.expectErrors
|
|
|
|
[ Review.Test.error
|
|
|
|
{ message = "Private type `Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Happiness"
|
|
|
|
}
|
|
|
|
|> Review.Test.atExactly { start = { row = 4, column = 22 }, end = { row = 4, column = 31 } }
|
|
|
|
|> Review.Test.whenFixed
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Happiness, rank)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
rank : { happiness : Happiness } -> Int
|
|
|
|
rank { happiness } = 0
|
|
|
|
"""
|
|
|
|
]
|
|
|
|
, test "reports when a private type is used in an extensible record" <|
|
|
|
|
\() ->
|
|
|
|
"""
|
|
|
|
module Happiness exposing (rank)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
rank : { a | happiness : Happiness } -> Int
|
|
|
|
rank { happiness } = 0
|
|
|
|
"""
|
|
|
|
|> Review.Test.run rule
|
|
|
|
|> Review.Test.expectErrors
|
|
|
|
[ Review.Test.error
|
|
|
|
{ message = "Private type `Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Happiness"
|
|
|
|
}
|
|
|
|
|> Review.Test.atExactly { start = { row = 4, column = 26 }, end = { row = 4, column = 35 } }
|
|
|
|
|> Review.Test.whenFixed
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Happiness, rank)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
rank : { a | happiness : Happiness } -> Int
|
|
|
|
rank { happiness } = 0
|
|
|
|
"""
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
typeTests : List Test
|
|
|
|
typeTests =
|
|
|
|
[ test "passes when an exposed type uses another exposed type" <|
|
|
|
|
\() ->
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Happiness, Mood(..))
|
|
|
|
type Mood = Happy Happiness
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
"""
|
|
|
|
|> Review.Test.run rule
|
|
|
|
|> Review.Test.expectNoErrors
|
|
|
|
, test "passes when an exposed opaque type uses a private type" <|
|
|
|
|
\() ->
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Mood)
|
|
|
|
type Mood = Happy Happiness
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
"""
|
|
|
|
|> Review.Test.run rule
|
|
|
|
|> Review.Test.expectNoErrors
|
|
|
|
, test "reports when an exposed open type uses a private type" <|
|
|
|
|
\() ->
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Mood(..))
|
|
|
|
type Mood = Happy Happiness
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
"""
|
|
|
|
|> Review.Test.run rule
|
|
|
|
|> Review.Test.expectErrors
|
|
|
|
[ Review.Test.error
|
|
|
|
{ message = "Private type `Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Happiness"
|
|
|
|
}
|
|
|
|
|> Review.Test.atExactly { start = { row = 3, column = 19 }, end = { row = 3, column = 28 } }
|
|
|
|
|> Review.Test.whenFixed
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Happiness, Mood(..))
|
|
|
|
type Mood = Happy Happiness
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
"""
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
typeAliasTests : List Test
|
|
|
|
typeAliasTests =
|
|
|
|
[ test "passes when everything is exposed" <|
|
|
|
|
\() ->
|
|
|
|
"""
|
|
|
|
module Happiness exposing (..)
|
|
|
|
type alias Happiness = { happiness : Int }
|
|
|
|
toString : Happiness -> String
|
|
|
|
toString howHappy = "Very"
|
|
|
|
"""
|
|
|
|
|> Review.Test.run rule
|
|
|
|
|> Review.Test.expectNoErrors
|
|
|
|
, test "does not report a function using an exposed type alias of a private type" <|
|
|
|
|
\() ->
|
|
|
|
let
|
|
|
|
project : Project
|
|
|
|
project =
|
|
|
|
Project.new
|
|
|
|
|> Project.addElmJson (createElmJson packageElmJson)
|
|
|
|
in
|
|
|
|
[ """
|
|
|
|
module Exposed exposing (Happiness, toString)
|
|
|
|
import Mood
|
|
|
|
type alias Happiness = Mood.Happiness
|
|
|
|
toString : Happiness -> String
|
|
|
|
toString happiness = "Happy"
|
|
|
|
""", """
|
|
|
|
module Mood exposing (Happiness)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
""" ]
|
|
|
|
|> Review.Test.runOnModulesWithProjectData project rule
|
|
|
|
|> Review.Test.expectNoErrors
|
|
|
|
, test "reports a function using a private type alias" <|
|
|
|
|
\() ->
|
|
|
|
let
|
|
|
|
project : Project
|
|
|
|
project =
|
|
|
|
Project.new
|
|
|
|
|> Project.addElmJson (createElmJson packageElmJson)
|
|
|
|
in
|
|
|
|
"""
|
|
|
|
module Exposed exposing (toString)
|
|
|
|
type alias Happiness = { happiness : Int }
|
|
|
|
toString : Happiness -> String
|
|
|
|
toString happiness = "Happy"
|
|
|
|
"""
|
|
|
|
|> Review.Test.runWithProjectData project rule
|
|
|
|
|> Review.Test.expectErrors
|
|
|
|
[ Review.Test.error
|
|
|
|
{ message = "Private type `Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Happiness"
|
|
|
|
}
|
|
|
|
|> Review.Test.atExactly { start = { row = 4, column = 12 }, end = { row = 4, column = 21 } }
|
|
|
|
|> Review.Test.whenFixed
|
|
|
|
"""
|
|
|
|
module Exposed exposing (Happiness, toString)
|
|
|
|
type alias Happiness = { happiness : Int }
|
|
|
|
toString : Happiness -> String
|
|
|
|
toString happiness = "Happy"
|
|
|
|
"""
|
|
|
|
]
|
|
|
|
, test "reports a function using an internal type alias" <|
|
|
|
|
\() ->
|
|
|
|
let
|
|
|
|
project : Project
|
|
|
|
project =
|
|
|
|
Project.new
|
|
|
|
|> Project.addElmJson (createElmJson packageElmJson)
|
|
|
|
in
|
|
|
|
[ """
|
|
|
|
module Exposed exposing (toString)
|
|
|
|
import Mood
|
|
|
|
toString : Mood.Happiness -> String
|
|
|
|
toString happiness = "Happy"
|
|
|
|
""", """
|
|
|
|
module Mood exposing (Happiness)
|
|
|
|
type alias Happiness = { howHappy : Int }
|
|
|
|
""" ]
|
|
|
|
|> Review.Test.runOnModulesWithProjectData project rule
|
|
|
|
|> Review.Test.expectErrorsForModules
|
|
|
|
[ ( "Exposed"
|
|
|
|
, [ Review.Test.error
|
|
|
|
{ message = "Private type `Mood.Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Mood.Happiness"
|
|
|
|
}
|
|
|
|
|> Review.Test.atExactly { start = { row = 4, column = 12 }, end = { row = 4, column = 26 } }
|
|
|
|
]
|
|
|
|
)
|
|
|
|
]
|
|
|
|
, test "reports a function using an internal type alias exposed via (..)" <|
|
|
|
|
\() ->
|
|
|
|
let
|
|
|
|
project : Project
|
|
|
|
project =
|
|
|
|
Project.new
|
|
|
|
|> Project.addElmJson (createElmJson packageElmJson)
|
|
|
|
in
|
|
|
|
[ """
|
|
|
|
module Exposed exposing (toString)
|
|
|
|
import Mood exposing (..)
|
|
|
|
toString : Happiness -> String
|
|
|
|
toString happiness = "Happy"
|
|
|
|
""", """
|
|
|
|
module Mood exposing (..)
|
|
|
|
type alias Happiness = { howHappy : Int }
|
|
|
|
""" ]
|
|
|
|
|> Review.Test.runOnModulesWithProjectData project rule
|
|
|
|
|> Review.Test.expectErrorsForModules
|
|
|
|
[ ( "Exposed"
|
|
|
|
, [ Review.Test.error
|
|
|
|
{ message = "Private type `Mood.Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Happiness"
|
|
|
|
}
|
|
|
|
|> Review.Test.atExactly { start = { row = 4, column = 12 }, end = { row = 4, column = 21 } }
|
|
|
|
]
|
|
|
|
)
|
|
|
|
]
|
|
|
|
, test "reports a function using an internal type alias exposed explicitly and imported via (..)" <|
|
|
|
|
\() ->
|
|
|
|
let
|
|
|
|
project : Project
|
|
|
|
project =
|
|
|
|
Project.new
|
|
|
|
|> Project.addElmJson (createElmJson packageElmJson)
|
|
|
|
in
|
|
|
|
[ """
|
|
|
|
module Exposed exposing (toString)
|
|
|
|
import Mood exposing (..)
|
|
|
|
toString : Happiness -> String
|
|
|
|
toString happiness = "Happy"
|
|
|
|
""", """
|
|
|
|
module Mood exposing (Happiness)
|
|
|
|
type alias Happiness = { howHappy : Int }
|
|
|
|
""" ]
|
|
|
|
|> Review.Test.runOnModulesWithProjectData project rule
|
|
|
|
|> Review.Test.expectErrorsForModules
|
|
|
|
[ ( "Exposed"
|
|
|
|
, [ Review.Test.error
|
|
|
|
{ message = "Private type `Mood.Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Happiness"
|
|
|
|
}
|
|
|
|
|> Review.Test.atExactly { start = { row = 4, column = 12 }, end = { row = 4, column = 21 } }
|
|
|
|
]
|
|
|
|
)
|
|
|
|
]
|
|
|
|
, describe "when an exposed type alias uses a private type" <|
|
|
|
|
[ test "does not report when the type alias is directly a private type" <|
|
|
|
|
\() ->
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Mood)
|
|
|
|
type alias Mood = Happiness Int
|
|
|
|
type Happiness a = Ecstatic
|
|
|
|
"""
|
|
|
|
|> Review.Test.run rule
|
|
|
|
|> Review.Test.expectNoErrors
|
|
|
|
, test "reports a private type in another type" <|
|
|
|
|
\() ->
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Mood)
|
|
|
|
type alias Mood = Maybe Happiness
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
"""
|
|
|
|
|> Review.Test.run rule
|
|
|
|
|> Review.Test.expectErrors
|
|
|
|
[ Review.Test.error
|
|
|
|
{ message = "Private type `Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Happiness"
|
|
|
|
}
|
|
|
|
|> Review.Test.atExactly { start = { row = 3, column = 25 }, end = { row = 3, column = 34 } }
|
|
|
|
|> Review.Test.whenFixed
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Happiness, Mood)
|
|
|
|
type alias Mood = Maybe Happiness
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
"""
|
|
|
|
]
|
|
|
|
, test "reports a private type in a record" <|
|
|
|
|
\() ->
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Mood)
|
|
|
|
type alias Mood = { happiness : Happiness }
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
"""
|
|
|
|
|> Review.Test.run rule
|
|
|
|
|> Review.Test.expectErrors
|
|
|
|
[ Review.Test.error
|
|
|
|
{ message = "Private type `Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Happiness"
|
|
|
|
}
|
|
|
|
|> Review.Test.atExactly { start = { row = 3, column = 33 }, end = { row = 3, column = 42 } }
|
|
|
|
|> Review.Test.whenFixed
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Happiness, Mood)
|
|
|
|
type alias Mood = { happiness : Happiness }
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
"""
|
|
|
|
]
|
|
|
|
, test "reports private type in an extensible record" <|
|
|
|
|
\() ->
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Mood)
|
|
|
|
type alias Mood = { a | happiness : Happiness }
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
"""
|
|
|
|
|> Review.Test.run rule
|
|
|
|
|> Review.Test.expectErrors
|
|
|
|
[ Review.Test.error
|
|
|
|
{ message = "Private type `Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Happiness"
|
|
|
|
}
|
|
|
|
|> Review.Test.atExactly { start = { row = 3, column = 37 }, end = { row = 3, column = 46 } }
|
|
|
|
|> Review.Test.whenFixed
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Happiness, Mood)
|
|
|
|
type alias Mood = { a | happiness : Happiness }
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
"""
|
|
|
|
]
|
|
|
|
, test "reports a private type in a tuple" <|
|
|
|
|
\() ->
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Mood)
|
|
|
|
type alias Mood = ( Happiness, Int )
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
"""
|
|
|
|
|> Review.Test.run rule
|
|
|
|
|> Review.Test.expectErrors
|
|
|
|
[ Review.Test.error
|
|
|
|
{ message = "Private type `Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Happiness"
|
|
|
|
}
|
|
|
|
|> Review.Test.atExactly { start = { row = 3, column = 21 }, end = { row = 3, column = 30 } }
|
|
|
|
|> Review.Test.whenFixed
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Happiness, Mood)
|
|
|
|
type alias Mood = ( Happiness, Int )
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
"""
|
|
|
|
]
|
|
|
|
, test "reports a private type in a function" <|
|
|
|
|
\() ->
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Mood)
|
|
|
|
type alias Mood = Happiness -> Int
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
"""
|
|
|
|
|> Review.Test.run rule
|
|
|
|
|> Review.Test.expectErrors
|
|
|
|
[ Review.Test.error
|
|
|
|
{ message = "Private type `Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Happiness"
|
|
|
|
}
|
|
|
|
|> Review.Test.atExactly { start = { row = 3, column = 19 }, end = { row = 3, column = 28 } }
|
|
|
|
|> Review.Test.whenFixed
|
|
|
|
"""
|
|
|
|
module Happiness exposing (Happiness, Mood)
|
|
|
|
type alias Mood = Happiness -> Int
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
"""
|
|
|
|
]
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
packageTests : List Test
|
|
|
|
packageTests =
|
|
|
|
[ test "reports a function exposed by a package module using a type from an internal module" <|
|
|
|
|
\() ->
|
|
|
|
let
|
|
|
|
project : Project
|
|
|
|
project =
|
|
|
|
Project.new
|
|
|
|
|> Project.addElmJson (createElmJson packageElmJson)
|
|
|
|
in
|
|
|
|
[ """
|
|
|
|
module Exposed exposing (toString)
|
|
|
|
import Mood
|
|
|
|
toString : Mood.Happiness -> String
|
|
|
|
toString happiness = "Happy"
|
|
|
|
""", """
|
|
|
|
module Mood exposing (Happiness)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
""" ]
|
|
|
|
|> Review.Test.runOnModulesWithProjectData project rule
|
|
|
|
|> Review.Test.expectErrorsForModules
|
|
|
|
[ ( "Exposed"
|
|
|
|
, [ Review.Test.error
|
|
|
|
{ message = "Private type `Mood.Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Mood.Happiness"
|
|
|
|
}
|
|
|
|
]
|
|
|
|
)
|
|
|
|
]
|
|
|
|
, test "does not report an exposed function using a type from an exposed module" <|
|
|
|
|
\() ->
|
|
|
|
let
|
|
|
|
project : Project
|
|
|
|
project =
|
|
|
|
Project.new
|
|
|
|
|> Project.addElmJson (createElmJson packageElmJson)
|
|
|
|
in
|
|
|
|
[ """
|
|
|
|
module Exposed exposing (toString)
|
|
|
|
import ExposedMood
|
|
|
|
toString : ExposedMood.Happiness -> String
|
|
|
|
toString happiness = "Happy"
|
|
|
|
""", """
|
|
|
|
module ExposedMood exposing (Happiness)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
""" ]
|
|
|
|
|> Review.Test.runOnModulesWithProjectData project rule
|
|
|
|
|> Review.Test.expectNoErrors
|
|
|
|
, test "reports an exposed function using an internal type from an aliased module" <|
|
|
|
|
\() ->
|
|
|
|
let
|
|
|
|
project : Project
|
|
|
|
project =
|
|
|
|
Project.new
|
|
|
|
|> Project.addElmJson (createElmJson packageElmJson)
|
|
|
|
in
|
|
|
|
[ """
|
|
|
|
module Exposed exposing (toString)
|
|
|
|
import Mood as M
|
|
|
|
toString : M.Happiness -> String
|
|
|
|
toString happiness = "Happy"
|
|
|
|
""", """
|
|
|
|
module Mood exposing (Happiness)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
""" ]
|
|
|
|
|> Review.Test.runOnModulesWithProjectData project rule
|
|
|
|
|> Review.Test.expectErrorsForModules
|
|
|
|
[ ( "Exposed"
|
|
|
|
, [ Review.Test.error
|
2021-08-19 21:50:50 +03:00
|
|
|
{ message = "Private type `Mood.Happiness` should be exposed"
|
2020-08-09 19:55:15 +03:00
|
|
|
, details = details
|
|
|
|
, under = "M.Happiness"
|
|
|
|
}
|
|
|
|
]
|
|
|
|
)
|
|
|
|
]
|
|
|
|
, test "reports an exposed function using an exposed type from an aliased module" <|
|
|
|
|
\() ->
|
|
|
|
let
|
|
|
|
project : Project
|
|
|
|
project =
|
|
|
|
Project.new
|
|
|
|
|> Project.addElmJson (createElmJson packageElmJson)
|
|
|
|
in
|
|
|
|
[ """
|
|
|
|
module Exposed exposing (toString)
|
|
|
|
import ExposedMood as M
|
|
|
|
toString : M.Happiness -> String
|
|
|
|
toString happiness = "Happy"
|
|
|
|
""", """
|
|
|
|
module ExposedMood exposing (Happiness)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
""" ]
|
|
|
|
|> Review.Test.runOnModulesWithProjectData project rule
|
|
|
|
|> Review.Test.expectNoErrors
|
|
|
|
, test "reports an exposed function using an internal type imported from a module" <|
|
|
|
|
\() ->
|
|
|
|
let
|
|
|
|
project : Project
|
|
|
|
project =
|
|
|
|
Project.new
|
|
|
|
|> Project.addElmJson (createElmJson packageElmJson)
|
|
|
|
in
|
|
|
|
[ """
|
|
|
|
module Exposed exposing (toString)
|
|
|
|
import Mood exposing (Happiness)
|
|
|
|
toString : Happiness -> String
|
|
|
|
toString happiness = "Happy"
|
|
|
|
""", """
|
|
|
|
module Mood exposing (Happiness)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
""" ]
|
|
|
|
|> Review.Test.runOnModulesWithProjectData project rule
|
|
|
|
|> Review.Test.expectErrorsForModules
|
|
|
|
[ ( "Exposed"
|
|
|
|
, [ Review.Test.error
|
|
|
|
{ message = "Private type `Mood.Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Happiness"
|
|
|
|
}
|
|
|
|
|> Review.Test.atExactly { start = { row = 4, column = 12 }, end = { row = 4, column = 21 } }
|
|
|
|
]
|
|
|
|
)
|
|
|
|
]
|
|
|
|
, test "reports an exposed function using an internal type imported exposing all" <|
|
|
|
|
\() ->
|
|
|
|
let
|
|
|
|
project : Project
|
|
|
|
project =
|
|
|
|
Project.new
|
|
|
|
|> Project.addElmJson (createElmJson packageElmJson)
|
|
|
|
in
|
|
|
|
[ """
|
|
|
|
module Exposed exposing (toRating)
|
|
|
|
import Mood exposing (..)
|
|
|
|
import Rating exposing (..)
|
|
|
|
toRating : Happiness -> Rating
|
|
|
|
toRating happiness = Rating.five
|
|
|
|
""", """
|
|
|
|
module Mood exposing (Happiness)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
""", """
|
|
|
|
module Rating exposing (Rating, five)
|
|
|
|
type Rating = Rating Int
|
|
|
|
five : Rating
|
|
|
|
five = Rating 5
|
|
|
|
""" ]
|
|
|
|
|> Review.Test.runOnModulesWithProjectData project rule
|
|
|
|
|> Review.Test.expectErrorsForModules
|
|
|
|
[ ( "Exposed"
|
|
|
|
, [ Review.Test.error
|
|
|
|
{ message = "Private type `Mood.Happiness` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Happiness"
|
|
|
|
}
|
|
|
|
, Review.Test.error
|
|
|
|
{ message = "Private type `Rating.Rating` should be exposed"
|
|
|
|
, details = details
|
|
|
|
, under = "Rating"
|
|
|
|
}
|
|
|
|
|> Review.Test.atExactly { start = { row = 5, column = 25 }, end = { row = 5, column = 31 } }
|
|
|
|
]
|
|
|
|
)
|
|
|
|
]
|
|
|
|
, test "does not report an internal function using a type from another internal module" <|
|
|
|
|
\() ->
|
|
|
|
let
|
|
|
|
project : Project
|
|
|
|
project =
|
|
|
|
Project.new
|
|
|
|
|> Project.addElmJson (createElmJson packageElmJson)
|
|
|
|
in
|
|
|
|
[ """
|
|
|
|
module Mood exposing (Happiness, toRating)
|
|
|
|
import Rating exposing (Rating)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
toRating : Happiness -> Rating
|
|
|
|
toRating happiness = Rating.five
|
|
|
|
""", """
|
|
|
|
module Rating exposing (Rating, five)
|
|
|
|
type Rating = Rating Int
|
|
|
|
five : Rating
|
|
|
|
five = Rating 5
|
|
|
|
""" ]
|
|
|
|
|> Review.Test.runOnModulesWithProjectData project rule
|
|
|
|
|> Review.Test.expectNoErrors
|
|
|
|
, test "does not report an exposed function using an exposed imported type" <|
|
|
|
|
\() ->
|
|
|
|
let
|
|
|
|
project : Project
|
|
|
|
project =
|
|
|
|
Project.new
|
|
|
|
|> Project.addElmJson (createElmJson packageElmJson)
|
|
|
|
in
|
|
|
|
[ """
|
|
|
|
module Exposed exposing (toString)
|
|
|
|
import ExposedMood exposing (Happiness)
|
|
|
|
toString : Happiness -> String
|
|
|
|
toString happiness = "Happy"
|
|
|
|
""", """
|
|
|
|
module ExposedMood exposing (Happiness)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
""" ]
|
|
|
|
|> Review.Test.runOnModulesWithProjectData project rule
|
|
|
|
|> Review.Test.expectNoErrors
|
|
|
|
, test "does not report an exposed function using an exposed type imported all" <|
|
|
|
|
\() ->
|
|
|
|
let
|
|
|
|
project : Project
|
|
|
|
project =
|
|
|
|
Project.new
|
|
|
|
|> Project.addElmJson (createElmJson packageElmJson)
|
|
|
|
in
|
|
|
|
[ """
|
|
|
|
module Exposed exposing (toString)
|
|
|
|
import ExposedMood exposing (..)
|
|
|
|
toString : Happiness -> String
|
|
|
|
toString happiness = "Happy"
|
|
|
|
""", """
|
|
|
|
module ExposedMood exposing (Happiness)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
""" ]
|
|
|
|
|> Review.Test.runOnModulesWithProjectData project rule
|
|
|
|
|> Review.Test.expectNoErrors
|
|
|
|
, test "does not report an exposed function using an type exposed all and imported all" <|
|
|
|
|
\() ->
|
|
|
|
let
|
|
|
|
project : Project
|
|
|
|
project =
|
|
|
|
Project.new
|
|
|
|
|> Project.addElmJson (createElmJson packageElmJson)
|
|
|
|
in
|
|
|
|
[ """
|
|
|
|
module Exposed exposing (toString)
|
|
|
|
import ExposedMood exposing (..)
|
|
|
|
toString : Happiness -> String
|
|
|
|
toString happiness = "Happy"
|
|
|
|
""", """
|
|
|
|
module ExposedMood exposing (..)
|
|
|
|
type Happiness = Ecstatic
|
|
|
|
""" ]
|
|
|
|
|> Review.Test.runOnModulesWithProjectData project rule
|
|
|
|
|> Review.Test.expectNoErrors
|
|
|
|
, test "does not report an exposed function using a dependency's type" <|
|
|
|
|
\() ->
|
|
|
|
let
|
|
|
|
project : Project
|
|
|
|
project =
|
|
|
|
Project.new
|
|
|
|
|> Project.addElmJson (createElmJson packageElmJson)
|
|
|
|
|> Project.addDependency dependency
|
|
|
|
in
|
|
|
|
"""
|
|
|
|
module Exposed exposing (toString)
|
|
|
|
import ExternalMood exposing (Happiness)
|
|
|
|
toString : Happiness -> String
|
|
|
|
toString happiness = "Happy"
|
|
|
|
"""
|
|
|
|
|> Review.Test.runWithProjectData project rule
|
|
|
|
|> Review.Test.expectNoErrors
|
|
|
|
, test "does not report an exposed function using a dependency's type exposing all" <|
|
|
|
|
\() ->
|
|
|
|
let
|
|
|
|
project : Project
|
|
|
|
project =
|
|
|
|
Project.new
|
|
|
|
|> Project.addElmJson (createElmJson packageElmJson)
|
|
|
|
|> Project.addDependency dependency
|
|
|
|
in
|
|
|
|
"""
|
|
|
|
module Exposed exposing (toString)
|
|
|
|
import ExternalMood exposing (..)
|
|
|
|
toString : Happiness -> String
|
|
|
|
toString happiness = "Happy"
|
|
|
|
"""
|
|
|
|
|> Review.Test.runWithProjectData project rule
|
|
|
|
|> Review.Test.expectNoErrors
|
|
|
|
, test "does not report an exposed function importing a dependency's type" <|
|
|
|
|
\() ->
|
|
|
|
let
|
|
|
|
project : Project
|
|
|
|
project =
|
|
|
|
Project.new
|
|
|
|
|> Project.addElmJson (createElmJson packageElmJson)
|
|
|
|
|> Project.addDependency dependency
|
|
|
|
in
|
|
|
|
"""
|
|
|
|
module Exposed exposing (toString)
|
|
|
|
import ExternalMood
|
|
|
|
toString : ExternalMood.Happiness -> String
|
|
|
|
toString happiness = "Happy"
|
|
|
|
"""
|
|
|
|
|> Review.Test.runWithProjectData project rule
|
|
|
|
|> Review.Test.expectNoErrors
|
|
|
|
, test "does not report an exposed function importing a dependency's type with alias" <|
|
|
|
|
\() ->
|
|
|
|
let
|
|
|
|
project : Project
|
|
|
|
project =
|
|
|
|
Project.new
|
|
|
|
|> Project.addElmJson (createElmJson packageElmJson)
|
|
|
|
|> Project.addDependency dependency
|
|
|
|
in
|
|
|
|
"""
|
|
|
|
module Exposed exposing (toString)
|
|
|
|
import ExternalMood as M
|
|
|
|
toString : M.Happiness -> String
|
|
|
|
toString happiness = "Happy"
|
|
|
|
"""
|
|
|
|
|> Review.Test.runWithProjectData project rule
|
|
|
|
|> Review.Test.expectNoErrors
|
2021-08-19 21:50:50 +03:00
|
|
|
, test "should not be confused about types that are named the same as local types" <|
|
|
|
|
\() ->
|
|
|
|
let
|
|
|
|
project : Project
|
|
|
|
project =
|
|
|
|
Project.new
|
|
|
|
|> Project.addElmJson (createElmJson packageElmJson)
|
|
|
|
|> Project.addDependency dependency
|
|
|
|
in
|
|
|
|
[ """module Exposed exposing (Project, toString)
|
|
|
|
|
|
|
|
import Internal exposing (Project)
|
|
|
|
|
|
|
|
type alias Project =
|
|
|
|
Internal.Project
|
|
|
|
|
|
|
|
toString : Project -> String
|
|
|
|
toString project = ""
|
|
|
|
"""
|
|
|
|
, """module Internal exposing (Project)
|
|
|
|
type Project = P
|
|
|
|
"""
|
|
|
|
]
|
|
|
|
|> Review.Test.runOnModulesWithProjectData project rule
|
|
|
|
|> Review.Test.expectNoErrors
|
2020-08-09 19:55:15 +03:00
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
createElmJson : String -> { path : String, raw : String, project : Elm.Project.Project }
|
|
|
|
createElmJson rawElmJson =
|
|
|
|
{ path = "elm.json"
|
|
|
|
, raw = rawElmJson
|
|
|
|
, project = createElmJsonProject rawElmJson
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
createElmJsonProject : String -> Elm.Project.Project
|
|
|
|
createElmJsonProject rawElmJson =
|
|
|
|
case Decode.decodeString Elm.Project.decoder rawElmJson of
|
|
|
|
Ok project ->
|
|
|
|
project
|
|
|
|
|
|
|
|
Err error ->
|
|
|
|
Debug.todo ("[elm.json]: " ++ Debug.toString error)
|
|
|
|
|
|
|
|
|
|
|
|
packageElmJson : String
|
|
|
|
packageElmJson =
|
|
|
|
"""{
|
|
|
|
"type": "package",
|
2020-09-22 20:40:30 +03:00
|
|
|
"name": "jfmengels/elm-review-common-tests",
|
2020-08-09 19:55:15 +03:00
|
|
|
"summary": "A test package",
|
|
|
|
"license": "MIT",
|
|
|
|
"version": "1.0.0",
|
|
|
|
"exposed-modules": [
|
|
|
|
"Exposed",
|
|
|
|
"ExposedMood"
|
|
|
|
],
|
|
|
|
"elm-version": "0.19.0 <= v < 0.20.0",
|
|
|
|
"dependencies": {
|
|
|
|
"elm/core": "1.0.2 <= v < 2.0.0"
|
|
|
|
},
|
|
|
|
"test-dependencies": {}
|
|
|
|
}"""
|
|
|
|
|
|
|
|
|
|
|
|
dependency : Dependency
|
|
|
|
dependency =
|
|
|
|
Dependency.create
|
|
|
|
"sparksp/external-mood"
|
|
|
|
(createElmJsonProject dependencyElmJson)
|
|
|
|
dependencyModules
|
|
|
|
|
|
|
|
|
|
|
|
dependencyModules : List Elm.Docs.Module
|
|
|
|
dependencyModules =
|
|
|
|
[ { name = "ExternalMood"
|
|
|
|
, comment = ""
|
|
|
|
, unions =
|
|
|
|
[ { name = "Happiness"
|
|
|
|
, comment = ""
|
|
|
|
, args = []
|
|
|
|
, tags =
|
|
|
|
[ ( "Ecstatic", [] )
|
|
|
|
, ( "FineIGuess", [] )
|
|
|
|
, ( "Unhappy", [] )
|
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
, aliases = []
|
|
|
|
, values = []
|
|
|
|
, binops = []
|
|
|
|
}
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
dependencyElmJson : String
|
|
|
|
dependencyElmJson =
|
|
|
|
"""{
|
|
|
|
"type": "package",
|
|
|
|
"name": "sparksp/external-mood",
|
|
|
|
"summary": "Moods for tests",
|
|
|
|
"license": "MIT",
|
|
|
|
"version": "1.0.0",
|
|
|
|
"exposed-modules": [
|
|
|
|
"ExternalMood"
|
|
|
|
],
|
|
|
|
"elm-version": "0.19.0 <= v <= 0.20.0",
|
|
|
|
"dependencies": {},
|
|
|
|
"test-dependencies": {}
|
|
|
|
}"""
|