commit
cee2b3a5bb
2
elm.json
2
elm.json
|
@ -6,6 +6,7 @@
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"exposed-modules": [
|
"exposed-modules": [
|
||||||
"Matrix",
|
"Matrix",
|
||||||
|
"Matrix.Event",
|
||||||
"Matrix.Settings",
|
"Matrix.Settings",
|
||||||
"Internal.Config.Default",
|
"Internal.Config.Default",
|
||||||
"Internal.Config.Leaks",
|
"Internal.Config.Leaks",
|
||||||
|
@ -19,6 +20,7 @@
|
||||||
"Internal.Values.Context",
|
"Internal.Values.Context",
|
||||||
"Internal.Values.Envelope",
|
"Internal.Values.Envelope",
|
||||||
"Internal.Values.Event",
|
"Internal.Values.Event",
|
||||||
|
"Internal.Values.Settings",
|
||||||
"Internal.Values.Vault",
|
"Internal.Values.Vault",
|
||||||
"Types"
|
"Types"
|
||||||
],
|
],
|
||||||
|
|
|
@ -46,6 +46,7 @@ import Internal.Config.Default as Default
|
||||||
import Internal.Tools.Decode as D
|
import Internal.Tools.Decode as D
|
||||||
import Internal.Tools.Encode as E
|
import Internal.Tools.Encode as E
|
||||||
import Internal.Values.Context as Context exposing (Context)
|
import Internal.Values.Context as Context exposing (Context)
|
||||||
|
import Internal.Values.Settings as Settings
|
||||||
import Json.Decode as D
|
import Json.Decode as D
|
||||||
import Json.Encode as E
|
import Json.Encode as E
|
||||||
|
|
||||||
|
@ -55,26 +56,19 @@ need the same values. The Envelope type wraps settings, tokens and values around
|
||||||
each data type so they can all enjoy those values without needing to explicitly
|
each data type so they can all enjoy those values without needing to explicitly
|
||||||
define them in their type.
|
define them in their type.
|
||||||
-}
|
-}
|
||||||
type Envelope a
|
type alias Envelope a =
|
||||||
= Envelope
|
|
||||||
{ content : a
|
{ content : a
|
||||||
, context : Context
|
, context : Context
|
||||||
, settings : Settings
|
, settings : Settings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
{-| Custom settings that can be manipulated by the user. These serve as a
|
{-| Settings value from
|
||||||
configuration for how the Elm SDK should behave.
|
[Internal.Values.Settings](Internal-Values-Settings#Settings). Can be used to
|
||||||
|
manipulate the Matrix Vault.
|
||||||
Custom settings are always part of the Envelope, allowing all functions to
|
|
||||||
behave under the user's preferred settings.
|
|
||||||
|
|
||||||
-}
|
-}
|
||||||
type alias Settings =
|
type alias Settings =
|
||||||
{ currentVersion : String
|
Settings.Settings
|
||||||
, deviceName : String
|
|
||||||
, syncTime : Int
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
{-| Decode an enveloped type from a JSON value. The decoder also imports any
|
{-| Decode an enveloped type from a JSON value. The decoder also imports any
|
||||||
|
@ -82,67 +76,25 @@ potential tokens, values and settings included in the JSON.
|
||||||
-}
|
-}
|
||||||
decoder : D.Decoder a -> D.Decoder (Envelope a)
|
decoder : D.Decoder a -> D.Decoder (Envelope a)
|
||||||
decoder xDecoder =
|
decoder xDecoder =
|
||||||
D.map3 (\a b c -> Envelope { content = a, context = b, settings = c })
|
D.map3 Envelope
|
||||||
(D.field "content" xDecoder)
|
(D.field "content" xDecoder)
|
||||||
(D.field "context" Context.decoder)
|
(D.field "context" Context.decoder)
|
||||||
(D.field "settings" decoderSettings)
|
(D.field "settings" Settings.decoder)
|
||||||
|
|
||||||
|
|
||||||
{-| Decode settings from a JSON value.
|
|
||||||
-}
|
|
||||||
decoderSettings : D.Decoder Settings
|
|
||||||
decoderSettings =
|
|
||||||
D.map3 Settings
|
|
||||||
(D.opFieldWithDefault "currentVersion" Default.currentVersion D.string)
|
|
||||||
(D.opFieldWithDefault "deviceName" Default.deviceName D.string)
|
|
||||||
(D.opFieldWithDefault "syncTime" Default.syncTime D.int)
|
|
||||||
|
|
||||||
|
|
||||||
{-| Encode an enveloped type into a JSON value. The function encodes all
|
{-| Encode an enveloped type into a JSON value. The function encodes all
|
||||||
non-standard settings, tokens and values.
|
non-standard settings, tokens and values.
|
||||||
-}
|
-}
|
||||||
encode : (a -> E.Value) -> Envelope a -> E.Value
|
encode : (a -> E.Value) -> Envelope a -> E.Value
|
||||||
encode encodeX (Envelope data) =
|
encode encodeX data =
|
||||||
E.object
|
E.object
|
||||||
[ ( "content", encodeX data.content )
|
[ ( "content", encodeX data.content )
|
||||||
, ( "context", Context.encode data.context )
|
, ( "context", Context.encode data.context )
|
||||||
, ( "settings", encodeSettings data.settings )
|
, ( "settings", Settings.encode data.settings )
|
||||||
, ( "version", E.string Default.currentVersion )
|
, ( "version", E.string Default.currentVersion )
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
{-| Encode the settings into a JSON value.
|
|
||||||
-}
|
|
||||||
encodeSettings : Settings -> E.Value
|
|
||||||
encodeSettings settings =
|
|
||||||
let
|
|
||||||
differentFrom : b -> b -> Maybe b
|
|
||||||
differentFrom defaultValue currentValue =
|
|
||||||
if currentValue == defaultValue then
|
|
||||||
Nothing
|
|
||||||
|
|
||||||
else
|
|
||||||
Just currentValue
|
|
||||||
in
|
|
||||||
E.maybeObject
|
|
||||||
[ ( "currentVersion"
|
|
||||||
, settings.currentVersion
|
|
||||||
|> differentFrom Default.currentVersion
|
|
||||||
|> Maybe.map E.string
|
|
||||||
)
|
|
||||||
, ( "deviceName"
|
|
||||||
, settings.deviceName
|
|
||||||
|> differentFrom Default.deviceName
|
|
||||||
|> Maybe.map E.string
|
|
||||||
)
|
|
||||||
, ( "syncTime"
|
|
||||||
, settings.syncTime
|
|
||||||
|> differentFrom Default.syncTime
|
|
||||||
|> Maybe.map E.int
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
{-| Map a function, then get its content. This is useful for getting information
|
{-| Map a function, then get its content. This is useful for getting information
|
||||||
from a data type inside an Envelope.
|
from a data type inside an Envelope.
|
||||||
|
|
||||||
|
@ -155,7 +107,7 @@ from a data type inside an Envelope.
|
||||||
|
|
||||||
-}
|
-}
|
||||||
extract : (a -> b) -> Envelope a -> b
|
extract : (a -> b) -> Envelope a -> b
|
||||||
extract f (Envelope data) =
|
extract f data =
|
||||||
f data.content
|
f data.content
|
||||||
|
|
||||||
|
|
||||||
|
@ -165,7 +117,7 @@ This can be helpful if you have a UI that displays custom settings to a user.
|
||||||
|
|
||||||
-}
|
-}
|
||||||
extractSettings : (Settings -> b) -> Envelope a -> b
|
extractSettings : (Settings -> b) -> Envelope a -> b
|
||||||
extractSettings f (Envelope data) =
|
extractSettings f data =
|
||||||
f data.settings
|
f data.settings
|
||||||
|
|
||||||
|
|
||||||
|
@ -186,14 +138,9 @@ from the [Internal.Config.Default](Internal-Config-Default) module.
|
||||||
-}
|
-}
|
||||||
init : a -> Envelope a
|
init : a -> Envelope a
|
||||||
init x =
|
init x =
|
||||||
Envelope
|
|
||||||
{ content = x
|
{ content = x
|
||||||
, context = Context.init
|
, context = Context.init
|
||||||
, settings =
|
, settings = Settings.init
|
||||||
{ currentVersion = Default.currentVersion
|
|
||||||
, deviceName = Default.deviceName
|
|
||||||
, syncTime = Default.syncTime
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -208,8 +155,7 @@ init x =
|
||||||
|
|
||||||
-}
|
-}
|
||||||
map : (a -> b) -> Envelope a -> Envelope b
|
map : (a -> b) -> Envelope a -> Envelope b
|
||||||
map f (Envelope data) =
|
map f data =
|
||||||
Envelope
|
|
||||||
{ content = f data.content
|
{ content = f data.content
|
||||||
, context = data.context
|
, context = data.context
|
||||||
, settings = data.settings
|
, settings = data.settings
|
||||||
|
@ -219,12 +165,8 @@ map f (Envelope data) =
|
||||||
{-| Update the Context in the Envelope.
|
{-| Update the Context in the Envelope.
|
||||||
-}
|
-}
|
||||||
mapContext : (Context -> Context) -> Envelope a -> Envelope a
|
mapContext : (Context -> Context) -> Envelope a -> Envelope a
|
||||||
mapContext f (Envelope data) =
|
mapContext f data =
|
||||||
Envelope
|
{ data | context = f data.context }
|
||||||
{ content = data.content
|
|
||||||
, context = f data.context
|
|
||||||
, settings = data.settings
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
{-| Map the contents of a function, where the result is wrapped in a `List`
|
{-| Map the contents of a function, where the result is wrapped in a `List`
|
||||||
|
@ -279,23 +221,19 @@ mapMaybe f =
|
||||||
|
|
||||||
-}
|
-}
|
||||||
mapSettings : (Settings -> Settings) -> Envelope a -> Envelope a
|
mapSettings : (Settings -> Settings) -> Envelope a -> Envelope a
|
||||||
mapSettings f (Envelope data) =
|
mapSettings f data =
|
||||||
Envelope
|
{ data | settings = f data.settings }
|
||||||
{ content = data.content
|
|
||||||
, context = data.context
|
|
||||||
, settings = f data.settings
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
toList : Envelope (List a) -> List (Envelope a)
|
toList : Envelope (List a) -> List (Envelope a)
|
||||||
toList (Envelope data) =
|
toList data =
|
||||||
List.map
|
List.map
|
||||||
(\content -> map (always content) (Envelope data))
|
(\content -> map (always content) data)
|
||||||
data.content
|
data.content
|
||||||
|
|
||||||
|
|
||||||
toMaybe : Envelope (Maybe a) -> Maybe (Envelope a)
|
toMaybe : Envelope (Maybe a) -> Maybe (Envelope a)
|
||||||
toMaybe (Envelope data) =
|
toMaybe data =
|
||||||
Maybe.map
|
Maybe.map
|
||||||
(\content -> map (always content) (Envelope data))
|
(\content -> map (always content) data)
|
||||||
data.content
|
data.content
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module Internal.Values.Event exposing
|
module Internal.Values.Event exposing
|
||||||
( Event
|
( Event
|
||||||
, UnsignedData, age, prevContent, redactedBecause, transactionId
|
, UnsignedData(..), age, prevContent, redactedBecause, transactionId
|
||||||
, encode, decoder
|
, encode, decoder
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -122,7 +122,9 @@ encodeUnsignedData (UnsignedData data) =
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
{-| Get the old content, if the event has changed or it has been edited.
|
{-| Determine the previous `content` value for this event. This field is only a
|
||||||
|
`Just value` if the event is a state event, and the Matrix Vault has permission
|
||||||
|
to see the previous content.
|
||||||
-}
|
-}
|
||||||
prevContent : Event -> Maybe E.Value
|
prevContent : Event -> Maybe E.Value
|
||||||
prevContent event =
|
prevContent event =
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
module Internal.Values.Settings exposing
|
||||||
|
( Settings, init
|
||||||
|
, encode, decoder
|
||||||
|
)
|
||||||
|
|
||||||
|
{-|
|
||||||
|
|
||||||
|
|
||||||
|
# Settings
|
||||||
|
|
||||||
|
The Settings module exposes a data type to configure settings in the enveloped
|
||||||
|
data types.
|
||||||
|
|
||||||
|
@docs Settings, init
|
||||||
|
|
||||||
|
|
||||||
|
## JSON coders
|
||||||
|
|
||||||
|
@docs encode, decoder
|
||||||
|
|
||||||
|
-}
|
||||||
|
|
||||||
|
import Internal.Config.Default as Default
|
||||||
|
import Internal.Tools.Decode as D
|
||||||
|
import Internal.Tools.Encode as E
|
||||||
|
import Json.Decode as D
|
||||||
|
import Json.Encode as E
|
||||||
|
|
||||||
|
|
||||||
|
{-| Custom settings that can be manipulated by the user. These serve as a
|
||||||
|
configuration for how the Elm SDK should behave.
|
||||||
|
|
||||||
|
Custom settings are always part of the Envelope, allowing all functions to
|
||||||
|
behave under the user's preferred settings.
|
||||||
|
|
||||||
|
-}
|
||||||
|
type alias Settings =
|
||||||
|
{ currentVersion : String
|
||||||
|
, deviceName : String
|
||||||
|
, syncTime : Int
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{-| Decode settings from a JSON value.
|
||||||
|
-}
|
||||||
|
decoder : D.Decoder Settings
|
||||||
|
decoder =
|
||||||
|
D.map3 Settings
|
||||||
|
(D.opFieldWithDefault "currentVersion" Default.currentVersion D.string)
|
||||||
|
(D.opFieldWithDefault "deviceName" Default.deviceName D.string)
|
||||||
|
(D.opFieldWithDefault "syncTime" Default.syncTime D.int)
|
||||||
|
|
||||||
|
|
||||||
|
{-| Encode the settings into a JSON value.
|
||||||
|
-}
|
||||||
|
encode : Settings -> E.Value
|
||||||
|
encode settings =
|
||||||
|
let
|
||||||
|
differentFrom : b -> b -> Maybe b
|
||||||
|
differentFrom defaultValue currentValue =
|
||||||
|
if currentValue == defaultValue then
|
||||||
|
Nothing
|
||||||
|
|
||||||
|
else
|
||||||
|
Just currentValue
|
||||||
|
in
|
||||||
|
E.maybeObject
|
||||||
|
[ ( "currentVersion"
|
||||||
|
, settings.currentVersion
|
||||||
|
|> differentFrom Default.currentVersion
|
||||||
|
|> Maybe.map E.string
|
||||||
|
)
|
||||||
|
, ( "deviceName"
|
||||||
|
, settings.deviceName
|
||||||
|
|> differentFrom Default.deviceName
|
||||||
|
|> Maybe.map E.string
|
||||||
|
)
|
||||||
|
, ( "syncTime"
|
||||||
|
, settings.syncTime
|
||||||
|
|> differentFrom Default.syncTime
|
||||||
|
|> Maybe.map E.int
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
{-| Create a new Settings module based on default values
|
||||||
|
-}
|
||||||
|
init : Settings
|
||||||
|
init =
|
||||||
|
{ currentVersion = Default.currentVersion
|
||||||
|
, deviceName = Default.deviceName
|
||||||
|
, syncTime = Default.syncTime
|
||||||
|
}
|
|
@ -6,10 +6,8 @@ module Internal.Values.Vault exposing (Vault)
|
||||||
|
|
||||||
-}
|
-}
|
||||||
|
|
||||||
import Internal.Values.Envelope as Envelope
|
|
||||||
|
|
||||||
|
|
||||||
{-| This is the Vault type.
|
{-| This is the Vault type.
|
||||||
-}
|
-}
|
||||||
type alias Vault =
|
type alias Vault =
|
||||||
Envelope.Envelope {}
|
()
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
module Matrix.Event exposing
|
||||||
|
( Event, content, eventType, stateKey
|
||||||
|
, eventId, roomId, sender, originServerTs
|
||||||
|
, previousContent, redactedBecause
|
||||||
|
)
|
||||||
|
|
||||||
|
{-|
|
||||||
|
|
||||||
|
|
||||||
|
# Matrix Events
|
||||||
|
|
||||||
|
This module contains all the functions necessary to view and manipulate Matrix
|
||||||
|
events.
|
||||||
|
|
||||||
|
|
||||||
|
## Event
|
||||||
|
|
||||||
|
@docs Event, content, eventType, stateKey
|
||||||
|
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
|
||||||
|
@docs eventId, roomId, sender, originServerTs
|
||||||
|
|
||||||
|
|
||||||
|
## Optional data
|
||||||
|
|
||||||
|
Occasionally, the Event might bring some extra information. Given how this
|
||||||
|
information isn't always applicable, it doesn't always exist.
|
||||||
|
|
||||||
|
@docs previousContent, redactedBecause
|
||||||
|
|
||||||
|
-}
|
||||||
|
|
||||||
|
import Internal.Values.Envelope as Envelope
|
||||||
|
import Internal.Values.Event as Internal
|
||||||
|
import Json.Encode
|
||||||
|
import Time
|
||||||
|
import Types exposing (Event(..))
|
||||||
|
|
||||||
|
|
||||||
|
{-| In Matrix, the primary form of communication is to send JSON values to one
|
||||||
|
another. These JSON values, together with their metadata, are bundled into Event
|
||||||
|
types. They contain information like:
|
||||||
|
|
||||||
|
- Who sent the JSON value
|
||||||
|
- How they intend you to decode it
|
||||||
|
- When they sent it
|
||||||
|
- In what room they sent it
|
||||||
|
|
||||||
|
-}
|
||||||
|
type alias Event =
|
||||||
|
Types.Event
|
||||||
|
|
||||||
|
|
||||||
|
{-| Receive the body of an Event, as created by the user that sent it.
|
||||||
|
-}
|
||||||
|
content : Event -> Json.Encode.Value
|
||||||
|
content (Event event) =
|
||||||
|
Envelope.extract .content event
|
||||||
|
|
||||||
|
|
||||||
|
{-| Determine the globally unique identifier for an event.
|
||||||
|
-}
|
||||||
|
eventId : Event -> String
|
||||||
|
eventId (Event event) =
|
||||||
|
Envelope.extract .eventId event
|
||||||
|
|
||||||
|
|
||||||
|
{-| To give a hint what the event's [content](#content) might look like, users
|
||||||
|
can use this eventType value to hint at how the JSON might be decoded.
|
||||||
|
|
||||||
|
Standard examples of event types are `m.room.message`, `m.room.member` and
|
||||||
|
`me.noordstar.game.chess.move`.
|
||||||
|
|
||||||
|
-}
|
||||||
|
eventType : Event -> String
|
||||||
|
eventType (Event event) =
|
||||||
|
Envelope.extract .eventType event
|
||||||
|
|
||||||
|
|
||||||
|
{-| Determine the timestamp of at what time the event was originally received by
|
||||||
|
the original homeserver.
|
||||||
|
|
||||||
|
Generally, this timestamp offers a relatively accurate indicator of when a
|
||||||
|
message was sent. However, this number isn't completely reliable! The timestamp
|
||||||
|
can be far in the past due to long network lag, and a (malicious) homeserver can
|
||||||
|
spoof this number to make it seem like something was sent ridiculously far in
|
||||||
|
the past - or even in the future.
|
||||||
|
|
||||||
|
-}
|
||||||
|
originServerTs : Event -> Time.Posix
|
||||||
|
originServerTs (Event event) =
|
||||||
|
Envelope.extract .originServerTs event
|
||||||
|
|
||||||
|
|
||||||
|
{-| Determine the previous `content` value for this event. This field is only a
|
||||||
|
`Just value` if the event is a state event, and the Matrix Vault has permission
|
||||||
|
to see the previous content.
|
||||||
|
-}
|
||||||
|
previousContent : Event -> Maybe Json.Encode.Value
|
||||||
|
previousContent (Event event) =
|
||||||
|
Envelope.extract Internal.prevContent event
|
||||||
|
|
||||||
|
|
||||||
|
{-| If the event has been redacted, the homeserver can display the event that
|
||||||
|
redacted it here.
|
||||||
|
-}
|
||||||
|
redactedBecause : Event -> Maybe Event
|
||||||
|
redactedBecause (Event event) =
|
||||||
|
Envelope.mapMaybe Internal.redactedBecause event
|
||||||
|
|> Maybe.map Event
|
||||||
|
|
||||||
|
|
||||||
|
{-| Unique id assigned to the Matrix room. You can use this room id to reference
|
||||||
|
or look up rooms.
|
||||||
|
-}
|
||||||
|
roomId : Event -> String
|
||||||
|
roomId (Event event) =
|
||||||
|
Envelope.extract .roomId event
|
||||||
|
|
||||||
|
|
||||||
|
{-| Determine the fully-qualified ID of the user who sent an event.
|
||||||
|
-}
|
||||||
|
sender : Event -> String
|
||||||
|
sender (Event event) =
|
||||||
|
Envelope.extract .sender event
|
||||||
|
|
||||||
|
|
||||||
|
{-| Determine an event's state key.
|
||||||
|
|
||||||
|
It is present if, and only if, the event is a _state_ event. The key makes the
|
||||||
|
piece of state unique in the room. Note that it is often `Just ""`. If it is not
|
||||||
|
present, its value is `Nothing`.
|
||||||
|
|
||||||
|
State keys starting with an `@` are reserved for referencing user IDs, such as
|
||||||
|
room members. With the exception of a few events, state events set with a given
|
||||||
|
user'd ID as the state key can only be set by that user.
|
||||||
|
|
||||||
|
-}
|
||||||
|
stateKey : Event -> Maybe String
|
||||||
|
stateKey (Event event) =
|
||||||
|
Envelope.extract .stateKey event
|
|
@ -1,4 +1,4 @@
|
||||||
module Types exposing (Vault(..))
|
module Types exposing (Vault(..), Event(..))
|
||||||
|
|
||||||
{-| The Elm SDK uses a lot of records and values that are easy to manipulate.
|
{-| The Elm SDK uses a lot of records and values that are easy to manipulate.
|
||||||
Yet, the [Elm design guidelines](https://package.elm-lang.org/help/design-guidelines#keep-tags-and-record-constructors-secret)
|
Yet, the [Elm design guidelines](https://package.elm-lang.org/help/design-guidelines#keep-tags-and-record-constructors-secret)
|
||||||
|
@ -12,14 +12,22 @@ access their content directly.
|
||||||
The opaque types are placed in a central module so all exposed modules can
|
The opaque types are placed in a central module so all exposed modules can
|
||||||
safely access all exposed data types without risking to create circular imports.
|
safely access all exposed data types without risking to create circular imports.
|
||||||
|
|
||||||
@docs Vault
|
@docs Vault, Event
|
||||||
|
|
||||||
-}
|
-}
|
||||||
|
|
||||||
|
import Internal.Values.Envelope as Envelope
|
||||||
|
import Internal.Values.Event as Event
|
||||||
import Internal.Values.Vault as Vault
|
import Internal.Values.Vault as Vault
|
||||||
|
|
||||||
|
|
||||||
|
{-| Opaque type for Matrix Event
|
||||||
|
-}
|
||||||
|
type Event
|
||||||
|
= Event (Envelope.Envelope Event.Event)
|
||||||
|
|
||||||
|
|
||||||
{-| Opaque type for Matrix Vault
|
{-| Opaque type for Matrix Vault
|
||||||
-}
|
-}
|
||||||
type Vault
|
type Vault
|
||||||
= Vault Vault.Vault
|
= Vault (Envelope.Envelope Vault.Vault)
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
module Test.Matrix.Settings exposing (..)
|
||||||
|
|
||||||
|
import Expect
|
||||||
|
import Fuzz
|
||||||
|
import Matrix.Settings
|
||||||
|
import Test exposing (..)
|
||||||
|
import Test.Types as TestTypes
|
||||||
|
|
||||||
|
|
||||||
|
settings : Test
|
||||||
|
settings =
|
||||||
|
describe "Exposed Matrix.Settings"
|
||||||
|
[ describe "Set values"
|
||||||
|
[ fuzz2 TestTypes.vault
|
||||||
|
Fuzz.string
|
||||||
|
"Set device name"
|
||||||
|
(\vault name ->
|
||||||
|
vault
|
||||||
|
|> Matrix.Settings.setDeviceName name
|
||||||
|
|> Matrix.Settings.getDeviceName
|
||||||
|
|> Expect.equal name
|
||||||
|
)
|
||||||
|
, fuzz2 TestTypes.vault
|
||||||
|
Fuzz.int
|
||||||
|
"Set sync time"
|
||||||
|
(\vault sync ->
|
||||||
|
vault
|
||||||
|
|> Matrix.Settings.setSyncTime sync
|
||||||
|
|> Matrix.Settings.getSyncTime
|
||||||
|
|> Expect.equal sync
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
-- , describe "Read values" []
|
||||||
|
]
|
|
@ -1,4 +1,4 @@
|
||||||
module Iddict exposing (..)
|
module Test.Tools.Iddict exposing (..)
|
||||||
|
|
||||||
import Expect
|
import Expect
|
||||||
import Fuzz exposing (Fuzzer)
|
import Fuzz exposing (Fuzzer)
|
|
@ -0,0 +1,66 @@
|
||||||
|
module Test.Tools.Timestamp exposing (..)
|
||||||
|
|
||||||
|
import Expect
|
||||||
|
import Fuzz exposing (Fuzzer)
|
||||||
|
import Internal.Tools.Timestamp as Timestamp exposing (Timestamp)
|
||||||
|
import Json.Decode as D
|
||||||
|
import Json.Encode as E
|
||||||
|
import Test exposing (..)
|
||||||
|
import Time
|
||||||
|
|
||||||
|
|
||||||
|
fuzzer : Fuzzer Timestamp
|
||||||
|
fuzzer =
|
||||||
|
Fuzz.map Time.millisToPosix Fuzz.int
|
||||||
|
|
||||||
|
|
||||||
|
suite : Test
|
||||||
|
suite =
|
||||||
|
describe "Timestamp"
|
||||||
|
[ describe "JSON"
|
||||||
|
[ fuzz2 fuzzer
|
||||||
|
Fuzz.int
|
||||||
|
"JSON encode -> JSON decode"
|
||||||
|
(\time indent ->
|
||||||
|
time
|
||||||
|
|> Timestamp.encode
|
||||||
|
|> E.encode indent
|
||||||
|
|> D.decodeString Timestamp.decoder
|
||||||
|
|> Expect.equal (Ok time)
|
||||||
|
)
|
||||||
|
, fuzz fuzzer
|
||||||
|
"JSON decode -> millis"
|
||||||
|
(\time ->
|
||||||
|
time
|
||||||
|
|> Timestamp.encode
|
||||||
|
|> D.decodeValue D.int
|
||||||
|
|> Expect.equal (Ok <| Time.posixToMillis time)
|
||||||
|
)
|
||||||
|
, fuzz Fuzz.int
|
||||||
|
"JSON decode -> time"
|
||||||
|
(\n ->
|
||||||
|
n
|
||||||
|
|> E.int
|
||||||
|
|> D.decodeValue Timestamp.decoder
|
||||||
|
|> Expect.equal (Ok <| Time.millisToPosix n)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
, describe "Identity"
|
||||||
|
[ fuzz fuzzer
|
||||||
|
"Posix -> int -> Posix"
|
||||||
|
(\time ->
|
||||||
|
time
|
||||||
|
|> Time.posixToMillis
|
||||||
|
|> Time.millisToPosix
|
||||||
|
|> Expect.equal time
|
||||||
|
)
|
||||||
|
, fuzz Fuzz.int
|
||||||
|
"int -> Posix -> int"
|
||||||
|
(\n ->
|
||||||
|
n
|
||||||
|
|> Time.millisToPosix
|
||||||
|
|> Time.posixToMillis
|
||||||
|
|> Expect.equal n
|
||||||
|
)
|
||||||
|
]
|
||||||
|
]
|
|
@ -0,0 +1,17 @@
|
||||||
|
module Test.Types exposing (..)
|
||||||
|
|
||||||
|
import Fuzz exposing (Fuzzer)
|
||||||
|
import Test.Values.Envelope as TestEnvelope
|
||||||
|
import Test.Values.Event as TestEvent
|
||||||
|
import Test.Values.Vault as TestVault
|
||||||
|
import Types exposing (..)
|
||||||
|
|
||||||
|
|
||||||
|
event : Fuzzer Event
|
||||||
|
event =
|
||||||
|
Fuzz.map Event (TestEnvelope.fuzzer TestEvent.fuzzer)
|
||||||
|
|
||||||
|
|
||||||
|
vault : Fuzzer Vault
|
||||||
|
vault =
|
||||||
|
Fuzz.map Vault (TestEnvelope.fuzzer TestVault.vault)
|
|
@ -1,4 +1,4 @@
|
||||||
module Context exposing (..)
|
module Test.Values.Context exposing (..)
|
||||||
|
|
||||||
import Expect
|
import Expect
|
||||||
import Fuzz exposing (Fuzzer)
|
import Fuzz exposing (Fuzzer)
|
|
@ -0,0 +1,65 @@
|
||||||
|
module Test.Values.Envelope exposing (..)
|
||||||
|
|
||||||
|
import Expect
|
||||||
|
import Fuzz exposing (Fuzzer)
|
||||||
|
import Internal.Config.Default as Default
|
||||||
|
import Internal.Values.Envelope as Envelope exposing (Envelope)
|
||||||
|
import Json.Decode as D
|
||||||
|
import Json.Encode as E
|
||||||
|
import Test exposing (..)
|
||||||
|
import Test.Values.Context as TestContext
|
||||||
|
import Test.Values.Settings as TestSettings
|
||||||
|
|
||||||
|
|
||||||
|
fuzzer : Fuzzer a -> Fuzzer (Envelope a)
|
||||||
|
fuzzer fuz =
|
||||||
|
Fuzz.map3 Envelope
|
||||||
|
fuz
|
||||||
|
TestContext.fuzzer
|
||||||
|
TestSettings.fuzzer
|
||||||
|
|
||||||
|
|
||||||
|
suite : Test
|
||||||
|
suite =
|
||||||
|
describe "Envelope value"
|
||||||
|
[ describe "init"
|
||||||
|
[ describe "Default settings"
|
||||||
|
[ fuzz Fuzz.string
|
||||||
|
"currentVersion"
|
||||||
|
(\s ->
|
||||||
|
s
|
||||||
|
|> Envelope.init
|
||||||
|
|> Envelope.extractSettings .currentVersion
|
||||||
|
|> Expect.equal Default.currentVersion
|
||||||
|
)
|
||||||
|
, fuzz Fuzz.string
|
||||||
|
"deviceName"
|
||||||
|
(\s ->
|
||||||
|
s
|
||||||
|
|> Envelope.init
|
||||||
|
|> Envelope.extractSettings .deviceName
|
||||||
|
|> Expect.equal Default.deviceName
|
||||||
|
)
|
||||||
|
, fuzz Fuzz.string
|
||||||
|
"syncTime"
|
||||||
|
(\s ->
|
||||||
|
s
|
||||||
|
|> Envelope.init
|
||||||
|
|> Envelope.extractSettings .syncTime
|
||||||
|
|> Expect.equal Default.syncTime
|
||||||
|
)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, describe "JSON"
|
||||||
|
[ fuzz2 (fuzzer Fuzz.string)
|
||||||
|
Fuzz.int
|
||||||
|
"JSON encode -> JSON decode"
|
||||||
|
(\envelope indent ->
|
||||||
|
envelope
|
||||||
|
|> Envelope.encode E.string
|
||||||
|
|> E.encode indent
|
||||||
|
|> D.decodeString (Envelope.decoder D.string)
|
||||||
|
|> Expect.equal (Ok envelope)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
]
|
|
@ -0,0 +1,50 @@
|
||||||
|
module Test.Values.Event exposing (..)
|
||||||
|
|
||||||
|
import Fuzz exposing (Fuzzer)
|
||||||
|
import Internal.Values.Event as Event exposing (Event)
|
||||||
|
import Json.Encode as E
|
||||||
|
import Test exposing (..)
|
||||||
|
import Test.Tools.Timestamp as TestTimestamp
|
||||||
|
|
||||||
|
|
||||||
|
fuzzer : Fuzzer Event
|
||||||
|
fuzzer =
|
||||||
|
Fuzz.map8 Event
|
||||||
|
valueFuzzer
|
||||||
|
Fuzz.string
|
||||||
|
TestTimestamp.fuzzer
|
||||||
|
Fuzz.string
|
||||||
|
Fuzz.string
|
||||||
|
(Fuzz.maybe Fuzz.string)
|
||||||
|
Fuzz.string
|
||||||
|
(Fuzz.maybe unsignedDataFuzzer)
|
||||||
|
|
||||||
|
|
||||||
|
unsignedDataFuzzer : Fuzzer Event.UnsignedData
|
||||||
|
unsignedDataFuzzer =
|
||||||
|
Fuzz.map4
|
||||||
|
(\age prev redact trans ->
|
||||||
|
Event.UnsignedData
|
||||||
|
{ age = age
|
||||||
|
, prevContent = prev
|
||||||
|
, redactedBecause = redact
|
||||||
|
, transactionId = trans
|
||||||
|
}
|
||||||
|
)
|
||||||
|
(Fuzz.maybe Fuzz.int)
|
||||||
|
(Fuzz.maybe valueFuzzer)
|
||||||
|
(Fuzz.maybe <| Fuzz.lazy (\_ -> fuzzer))
|
||||||
|
(Fuzz.maybe Fuzz.string)
|
||||||
|
|
||||||
|
|
||||||
|
{-| Example values that can be used for arbitrary JSON values
|
||||||
|
-}
|
||||||
|
valueFuzzer : Fuzzer E.Value
|
||||||
|
valueFuzzer =
|
||||||
|
Fuzz.oneOf
|
||||||
|
[ Fuzz.map E.int Fuzz.int
|
||||||
|
, Fuzz.map E.string Fuzz.string
|
||||||
|
, Fuzz.map (E.list E.int) (Fuzz.list Fuzz.int)
|
||||||
|
, Fuzz.map (E.list E.string) (Fuzz.list Fuzz.string)
|
||||||
|
, Fuzz.map Event.encode (Fuzz.lazy (\_ -> fuzzer))
|
||||||
|
]
|
|
@ -0,0 +1,80 @@
|
||||||
|
module Test.Values.Settings exposing (..)
|
||||||
|
|
||||||
|
import Expect
|
||||||
|
import Fuzz exposing (Fuzzer)
|
||||||
|
import Internal.Config.Default as Default
|
||||||
|
import Internal.Values.Settings as Settings exposing (Settings)
|
||||||
|
import Json.Decode as D
|
||||||
|
import Json.Encode as E
|
||||||
|
import Test exposing (..)
|
||||||
|
|
||||||
|
|
||||||
|
fuzzer : Fuzzer Settings
|
||||||
|
fuzzer =
|
||||||
|
Fuzz.map3 Settings
|
||||||
|
(Fuzz.oneOf
|
||||||
|
[ Fuzz.constant Default.currentVersion
|
||||||
|
, Fuzz.string
|
||||||
|
]
|
||||||
|
)
|
||||||
|
(Fuzz.oneOf
|
||||||
|
[ Fuzz.constant Default.deviceName
|
||||||
|
, Fuzz.string
|
||||||
|
]
|
||||||
|
)
|
||||||
|
(Fuzz.oneOf
|
||||||
|
[ Fuzz.constant Default.syncTime
|
||||||
|
, Fuzz.int
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
suite : Test
|
||||||
|
suite =
|
||||||
|
describe "Settings"
|
||||||
|
[ describe "init"
|
||||||
|
[ test "Current version"
|
||||||
|
(Settings.init
|
||||||
|
|> .currentVersion
|
||||||
|
|> Expect.equal Default.currentVersion
|
||||||
|
|> always
|
||||||
|
)
|
||||||
|
, test "Device name"
|
||||||
|
(Settings.init
|
||||||
|
|> .deviceName
|
||||||
|
|> Expect.equal Default.deviceName
|
||||||
|
|> always
|
||||||
|
)
|
||||||
|
, test "Sync time"
|
||||||
|
(Settings.init
|
||||||
|
|> .syncTime
|
||||||
|
|> Expect.equal Default.syncTime
|
||||||
|
|> always
|
||||||
|
)
|
||||||
|
, test "JSON encode init is {}"
|
||||||
|
(Settings.init
|
||||||
|
|> Settings.encode
|
||||||
|
|> E.encode 0
|
||||||
|
|> Expect.equal "{}"
|
||||||
|
|> always
|
||||||
|
)
|
||||||
|
, test "JSON decode {} is init"
|
||||||
|
("{}"
|
||||||
|
|> D.decodeString Settings.decoder
|
||||||
|
|> Expect.equal (Ok Settings.init)
|
||||||
|
|> always
|
||||||
|
)
|
||||||
|
]
|
||||||
|
, describe "JSON"
|
||||||
|
[ fuzz2 fuzzer
|
||||||
|
Fuzz.int
|
||||||
|
"JSON encode -> JSON decode -> identical"
|
||||||
|
(\settings indent ->
|
||||||
|
settings
|
||||||
|
|> Settings.encode
|
||||||
|
|> E.encode indent
|
||||||
|
|> D.decodeString Settings.decoder
|
||||||
|
|> Expect.equal (Ok settings)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
]
|
|
@ -0,0 +1,10 @@
|
||||||
|
module Test.Values.Vault exposing (..)
|
||||||
|
|
||||||
|
import Fuzz exposing (Fuzzer)
|
||||||
|
import Internal.Values.Vault exposing (Vault)
|
||||||
|
import Test exposing (..)
|
||||||
|
|
||||||
|
|
||||||
|
vault : Fuzzer Vault
|
||||||
|
vault =
|
||||||
|
Fuzz.unit
|
|
@ -1,53 +0,0 @@
|
||||||
module Vault exposing (..)
|
|
||||||
|
|
||||||
import Expect
|
|
||||||
import Fuzz exposing (Fuzzer)
|
|
||||||
import Internal.Config.Default as Default
|
|
||||||
import Internal.Values.Envelope as Envelope
|
|
||||||
import Matrix
|
|
||||||
import Matrix.Settings
|
|
||||||
import Test exposing (..)
|
|
||||||
import Types
|
|
||||||
|
|
||||||
|
|
||||||
fuzzer : Fuzzer Matrix.Vault
|
|
||||||
fuzzer =
|
|
||||||
Fuzz.constant <| Types.Vault <| Envelope.init {}
|
|
||||||
|
|
||||||
|
|
||||||
settings : Test
|
|
||||||
settings =
|
|
||||||
describe "Edit settings"
|
|
||||||
[ fuzz fuzzer
|
|
||||||
"Default device name"
|
|
||||||
(\vault ->
|
|
||||||
vault
|
|
||||||
|> Matrix.Settings.getDeviceName
|
|
||||||
|> Expect.equal Default.deviceName
|
|
||||||
)
|
|
||||||
, fuzz2 fuzzer
|
|
||||||
Fuzz.string
|
|
||||||
"Set device name"
|
|
||||||
(\vault name ->
|
|
||||||
vault
|
|
||||||
|> Matrix.Settings.setDeviceName name
|
|
||||||
|> Matrix.Settings.getDeviceName
|
|
||||||
|> Expect.equal name
|
|
||||||
)
|
|
||||||
, fuzz fuzzer
|
|
||||||
"Default sync time"
|
|
||||||
(\vault ->
|
|
||||||
vault
|
|
||||||
|> Matrix.Settings.getSyncTime
|
|
||||||
|> Expect.equal Default.syncTime
|
|
||||||
)
|
|
||||||
, fuzz2 fuzzer
|
|
||||||
Fuzz.int
|
|
||||||
"Set sync time"
|
|
||||||
(\vault sync ->
|
|
||||||
vault
|
|
||||||
|> Matrix.Settings.setSyncTime sync
|
|
||||||
|> Matrix.Settings.getSyncTime
|
|
||||||
|> Expect.equal sync
|
|
||||||
)
|
|
||||||
]
|
|
Loading…
Reference in New Issue