Sparkle is a library that leverages the power of PureScripts type system to automatically create user interfaces based on type signatures.
The internal mechanism of this library is similar to QuickCheck. However, instead of using randomly generated input data, Sparkle creates reactive web interfaces for "interactive testing". It uses the Flare library to create those widgets.
Examples
To demonstrate the basic functionality of Sparkle, consider these functions from the standard libraries:
1 length :: String -> Int 2 charCodeAt :: Int -> String -> Maybe Int 3 joinWith :: String -> Array String -> String 1 partition :: ∀ a. (a -> Boolean) -> Array a -> { yes :: Array a 2 , no :: Array a }
To create the interactive user interfaces, the only thing we have to do is to call "sparkle
":
1 module Test.Main where 2 3 import Prelude 4 5 import Data.Array (partition) 6 import Data.Int (even) 8 import Data.String (length, charCodeAt, joinWith) 9 10 import Sparkle 11 12 main = do 13 sparkle "length" length 14 sparkle "charCodeAt" charCodeAt 15 sparkle "joinWith" joinWith 16 sparkle "partition even" (partition even)
This creates the following widgets for us:
Notice how the type signatures are used to automatically create appropriate input fields forString
, Int
, Array String
as well as Array Int
. The type signature
of the return types is used for syntax highlighting (and for generating
mouse-over hints).
Interactive documentation
Sparkle widgets can be useful when writing module documentations. Suppose we have a functionmixHSL :: Color -> Color -> Number -> Colorthat we want to document. Sparkle already has support for the
Color
type, but a general-purpose Number
input would not be very helpful, as the value should be in the interval [0, 1]. Sparkle provides a newtype SmallNumber
that limits
the values to this interval (and changes the input to a slider). Using this
trick, we can auto-generate the following widget:
For a full interactive documentation page, see these examples.
Sparkle test cases
The following widgets are interactive tests for Sparkle itself. The first few tests show the identity functionid
with monomorphized type annotations, for example id :: Int -> Int
or id :: Tuple Int String -> Tuple Int String
.
Later tests showcase some complex output types.
Custom input fields
What if you want to test your own library with custom data types? Suppose we want to create a test for the following function fromData.String.Regex
:
1 match :: Regex -> String -> Maybe (Array (Maybe String))Sparkle provides the type class
Flammable
(analogous to QuickChecks Arbitrary
):
1 class Flammable a where 2 spark :: ∀ e. UI e aInstances must provide a way to create a Flare user interface (
UI
) which holds a value of type a
.To avoid orphan instances, we create a newtype wrapper and write a
Flammable
instance for the newtype:
1 newtype TRegex = TRegex Regex 2 3 instance flammableTRegex :: Flammable TRegex where 4 spark = fieldset "Regex" $ TRegex <$> 5 (regex <$> string "Pattern" "fo+" 6 <*> (parseFlags <$> string "Flags (g,i,m)" "g"))Then, we can use "
sparkle
" as before:
1 sparkle "match" $ \(TRegex regex) string -> match regex stringto create the following interactive test: