BitBadger.Documents/src/Tests/PostgresTests.fs

2217 lines
96 KiB
Forth

module PostgresTests
open System.IO
open Expecto
open BitBadger.Documents
open BitBadger.Documents.Postgres
open BitBadger.Documents.Tests
(** UNIT TESTS **)
/// Unit tests for the Parameters module of the PostgreSQL library
let parametersTests = testList "Parameters" [
testList "idParam" [
// NOTE: these tests also exercise all branches of the internal parameterFor function
test "succeeds for byte ID" {
Expect.equal (idParam (sbyte 7)) ("@id", Sql.int8 (sbyte 7)) "Byte ID parameter not constructed correctly"
}
test "succeeds for unsigned byte ID" {
Expect.equal
(idParam (byte 7))
("@id", Sql.int8 (int8 (byte 7)))
"Unsigned byte ID parameter not constructed correctly"
}
test "succeeds for short ID" {
Expect.equal
(idParam (int16 44)) ("@id", Sql.int16 (int16 44)) "Short ID parameter not constructed correctly"
}
test "succeeds for unsigned short ID" {
Expect.equal
(idParam (uint16 64))
("@id", Sql.int16 (int16 64))
"Unsigned short ID parameter not constructed correctly"
}
test "succeeds for integer ID" {
Expect.equal (idParam 88) ("@id", Sql.int 88) "Int ID parameter not constructed correctly"
}
test "succeeds for unsigned integer ID" {
Expect.equal (idParam (uint 889)) ("@id", Sql.int 889) "Unsigned int ID parameter not constructed correctly"
}
test "succeeds for long ID" {
Expect.equal
(idParam (int64 123)) ("@id", Sql.int64 (int64 123)) "Long ID parameter not constructed correctly"
}
test "succeeds for unsigned long ID" {
Expect.equal
(idParam (uint64 6464))
("@id", Sql.int64 (int64 6464))
"Unsigned long ID parameter not constructed correctly"
}
test "succeeds for decimal ID" {
Expect.equal
(idParam (decimal 4.56))
("@id", Sql.decimal (decimal 4.56))
"Decimal ID parameter not constructed correctly"
}
test "succeeds for single ID" {
Expect.equal
(idParam (single 5.67))
("@id", Sql.double (double (single 5.67)))
"Single ID parameter not constructed correctly"
}
test "succeeds for double ID" {
Expect.equal
(idParam (double 6.78))
("@id", Sql.double (double 6.78))
"Double ID parameter not constructed correctly"
}
test "succeeds for string ID" {
Expect.equal (idParam "99") ("@id", Sql.string "99") "String ID parameter not constructed correctly"
}
test "succeeds for non-numeric non-string ID" {
let target = { new obj() with override _.ToString() = "ToString was called" }
Expect.equal
(idParam target)
("@id", Sql.string "ToString was called")
"Non-numeric, non-string parameter not constructed correctly"
}
]
test "jsonParam succeeds" {
Expect.equal
(jsonParam "@test" {| Something = "good" |})
("@test", Sql.jsonb """{"Something":"good"}""")
"JSON parameter not constructed correctly"
}
testList "addFieldParams" [
test "succeeds when a parameter is added" {
let paramList = addFieldParams [ Field.Where "it" (Equal "242") ] []
Expect.hasLength paramList 1 "There should have been a parameter added"
let name, value = Seq.head paramList
Expect.equal name "@field0" "Field parameter name not correct"
Expect.equal value (Sql.string "242") "Parameter value not correct"
}
test "succeeds when multiple independent parameters are added" {
let paramList = addFieldParams [ Field.Equal "me" "you"; Field.Greater "us" "them" ] [ idParam 14 ]
Expect.hasLength paramList 3 "There should have been 2 parameters added"
let p = Array.ofSeq paramList
Expect.equal (fst p[0]) "@id" "First field parameter name not correct"
Expect.equal (snd p[0]) (Sql.int 14) "First parameter value not correct"
Expect.equal (fst p[1]) "@field0" "Second field parameter name not correct"
Expect.equal (snd p[1]) (Sql.string "you") "Second parameter value not correct"
Expect.equal (fst p[2]) "@field1" "Third parameter name not correct"
Expect.equal (snd p[2]) (Sql.string "them") "Third parameter value not correct"
}
test "succeeds when a parameter is not added" {
let paramList = addFieldParams [ Field.Exists "tacos" ] []
Expect.isEmpty paramList "There should not have been any parameters added"
}
test "succeeds when two parameters are added for one field" {
let paramList = addFieldParams [ { Field.Between "that" "eh" "zed" with ParameterName = Some "@test" } ] []
Expect.hasLength paramList 2 "There should have been 2 parameters added"
let name, value = Seq.head paramList
Expect.equal name "@testmin" "Minimum field name not correct"
Expect.equal value (Sql.string "eh") "Minimum parameter value not correct"
let name, value = paramList |> Seq.skip 1 |> Seq.head
Expect.equal name "@testmax" "Maximum field name not correct"
Expect.equal value (Sql.string "zed") "Maximum parameter value not correct"
}
]
testList "fieldNameParams" [
test "succeeds for one name" {
let name, value = fieldNameParams [ "bob" ]
Expect.equal name "@name" "The parameter name was incorrect"
Expect.equal value (Sql.string "bob") "The parameter value was incorrect"
}
test "succeeds for multiple names" {
let name, value = fieldNameParams [ "bob"; "tom"; "mike" ]
Expect.equal name "@name" "The parameter name was incorrect"
Expect.equal value (Sql.stringArray [| "bob"; "tom"; "mike" |]) "The parameter value was incorrect"
}
]
test "noParams succeeds" {
Expect.isEmpty noParams "The no-params sequence should be empty"
}
]
/// Unit tests for the Query module of the PostgreSQL library
let queryTests = testList "Query" [
testList "whereByFields" [
test "succeeds for a single field when a logical comparison is passed" {
Expect.equal
(Query.whereByFields Any [ { Field.Greater "theField" "0" with ParameterName = Some "@test" } ])
"data->>'theField' > @test"
"WHERE clause not correct"
}
test "succeeds for a single field when an existence comparison is passed" {
Expect.equal
(Query.whereByFields Any [ Field.NotExists "thatField" ])
"data->>'thatField' IS NULL"
"WHERE clause not correct"
}
test "succeeds for a single field when a between comparison is passed with numeric values" {
Expect.equal
(Query.whereByFields All [ { Field.Between "aField" 50 99 with ParameterName = Some "@range" } ])
"(data->>'aField')::numeric BETWEEN @rangemin AND @rangemax"
"WHERE clause not correct"
}
test "succeeds for a single field when a between comparison is passed with non-numeric values" {
Expect.equal
(Query.whereByFields Any [ { Field.Between "field0" "a" "b" with ParameterName = Some "@alpha" } ])
"data->>'field0' BETWEEN @alphamin AND @alphamax"
"WHERE clause not correct"
}
test "succeeds for all multiple fields with logical comparisons" {
Expect.equal
(Query.whereByFields All [ Field.Equal "theFirst" "1"; Field.Equal "numberTwo" "2" ])
"data->>'theFirst' = @field0 AND data->>'numberTwo' = @field1"
"WHERE clause not correct"
}
test "succeeds for any multiple fields with an existence comparisons" {
Expect.equal
(Query.whereByFields Any [ Field.NotExists "thatField"; Field.GreaterOrEqual "thisField" 18 ])
"data->>'thatField' IS NULL OR (data->>'thisField')::numeric >= @field0"
"WHERE clause not correct"
}
test "succeeds for all multiple fields with between comparisons" {
Expect.equal
(Query.whereByFields All [ Field.Between "aField" 50 99; Field.Between "anotherField" "a" "b" ])
"(data->>'aField')::numeric BETWEEN @field0min AND @field0max AND data->>'anotherField' BETWEEN @field1min AND @field1max"
"WHERE clause not correct"
}
test "succeeds for a field with an In comparison with alphanumeric values" {
Expect.equal
(Query.whereByFields All [ Field.In "this" [ "a"; "b"; "c" ] ])
"data->>'this' IN (@field0_0, @field0_1, @field0_2)"
"WHERE clause not correct"
}
test "succeeds for a field with an In comparison with numeric values" {
Expect.equal
(Query.whereByFields All [ Field.In "this" [ 7; 14; 21 ] ])
"(data->>'this')::numeric IN (@field0_0, @field0_1, @field0_2)"
"WHERE clause not correct"
}
test "succeeds for a field with an InArray comparison" {
Expect.equal
(Query.whereByFields All [ Field.InArray "theField" "the_table" [ "q", "r" ] ])
"data->'theField' ?| @field0"
"WHERE clause not correct"
}
]
testList "whereById" [
test "succeeds for numeric ID" {
Expect.equal (Query.whereById 18) "(data->>'Id')::numeric = @id" "WHERE clause not correct"
}
test "succeeds for string ID" {
Expect.equal (Query.whereById "18") "data->>'Id' = @id" "WHERE clause not correct"
}
test "succeeds for non-numeric non-string ID" {
Expect.equal
(Query.whereById (System.Uri "https://example.com")) "data->>'Id' = @id" "WHERE clause not correct"
}
]
testList "Definition" [
test "ensureTable succeeds" {
Expect.equal
(Query.Definition.ensureTable PostgresDb.TableName)
$"CREATE TABLE IF NOT EXISTS {PostgresDb.TableName} (data JSONB NOT NULL)"
"CREATE TABLE statement not constructed correctly"
}
test "ensureDocumentIndex succeeds for full index" {
Expect.equal
(Query.Definition.ensureDocumentIndex "schema.tbl" Full)
"CREATE INDEX IF NOT EXISTS idx_tbl_document ON schema.tbl USING GIN (data)"
"CREATE INDEX statement not constructed correctly"
}
test "ensureDocumentIndex succeeds for JSONB Path Ops index" {
Expect.equal
(Query.Definition.ensureDocumentIndex PostgresDb.TableName Optimized)
(sprintf "CREATE INDEX IF NOT EXISTS idx_%s_document ON %s USING GIN (data jsonb_path_ops)"
PostgresDb.TableName PostgresDb.TableName)
"CREATE INDEX statement not constructed correctly"
}
]
test "whereDataContains succeeds" {
Expect.equal (Query.whereDataContains "@test") "data @> @test" "WHERE clause not correct"
}
test "whereJsonPathMatches succeeds" {
Expect.equal (Query.whereJsonPathMatches "@path") "data @? @path::jsonpath" "WHERE clause not correct"
}
test "patch succeeds" {
Expect.equal
(Query.patch PostgresDb.TableName)
$"UPDATE {PostgresDb.TableName} SET data = data || @data"
"Patch query not correct"
}
test "removeFields succeeds" {
Expect.equal
(Query.removeFields PostgresDb.TableName)
$"UPDATE {PostgresDb.TableName} SET data = data - @name"
"Field removal query not correct"
}
test "byId succeeds" {
Expect.equal (Query.byId "test" "14") "test WHERE data->>'Id' = @id" "By-ID query not correct"
}
test "byFields succeeds" {
Expect.equal
(Query.byFields "unit" Any [ Field.Greater "That" 14 ])
"unit WHERE (data->>'That')::numeric > @field0"
"By-Field query not correct"
}
test "byContains succeeds" {
Expect.equal (Query.byContains "exam") "exam WHERE data @> @criteria" "By-Contains query not correct"
}
test "byPathMach succeeds" {
Expect.equal
(Query.byPathMatch "verify") "verify WHERE data @? @path::jsonpath" "By-JSON Path query not correct"
}
]
(** INTEGRATION TESTS **)
open ThrowawayDb.Postgres
open Types
/// Load the test documents into the database
let loadDocs () = backgroundTask {
for doc in testDocuments do do! insert PostgresDb.TableName doc
}
/// Set up a stream writer for a test
let writeStream (stream: Stream) =
let writer = new StreamWriter(stream)
writer.AutoFlush <- true
writer
/// Get the text of the given stream
let streamText (stream: Stream) =
stream.Position <- 0L
use reader = new StreamReader(stream)
reader.ReadToEnd()
/// Integration tests for the Configuration module of the PostgreSQL library
let configurationTests = testList "Configuration" [
test "useDataSource disposes existing source" {
use db1 = ThrowawayDatabase.Create PostgresDb.ConnStr.Value
let source = PostgresDb.MkDataSource db1.ConnectionString
Configuration.useDataSource source
use db2 = ThrowawayDatabase.Create PostgresDb.ConnStr.Value
Configuration.useDataSource (PostgresDb.MkDataSource db2.ConnectionString)
Expect.throws (fun () -> source.OpenConnection() |> ignore) "Data source should have been disposed"
}
test "dataSource returns configured data source" {
use db = ThrowawayDatabase.Create PostgresDb.ConnStr.Value
let source = PostgresDb.MkDataSource db.ConnectionString
Configuration.useDataSource source
Expect.isTrue (obj.ReferenceEquals(source, Configuration.dataSource ())) "Data source should have been the same"
}
]
/// Integration tests for the Custom module of the PostgreSQL library
let customTests = testList "Custom" [
testList "list" [
testTask "succeeds when data is found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! docs = Custom.list (Query.find PostgresDb.TableName) [] fromData<JsonDocument>
Expect.hasLength docs 5 "There should have been 5 documents returned"
}
testTask "succeeds when data is not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! docs =
Custom.list
$"SELECT data FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath"
[ "@path", Sql.string "$.NumValue ? (@ > 100)" ]
fromData<JsonDocument>
Expect.isEmpty docs "There should have been no documents returned"
}
]
testList "jsonArray" [
testTask "succeeds when data is found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! docs = Custom.jsonArray (Query.find PostgresDb.TableName) [] jsonFromData
Expect.stringStarts docs "[" "The JSON array should have started with `[`"
Expect.hasLength ((string docs).Split "{\"Id\":") 6 "There should have been 5 documents returned"
Expect.stringEnds docs "]" "The JSON array should have ended with `[`"
}
testTask "succeeds when data is not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! docs =
Custom.jsonArray
$"SELECT data FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath"
[ "@path", Sql.string "$.NumValue ? (@ > 100)" ]
jsonFromData
Expect.equal docs "[]" "There should have been no documents returned"
}
]
testList "writeJsonArray" [
testTask "succeeds when data is found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Custom.writeJsonArray (Query.find PostgresDb.TableName) [] writer jsonFromData
let docs = streamText stream
Expect.stringStarts docs "[" "The JSON array should have started with `[`"
Expect.hasLength (docs.Split "{\"Id\":") 6 "There should have been 5 documents returned"
Expect.stringEnds docs "]" "The JSON array should have ended with `[`"
}
testTask "succeeds when data is not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Custom.writeJsonArray
$"SELECT data FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath"
[ "@path", Sql.string "$.NumValue ? (@ > 100)" ]
writer
jsonFromData
Expect.equal (streamText stream) "[]" "There should have been no documents returned"
}
]
testList "single" [
testTask "succeeds when a row is found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc =
Custom.single
$"SELECT data FROM {PostgresDb.TableName} WHERE data ->> 'Id' = @id"
[ "@id", Sql.string "one"]
fromData<JsonDocument>
Expect.isSome doc "There should have been a document returned"
Expect.equal doc.Value.Id "one" "The incorrect document was returned"
}
testTask "succeeds when a row is not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc =
Custom.single
$"SELECT data FROM {PostgresDb.TableName} WHERE data ->> 'Id' = @id"
[ "@id", Sql.string "eighty" ]
fromData<JsonDocument>
Expect.isNone doc "There should not have been a document returned"
}
]
testList "jsonSingle" [
testTask "succeeds when a row is found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc =
Custom.jsonSingle
$"SELECT data FROM {PostgresDb.TableName} WHERE data ->> 'Id' = @id"
[ "@id", Sql.string "one"]
jsonFromData
Expect.stringStarts doc "{" "The document should have started with an open brace"
Expect.stringContains doc "\"Id\": \"one\"" "An incorrect document was returned"
Expect.stringEnds doc "}" "The document should have ended with a closing brace"
}
testTask "succeeds when a row is not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc =
Custom.jsonSingle
$"SELECT data FROM {PostgresDb.TableName} WHERE data ->> 'Id' = @id"
[ "@id", Sql.string "eighty" ]
jsonFromData
Expect.equal doc "{}" "There should not have been a document returned"
}
]
testList "nonQuery" [
testTask "succeeds when operating on data" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! Custom.nonQuery $"DELETE FROM {PostgresDb.TableName}" []
let! remaining = Count.all PostgresDb.TableName
Expect.equal remaining 0 "There should be no documents remaining in the table"
}
testTask "succeeds when no data matches where clause" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! Custom.nonQuery
$"DELETE FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath"
[ "@path", Sql.string "$.NumValue ? (@ > 100)" ]
let! remaining = Count.all PostgresDb.TableName
Expect.equal remaining 5 "There should be 5 documents remaining in the table"
}
]
testTask "scalar succeeds" {
use db = PostgresDb.BuildDb()
let! nbr = Custom.scalar "SELECT 5 AS test_value" [] (fun row -> row.int "test_value")
Expect.equal nbr 5 "The query should have returned the number 5"
}
]
/// Integration tests for the Definition module of the PostgreSQL library
let definitionTests = testList "Definition" [
testTask "ensureTable succeeds" {
use db = PostgresDb.BuildDb()
let tableExists () =
Custom.scalar "SELECT EXISTS (SELECT 1 FROM pg_class WHERE relname = 'ensured') AS it" [] toExists
let keyExists () =
Custom.scalar
"SELECT EXISTS (SELECT 1 FROM pg_class WHERE relname = 'idx_ensured_key') AS it" [] toExists
let! exists = tableExists ()
let! alsoExists = keyExists ()
Expect.isFalse exists "The table should not exist already"
Expect.isFalse alsoExists "The key index should not exist already"
do! Definition.ensureTable "ensured"
let! exists' = tableExists ()
let! alsoExists' = keyExists ()
Expect.isTrue exists' "The table should now exist"
Expect.isTrue alsoExists' "The key index should now exist"
}
testTask "ensureDocumentIndex succeeds" {
use db = PostgresDb.BuildDb()
let indexExists () =
Custom.scalar
"SELECT EXISTS (SELECT 1 FROM pg_class WHERE relname = 'idx_ensured_document') AS it" [] toExists
let! exists = indexExists ()
Expect.isFalse exists "The index should not exist already"
do! Definition.ensureTable "ensured"
do! Definition.ensureDocumentIndex "ensured" Optimized
let! exists' = indexExists ()
Expect.isTrue exists' "The index should now exist"
}
testTask "ensureFieldIndex succeeds" {
use db = PostgresDb.BuildDb()
let indexExists () =
Custom.scalar "SELECT EXISTS (SELECT 1 FROM pg_class WHERE relname = 'idx_ensured_test') AS it" [] toExists
let! exists = indexExists ()
Expect.isFalse exists "The index should not exist already"
do! Definition.ensureTable "ensured"
do! Definition.ensureFieldIndex "ensured" "test" [ "Id"; "Category" ]
let! exists' = indexExists ()
Expect.isTrue exists' "The index should now exist"
}
]
/// Integration tests for the (auto-opened) Document module of the PostgreSQL library
let documentTests = testList "Document" [
testList "insert" [
testTask "succeeds" {
use db = PostgresDb.BuildDb()
let! before = Find.all<SubDocument> PostgresDb.TableName
Expect.equal before [] "There should be no documents in the table"
let testDoc = { emptyDoc with Id = "turkey"; Sub = Some { Foo = "gobble"; Bar = "gobble" } }
do! insert PostgresDb.TableName testDoc
let! after = Find.all<JsonDocument> PostgresDb.TableName
Expect.equal after [ testDoc ] "There should have been one document inserted"
}
testTask "fails for duplicate key" {
use db = PostgresDb.BuildDb()
do! insert PostgresDb.TableName { emptyDoc with Id = "test" }
Expect.throws
(fun () ->
insert PostgresDb.TableName {emptyDoc with Id = "test" }
|> Async.AwaitTask
|> Async.RunSynchronously)
"An exception should have been raised for duplicate document ID insert"
}
testTask "succeeds when adding a numeric auto ID" {
try
Configuration.useAutoIdStrategy Number
Configuration.useIdField "Key"
use db = PostgresDb.BuildDb()
let! before = Count.all PostgresDb.TableName
Expect.equal before 0 "There should be no documents in the table"
do! insert PostgresDb.TableName { Key = 0; Text = "one" }
do! insert PostgresDb.TableName { Key = 0; Text = "two" }
do! insert PostgresDb.TableName { Key = 77; Text = "three" }
do! insert PostgresDb.TableName { Key = 0; Text = "four" }
let! after = Find.allOrdered<NumIdDocument> PostgresDb.TableName [ Field.Named "n:Key" ]
Expect.hasLength after 4 "There should have been 4 documents returned"
Expect.equal (after |> List.map _.Key) [ 1; 2; 77; 78 ] "The IDs were not generated correctly"
finally
Configuration.useAutoIdStrategy Disabled
Configuration.useIdField "Id"
}
testTask "succeeds when adding a GUID auto ID" {
try
Configuration.useAutoIdStrategy Guid
use db = PostgresDb.BuildDb()
let! before = Count.all PostgresDb.TableName
Expect.equal before 0 "There should be no documents in the table"
do! insert PostgresDb.TableName { emptyDoc with Value = "one" }
do! insert PostgresDb.TableName { emptyDoc with Value = "two" }
do! insert PostgresDb.TableName { emptyDoc with Id = "abc123"; Value = "three" }
do! insert PostgresDb.TableName { emptyDoc with Value = "four" }
let! after = Find.all<JsonDocument> PostgresDb.TableName
Expect.hasLength after 4 "There should have been 4 documents returned"
Expect.hasCountOf after 3u (fun doc -> doc.Id.Length = 32) "Three of the IDs should have been GUIDs"
Expect.hasCountOf after 1u (fun doc -> doc.Id = "abc123") "The provided ID should have been used as-is"
finally
Configuration.useAutoIdStrategy Disabled
}
testTask "succeeds when adding a RandomString auto ID" {
try
Configuration.useAutoIdStrategy RandomString
Configuration.useIdStringLength 44
use db = PostgresDb.BuildDb()
let! before = Count.all PostgresDb.TableName
Expect.equal before 0 "There should be no documents in the table"
do! insert PostgresDb.TableName { emptyDoc with Value = "one" }
do! insert PostgresDb.TableName { emptyDoc with Value = "two" }
do! insert PostgresDb.TableName { emptyDoc with Id = "abc123"; Value = "three" }
do! insert PostgresDb.TableName { emptyDoc with Value = "four" }
let! after = Find.all<JsonDocument> PostgresDb.TableName
Expect.hasLength after 4 "There should have been 4 documents returned"
Expect.hasCountOf
after 3u (fun doc -> doc.Id.Length = 44)
"Three of the IDs should have been 44-character random strings"
Expect.hasCountOf after 1u (fun doc -> doc.Id = "abc123") "The provided ID should have been used as-is"
finally
Configuration.useAutoIdStrategy Disabled
Configuration.useIdStringLength 16
}
]
testList "save" [
testTask "succeeds when a document is inserted" {
use db = PostgresDb.BuildDb()
let! before = Find.all<JsonDocument> PostgresDb.TableName
Expect.equal before [] "There should be no documents in the table"
let testDoc = { emptyDoc with Id = "test"; Sub = Some { Foo = "a"; Bar = "b" } }
do! save PostgresDb.TableName testDoc
let! after = Find.all<JsonDocument> PostgresDb.TableName
Expect.equal after [ testDoc ] "There should have been one document inserted"
}
testTask "succeeds when a document is updated" {
use db = PostgresDb.BuildDb()
let testDoc = { emptyDoc with Id = "test"; Sub = Some { Foo = "a"; Bar = "b" } }
do! insert PostgresDb.TableName testDoc
let! before = Find.byId<string, JsonDocument> PostgresDb.TableName "test"
Expect.isSome before "There should have been a document returned"
Expect.equal before.Value testDoc "The document is not correct"
let upd8Doc = { testDoc with Sub = Some { Foo = "c"; Bar = "d" } }
do! save PostgresDb.TableName upd8Doc
let! after = Find.byId<string, JsonDocument> PostgresDb.TableName "test"
Expect.isSome after "There should have been a document returned post-update"
Expect.equal after.Value upd8Doc "The updated document is not correct"
}
]
]
/// Integration tests for the Count module of the PostgreSQL library
let countTests = testList "Count" [
testTask "all succeeds" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! theCount = Count.all PostgresDb.TableName
Expect.equal theCount 5 "There should have been 5 matching documents"
}
testList "byFields" [
testTask "succeeds when items are found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! theCount =
Count.byFields PostgresDb.TableName Any [ Field.Between "NumValue" 15 20; Field.Equal "NumValue" 0 ]
Expect.equal theCount 3 "There should have been 3 matching documents"
}
testTask "succeeds when items are not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! theCount = Count.byFields PostgresDb.TableName All [ Field.Exists "Sub"; Field.Greater "NumValue" 100 ]
Expect.equal theCount 0 "There should have been no matching documents"
}
]
testTask "byContains succeeds" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! theCount = Count.byContains PostgresDb.TableName {| Value = "purple" |}
Expect.equal theCount 2 "There should have been 2 matching documents"
}
testTask "byJsonPath succeeds" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! theCount = Count.byJsonPath PostgresDb.TableName "$.NumValue ? (@ > 5)"
Expect.equal theCount 3 "There should have been 3 matching documents"
}
]
/// Integration tests for the Exists module of the PostgreSQL library
let existsTests = testList "Exists" [
testList "byId" [
testTask "succeeds when a document exists" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! exists = Exists.byId PostgresDb.TableName "three"
Expect.isTrue exists "There should have been an existing document"
}
testTask "succeeds when a document does not exist" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! exists = Exists.byId PostgresDb.TableName "seven"
Expect.isFalse exists "There should not have been an existing document"
}
]
testList "byFields" [
testTask "succeeds when documents exist" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! exists = Exists.byFields PostgresDb.TableName Any [ Field.Exists "Sub"; Field.Exists "Boo" ]
Expect.isTrue exists "There should have been existing documents"
}
testTask "succeeds when documents do not exist" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! exists = Exists.byFields PostgresDb.TableName All [ Field.Equal "NumValue" "six"; Field.Exists "Nope" ]
Expect.isFalse exists "There should not have been existing documents"
}
]
testList "byContains" [
testTask "succeeds when documents exist" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! exists = Exists.byContains PostgresDb.TableName {| NumValue = 10 |}
Expect.isTrue exists "There should have been existing documents"
}
testTask "succeeds when no matching documents exist" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! exists = Exists.byContains PostgresDb.TableName {| Nothing = "none" |}
Expect.isFalse exists "There should not have been any existing documents"
}
]
testList "byJsonPath" [
testTask "succeeds when documents exist" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! exists = Exists.byJsonPath PostgresDb.TableName """$.Sub.Foo ? (@ == "green")"""
Expect.isTrue exists "There should have been existing documents"
}
testTask "succeeds when no matching documents exist" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! exists = Exists.byJsonPath PostgresDb.TableName "$.NumValue ? (@ > 1000)"
Expect.isFalse exists "There should not have been any existing documents"
}
]
]
/// Integration tests for the Find module of the PostgreSQL library
let findTests = testList "Find" [
testList "all" [
testTask "succeeds when there is data" {
use db = PostgresDb.BuildDb()
do! insert PostgresDb.TableName { Foo = "one"; Bar = "two" }
do! insert PostgresDb.TableName { Foo = "three"; Bar = "four" }
do! insert PostgresDb.TableName { Foo = "five"; Bar = "six" }
let! results = Find.all<SubDocument> PostgresDb.TableName
Expect.equal
results
[ { Foo = "one"; Bar = "two" }; { Foo = "three"; Bar = "four" }; { Foo = "five"; Bar = "six" } ]
"There should have been 3 documents returned"
}
testTask "succeeds when there is no data" {
use db = PostgresDb.BuildDb()
let! results = Find.all<SubDocument> PostgresDb.TableName
Expect.equal results [] "There should have been no documents returned"
}
]
testList "allOrdered" [
testTask "succeeds when ordering numerically" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! results = Find.allOrdered<JsonDocument> PostgresDb.TableName [ Field.Named "n:NumValue" ]
Expect.hasLength results 5 "There should have been 5 documents returned"
Expect.equal
(results |> List.map _.Id |> String.concat "|")
"one|three|two|four|five"
"The documents were not ordered correctly"
}
testTask "succeeds when ordering numerically descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! results = Find.allOrdered<JsonDocument> PostgresDb.TableName [ Field.Named "n:NumValue DESC" ]
Expect.hasLength results 5 "There should have been 5 documents returned"
Expect.equal
(results |> List.map _.Id |> String.concat "|")
"five|four|two|three|one"
"The documents were not ordered correctly"
}
testTask "succeeds when ordering alphabetically" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! results = Find.allOrdered<JsonDocument> PostgresDb.TableName [ Field.Named "Id DESC" ]
Expect.hasLength results 5 "There should have been 5 documents returned"
Expect.equal
(results |> List.map _.Id |> String.concat "|")
"two|three|one|four|five"
"The documents were not ordered correctly"
}
]
testList "byId" [
testTask "succeeds when a document is found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc = Find.byId<string, JsonDocument> PostgresDb.TableName "two"
Expect.isSome doc "There should have been a document returned"
Expect.equal doc.Value.Id "two" "The incorrect document was returned"
}
testTask "succeeds when a document is not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc = Find.byId<string, JsonDocument> PostgresDb.TableName "three hundred eighty-seven"
Expect.isNone doc "There should not have been a document returned"
}
]
testList "byFields" [
testTask "succeeds when documents are found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! docs =
Find.byFields<JsonDocument>
PostgresDb.TableName All [ Field.In "Value" [ "purple"; "blue" ]; Field.Exists "Sub" ]
Expect.hasLength docs 1 "There should have been one document returned"
}
testTask "succeeds when documents are found using IN with numeric field" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! docs = Find.byFields<JsonDocument> PostgresDb.TableName All [ Field.In "NumValue" [ 2; 4; 6; 8 ] ]
Expect.hasLength docs 1 "There should have been one document returned"
}
testTask "succeeds when documents are not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! docs =
Find.byFields<JsonDocument>
PostgresDb.TableName All [ Field.Equal "Value" "mauve"; Field.NotEqual "NumValue" 40 ]
Expect.isEmpty docs "There should have been no documents returned"
}
testTask "succeeds for InArray when matching documents exist" {
use db = PostgresDb.BuildDb()
do! Definition.ensureTable PostgresDb.TableName
for doc in ArrayDocument.TestDocuments do do! insert PostgresDb.TableName doc
let! docs =
Find.byFields<ArrayDocument>
PostgresDb.TableName All [ Field.InArray "Values" PostgresDb.TableName [ "c" ] ]
Expect.hasLength docs 2 "There should have been two documents returned"
}
testTask "succeeds for InArray when no matching documents exist" {
use db = PostgresDb.BuildDb()
do! Definition.ensureTable PostgresDb.TableName
for doc in ArrayDocument.TestDocuments do do! insert PostgresDb.TableName doc
let! docs =
Find.byFields<ArrayDocument>
PostgresDb.TableName All [ Field.InArray "Values" PostgresDb.TableName [ "j" ] ]
Expect.isEmpty docs "There should have been no documents returned"
}
]
testList "byFieldsOrdered" [
testTask "succeeds when sorting ascending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! docs =
Find.byFieldsOrdered<JsonDocument>
PostgresDb.TableName All [ Field.Equal "Value" "purple" ] [ Field.Named "Id" ]
Expect.hasLength docs 2 "There should have been two documents returned"
Expect.equal
(docs |> List.map _.Id |> String.concat "|") "five|four" "Documents not ordered correctly"
}
testTask "succeeds when sorting descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! docs =
Find.byFieldsOrdered<JsonDocument>
PostgresDb.TableName All [ Field.Equal "Value" "purple" ] [ Field.Named "Id DESC" ]
Expect.hasLength docs 2 "There should have been two documents returned"
Expect.equal
(docs |> List.map _.Id |> String.concat "|") "four|five" "Documents not ordered correctly"
}
]
testList "byContains" [
testTask "succeeds when documents are found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! docs = Find.byContains<JsonDocument> PostgresDb.TableName {| Sub = {| Foo = "green" |} |}
Expect.equal (List.length docs) 2 "There should have been two documents returned"
}
testTask "succeeds when documents are not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! docs = Find.byContains<JsonDocument> PostgresDb.TableName {| Value = "mauve" |}
Expect.isEmpty docs "There should have been no documents returned"
}
]
testList "byContainsOrdered" [
// Id = two, Sub.Bar = blue; Id = four, Sub.Bar = red
testTask "succeeds when sorting ascending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! docs =
Find.byContainsOrdered<JsonDocument>
PostgresDb.TableName {| Sub = {| Foo = "green" |} |} [ Field.Named "Sub.Bar" ]
Expect.hasLength docs 2 "There should have been two documents returned"
Expect.equal
(docs |> List.map _.Id |> String.concat "|") "two|four" "Documents not ordered correctly"
}
testTask "succeeds when sorting descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! docs =
Find.byContainsOrdered<JsonDocument>
PostgresDb.TableName {| Sub = {| Foo = "green" |} |} [ Field.Named "Sub.Bar DESC" ]
Expect.hasLength docs 2 "There should have been two documents returned"
Expect.equal
(docs |> List.map _.Id |> String.concat "|") "four|two" "Documents not ordered correctly"
}
]
testList "byJsonPath" [
testTask "succeeds when documents are found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! docs = Find.byJsonPath<JsonDocument> PostgresDb.TableName "$.NumValue ? (@ < 15)"
Expect.equal (List.length docs) 3 "There should have been 3 documents returned"
}
testTask "succeeds when documents are not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! docs = Find.byJsonPath<JsonDocument> PostgresDb.TableName "$.NumValue ? (@ < 0)"
Expect.isEmpty docs "There should have been no documents returned"
}
]
testList "byJsonPathOrdered" [
// Id = one, NumValue = 0; Id = two, NumValue = 10; Id = three, NumValue = 4
testTask "succeeds when sorting ascending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! docs =
Find.byJsonPathOrdered<JsonDocument>
PostgresDb.TableName "$.NumValue ? (@ < 15)" [ Field.Named "n:NumValue" ]
Expect.hasLength docs 3 "There should have been 3 documents returned"
Expect.equal
(docs |> List.map _.Id |> String.concat "|") "one|three|two" "Documents not ordered correctly"
}
testTask "succeeds when sorting descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! docs =
Find.byJsonPathOrdered<JsonDocument>
PostgresDb.TableName "$.NumValue ? (@ < 15)" [ Field.Named "n:NumValue DESC" ]
Expect.hasLength docs 3 "There should have been 3 documents returned"
Expect.equal
(docs |> List.map _.Id |> String.concat "|") "two|three|one" "Documents not ordered correctly"
}
]
testList "firstByFields" [
testTask "succeeds when a document is found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc = Find.firstByFields<JsonDocument> PostgresDb.TableName Any [ Field.Equal "Value" "another" ]
Expect.isSome doc "There should have been a document returned"
Expect.equal doc.Value.Id "two" "The incorrect document was returned"
}
testTask "succeeds when multiple documents are found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc = Find.firstByFields<JsonDocument> PostgresDb.TableName Any [ Field.Equal "Value" "purple" ]
Expect.isSome doc "There should have been a document returned"
Expect.contains [ "five"; "four" ] doc.Value.Id "An incorrect document was returned"
}
testTask "succeeds when a document is not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc = Find.firstByFields<JsonDocument> PostgresDb.TableName Any [ Field.Equal "Value" "absent" ]
Expect.isNone doc "There should not have been a document returned"
}
]
testList "firstByFieldsOrdered" [
testTask "succeeds when sorting ascending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc =
Find.firstByFieldsOrdered<JsonDocument>
PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] [ Field.Named "Id" ]
Expect.isSome doc "There should have been a document returned"
Expect.equal "five" doc.Value.Id "An incorrect document was returned"
}
testTask "succeeds when sorting descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc =
Find.firstByFieldsOrdered<JsonDocument>
PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] [ Field.Named "Id DESC" ]
Expect.isSome doc "There should have been a document returned"
Expect.equal "four" doc.Value.Id "An incorrect document was returned"
}
]
testList "firstByContains" [
testTask "succeeds when a document is found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc = Find.firstByContains<JsonDocument> PostgresDb.TableName {| Value = "another" |}
Expect.isSome doc "There should have been a document returned"
Expect.equal doc.Value.Id "two" "The incorrect document was returned"
}
testTask "succeeds when multiple documents are found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc = Find.firstByContains<JsonDocument> PostgresDb.TableName {| Sub = {| Foo = "green" |} |}
Expect.isSome doc "There should have been a document returned"
Expect.contains [ "two"; "four" ] doc.Value.Id "An incorrect document was returned"
}
testTask "succeeds when a document is not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc = Find.firstByContains<JsonDocument> PostgresDb.TableName {| Value = "absent" |}
Expect.isNone doc "There should not have been a document returned"
}
]
testList "firstByContainsOrdered" [
testTask "succeeds when sorting ascending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc =
Find.firstByContainsOrdered<JsonDocument>
PostgresDb.TableName {| Sub = {| Foo = "green" |} |} [ Field.Named "Value" ]
Expect.isSome doc "There should have been a document returned"
Expect.equal "two" doc.Value.Id "An incorrect document was returned"
}
testTask "succeeds when sorting descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc =
Find.firstByContainsOrdered<JsonDocument>
PostgresDb.TableName {| Sub = {| Foo = "green" |} |} [ Field.Named "Value DESC" ]
Expect.isSome doc "There should have been a document returned"
Expect.equal "four" doc.Value.Id "An incorrect document was returned"
}
]
testList "firstByJsonPath" [
testTask "succeeds when a document is found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc = Find.firstByJsonPath<JsonDocument> PostgresDb.TableName """$.Value ? (@ == "FIRST!")"""
Expect.isSome doc "There should have been a document returned"
Expect.equal doc.Value.Id "one" "The incorrect document was returned"
}
testTask "succeeds when multiple documents are found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc = Find.firstByJsonPath<JsonDocument> PostgresDb.TableName """$.Sub.Foo ? (@ == "green")"""
Expect.isSome doc "There should have been a document returned"
Expect.contains [ "two"; "four" ] doc.Value.Id "An incorrect document was returned"
}
testTask "succeeds when a document is not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc = Find.firstByJsonPath<JsonDocument> PostgresDb.TableName """$.Id ? (@ == "nope")"""
Expect.isNone doc "There should not have been a document returned"
}
]
testList "firstByJsonPathOrdered" [
testTask "succeeds when sorting ascending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc =
Find.firstByJsonPathOrdered<JsonDocument>
PostgresDb.TableName """$.Sub.Foo ? (@ == "green")""" [ Field.Named "Sub.Bar" ]
Expect.isSome doc "There should have been a document returned"
Expect.equal "two" doc.Value.Id "An incorrect document was returned"
}
testTask "succeeds when sorting descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! doc =
Find.firstByJsonPathOrdered<JsonDocument>
PostgresDb.TableName """$.Sub.Foo ? (@ == "green")""" [ Field.Named "Sub.Bar DESC" ]
Expect.isSome doc "There should have been a document returned"
Expect.equal "four" doc.Value.Id "An incorrect document was returned"
}
]
]
/// Verify a JSON array begins with "[" and ends with "]"
let private verifyBeginEnd json =
Expect.stringStarts json "[" "The array should have started with `[`"
Expect.stringEnds json "]" "The array should have ended with `]`"
/// Verify the presence of a document by its ID
let private verifyDocById json docId =
Expect.stringContains json $"{{\"Id\": \"%s{docId}\"," $"Document `{docId}` not present"
/// Verify the presence of a document by its ID
let private verifySingleById json docId =
verifyBeginEnd json
Expect.stringContains json $"{{\"Id\": \"%s{docId}\"," $"Document `{docId}` not present"
/// Verify the presence of any of the given document IDs in the given JSON
let private verifyAnyById (json: string) (docIds: string list) =
match docIds |> List.tryFind (fun it -> json.Contains $"{{\"Id\": \"{it}\"") with
| Some _ -> ()
| None ->
let ids = docIds |> String.concat ", "
Expect.isTrue false $"Could not find any of IDs {ids} in {json}"
/// Verify the JSON for `all` returning data
let private verifyAllData json =
verifyBeginEnd json
[ "one"; "two"; "three"; "four"; "five" ] |> List.iter (verifyDocById json)
/// Verify an empty JSON array
let private verifyEmpty json =
Expect.equal json "[]" "There should be no documents returned"
/// Verify an empty JSON document
let private verifyNoDoc json =
Expect.equal json "{}" "There should be no document returned"
/// Verify the JSON for an ordered query
let private verifyExpectedOrder (json: string) idFirst idSecond idThird idFourth idFifth =
let firstIdx = json.IndexOf $"{{\"Id\": \"%s{idFirst}\","
let secondIdx = json.IndexOf $"{{\"Id\": \"%s{idSecond}\","
verifyBeginEnd json
Expect.isGreaterThan secondIdx firstIdx $"`{idSecond}` should have been after `{idFirst}`"
match idThird with
| Some id3 ->
let thirdIdx = json.IndexOf $"{{\"Id\": \"%s{id3}\","
Expect.isGreaterThan thirdIdx secondIdx $"`{id3}` should have been after `{idSecond}`"
match idFourth with
| Some id4 ->
let fourthIdx = json.IndexOf $"{{\"Id\": \"%s{id4}\","
Expect.isGreaterThan fourthIdx thirdIdx $"`{id4}` should have been after `{id3}`"
match idFifth with
| Some id5 ->
let fifthIdx = json.IndexOf $"{{\"Id\": \"%s{id5}\","
Expect.isGreaterThan fifthIdx fourthIdx $"`{id5}` should have been after `{id4}`"
| None -> ()
| None -> ()
| None -> ()
/// Integration tests for the Json module of the PostgreSQL library
let jsonTests = testList "Json" [
testList "all" [
testTask "succeeds when there is data" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.all PostgresDb.TableName
verifyAllData json
}
testTask "succeeds when there is no data" {
use db = PostgresDb.BuildDb()
let! json = Json.all PostgresDb.TableName
verifyEmpty json
}
]
testList "allOrdered" [
testTask "succeeds when ordering numerically" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.allOrdered PostgresDb.TableName [ Field.Named "n:NumValue" ]
verifyExpectedOrder json "one" "three" (Some "two") (Some "four") (Some "five")
}
testTask "succeeds when ordering numerically descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.allOrdered PostgresDb.TableName [ Field.Named "n:NumValue DESC" ]
verifyExpectedOrder json "five" "four" (Some "two") (Some "three") (Some "one")
}
testTask "succeeds when ordering alphabetically" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.allOrdered PostgresDb.TableName [ Field.Named "Id DESC" ]
verifyExpectedOrder json "two" "three" (Some "one") (Some "four") (Some "five")
}
]
testList "byId" [
testTask "succeeds when a document is found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.byId PostgresDb.TableName "two"
Expect.stringStarts json """{"Id": "two",""" "An incorrect document was returned"
Expect.stringEnds json "}" "JSON should have ended with this document"
}
testTask "succeeds when a document is not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.byId PostgresDb.TableName "three hundred eighty-seven"
verifyNoDoc json
}
]
testList "byFields" [
testTask "succeeds when documents are found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json =
Json.byFields PostgresDb.TableName All [ Field.In "Value" [ "purple"; "blue" ]; Field.Exists "Sub" ]
verifySingleById json "four"
}
testTask "succeeds when documents are found using IN with numeric field" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.byFields PostgresDb.TableName All [ Field.In "NumValue" [ 2; 4; 6; 8 ] ]
verifySingleById json "three"
}
testTask "succeeds when documents are not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json =
Json.byFields PostgresDb.TableName All [ Field.Equal "Value" "mauve"; Field.NotEqual "NumValue" 40 ]
verifyEmpty json
}
testTask "succeeds for InArray when matching documents exist" {
use db = PostgresDb.BuildDb()
do! Definition.ensureTable PostgresDb.TableName
for doc in ArrayDocument.TestDocuments do do! insert PostgresDb.TableName doc
let! json = Json.byFields PostgresDb.TableName All [ Field.InArray "Values" PostgresDb.TableName [ "c" ] ]
verifyBeginEnd json
verifyDocById json "first"
verifyDocById json "second"
}
testTask "succeeds for InArray when no matching documents exist" {
use db = PostgresDb.BuildDb()
do! Definition.ensureTable PostgresDb.TableName
for doc in ArrayDocument.TestDocuments do do! insert PostgresDb.TableName doc
let! json = Json.byFields PostgresDb.TableName All [ Field.InArray "Values" PostgresDb.TableName [ "j" ] ]
verifyEmpty json
}
]
testList "byFieldsOrdered" [
testTask "succeeds when sorting ascending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json =
Json.byFieldsOrdered PostgresDb.TableName All [ Field.Equal "Value" "purple" ] [ Field.Named "Id" ]
verifyExpectedOrder json "five" "four" None None None
}
testTask "succeeds when sorting descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json =
Json.byFieldsOrdered PostgresDb.TableName All [ Field.Equal "Value" "purple" ] [ Field.Named "Id DESC" ]
verifyExpectedOrder json "four" "five" None None None
}
]
testList "byContains" [
testTask "succeeds when documents are found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.byContains PostgresDb.TableName {| Sub = {| Foo = "green" |} |}
verifyBeginEnd json
verifyDocById json "two"
verifyDocById json "four"
}
testTask "succeeds when documents are not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.byContains PostgresDb.TableName {| Value = "mauve" |}
verifyEmpty json
}
]
testList "byContainsOrdered" [
// Id = two, Sub.Bar = blue; Id = four, Sub.Bar = red
testTask "succeeds when sorting ascending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json =
Json.byContainsOrdered PostgresDb.TableName {| Sub = {| Foo = "green" |} |} [ Field.Named "Sub.Bar" ]
verifyExpectedOrder json "two" "four" None None None
}
testTask "succeeds when sorting descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json =
Json.byContainsOrdered
PostgresDb.TableName {| Sub = {| Foo = "green" |} |} [ Field.Named "Sub.Bar DESC" ]
verifyExpectedOrder json "four" "two" None None None
}
]
testList "byJsonPath" [
testTask "succeeds when documents are found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.byJsonPath PostgresDb.TableName "$.NumValue ? (@ < 15)"
verifyBeginEnd json
verifyDocById json "one"
verifyDocById json "two"
verifyDocById json "three"
}
testTask "succeeds when documents are not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.byJsonPath PostgresDb.TableName "$.NumValue ? (@ < 0)"
verifyEmpty json
}
]
testList "byJsonPathOrdered" [
// Id = one, NumValue = 0; Id = two, NumValue = 10; Id = three, NumValue = 4
testTask "succeeds when sorting ascending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.byJsonPathOrdered PostgresDb.TableName "$.NumValue ? (@ < 15)" [ Field.Named "n:NumValue" ]
verifyExpectedOrder json "one" "three" (Some "two") None None
}
testTask "succeeds when sorting descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json =
Json.byJsonPathOrdered PostgresDb.TableName "$.NumValue ? (@ < 15)" [ Field.Named "n:NumValue DESC" ]
verifyExpectedOrder json "two" "three" (Some "one") None None
}
]
testList "firstByFields" [
testTask "succeeds when a document is found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.firstByFields PostgresDb.TableName Any [ Field.Equal "Value" "another" ]
verifyDocById json "two"
}
testTask "succeeds when multiple documents are found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.firstByFields PostgresDb.TableName Any [ Field.Equal "Value" "purple" ]
verifyAnyById json [ "five"; "four" ]
}
testTask "succeeds when a document is not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.firstByFields PostgresDb.TableName Any [ Field.Equal "Value" "absent" ]
verifyNoDoc json
}
]
testList "firstByFieldsOrdered" [
testTask "succeeds when sorting ascending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json =
Json.firstByFieldsOrdered PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] [ Field.Named "Id" ]
verifyDocById json "five"
}
testTask "succeeds when sorting descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json =
Json.firstByFieldsOrdered
PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] [ Field.Named "Id DESC" ]
verifyDocById json "four"
}
]
testList "firstByContains" [
testTask "succeeds when a document is found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.firstByContains PostgresDb.TableName {| Value = "another" |}
verifyDocById json "two"
}
testTask "succeeds when multiple documents are found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.firstByContains PostgresDb.TableName {| Sub = {| Foo = "green" |} |}
verifyAnyById json [ "two"; "four" ]
}
testTask "succeeds when a document is not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.firstByContains PostgresDb.TableName {| Value = "absent" |}
verifyNoDoc json
}
]
testList "firstByContainsOrdered" [
testTask "succeeds when sorting ascending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json =
Json.firstByContainsOrdered PostgresDb.TableName {| Sub = {| Foo = "green" |} |} [ Field.Named "Value" ]
verifyDocById json "two"
}
testTask "succeeds when sorting descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json =
Json.firstByContainsOrdered
PostgresDb.TableName {| Sub = {| Foo = "green" |} |} [ Field.Named "Value DESC" ]
verifyDocById json "four"
}
]
testList "firstByJsonPath" [
testTask "succeeds when a document is found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.firstByJsonPath PostgresDb.TableName """$.Value ? (@ == "FIRST!")"""
verifyDocById json "one"
}
testTask "succeeds when multiple documents are found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.firstByJsonPath PostgresDb.TableName """$.Sub.Foo ? (@ == "green")"""
verifyAnyById json [ "two"; "four" ]
}
testTask "succeeds when a document is not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json = Json.firstByJsonPath PostgresDb.TableName """$.Id ? (@ == "nope")"""
verifyNoDoc json
}
]
testList "firstByJsonPathOrdered" [
testTask "succeeds when sorting ascending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json =
Json.firstByJsonPathOrdered
PostgresDb.TableName """$.Sub.Foo ? (@ == "green")""" [ Field.Named "Sub.Bar" ]
verifyDocById json "two"
}
testTask "succeeds when sorting descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let! json =
Json.firstByJsonPathOrdered
PostgresDb.TableName """$.Sub.Foo ? (@ == "green")""" [ Field.Named "Sub.Bar DESC" ]
verifyDocById json "four"
}
]
testList "writeAll" [
testTask "succeeds when there is data" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeAll PostgresDb.TableName writer
verifyAllData (streamText stream)
}
testTask "succeeds when there is no data" {
use db = PostgresDb.BuildDb()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeAll PostgresDb.TableName writer
verifyEmpty (streamText stream)
}
]
testList "writeAllOrdered" [
testTask "succeeds when ordering numerically" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeAllOrdered PostgresDb.TableName writer [ Field.Named "n:NumValue" ]
verifyExpectedOrder (streamText stream) "one" "three" (Some "two") (Some "four") (Some "five")
}
testTask "succeeds when ordering numerically descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeAllOrdered PostgresDb.TableName writer [ Field.Named "n:NumValue DESC" ]
verifyExpectedOrder (streamText stream) "five" "four" (Some "two") (Some "three") (Some "one")
}
testTask "succeeds when ordering alphabetically" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeAllOrdered PostgresDb.TableName writer [ Field.Named "Id DESC" ]
verifyExpectedOrder (streamText stream) "two" "three" (Some "one") (Some "four") (Some "five")
}
]
testList "writeById" [
testTask "succeeds when a document is found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeById PostgresDb.TableName writer "two"
let json = streamText stream
Expect.stringStarts json """{"Id": "two",""" "An incorrect document was returned"
Expect.stringEnds json "}" "JSON should have ended with this document"
}
testTask "succeeds when a document is not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeById PostgresDb.TableName writer "three hundred eighty-seven"
verifyNoDoc (streamText stream)
}
]
testList "writeByFields" [
testTask "succeeds when documents are found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeByFields
PostgresDb.TableName writer All [ Field.In "Value" [ "purple"; "blue" ]; Field.Exists "Sub" ]
verifySingleById (streamText stream) "four"
}
testTask "succeeds when documents are found using IN with numeric field" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeByFields PostgresDb.TableName writer All [ Field.In "NumValue" [ 2; 4; 6; 8 ] ]
verifySingleById (streamText stream) "three"
}
testTask "succeeds when documents are not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeByFields
PostgresDb.TableName writer All [ Field.Equal "Value" "mauve"; Field.NotEqual "NumValue" 40 ]
verifyEmpty (streamText stream)
}
testTask "succeeds for InArray when matching documents exist" {
use db = PostgresDb.BuildDb()
do! Definition.ensureTable PostgresDb.TableName
for doc in ArrayDocument.TestDocuments do do! insert PostgresDb.TableName doc
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeByFields
PostgresDb.TableName writer All [ Field.InArray "Values" PostgresDb.TableName [ "c" ] ]
let json = streamText stream
verifyBeginEnd json
verifyDocById json "first"
verifyDocById json "second"
}
testTask "succeeds for InArray when no matching documents exist" {
use db = PostgresDb.BuildDb()
do! Definition.ensureTable PostgresDb.TableName
for doc in ArrayDocument.TestDocuments do do! insert PostgresDb.TableName doc
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeByFields
PostgresDb.TableName writer All [ Field.InArray "Values" PostgresDb.TableName [ "j" ] ]
verifyEmpty (streamText stream)
}
]
testList "writeByFieldsOrdered" [
testTask "succeeds when sorting ascending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeByFieldsOrdered
PostgresDb.TableName writer All [ Field.Equal "Value" "purple" ] [ Field.Named "Id" ]
verifyExpectedOrder (streamText stream) "five" "four" None None None
}
testTask "succeeds when sorting descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeByFieldsOrdered
PostgresDb.TableName writer All [ Field.Equal "Value" "purple" ] [ Field.Named "Id DESC" ]
verifyExpectedOrder (streamText stream) "four" "five" None None None
}
]
testList "writeByContains" [
testTask "succeeds when documents are found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeByContains PostgresDb.TableName writer {| Sub = {| Foo = "green" |} |}
let json = streamText stream
verifyBeginEnd json
verifyDocById json "two"
verifyDocById json "four"
}
testTask "succeeds when documents are not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeByContains PostgresDb.TableName writer {| Value = "mauve" |}
verifyEmpty (streamText stream)
}
]
testList "writeByContainsOrdered" [
// Id = two, Sub.Bar = blue; Id = four, Sub.Bar = red
testTask "succeeds when sorting ascending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeByContainsOrdered
PostgresDb.TableName writer {| Sub = {| Foo = "green" |} |} [ Field.Named "Sub.Bar" ]
verifyExpectedOrder (streamText stream) "two" "four" None None None
}
testTask "succeeds when sorting descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeByContainsOrdered
PostgresDb.TableName writer {| Sub = {| Foo = "green" |} |} [ Field.Named "Sub.Bar DESC" ]
verifyExpectedOrder (streamText stream) "four" "two" None None None
}
]
testList "writeByJsonPath" [
testTask "succeeds when documents are found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeByJsonPath PostgresDb.TableName writer "$.NumValue ? (@ < 15)"
let json = streamText stream
verifyBeginEnd json
verifyDocById json "one"
verifyDocById json "two"
verifyDocById json "three"
}
testTask "succeeds when documents are not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeByJsonPath PostgresDb.TableName writer "$.NumValue ? (@ < 0)"
verifyEmpty (streamText stream)
}
]
testList "writeByJsonPathOrdered" [
// Id = one, NumValue = 0; Id = two, NumValue = 10; Id = three, NumValue = 4
testTask "succeeds when sorting ascending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeByJsonPathOrdered
PostgresDb.TableName writer "$.NumValue ? (@ < 15)" [ Field.Named "n:NumValue" ]
verifyExpectedOrder (streamText stream) "one" "three" (Some "two") None None
}
testTask "succeeds when sorting descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeByJsonPathOrdered
PostgresDb.TableName writer "$.NumValue ? (@ < 15)" [ Field.Named "n:NumValue DESC" ]
verifyExpectedOrder (streamText stream) "two" "three" (Some "one") None None
}
]
testList "writeFirstByFields" [
testTask "succeeds when a document is found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeFirstByFields PostgresDb.TableName writer Any [ Field.Equal "Value" "another" ]
verifyDocById (streamText stream) "two"
}
testTask "succeeds when multiple documents are found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeFirstByFields PostgresDb.TableName writer Any [ Field.Equal "Value" "purple" ]
verifyAnyById (streamText stream) [ "five"; "four" ]
}
testTask "succeeds when a document is not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeFirstByFields PostgresDb.TableName writer Any [ Field.Equal "Value" "absent" ]
verifyNoDoc (streamText stream)
}
]
testList "writeFirstByFieldsOrdered" [
testTask "succeeds when sorting ascending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeFirstByFieldsOrdered
PostgresDb.TableName writer Any [ Field.Equal "Value" "purple" ] [ Field.Named "Id" ]
verifyDocById (streamText stream) "five"
}
testTask "succeeds when sorting descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeFirstByFieldsOrdered
PostgresDb.TableName writer Any [ Field.Equal "Value" "purple" ] [ Field.Named "Id DESC" ]
verifyDocById (streamText stream) "four"
}
]
testList "writeFirstByContains" [
testTask "succeeds when a document is found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeFirstByContains PostgresDb.TableName writer {| Value = "another" |}
verifyDocById (streamText stream) "two"
}
testTask "succeeds when multiple documents are found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeFirstByContains PostgresDb.TableName writer {| Sub = {| Foo = "green" |} |}
verifyAnyById (streamText stream) [ "two"; "four" ]
}
testTask "succeeds when a document is not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeFirstByContains PostgresDb.TableName writer {| Value = "absent" |}
verifyNoDoc (streamText stream)
}
]
testList "writeFirstByContainsOrdered" [
testTask "succeeds when sorting ascending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeFirstByContainsOrdered
PostgresDb.TableName writer {| Sub = {| Foo = "green" |} |} [ Field.Named "Value" ]
verifyDocById (streamText stream) "two"
}
testTask "succeeds when sorting descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeFirstByContainsOrdered
PostgresDb.TableName writer {| Sub = {| Foo = "green" |} |} [ Field.Named "Value DESC" ]
verifyDocById (streamText stream) "four"
}
]
testList "writeFirstByJsonPath" [
testTask "succeeds when a document is found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeFirstByJsonPath PostgresDb.TableName writer """$.Value ? (@ == "FIRST!")"""
verifyDocById (streamText stream) "one"
}
testTask "succeeds when multiple documents are found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeFirstByJsonPath PostgresDb.TableName writer """$.Sub.Foo ? (@ == "green")"""
verifyAnyById (streamText stream) [ "two"; "four" ]
}
testTask "succeeds when a document is not found" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeFirstByJsonPath PostgresDb.TableName writer """$.Id ? (@ == "nope")"""
verifyNoDoc (streamText stream)
}
]
testList "writeFirstByJsonPathOrdered" [
testTask "succeeds when sorting ascending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeFirstByJsonPathOrdered
PostgresDb.TableName writer """$.Sub.Foo ? (@ == "green")""" [ Field.Named "Sub.Bar" ]
verifyDocById (streamText stream) "two"
}
testTask "succeeds when sorting descending" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
use stream = new MemoryStream()
use writer = writeStream stream
do! Json.writeFirstByJsonPathOrdered
PostgresDb.TableName writer """$.Sub.Foo ? (@ == "green")""" [ Field.Named "Sub.Bar DESC" ]
verifyDocById (streamText stream) "four"
}
]
]
/// Integration tests for the Update module of the PostgreSQL library
let updateTests = testList "Update" [
testList "byId" [
testTask "succeeds when a document is updated" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
let testDoc = { emptyDoc with Id = "one"; Sub = Some { Foo = "blue"; Bar = "red" } }
do! Update.byId PostgresDb.TableName "one" testDoc
let! after = Find.byId<string, JsonDocument> PostgresDb.TableName "one"
Expect.isSome after "There should have been a document returned post-update"
Expect.equal after.Value testDoc "The updated document is not correct"
}
testTask "succeeds when no document is updated" {
use db = PostgresDb.BuildDb()
let! before = Count.all PostgresDb.TableName
Expect.equal before 0 "There should have been no documents returned"
// This not raising an exception is the test
do! Update.byId
PostgresDb.TableName "test" { emptyDoc with Id = "x"; Sub = Some { Foo = "blue"; Bar = "red" } }
}
]
testList "byFunc" [
testTask "succeeds when a document is updated" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! Update.byFunc PostgresDb.TableName _.Id { Id = "one"; Value = "le un"; NumValue = 1; Sub = None }
let! after = Find.byId<string, JsonDocument> PostgresDb.TableName "one"
Expect.isSome after "There should have been a document returned post-update"
Expect.equal
after.Value
{ Id = "one"; Value = "le un"; NumValue = 1; Sub = None }
"The updated document is not correct"
}
testTask "succeeds when no document is updated" {
use db = PostgresDb.BuildDb()
let! before = Count.all PostgresDb.TableName
Expect.equal before 0 "There should have been no documents returned"
// This not raising an exception is the test
do! Update.byFunc PostgresDb.TableName _.Id { Id = "one"; Value = "le un"; NumValue = 1; Sub = None }
}
]
]
/// Integration tests for the Patch module of the PostgreSQL library
let patchTests = testList "Patch" [
testList "byId" [
testTask "succeeds when a document is updated" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! Patch.byId PostgresDb.TableName "one" {| NumValue = 44 |}
let! after = Find.byId<string, JsonDocument> PostgresDb.TableName "one"
Expect.isSome after "There should have been a document returned post-update"
Expect.equal after.Value.NumValue 44 "The updated document is not correct"
}
testTask "succeeds when no document is updated" {
use db = PostgresDb.BuildDb()
let! before = Count.all PostgresDb.TableName
Expect.equal before 0 "There should have been no documents returned"
// This not raising an exception is the test
do! Patch.byId PostgresDb.TableName "test" {| Foo = "green" |}
}
]
testList "byFields" [
testTask "succeeds when a document is updated" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! Patch.byFields PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] {| NumValue = 77 |}
let! after = Count.byFields PostgresDb.TableName Any [ Field.Equal "NumValue" 77 ]
Expect.equal after 2 "There should have been 2 documents returned"
}
testTask "succeeds when no document is updated" {
use db = PostgresDb.BuildDb()
let! before = Count.all PostgresDb.TableName
Expect.equal before 0 "There should have been no documents returned"
// This not raising an exception is the test
do! Patch.byFields PostgresDb.TableName Any [ Field.Equal "Value" "burgundy" ] {| Foo = "green" |}
}
]
testList "byContains" [
testTask "succeeds when a document is updated" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! Patch.byContains PostgresDb.TableName {| Value = "purple" |} {| NumValue = 77 |}
let! after = Count.byContains PostgresDb.TableName {| NumValue = 77 |}
Expect.equal after 2 "There should have been 2 documents returned"
}
testTask "succeeds when no document is updated" {
use db = PostgresDb.BuildDb()
let! before = Count.all PostgresDb.TableName
Expect.equal before 0 "There should have been no documents returned"
// This not raising an exception is the test
do! Patch.byContains PostgresDb.TableName {| Value = "burgundy" |} {| Foo = "green" |}
}
]
testList "byJsonPath" [
testTask "succeeds when a document is updated" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! Patch.byJsonPath PostgresDb.TableName "$.NumValue ? (@ > 10)" {| NumValue = 1000 |}
let! after = Count.byJsonPath PostgresDb.TableName "$.NumValue ? (@ > 999)"
Expect.equal after 2 "There should have been 2 documents returned"
}
testTask "succeeds when no document is updated" {
use db = PostgresDb.BuildDb()
let! before = Count.all PostgresDb.TableName
Expect.equal before 0 "There should have been no documents returned"
// This not raising an exception is the test
do! Patch.byJsonPath PostgresDb.TableName "$.NumValue ? (@ < 0)" {| Foo = "green" |}
}
]
]
/// Integration tests for the RemoveFields module of the PostgreSQL library
let removeFieldsTests = testList "RemoveFields" [
testList "byId" [
testTask "succeeds when multiple fields are removed" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! RemoveFields.byId PostgresDb.TableName "two" [ "Sub"; "Value" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ]
Expect.equal noSubs 4 "There should now be 4 documents without Sub fields"
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ]
Expect.equal noValue 1 "There should be 1 document without Value fields"
}
testTask "succeeds when a single field is removed" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! RemoveFields.byId PostgresDb.TableName "two" [ "Sub" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ]
Expect.equal noSubs 4 "There should now be 4 documents without Sub fields"
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ]
Expect.equal noValue 0 "There should be no documents without Value fields"
}
testTask "succeeds when a field is not removed" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
// This not raising an exception is the test
do! RemoveFields.byId PostgresDb.TableName "two" [ "AFieldThatIsNotThere" ]
}
testTask "succeeds when no document is matched" {
use db = PostgresDb.BuildDb()
// This not raising an exception is the test
do! RemoveFields.byId PostgresDb.TableName "two" [ "Value" ]
}
]
testList "byFields" [
testTask "succeeds when multiple fields are removed" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! RemoveFields.byFields PostgresDb.TableName Any [ Field.Equal "NumValue" 17 ] [ "Sub"; "Value" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ]
Expect.equal noSubs 4 "There should now be 4 documents without Sub fields"
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ]
Expect.equal noValue 1 "There should be 1 document without Value fields"
}
testTask "succeeds when a single field is removed" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! RemoveFields.byFields PostgresDb.TableName Any [ Field.Equal "NumValue" 17 ] [ "Sub" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ]
Expect.equal noSubs 4 "There should now be 4 documents without Sub fields"
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ]
Expect.equal noValue 0 "There should be no documents without Value fields"
}
testTask "succeeds when a field is not removed" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
// This not raising an exception is the test
do! RemoveFields.byFields PostgresDb.TableName Any [ Field.Equal "NumValue" 17 ] [ "Nothing" ]
}
testTask "succeeds when no document is matched" {
use db = PostgresDb.BuildDb()
// This not raising an exception is the test
do! RemoveFields.byFields PostgresDb.TableName Any [ Field.NotEqual "Abracadabra" "apple" ] [ "Value" ]
}
]
testList "byContains" [
testTask "succeeds when multiple fields are removed" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! RemoveFields.byContains PostgresDb.TableName {| NumValue = 17 |} [ "Sub"; "Value" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ]
Expect.equal noSubs 4 "There should now be 4 documents without Sub fields"
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ]
Expect.equal noValue 1 "There should be 1 document without Value fields"
}
testTask "succeeds when a single field is removed" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! RemoveFields.byContains PostgresDb.TableName {| NumValue = 17 |} [ "Sub" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ]
Expect.equal noSubs 4 "There should now be 4 documents without Sub fields"
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ]
Expect.equal noValue 0 "There should be no documents without Value fields"
}
testTask "succeeds when a field is not removed" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
// This not raising an exception is the test
do! RemoveFields.byContains PostgresDb.TableName {| NumValue = 17 |} [ "Nothing" ]
}
testTask "succeeds when no document is matched" {
use db = PostgresDb.BuildDb()
// This not raising an exception is the test
do! RemoveFields.byContains PostgresDb.TableName {| Abracadabra = "apple" |} [ "Value" ]
}
]
testList "byJsonPath" [
testTask "succeeds when multiple fields are removed" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! RemoveFields.byJsonPath PostgresDb.TableName "$.NumValue ? (@ == 17)" [ "Sub"; "Value" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ]
Expect.equal noSubs 4 "There should now be 4 documents without Sub fields"
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ]
Expect.equal noValue 1 "There should be 1 document without Value fields"
}
testTask "succeeds when a single field is removed" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! RemoveFields.byJsonPath PostgresDb.TableName "$.NumValue ? (@ == 17)" [ "Sub" ]
let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ]
Expect.equal noSubs 4 "There should now be 4 documents without Sub fields"
let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ]
Expect.equal noValue 0 "There should be no documents without Value fields"
}
testTask "succeeds when a field is not removed" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
// This not raising an exception is the test
do! RemoveFields.byJsonPath PostgresDb.TableName "$.NumValue ? (@ == 17)" [ "Nothing" ]
}
testTask "succeeds when no document is matched" {
use db = PostgresDb.BuildDb()
// This not raising an exception is the test
do! RemoveFields.byJsonPath PostgresDb.TableName "$.Abracadabra ? (@ == \"apple\")" [ "Value" ]
}
]
]
/// Integration tests for the Delete module of the PostgreSQL library
let deleteTests = testList "Delete" [
testList "byId" [
testTask "succeeds when a document is deleted" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! Delete.byId PostgresDb.TableName "four"
let! remaining = Count.all PostgresDb.TableName
Expect.equal remaining 4 "There should have been 4 documents remaining"
}
testTask "succeeds when a document is not deleted" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! Delete.byId PostgresDb.TableName "thirty"
let! remaining = Count.all PostgresDb.TableName
Expect.equal remaining 5 "There should have been 5 documents remaining"
}
]
testList "byFields" [
testTask "succeeds when documents are deleted" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! Delete.byFields PostgresDb.TableName Any [ Field.Equal "Value" "purple" ]
let! remaining = Count.all PostgresDb.TableName
Expect.equal remaining 3 "There should have been 3 documents remaining"
}
testTask "succeeds when documents are not deleted" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! Delete.byFields PostgresDb.TableName Any [ Field.Equal "Value" "crimson" ]
let! remaining = Count.all PostgresDb.TableName
Expect.equal remaining 5 "There should have been 5 documents remaining"
}
]
testList "byContains" [
testTask "succeeds when documents are deleted" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! Delete.byContains PostgresDb.TableName {| Value = "purple" |}
let! remaining = Count.all PostgresDb.TableName
Expect.equal remaining 3 "There should have been 3 documents remaining"
}
testTask "succeeds when documents are not deleted" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! Delete.byContains PostgresDb.TableName {| Value = "crimson" |}
let! remaining = Count.all PostgresDb.TableName
Expect.equal remaining 5 "There should have been 5 documents remaining"
}
]
testList "byJsonPath" [
testTask "succeeds when documents are deleted" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! Delete.byJsonPath PostgresDb.TableName """$.Sub.Foo ? (@ == "green")"""
let! remaining = Count.all PostgresDb.TableName
Expect.equal remaining 3 "There should have been 3 documents remaining"
}
testTask "succeeds when documents are not deleted" {
use db = PostgresDb.BuildDb()
do! loadDocs ()
do! Delete.byJsonPath PostgresDb.TableName "$.NumValue ? (@ > 100)"
let! remaining = Count.all PostgresDb.TableName
Expect.equal remaining 5 "There should have been 5 documents remaining"
}
]
]
/// All tests for the PostgreSQL library
let all = testList "Postgres" [
testList "Unit" [ parametersTests; queryTests ]
testSequenced <| testList "Integration" [
configurationTests
customTests
definitionTests
documentTests
countTests
existsTests
findTests
jsonTests
updateTests
patchTests
removeFieldsTests
deleteTests
]
]