diff --git a/src/Tests.CSharp/SqliteCSharpTests.cs b/src/Tests.CSharp/SqliteCSharpTests.cs
index e0c534e..13cc1f3 100644
--- a/src/Tests.CSharp/SqliteCSharpTests.cs
+++ b/src/Tests.CSharp/SqliteCSharpTests.cs
@@ -1,6 +1,5 @@
using Expecto.CSharp;
using Expecto;
-using Microsoft.Data.Sqlite;
using Microsoft.FSharp.Core;
using BitBadger.Documents.Sqlite;
@@ -14,123 +13,125 @@ using static Runner;
public static class SqliteCSharpTests
{
///
- /// Unit tests for the SQLite library
+ /// Unit tests for the Query module of the SQLite library
///
- private static readonly Test Unit = TestList("Unit",
+ private static readonly Test QueryTests = TestList("Query",
[
- TestList("Query",
+ TestList("WhereByFields",
[
- TestList("WhereByFields",
- [
- TestCase("succeeds for a single field when a logical operator is passed", () =>
- {
- Expect.equal(
- Sqlite.Query.WhereByFields(FieldMatch.Any,
- [Field.GT("theField", 0).WithParameterName("@test")]),
- "data->>'theField' > @test", "WHERE clause not correct");
- }),
- TestCase("succeeds for a single field when an existence operator is passed", () =>
- {
- Expect.equal(Sqlite.Query.WhereByFields(FieldMatch.Any, [Field.NEX("thatField")]),
- "data->>'thatField' IS NULL", "WHERE clause not correct");
- }),
- TestCase("succeeds for a single field when a between operator is passed", () =>
- {
- Expect.equal(
- Sqlite.Query.WhereByFields(FieldMatch.All,
- [Field.BT("aField", 50, 99).WithParameterName("@range")]),
- "data->>'aField' BETWEEN @rangemin AND @rangemax", "WHERE clause not correct");
- }),
- TestCase("succeeds for all multiple fields with logical operators", () =>
- {
- Expect.equal(
- Sqlite.Query.WhereByFields(FieldMatch.All,
- [Field.EQ("theFirst", "1"), Field.EQ("numberTwo", "2")]),
- "data->>'theFirst' = @field0 AND data->>'numberTwo' = @field1", "WHERE clause not correct");
- }),
- TestCase("succeeds for any multiple fields with an existence operator", () =>
- {
- Expect.equal(
- Sqlite.Query.WhereByFields(FieldMatch.Any, [Field.NEX("thatField"), Field.GE("thisField", 18)]),
- "data->>'thatField' IS NULL OR data->>'thisField' >= @field0", "WHERE clause not correct");
- }),
- TestCase("succeeds for all multiple fields with between operators", () =>
- {
- Expect.equal(
- Sqlite.Query.WhereByFields(FieldMatch.All,
- [Field.BT("aField", 50, 99), Field.BT("anotherField", "a", "b")]),
- "data->>'aField' BETWEEN @field0min AND @field0max AND data->>'anotherField' BETWEEN @field1min AND @field1max",
- "WHERE clause not correct");
- })
- ]),
- TestCase("WhereById succeeds", () =>
+ TestCase("succeeds for a single field when a logical operator is passed", () =>
{
- Expect.equal(Sqlite.Query.WhereById("@id"), "data->>'Id' = @id", "WHERE clause not correct");
+ Expect.equal(
+ Sqlite.Query.WhereByFields(FieldMatch.Any, [Field.GT("theField", 0).WithParameterName("@test")]),
+ "data->>'theField' > @test", "WHERE clause not correct");
}),
- TestCase("Patch succeeds", () =>
+ TestCase("succeeds for a single field when an existence operator is passed", () =>
{
- Expect.equal(Sqlite.Query.Patch(SqliteDb.TableName),
- $"UPDATE {SqliteDb.TableName} SET data = json_patch(data, json(@data))", "Patch query not correct");
+ Expect.equal(Sqlite.Query.WhereByFields(FieldMatch.Any, [Field.NEX("thatField")]),
+ "data->>'thatField' IS NULL", "WHERE clause not correct");
}),
- TestCase("RemoveFields succeeds", () =>
+ TestCase("succeeds for a single field when a between operator is passed", () =>
{
- Expect.equal(Sqlite.Query.RemoveFields(SqliteDb.TableName, [new("@a", "a"), new("@b", "b")]),
- $"UPDATE {SqliteDb.TableName} SET data = json_remove(data, @a, @b)",
- "Field removal query not correct");
+ Expect.equal(
+ Sqlite.Query.WhereByFields(FieldMatch.All,
+ [Field.BT("aField", 50, 99).WithParameterName("@range")]),
+ "data->>'aField' BETWEEN @rangemin AND @rangemax", "WHERE clause not correct");
}),
- TestCase("ById succeeds", () =>
+ TestCase("succeeds for all multiple fields with logical operators", () =>
{
- Expect.equal(Sqlite.Query.ById("test", "14"), "test WHERE data->>'Id' = @id",
- "By-ID query not correct");
+ Expect.equal(
+ Sqlite.Query.WhereByFields(FieldMatch.All, [Field.EQ("theFirst", "1"), Field.EQ("numberTwo", "2")]),
+ "data->>'theFirst' = @field0 AND data->>'numberTwo' = @field1", "WHERE clause not correct");
}),
- TestCase("ByFields succeeds", () =>
+ TestCase("succeeds for any multiple fields with an existence operator", () =>
{
- Expect.equal(Sqlite.Query.ByFields("unit", FieldMatch.Any, [Field.GT("That", 14)]),
- "unit WHERE data->>'That' > @field0", "By-Field query not correct");
+ Expect.equal(
+ Sqlite.Query.WhereByFields(FieldMatch.Any, [Field.NEX("thatField"), Field.GE("thisField", 18)]),
+ "data->>'thatField' IS NULL OR data->>'thisField' >= @field0", "WHERE clause not correct");
}),
- TestCase("Definition.EnsureTable succeeds", () =>
+ TestCase("succeeds for all multiple fields with between operators", () =>
{
- Expect.equal(Sqlite.Query.Definition.EnsureTable("tbl"),
- "CREATE TABLE IF NOT EXISTS tbl (data TEXT NOT NULL)", "CREATE TABLE statement not correct");
+ Expect.equal(
+ Sqlite.Query.WhereByFields(FieldMatch.All,
+ [Field.BT("aField", 50, 99), Field.BT("anotherField", "a", "b")]),
+ "data->>'aField' BETWEEN @field0min AND @field0max AND data->>'anotherField' BETWEEN @field1min AND @field1max",
+ "WHERE clause not correct");
})
]),
- TestList("Parameters",
- [
- TestCase("Id succeeds", () =>
- {
- var theParam = Parameters.Id(7);
- Expect.equal(theParam.ParameterName, "@id", "The parameter name is incorrect");
- Expect.equal(theParam.Value, "7", "The parameter value is incorrect");
- }),
- TestCase("Json succeeds", () =>
- {
- var theParam = Parameters.Json("@test", new { Nice = "job" });
- Expect.equal(theParam.ParameterName, "@test", "The parameter name is incorrect");
- Expect.equal(theParam.Value, "{\"Nice\":\"job\"}", "The parameter value is incorrect");
- }),
-#pragma warning disable CS0618
- TestCase("AddField succeeds when adding a parameter", () =>
- {
- var paramList = Parameters.AddField("@field", Field.EQ("it", 99), []).ToList();
- Expect.hasLength(paramList, 1, "There should have been a parameter added");
- var theParam = paramList[0];
- Expect.equal(theParam.ParameterName, "@field", "The parameter name is incorrect");
- Expect.equal(theParam.Value, 99, "The parameter value is incorrect");
- }),
- TestCase("AddField succeeds when not adding a parameter", () =>
- {
- var paramSeq = Parameters.AddField("@it", Field.EX("Coffee"), []);
- Expect.isEmpty(paramSeq, "There should not have been any parameters added");
- }),
-#pragma warning restore CS0618
- TestCase("None succeeds", () =>
- {
- Expect.isEmpty(Parameters.None, "The parameter list should have been empty");
- })
- ])
- // Results are exhaustively executed in the context of other tests
+ TestCase("WhereById succeeds", () =>
+ {
+ Expect.equal(Sqlite.Query.WhereById("@id"), "data->>'Id' = @id", "WHERE clause not correct");
+ }),
+ TestCase("Patch succeeds", () =>
+ {
+ Expect.equal(Sqlite.Query.Patch(SqliteDb.TableName),
+ $"UPDATE {SqliteDb.TableName} SET data = json_patch(data, json(@data))", "Patch query not correct");
+ }),
+ TestCase("RemoveFields succeeds", () =>
+ {
+ Expect.equal(Sqlite.Query.RemoveFields(SqliteDb.TableName, [new("@a", "a"), new("@b", "b")]),
+ $"UPDATE {SqliteDb.TableName} SET data = json_remove(data, @a, @b)",
+ "Field removal query not correct");
+ }),
+ TestCase("ById succeeds", () =>
+ {
+ Expect.equal(Sqlite.Query.ById("test", "14"), "test WHERE data->>'Id' = @id", "By-ID query not correct");
+ }),
+ TestCase("ByFields succeeds", () =>
+ {
+ Expect.equal(Sqlite.Query.ByFields("unit", FieldMatch.Any, [Field.GT("That", 14)]),
+ "unit WHERE data->>'That' > @field0", "By-Field query not correct");
+ }),
+ TestCase("Definition.EnsureTable succeeds", () =>
+ {
+ Expect.equal(Sqlite.Query.Definition.EnsureTable("tbl"),
+ "CREATE TABLE IF NOT EXISTS tbl (data TEXT NOT NULL)", "CREATE TABLE statement not correct");
+ })
]);
+ ///
+ /// Unit tests for the Parameters module of the SQLite library
+ ///
+ private static readonly Test ParametersTests = TestList("Parameters",
+ [
+ TestCase("Id succeeds", () =>
+ {
+ var theParam = Parameters.Id(7);
+ Expect.equal(theParam.ParameterName, "@id", "The parameter name is incorrect");
+ Expect.equal(theParam.Value, "7", "The parameter value is incorrect");
+ }),
+ TestCase("Json succeeds", () =>
+ {
+ var theParam = Parameters.Json("@test", new { Nice = "job" });
+ Expect.equal(theParam.ParameterName, "@test", "The parameter name is incorrect");
+ Expect.equal(theParam.Value, "{\"Nice\":\"job\"}", "The parameter value is incorrect");
+ }),
+#pragma warning disable CS0618
+ TestCase("AddField succeeds when adding a parameter", () =>
+ {
+ var paramList = Parameters.AddField("@field", Field.EQ("it", 99), []).ToList();
+ Expect.hasLength(paramList, 1, "There should have been a parameter added");
+ var theParam = paramList[0];
+ Expect.equal(theParam.ParameterName, "@field", "The parameter name is incorrect");
+ Expect.equal(theParam.Value, 99, "The parameter value is incorrect");
+ }),
+ TestCase("AddField succeeds when not adding a parameter", () =>
+ {
+ var paramSeq = Parameters.AddField("@it", Field.EX("Coffee"), []);
+ Expect.isEmpty(paramSeq, "There should not have been any parameters added");
+ }),
+#pragma warning restore CS0618
+ TestCase("None succeeds", () =>
+ {
+ Expect.isEmpty(Parameters.None, "The parameter list should have been empty");
+ })
+ ]);
+
+ // Results are exhaustively executed in the context of other tests
+
+ ///
+ /// Documents used for integration tests
+ ///
private static readonly List TestDocuments =
[
new() { Id = "one", Value = "FIRST!", NumValue = 0 },
@@ -148,144 +149,158 @@ public static class SqliteCSharpTests
foreach (var doc in TestDocuments) await Document.Insert(SqliteDb.TableName, doc);
}
- private static readonly Test Integration = TestList("Integration",
- [
- TestCase("Configuration.UseConnectionString succeeds", () =>
+ ///
+ /// Integration tests for the Configuration module of the SQLite library
+ ///
+ private static readonly Test ConfigurationTests = TestCase("Configuration.UseConnectionString succeeds", () =>
+ {
+ try
{
- try
+ Sqlite.Configuration.UseConnectionString("Data Source=test.db");
+ Expect.equal(Sqlite.Configuration.connectionString,
+ new FSharpOption("Data Source=test.db;Foreign Keys=True"), "Connection string incorrect");
+ }
+ finally
+ {
+ Sqlite.Configuration.UseConnectionString("Data Source=:memory:");
+ }
+ });
+
+ ///
+ /// Integration tests for the Custom module of the SQLite library
+ ///
+ private static readonly Test CustomTests = TestList("Custom",
+ [
+ TestList("Single",
+ [
+ TestCase("succeeds when a row is found", async () =>
{
- Sqlite.Configuration.UseConnectionString("Data Source=test.db");
- Expect.equal(Sqlite.Configuration.connectionString,
- new FSharpOption("Data Source=test.db;Foreign Keys=True"), "Connection string incorrect");
- }
- finally
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ var doc = await Custom.Single($"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id",
+ [Parameters.Id("one")], Results.FromData);
+ Expect.isNotNull(doc, "There should have been a document returned");
+ Expect.equal(doc!.Id, "one", "The incorrect document was returned");
+ }),
+ TestCase("succeeds when a row is not found", async () =>
{
- Sqlite.Configuration.UseConnectionString("Data Source=:memory:");
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ var doc = await Custom.Single($"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id",
+ [Parameters.Id("eighty")], Results.FromData);
+ Expect.isNull(doc, "There should not have been a document returned");
+ })
+ ]),
+ TestList("List",
+ [
+ TestCase("succeeds when data is found", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ var docs = await Custom.List(Query.Find(SqliteDb.TableName), Parameters.None,
+ Results.FromData);
+ Expect.equal(docs.Count, 5, "There should have been 5 documents returned");
+ }),
+ TestCase("succeeds when data is not found", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ var docs = await Custom.List(
+ $"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value", [new("@value", 100)],
+ Results.FromData);
+ Expect.isEmpty(docs, "There should have been no documents returned");
+ })
+ ]),
+ TestList("NonQuery",
+ [
+ TestCase("succeeds when operating on data", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ await Custom.NonQuery($"DELETE FROM {SqliteDb.TableName}", Parameters.None);
+
+ var remaining = await Count.All(SqliteDb.TableName);
+ Expect.equal(remaining, 0L, "There should be no documents remaining in the table");
+ }),
+ TestCase("succeeds when no data matches where clause", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ await Custom.NonQuery($"DELETE FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value",
+ [new("@value", 100)]);
+
+ var remaining = await Count.All(SqliteDb.TableName);
+ Expect.equal(remaining, 5L, "There should be 5 documents remaining in the table");
+ })
+ ]),
+ TestCase("Scalar succeeds", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+
+ var nbr = await Custom.Scalar("SELECT 5 AS test_value", Parameters.None, rdr => rdr.GetInt32(0));
+ Expect.equal(nbr, 5, "The query should have returned the number 5");
+ })
+ ]);
+
+ ///
+ /// Integration tests for the Definition module of the SQLite library
+ ///
+ private static readonly Test DefinitionTests = TestList("Definition",
+ [
+ TestCase("EnsureTable succeeds", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+
+ var exists = await ItExists("ensured");
+ var alsoExists = await ItExists("idx_ensured_key");
+ Expect.isFalse(exists, "The table should not exist already");
+ Expect.isFalse(alsoExists, "The key index should not exist already");
+
+ await Definition.EnsureTable("ensured");
+
+ exists = await ItExists("ensured");
+ alsoExists = await ItExists("idx_ensured_key");
+ Expect.isTrue(exists, "The table should now exist");
+ Expect.isTrue(alsoExists, "The key index should now exist");
+ return;
+
+ async ValueTask ItExists(string name)
+ {
+ return await Custom.Scalar($"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = @name) AS it",
+ [new("@name", name)], Results.ToExists);
}
}),
- TestList("Custom",
- [
- TestList("Single",
- [
- TestCase("succeeds when a row is found", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
+ TestCase("EnsureFieldIndex succeeds", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
- var doc = await Custom.Single($"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id",
- new[] { Parameters.Id("one") }, Results.FromData);
- Expect.isNotNull(doc, "There should have been a document returned");
- Expect.equal(doc!.Id, "one", "The incorrect document was returned");
- }),
- TestCase("succeeds when a row is not found", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
+ var exists = await IndexExists();
+ Expect.isFalse(exists, "The index should not exist already");
- var doc = await Custom.Single($"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id",
- new[] { Parameters.Id("eighty") }, Results.FromData);
- Expect.isNull(doc, "There should not have been a document returned");
- })
- ]),
- TestList("List",
- [
- TestCase("succeeds when data is found", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
+ await Definition.EnsureTable("ensured");
+ await Definition.EnsureFieldIndex("ensured", "test", ["Id", "Category"]);
+ exists = await IndexExists();
+ Expect.isTrue(exists, "The index should now exist");
+ return;
- var docs = await Custom.List(Query.Find(SqliteDb.TableName), Parameters.None,
- Results.FromData);
- Expect.equal(docs.Count, 5, "There should have been 5 documents returned");
- }),
- TestCase("succeeds when data is not found", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
+ Task IndexExists() => Custom.Scalar(
+ $"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = 'idx_ensured_test') AS it",
+ Parameters.None, Results.ToExists);
+ })
+ ]);
- var docs = await Custom.List(
- $"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value",
- new[] { new SqliteParameter("@value", 100) }, Results.FromData);
- Expect.isEmpty(docs, "There should have been no documents returned");
- })
- ]),
- TestList("NonQuery",
- [
- TestCase("succeeds when operating on data", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- await Custom.NonQuery($"DELETE FROM {SqliteDb.TableName}", Parameters.None);
-
- var remaining = await Count.All(SqliteDb.TableName);
- Expect.equal(remaining, 0L, "There should be no documents remaining in the table");
- }),
- TestCase("succeeds when no data matches where clause", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- await Custom.NonQuery($"DELETE FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value",
- new[] { new SqliteParameter("@value", 100) });
-
- var remaining = await Count.All(SqliteDb.TableName);
- Expect.equal(remaining, 5L, "There should be 5 documents remaining in the table");
- })
- ]),
- TestCase("Scalar succeeds", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
-
- var nbr = await Custom.Scalar("SELECT 5 AS test_value", Parameters.None, rdr => rdr.GetInt32(0));
- Expect.equal(nbr, 5, "The query should have returned the number 5");
- })
- ]),
- TestList("Definition",
- [
- TestCase("EnsureTable succeeds", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
-
- var exists = await ItExists("ensured");
- var alsoExists = await ItExists("idx_ensured_key");
- Expect.isFalse(exists, "The table should not exist already");
- Expect.isFalse(alsoExists, "The key index should not exist already");
-
- await Definition.EnsureTable("ensured");
-
- exists = await ItExists("ensured");
- alsoExists = await ItExists("idx_ensured_key");
- Expect.isTrue(exists, "The table should now exist");
- Expect.isTrue(alsoExists, "The key index should now exist");
- return;
-
- async ValueTask ItExists(string name)
- {
- return await Custom.Scalar(
- $"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = @name) AS it",
- new SqliteParameter[] { new("@name", name) }, Results.ToExists);
- }
- }),
- TestCase("EnsureFieldIndex succeeds", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
-
- var exists = await IndexExists();
- Expect.isFalse(exists, "The index should not exist already");
-
- await Definition.EnsureTable("ensured");
- await Definition.EnsureFieldIndex("ensured", "test", new[] { "Id", "Category" });
- exists = await IndexExists();
- Expect.isTrue(exists, "The index should now exist");
- return;
-
- Task IndexExists() => Custom.Scalar(
- $"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = 'idx_ensured_test') AS it",
- Parameters.None, Results.ToExists);
- })
- ]),
- TestList("Document.Insert",
+ ///
+ /// Integration tests for the Document module of the SQLite library
+ ///
+ private static readonly Test DocumentTests = TestList("Document",
+ [
+ TestList("Insert",
[
TestCase("succeeds", async () =>
{
@@ -344,401 +359,443 @@ public static class SqliteCSharpTests
Expect.equal(after!.Id, "test", "The updated document is not correct");
Expect.isNull(after.Sub, "There should not have been a sub-document in the updated document");
})
- ]),
- TestList("Count",
+ ])
+ ]);
+
+ ///
+ /// Integration tests for the Count module of the SQLite library
+ ///
+ private static readonly Test CountTests = TestList("Count",
+ [
+ TestCase("All succeeds", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ var theCount = await Count.All(SqliteDb.TableName);
+ Expect.equal(theCount, 5L, "There should have been 5 matching documents");
+ }),
+ TestList("ByFields",
[
- TestCase("All succeeds", async () =>
+ TestCase("succeeds for numeric range", async () =>
{
await using var db = await SqliteDb.BuildDb();
await LoadDocs();
- var theCount = await Count.All(SqliteDb.TableName);
- Expect.equal(theCount, 5L, "There should have been 5 matching documents");
+ var theCount = await Count.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.BT("NumValue", 10, 20)]);
+ Expect.equal(theCount, 3L, "There should have been 3 matching documents");
}),
- TestList("ByFields",
- [
- TestCase("succeeds for numeric range", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
+ TestCase("succeeds for non-numeric range", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
- var theCount = await Count.ByFields(SqliteDb.TableName, FieldMatch.Any,
- [Field.BT("NumValue", 10, 20)]);
- Expect.equal(theCount, 3L, "There should have been 3 matching documents");
- }),
- TestCase("succeeds for non-numeric range", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- var theCount = await Count.ByFields(SqliteDb.TableName, FieldMatch.Any,
- [Field.BT("Value", "aardvark", "apple")]);
- Expect.equal(theCount, 1L, "There should have been 1 matching document");
- })
- ])
- ]),
- TestList("Exists",
- [
- TestList("ById",
- [
- TestCase("succeeds when a document exists", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- var exists = await Exists.ById(SqliteDb.TableName, "three");
- Expect.isTrue(exists, "There should have been an existing document");
- }),
- TestCase("succeeds when a document does not exist", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- var exists = await Exists.ById(SqliteDb.TableName, "seven");
- Expect.isFalse(exists, "There should not have been an existing document");
- })
- ]),
- TestList("ByFields",
- [
- TestCase("succeeds when documents exist", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- var exists = await Exists.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.GE("NumValue", 10)]);
- Expect.isTrue(exists, "There should have been existing documents");
- }),
- TestCase("succeeds when no matching documents exist", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- var exists = await Exists.ByFields(SqliteDb.TableName, FieldMatch.Any,
- [Field.EQ("Nothing", "none")]);
- Expect.isFalse(exists, "There should not have been any existing documents");
- })
- ])
- ]),
- TestList("Find",
- [
- TestList("All",
- [
- TestCase("succeeds when there is data", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
-
- await Document.Insert(SqliteDb.TableName, new JsonDocument { Id = "one", Value = "two" });
- await Document.Insert(SqliteDb.TableName, new JsonDocument { Id = "three", Value = "four" });
- await Document.Insert(SqliteDb.TableName, new JsonDocument { Id = "five", Value = "six" });
-
- var results = await Find.All(SqliteDb.TableName);
- Expect.equal(results.Count, 3, "There should have been 3 documents returned");
- }),
- TestCase("succeeds when there is no data", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- var results = await Find.All(SqliteDb.TableName);
- Expect.isEmpty(results, "There should have been no documents returned");
- })
- ]),
- TestList("ById",
- [
- TestCase("succeeds when a document is found", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- var doc = await Find.ById(SqliteDb.TableName, "two");
- Expect.isNotNull(doc, "There should have been a document returned");
- Expect.equal(doc!.Id, "two", "The incorrect document was returned");
- }),
- TestCase("succeeds when a document is not found", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- var doc = await Find.ById(SqliteDb.TableName, "twenty two");
- Expect.isNull(doc, "There should not have been a document returned");
- })
- ]),
- TestList("ByFields",
- [
- TestCase("succeeds when documents are found", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- var docs = await Find.ByFields(SqliteDb.TableName, FieldMatch.Any,
- [Field.GT("NumValue", 15)]);
- Expect.equal(docs.Count, 2, "There should have been two documents returned");
- }),
- TestCase("succeeds when documents are not found", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- var docs = await Find.ByFields(SqliteDb.TableName, FieldMatch.Any,
- [Field.EQ("Value", "mauve")]);
- Expect.isEmpty(docs, "There should have been no documents returned");
- })
- ]),
- TestList("FirstByFields",
- [
- TestCase("succeeds when a document is found", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- var doc = await Find.FirstByFields(SqliteDb.TableName, FieldMatch.Any,
- [Field.EQ("Value", "another")]);
- Expect.isNotNull(doc, "There should have been a document returned");
- Expect.equal(doc!.Id, "two", "The incorrect document was returned");
- }),
- TestCase("succeeds when multiple documents are found", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- var doc = await Find.FirstByFields(SqliteDb.TableName, FieldMatch.Any,
- [Field.EQ("Sub.Foo", "green")]);
- Expect.isNotNull(doc, "There should have been a document returned");
- Expect.contains(new[] { "two", "four" }, doc!.Id, "An incorrect document was returned");
- }),
- TestCase("succeeds when a document is not found", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- var doc = await Find.FirstByFields(SqliteDb.TableName, FieldMatch.Any,
- [Field.EQ("Value", "absent")]);
- Expect.isNull(doc, "There should not have been a document returned");
- })
- ])
- ]),
- TestList("Update",
- [
- TestList("ById",
- [
- TestCase("succeeds when a document is updated", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- var testDoc = new JsonDocument { Id = "one", Sub = new() { Foo = "blue", Bar = "red" } };
- await Update.ById(SqliteDb.TableName, "one", testDoc);
- var after = await Find.ById(SqliteDb.TableName, "one");
- Expect.isNotNull(after, "There should have been a document returned post-update");
- Expect.equal(after!.Id, "one", "The updated document is not correct");
- Expect.isNotNull(after.Sub, "The updated document should have had a sub-document");
- Expect.equal(after.Sub!.Foo, "blue", "The updated sub-document is not correct");
- Expect.equal(after.Sub.Bar, "red", "The updated sub-document is not correct");
- }),
- TestCase("succeeds when no document is updated", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
-
- var before = await Find.All(SqliteDb.TableName);
- Expect.isEmpty(before, "There should have been no documents returned");
-
- // This not raising an exception is the test
- await Update.ById(SqliteDb.TableName, "test",
- new JsonDocument { Id = "x", Sub = new() { Foo = "blue", Bar = "red" } });
- })
- ]),
- TestList("ByFunc",
- [
- TestCase("succeeds when a document is updated", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- await Update.ByFunc(SqliteDb.TableName, doc => doc.Id,
- new JsonDocument { Id = "one", Value = "le un", NumValue = 1 });
- var after = await Find.ById(SqliteDb.TableName, "one");
- Expect.isNotNull(after, "There should have been a document returned post-update");
- Expect.equal(after!.Id, "one", "The updated document is incorrect");
- Expect.equal(after.Value, "le un", "The updated document is incorrect");
- Expect.equal(after.NumValue, 1, "The updated document is incorrect");
- Expect.isNull(after.Sub, "The updated document should not have a sub-document");
- }),
- TestCase("succeeds when no document is updated", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
-
- var before = await Find.All(SqliteDb.TableName);
- Expect.isEmpty(before, "There should have been no documents returned");
-
- // This not raising an exception is the test
- await Update.ByFunc(SqliteDb.TableName, doc => doc.Id,
- new JsonDocument { Id = "one", Value = "le un", NumValue = 1 });
- })
- ]),
- ]),
- TestList("Patch",
- [
- TestList("ById",
- [
- TestCase("succeeds when a document is updated", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- await Patch.ById(SqliteDb.TableName, "one", new { NumValue = 44 });
- var after = await Find.ById(SqliteDb.TableName, "one");
- Expect.isNotNull(after, "There should have been a document returned post-update");
- Expect.equal(after!.Id, "one", "The updated document is not correct");
- Expect.equal(after.NumValue, 44, "The updated document is not correct");
- }),
- TestCase("succeeds when no document is updated", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
-
- var before = await Find.All(SqliteDb.TableName);
- Expect.isEmpty(before, "There should have been no documents returned");
-
- // This not raising an exception is the test
- await Patch.ById(SqliteDb.TableName, "test", new { Foo = "green" });
- })
- ]),
- TestList("ByFields",
- [
- TestCase("succeeds when a document is updated", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- await Patch.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("Value", "purple")],
- new { NumValue = 77 });
- var after = await Count.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", 77)]);
- Expect.equal(after, 2L, "There should have been 2 documents returned");
- }),
- TestCase("succeeds when no document is updated", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
-
- var before = await Find.All(SqliteDb.TableName);
- Expect.isEmpty(before, "There should have been no documents returned");
-
- // This not raising an exception is the test
- await Patch.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("Value", "burgundy")],
- new { Foo = "green" });
- })
- ])
- ]),
- TestList("RemoveFields",
- [
- TestList("ById",
- [
- TestCase("succeeds when fields are removed", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- await RemoveFields.ById(SqliteDb.TableName, "two", new[] { "Sub", "Value" });
- var updated = await Find.ById(SqliteDb.TableName, "two");
- Expect.isNotNull(updated, "The updated document should have been retrieved");
- Expect.equal(updated.Value, "", "The string value should have been removed");
- Expect.isNull(updated.Sub, "The sub-document should have been removed");
- }),
- TestCase("succeeds when a field is not removed", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- // This not raising an exception is the test
- await RemoveFields.ById(SqliteDb.TableName, "two", new[] { "AFieldThatIsNotThere" });
- }),
- TestCase("succeeds when no document is matched", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
-
- // This not raising an exception is the test
- await RemoveFields.ById(SqliteDb.TableName, "two", new[] { "Value" });
- })
- ]),
- TestList("ByFields",
- [
- TestCase("succeeds when a field is removed", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- await RemoveFields.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", 17)],
- new[] { "Sub" });
- var updated = await Find.ById(SqliteDb.TableName, "four");
- Expect.isNotNull(updated, "The updated document should have been retrieved");
- Expect.isNull(updated.Sub, "The sub-document should have been removed");
- }),
- TestCase("succeeds when a field is not removed", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- // This not raising an exception is the test
- await RemoveFields.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", 17)],
- new[] { "Nothing" });
- }),
- TestCase("succeeds when no document is matched", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
-
- // This not raising an exception is the test
- await RemoveFields.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.NE("Abracadabra", "apple")],
- new[] { "Value" });
- })
- ])
- ]),
- TestList("Delete",
- [
- TestList("ById",
- [
- TestCase("succeeds when a document is deleted", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- await Delete.ById(SqliteDb.TableName, "four");
- var remaining = await Count.All(SqliteDb.TableName);
- Expect.equal(remaining, 4L, "There should have been 4 documents remaining");
- }),
- TestCase("succeeds when a document is not deleted", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- await Delete.ById(SqliteDb.TableName, "thirty");
- var remaining = await Count.All(SqliteDb.TableName);
- Expect.equal(remaining, 5L, "There should have been 5 documents remaining");
- })
- ]),
- TestList("ByFields",
- [
- TestCase("succeeds when documents are deleted", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- await Delete.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.NE("Value", "purple")]);
- var remaining = await Count.All(SqliteDb.TableName);
- Expect.equal(remaining, 2L, "There should have been 2 documents remaining");
- }),
- TestCase("succeeds when documents are not deleted", async () =>
- {
- await using var db = await SqliteDb.BuildDb();
- await LoadDocs();
-
- await Delete.ByFields(SqliteDb.TableName, FieldMatch.All, [Field.EQ("Value", "crimson")]);
- var remaining = await Count.All(SqliteDb.TableName);
- Expect.equal(remaining, 5L, "There should have been 5 documents remaining");
- })
- ])
- ]),
- TestCase("Clean up database", () => Sqlite.Configuration.UseConnectionString("data source=:memory:"))
+ var theCount = await Count.ByFields(SqliteDb.TableName, FieldMatch.Any,
+ [Field.BT("Value", "aardvark", "apple")]);
+ Expect.equal(theCount, 1L, "There should have been 1 matching document");
+ })
+ ])
]);
+ ///
+ /// Integration tests for the Exists module of the SQLite library
+ ///
+ private static readonly Test ExistsTests = TestList("Exists",
+ [
+ TestList("ById",
+ [
+ TestCase("succeeds when a document exists", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ var exists = await Exists.ById(SqliteDb.TableName, "three");
+ Expect.isTrue(exists, "There should have been an existing document");
+ }),
+ TestCase("succeeds when a document does not exist", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ var exists = await Exists.ById(SqliteDb.TableName, "seven");
+ Expect.isFalse(exists, "There should not have been an existing document");
+ })
+ ]),
+ TestList("ByFields",
+ [
+ TestCase("succeeds when documents exist", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ var exists = await Exists.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.GE("NumValue", 10)]);
+ Expect.isTrue(exists, "There should have been existing documents");
+ }),
+ TestCase("succeeds when no matching documents exist", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ var exists = await Exists.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("Nothing", "none")]);
+ Expect.isFalse(exists, "There should not have been any existing documents");
+ })
+ ])
+ ]);
+
+ ///
+ /// Integration tests for the Find module of the SQLite library
+ ///
+ private static readonly Test FindTests = TestList("Find",
+ [
+ TestList("All",
+ [
+ TestCase("succeeds when there is data", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+
+ await Document.Insert(SqliteDb.TableName, new JsonDocument { Id = "one", Value = "two" });
+ await Document.Insert(SqliteDb.TableName, new JsonDocument { Id = "three", Value = "four" });
+ await Document.Insert(SqliteDb.TableName, new JsonDocument { Id = "five", Value = "six" });
+
+ var results = await Find.All(SqliteDb.TableName);
+ Expect.equal(results.Count, 3, "There should have been 3 documents returned");
+ }),
+ TestCase("succeeds when there is no data", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ var results = await Find.All(SqliteDb.TableName);
+ Expect.isEmpty(results, "There should have been no documents returned");
+ })
+ ]),
+ TestList("ById",
+ [
+ TestCase("succeeds when a document is found", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ var doc = await Find.ById(SqliteDb.TableName, "two");
+ Expect.isNotNull(doc, "There should have been a document returned");
+ Expect.equal(doc!.Id, "two", "The incorrect document was returned");
+ }),
+ TestCase("succeeds when a document is not found", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ var doc = await Find.ById(SqliteDb.TableName, "twenty two");
+ Expect.isNull(doc, "There should not have been a document returned");
+ })
+ ]),
+ TestList("ByFields",
+ [
+ TestCase("succeeds when documents are found", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ var docs = await Find.ByFields(SqliteDb.TableName, FieldMatch.Any,
+ [Field.GT("NumValue", 15)]);
+ Expect.equal(docs.Count, 2, "There should have been two documents returned");
+ }),
+ TestCase("succeeds when documents are not found", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ var docs = await Find.ByFields(SqliteDb.TableName, FieldMatch.Any,
+ [Field.EQ("Value", "mauve")]);
+ Expect.isEmpty(docs, "There should have been no documents returned");
+ })
+ ]),
+ TestList("FirstByFields",
+ [
+ TestCase("succeeds when a document is found", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ var doc = await Find.FirstByFields(SqliteDb.TableName, FieldMatch.Any,
+ [Field.EQ("Value", "another")]);
+ Expect.isNotNull(doc, "There should have been a document returned");
+ Expect.equal(doc!.Id, "two", "The incorrect document was returned");
+ }),
+ TestCase("succeeds when multiple documents are found", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ var doc = await Find.FirstByFields(SqliteDb.TableName, FieldMatch.Any,
+ [Field.EQ("Sub.Foo", "green")]);
+ Expect.isNotNull(doc, "There should have been a document returned");
+ Expect.contains(["two", "four"], doc!.Id, "An incorrect document was returned");
+ }),
+ TestCase("succeeds when a document is not found", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ var doc = await Find.FirstByFields(SqliteDb.TableName, FieldMatch.Any,
+ [Field.EQ("Value", "absent")]);
+ Expect.isNull(doc, "There should not have been a document returned");
+ })
+ ])
+ ]);
+
+ ///
+ /// Integration tests for the Update module of the SQLite library
+ ///
+ private static readonly Test UpdateTests = TestList("Update",
+ [
+ TestList("ById",
+ [
+ TestCase("succeeds when a document is updated", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ var testDoc = new JsonDocument { Id = "one", Sub = new() { Foo = "blue", Bar = "red" } };
+ await Update.ById(SqliteDb.TableName, "one", testDoc);
+ var after = await Find.ById(SqliteDb.TableName, "one");
+ Expect.isNotNull(after, "There should have been a document returned post-update");
+ Expect.equal(after!.Id, "one", "The updated document is not correct");
+ Expect.isNotNull(after.Sub, "The updated document should have had a sub-document");
+ Expect.equal(after.Sub!.Foo, "blue", "The updated sub-document is not correct");
+ Expect.equal(after.Sub.Bar, "red", "The updated sub-document is not correct");
+ }),
+ TestCase("succeeds when no document is updated", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+
+ var before = await Find.All(SqliteDb.TableName);
+ Expect.isEmpty(before, "There should have been no documents returned");
+
+ // This not raising an exception is the test
+ await Update.ById(SqliteDb.TableName, "test",
+ new JsonDocument { Id = "x", Sub = new() { Foo = "blue", Bar = "red" } });
+ })
+ ]),
+ TestList("ByFunc",
+ [
+ TestCase("succeeds when a document is updated", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ await Update.ByFunc(SqliteDb.TableName, doc => doc.Id,
+ new JsonDocument { Id = "one", Value = "le un", NumValue = 1 });
+ var after = await Find.ById(SqliteDb.TableName, "one");
+ Expect.isNotNull(after, "There should have been a document returned post-update");
+ Expect.equal(after!.Id, "one", "The updated document is incorrect");
+ Expect.equal(after.Value, "le un", "The updated document is incorrect");
+ Expect.equal(after.NumValue, 1, "The updated document is incorrect");
+ Expect.isNull(after.Sub, "The updated document should not have a sub-document");
+ }),
+ TestCase("succeeds when no document is updated", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+
+ var before = await Find.All(SqliteDb.TableName);
+ Expect.isEmpty(before, "There should have been no documents returned");
+
+ // This not raising an exception is the test
+ await Update.ByFunc(SqliteDb.TableName, doc => doc.Id,
+ new JsonDocument { Id = "one", Value = "le un", NumValue = 1 });
+ })
+ ]),
+ ]);
+
+ ///
+ /// Integration tests for the Patch module of the SQLite library
+ ///
+ private static readonly Test PatchTests = TestList("Patch",
+ [
+ TestList("ById",
+ [
+ TestCase("succeeds when a document is updated", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ await Patch.ById(SqliteDb.TableName, "one", new { NumValue = 44 });
+ var after = await Find.ById(SqliteDb.TableName, "one");
+ Expect.isNotNull(after, "There should have been a document returned post-update");
+ Expect.equal(after!.Id, "one", "The updated document is not correct");
+ Expect.equal(after.NumValue, 44, "The updated document is not correct");
+ }),
+ TestCase("succeeds when no document is updated", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+
+ var before = await Find.All(SqliteDb.TableName);
+ Expect.isEmpty(before, "There should have been no documents returned");
+
+ // This not raising an exception is the test
+ await Patch.ById(SqliteDb.TableName, "test", new { Foo = "green" });
+ })
+ ]),
+ TestList("ByFields",
+ [
+ TestCase("succeeds when a document is updated", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ await Patch.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("Value", "purple")],
+ new { NumValue = 77 });
+ var after = await Count.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", 77)]);
+ Expect.equal(after, 2L, "There should have been 2 documents returned");
+ }),
+ TestCase("succeeds when no document is updated", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+
+ var before = await Find.All(SqliteDb.TableName);
+ Expect.isEmpty(before, "There should have been no documents returned");
+
+ // This not raising an exception is the test
+ await Patch.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("Value", "burgundy")],
+ new { Foo = "green" });
+ })
+ ])
+ ]);
+
+ ///
+ /// Integration tests for the RemoveFields module of the SQLite library
+ ///
+ private static readonly Test RemoveFieldsTests = TestList("RemoveFields",
+ [
+ TestList("ById",
+ [
+ TestCase("succeeds when fields are removed", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ await RemoveFields.ById(SqliteDb.TableName, "two", ["Sub", "Value"]);
+ var updated = await Find.ById(SqliteDb.TableName, "two");
+ Expect.isNotNull(updated, "The updated document should have been retrieved");
+ Expect.equal(updated.Value, "", "The string value should have been removed");
+ Expect.isNull(updated.Sub, "The sub-document should have been removed");
+ }),
+ TestCase("succeeds when a field is not removed", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ // This not raising an exception is the test
+ await RemoveFields.ById(SqliteDb.TableName, "two", ["AFieldThatIsNotThere"]);
+ }),
+ TestCase("succeeds when no document is matched", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+
+ // This not raising an exception is the test
+ await RemoveFields.ById(SqliteDb.TableName, "two", ["Value"]);
+ })
+ ]),
+ TestList("ByFields",
+ [
+ TestCase("succeeds when a field is removed", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ await RemoveFields.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", 17)], ["Sub"]);
+ var updated = await Find.ById(SqliteDb.TableName, "four");
+ Expect.isNotNull(updated, "The updated document should have been retrieved");
+ Expect.isNull(updated.Sub, "The sub-document should have been removed");
+ }),
+ TestCase("succeeds when a field is not removed", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ // This not raising an exception is the test
+ await RemoveFields.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", 17)],
+ ["Nothing"]);
+ }),
+ TestCase("succeeds when no document is matched", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+
+ // This not raising an exception is the test
+ await RemoveFields.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.NE("Abracadabra", "apple")],
+ ["Value"]);
+ })
+ ])
+ ]);
+
+ ///
+ /// Integration tests for the Delete module of the SQLite library
+ ///
+ private static readonly Test DeleteTests = TestList("Delete",
+ [
+ TestList("ById",
+ [
+ TestCase("succeeds when a document is deleted", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ await Delete.ById(SqliteDb.TableName, "four");
+ var remaining = await Count.All(SqliteDb.TableName);
+ Expect.equal(remaining, 4L, "There should have been 4 documents remaining");
+ }),
+ TestCase("succeeds when a document is not deleted", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ await Delete.ById(SqliteDb.TableName, "thirty");
+ var remaining = await Count.All(SqliteDb.TableName);
+ Expect.equal(remaining, 5L, "There should have been 5 documents remaining");
+ })
+ ]),
+ TestList("ByFields",
+ [
+ TestCase("succeeds when documents are deleted", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ await Delete.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.NE("Value", "purple")]);
+ var remaining = await Count.All(SqliteDb.TableName);
+ Expect.equal(remaining, 2L, "There should have been 2 documents remaining");
+ }),
+ TestCase("succeeds when documents are not deleted", async () =>
+ {
+ await using var db = await SqliteDb.BuildDb();
+ await LoadDocs();
+
+ await Delete.ByFields(SqliteDb.TableName, FieldMatch.All, [Field.EQ("Value", "crimson")]);
+ var remaining = await Count.All(SqliteDb.TableName);
+ Expect.equal(remaining, 5L, "There should have been 5 documents remaining");
+ })
+ ])
+ ]);
+
///
/// All tests for SQLite C# functions and methods
///
[Tests]
- public static readonly Test All = TestList("Sqlite.C#", [Unit, TestSequenced(Integration)]);
+ public static readonly Test All = TestList("Sqlite.C#",
+ [
+ TestList("Unit", [QueryTests, ParametersTests]),
+ TestSequenced(TestList("Integration",
+ [
+ ConfigurationTests,
+ CustomTests,
+ DefinitionTests,
+ DocumentTests,
+ CountTests,
+ ExistsTests,
+ FindTests,
+ UpdateTests,
+ PatchTests,
+ RemoveFieldsTests,
+ DeleteTests,
+ TestCase("Clean up database", () => Sqlite.Configuration.UseConnectionString("data source=:memory:"))
+ ]))
+ ]);
}
diff --git a/src/Tests/SqliteTests.fs b/src/Tests/SqliteTests.fs
index c6a0ee3..1006e25 100644
--- a/src/Tests/SqliteTests.fs
+++ b/src/Tests/SqliteTests.fs
@@ -10,651 +10,685 @@ open Types
#nowarn "0044"
-/// Unit tests for the SQLite library
-let unitTests =
- testList "Unit" [
- testList "Query" [
- testList "whereByFields" [
- test "succeeds for a single field when a logical operator is passed" {
- Expect.equal
- (Query.whereByFields Any [ { Field.GT "theField" 0 with ParameterName = Some "@test" } ])
- "data->>'theField' > @test"
- "WHERE clause not correct"
- }
- test "succeeds for a single field when an existence operator is passed" {
- Expect.equal
- (Query.whereByFields Any [ Field.NEX "thatField" ])
- "data->>'thatField' IS NULL"
- "WHERE clause not correct"
- }
- test "succeeds for a single field when a between operator is passed" {
- Expect.equal
- (Query.whereByFields All [ { Field.BT "aField" 50 99 with ParameterName = Some "@range" } ])
- "data->>'aField' BETWEEN @rangemin AND @rangemax"
- "WHERE clause not correct"
- }
- test "succeeds for all multiple fields with logical operators" {
- Expect.equal
- (Query.whereByFields All [ Field.EQ "theFirst" "1"; Field.EQ "numberTwo" "2" ])
- "data->>'theFirst' = @field0 AND data->>'numberTwo' = @field1"
- "WHERE clause not correct"
- }
- test "succeeds for any multiple fields with an existence operator" {
- Expect.equal
- (Query.whereByFields Any [ Field.NEX "thatField"; Field.GE "thisField" 18 ])
- "data->>'thatField' IS NULL OR data->>'thisField' >= @field0"
- "WHERE clause not correct"
- }
- test "succeeds for all multiple fields with between operators" {
- Expect.equal
- (Query.whereByFields All [ Field.BT "aField" 50 99; Field.BT "anotherField" "a" "b" ])
- "data->>'aField' BETWEEN @field0min AND @field0max AND data->>'anotherField' BETWEEN @field1min AND @field1max"
- "WHERE clause not correct"
- }
- ]
- test "whereById succeeds" {
- Expect.equal (Query.whereById "@id") "data->>'Id' = @id" "WHERE clause not correct"
- }
- test "patch succeeds" {
- Expect.equal
- (Query.patch SqliteDb.TableName)
- $"UPDATE {SqliteDb.TableName} SET data = json_patch(data, json(@data))"
- "Patch query not correct"
- }
- test "removeFields succeeds" {
- Expect.equal
- (Query.removeFields SqliteDb.TableName [ SqliteParameter("@a", "a"); SqliteParameter("@b", "b") ])
- $"UPDATE {SqliteDb.TableName} SET data = json_remove(data, @a, @b)"
- "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.GT "That" 14 ])
- "unit WHERE data->>'That' > @field0"
- "By-Field query not correct"
- }
- test "Definition.ensureTable succeeds" {
- Expect.equal
- (Query.Definition.ensureTable "tbl")
- "CREATE TABLE IF NOT EXISTS tbl (data TEXT NOT NULL)"
- "CREATE TABLE statement not correct"
- }
- ]
- testList "Parameters" [
- test "idParam succeeds" {
- let theParam = idParam 7
- Expect.equal theParam.ParameterName "@id" "The parameter name is incorrect"
- Expect.equal theParam.Value "7" "The parameter value is incorrect"
- }
- test "jsonParam succeeds" {
- let theParam = jsonParam "@test" {| Nice = "job" |}
- Expect.equal theParam.ParameterName "@test" "The parameter name is incorrect"
- Expect.equal theParam.Value """{"Nice":"job"}""" "The parameter value is incorrect"
- }
- testList "addFieldParam" [
- test "succeeds when adding a parameter" {
- let paramList = addFieldParam "@field" (Field.EQ "it" 99) []
- Expect.hasLength paramList 1 "There should have been a parameter added"
- let theParam = Seq.head paramList
- Expect.equal theParam.ParameterName "@field" "The parameter name is incorrect"
- Expect.equal theParam.Value 99 "The parameter value is incorrect"
- }
- test "succeeds when not adding a parameter" {
- let paramList = addFieldParam "@it" (Field.NEX "Coffee") []
- Expect.isEmpty paramList "There should not have been any parameters added"
- }
- ]
- test "noParams succeeds" {
- Expect.isEmpty noParams "The parameter list should have been empty"
- }
- ]
- // Results are exhaustively executed in the context of other tests
- ]
+(** UNIT TESTS **)
-/// These tests each use a fresh copy of a SQLite database
-let integrationTests =
- let documents = [
- { Id = "one"; Value = "FIRST!"; NumValue = 0; Sub = None }
- { Id = "two"; Value = "another"; NumValue = 10; Sub = Some { Foo = "green"; Bar = "blue" } }
- { Id = "three"; Value = ""; NumValue = 4; Sub = None }
- { Id = "four"; Value = "purple"; NumValue = 17; Sub = Some { Foo = "green"; Bar = "red" } }
- { Id = "five"; Value = "purple"; NumValue = 18; Sub = None }
- ]
- let loadDocs () = backgroundTask {
- for doc in documents do do! insert SqliteDb.TableName doc
- }
- testList "Integration" [
- testList "Configuration" [
- test "useConnectionString / connectionString succeed" {
- try
- Configuration.useConnectionString "Data Source=test.db"
- Expect.equal
- Configuration.connectionString
- (Some "Data Source=test.db;Foreign Keys=True")
- "Connection string incorrect"
- finally
- Configuration.useConnectionString "Data Source=:memory:"
- }
- test "useSerializer succeeds" {
- try
- Configuration.useSerializer
- { new IDocumentSerializer with
- member _.Serialize<'T>(it: 'T) : string = """{"Overridden":true}"""
- member _.Deserialize<'T>(it: string) : 'T = Unchecked.defaultof<'T>
- }
-
- let serialized = Configuration.serializer().Serialize { Foo = "howdy"; Bar = "bye"}
- Expect.equal serialized """{"Overridden":true}""" "Specified serializer was not used"
-
- let deserialized = Configuration.serializer().Deserialize """{"Something":"here"}"""
- Expect.isNull deserialized "Specified serializer should have returned null"
- finally
- Configuration.useSerializer DocumentSerializer.``default``
- }
- test "serializer returns configured serializer" {
- Expect.isTrue (obj.ReferenceEquals(DocumentSerializer.``default``, Configuration.serializer ()))
- "Serializer should have been the same"
- }
- test "useIdField / idField succeeds" {
- Expect.equal (Configuration.idField ()) "Id" "The default configured ID field was incorrect"
- Configuration.useIdField "id"
- Expect.equal (Configuration.idField ()) "id" "useIdField did not set the ID field"
- Configuration.useIdField "Id"
- }
- ]
- testList "Custom" [
- testList "single" [
- testTask "succeeds when a row is found" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- let! doc =
- Custom.single
- $"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id"
- [ SqliteParameter("@id", "one") ]
- fromData
- 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 = SqliteDb.BuildDb()
- do! loadDocs ()
-
- let! doc =
- Custom.single
- $"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id"
- [ SqliteParameter("@id", "eighty") ]
- fromData
- Expect.isNone doc "There should not have been a document returned"
- }
- ]
- testList "list" [
- testTask "succeeds when data is found" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- let! docs = Custom.list (Query.selectFromTable SqliteDb.TableName) [] fromData
- Expect.hasCountOf docs 5u (fun _ -> true) "There should have been 5 documents returned"
- }
- testTask "succeeds when data is not found" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- let! docs =
- Custom.list
- $"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value"
- [ SqliteParameter("@value", 100) ]
- fromData
- Expect.isEmpty docs "There should have been no documents returned"
- }
- ]
- testList "nonQuery" [
- testTask "succeeds when operating on data" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- do! Custom.nonQuery $"DELETE FROM {SqliteDb.TableName}" []
-
- let! remaining = Count.all SqliteDb.TableName
- Expect.equal remaining 0L "There should be no documents remaining in the table"
- }
- testTask "succeeds when no data matches where clause" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- do! Custom.nonQuery
- $"DELETE FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value"
- [ SqliteParameter("@value", 100) ]
-
- let! remaining = Count.all SqliteDb.TableName
- Expect.equal remaining 5L "There should be 5 documents remaining in the table"
- }
- ]
- testTask "scalar succeeds" {
- use! db = SqliteDb.BuildDb()
-
- let! nbr = Custom.scalar "SELECT 5 AS test_value" [] _.GetInt32(0)
- Expect.equal nbr 5 "The query should have returned the number 5"
- }
- ]
- testList "Definition" [
- testTask "ensureTable succeeds" {
- use! db = SqliteDb.BuildDb()
- let itExists (name: string) =
- Custom.scalar
- $"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = @name) AS it"
- [ SqliteParameter("@name", name) ]
- toExists
-
- let! exists = itExists "ensured"
- let! alsoExists = itExists "idx_ensured_key"
- 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' = itExists "ensured"
- let! alsoExists' = itExists "idx_ensured_key"
- Expect.isTrue exists' "The table should now exist"
- Expect.isTrue alsoExists' "The key index should now exist"
- }
- testTask "ensureFieldIndex succeeds" {
- use! db = SqliteDb.BuildDb()
- let indexExists () =
- Custom.scalar
- $"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = '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" [ "Name"; "Age" ]
- let! exists' = indexExists ()
- Expect.isTrue exists' "The index should now exist"
- }
- ]
- testList "insert" [
- testTask "succeeds" {
- use! db = SqliteDb.BuildDb()
- let! before = Find.all SqliteDb.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 SqliteDb.TableName testDoc
- let! after = Find.all SqliteDb.TableName
- Expect.equal after [ testDoc ] "There should have been one document inserted"
- }
- testTask "fails for duplicate key" {
- use! db = SqliteDb.BuildDb()
- do! insert SqliteDb.TableName { emptyDoc with Id = "test" }
- Expect.throws
- (fun () ->
- insert SqliteDb.TableName {emptyDoc with Id = "test" } |> Async.AwaitTask |> Async.RunSynchronously)
- "An exception should have been raised for duplicate document ID insert"
- }
- ]
- testList "save" [
- testTask "succeeds when a document is inserted" {
- use! db = SqliteDb.BuildDb()
- let! before = Find.all SqliteDb.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 SqliteDb.TableName testDoc
- let! after = Find.all SqliteDb.TableName
- Expect.equal after [ testDoc ] "There should have been one document inserted"
- }
- testTask "succeeds when a document is updated" {
- use! db = SqliteDb.BuildDb()
- let testDoc = { emptyDoc with Id = "test"; Sub = Some { Foo = "a"; Bar = "b" } }
- do! insert SqliteDb.TableName testDoc
-
- let! before = Find.byId SqliteDb.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 SqliteDb.TableName upd8Doc
- let! after = Find.byId SqliteDb.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"
- }
- ]
- testList "Count" [
- testTask "all succeeds" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- let! theCount = Count.all SqliteDb.TableName
- Expect.equal theCount 5L "There should have been 5 matching documents"
- }
- testList "byFields" [
- testTask "succeeds for a numeric range" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- let! theCount = Count.byFields SqliteDb.TableName Any [ Field.BT "NumValue" 10 20 ]
- Expect.equal theCount 3L "There should have been 3 matching documents"
- }
- testTask "succeeds for a non-numeric range" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- let! theCount = Count.byFields SqliteDb.TableName Any [ Field.BT "Value" "aardvark" "apple" ]
- Expect.equal theCount 1L "There should have been 1 matching document"
- }
- ]
- ]
- testList "Exists" [
- testList "byId" [
- testTask "succeeds when a document exists" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- let! exists = Exists.byId SqliteDb.TableName "three"
- Expect.isTrue exists "There should have been an existing document"
- }
- testTask "succeeds when a document does not exist" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- let! exists = Exists.byId SqliteDb.TableName "seven"
- Expect.isFalse exists "There should not have been an existing document"
- }
- ]
- testList "byFields" [
- testTask "succeeds when documents exist" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- let! exists = Exists.byFields SqliteDb.TableName Any [ Field.EQ "NumValue" 10 ]
- Expect.isTrue exists "There should have been existing documents"
- }
- testTask "succeeds when no matching documents exist" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- let! exists = Exists.byFields SqliteDb.TableName Any [ Field.LT "Nothing" "none" ]
- Expect.isFalse exists "There should not have been any existing documents"
- }
- ]
- ]
- testList "Find" [
- testList "all" [
- testTask "succeeds when there is data" {
- use! db = SqliteDb.BuildDb()
-
- do! insert SqliteDb.TableName { Foo = "one"; Bar = "two" }
- do! insert SqliteDb.TableName { Foo = "three"; Bar = "four" }
- do! insert SqliteDb.TableName { Foo = "five"; Bar = "six" }
-
- let! results = Find.all SqliteDb.TableName
- let expected = [
- { Foo = "one"; Bar = "two" }
- { Foo = "three"; Bar = "four" }
- { Foo = "five"; Bar = "six" }
- ]
- Expect.equal results expected "There should have been 3 documents returned"
- }
- testTask "succeeds when there is no data" {
- use! db = SqliteDb.BuildDb()
- let! results = Find.all SqliteDb.TableName
- Expect.equal results [] "There should have been no documents returned"
- }
- ]
- testList "byId" [
- testTask "succeeds when a document is found" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- let! doc = Find.byId SqliteDb.TableName "two"
- Expect.isTrue (Option.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 = SqliteDb.BuildDb()
- do! loadDocs ()
-
- let! doc = Find.byId SqliteDb.TableName "three hundred eighty-seven"
- Expect.isFalse (Option.isSome doc) "There should not have been a document returned"
- }
- ]
- testList "byFields" [
- testTask "succeeds when documents are found" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- let! docs = Find.byFields SqliteDb.TableName Any [ Field.GT "NumValue" 15 ]
- Expect.equal (List.length docs) 2 "There should have been two documents returned"
- }
- testTask "succeeds when documents are not found" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- let! docs = Find.byFields SqliteDb.TableName Any [ Field.GT "NumValue" 100 ]
- Expect.isTrue (List.isEmpty docs) "There should have been no documents returned"
- }
- ]
- testList "firstByFields" [
- testTask "succeeds when a document is found" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- let! doc = Find.firstByFields SqliteDb.TableName Any [ Field.EQ "Value" "another" ]
- Expect.isTrue (Option.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 = SqliteDb.BuildDb()
- do! loadDocs ()
-
- let! doc = Find.firstByFields SqliteDb.TableName Any [ Field.EQ "Sub.Foo" "green" ]
- Expect.isTrue (Option.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 = SqliteDb.BuildDb()
- do! loadDocs ()
-
- let! doc = Find.firstByFields SqliteDb.TableName Any [ Field.EQ "Value" "absent" ]
- Expect.isFalse (Option.isSome doc) "There should not have been a document returned"
- }
- ]
- ]
- testList "Update" [
- testList "byId" [
- testTask "succeeds when a document is updated" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- let testDoc = { emptyDoc with Id = "one"; Sub = Some { Foo = "blue"; Bar = "red" } }
- do! Update.byId SqliteDb.TableName "one" testDoc
- let! after = Find.byId SqliteDb.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 = SqliteDb.BuildDb()
-
- let! before = Find.all SqliteDb.TableName
- Expect.isEmpty before "There should have been no documents returned"
-
- // This not raising an exception is the test
- do! Update.byId
- SqliteDb.TableName
- "test"
- { emptyDoc with Id = "x"; Sub = Some { Foo = "blue"; Bar = "red" } }
- }
- ]
- testList "byFunc" [
- testTask "succeeds when a document is updated" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- do! Update.byFunc
- SqliteDb.TableName (_.Id) { Id = "one"; Value = "le un"; NumValue = 1; Sub = None }
- let! after = Find.byId SqliteDb.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 = SqliteDb.BuildDb()
-
- let! before = Find.all SqliteDb.TableName
- Expect.isEmpty before "There should have been no documents returned"
-
- // This not raising an exception is the test
- do! Update.byFunc
- SqliteDb.TableName (_.Id) { Id = "one"; Value = "le un"; NumValue = 1; Sub = None }
- }
- ]
- ]
- testList "Patch" [
- testList "byId" [
- testTask "succeeds when a document is updated" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- do! Patch.byId SqliteDb.TableName "one" {| NumValue = 44 |}
- let! after = Find.byId SqliteDb.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 = SqliteDb.BuildDb()
-
- let! before = Find.all SqliteDb.TableName
- Expect.isEmpty before "There should have been no documents returned"
-
- // This not raising an exception is the test
- do! Patch.byId SqliteDb.TableName "test" {| Foo = "green" |}
- }
- ]
- testList "byFields" [
- testTask "succeeds when a document is updated" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- do! Patch.byFields SqliteDb.TableName Any [ Field.EQ "Value" "purple" ] {| NumValue = 77 |}
- let! after = Count.byFields SqliteDb.TableName Any [ Field.EQ "NumValue" 77 ]
- Expect.equal after 2L "There should have been 2 documents returned"
- }
- testTask "succeeds when no document is updated" {
- use! db = SqliteDb.BuildDb()
-
- let! before = Find.all SqliteDb.TableName
- Expect.isEmpty before "There should have been no documents returned"
-
- // This not raising an exception is the test
- do! Patch.byFields SqliteDb.TableName Any [ Field.EQ "Value" "burgundy" ] {| Foo = "green" |}
- }
- ]
- ]
- testList "RemoveFields" [
- testList "byId" [
- testTask "succeeds when fields is removed" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- do! RemoveFields.byId SqliteDb.TableName "two" [ "Sub"; "Value" ]
- try
- let! _ = Find.byId SqliteDb.TableName "two"
- Expect.isTrue false "The updated document should have failed to parse"
- with
- | :? JsonException -> ()
- | exn as ex -> Expect.isTrue false $"Threw {ex.GetType().Name} ({ex.Message})"
- }
- testTask "succeeds when a field is not removed" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- // This not raising an exception is the test
- do! RemoveFields.byId SqliteDb.TableName "two" [ "AFieldThatIsNotThere" ]
- }
- testTask "succeeds when no document is matched" {
- use! db = SqliteDb.BuildDb()
-
- // This not raising an exception is the test
- do! RemoveFields.byId SqliteDb.TableName "two" [ "Value" ]
- }
- ]
- testList "byFields" [
- testTask "succeeds when a field is removed" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- do! RemoveFields.byFields SqliteDb.TableName Any [ Field.EQ "NumValue" 17 ] [ "Sub" ]
- try
- let! _ = Find.byId SqliteDb.TableName "four"
- Expect.isTrue false "The updated document should have failed to parse"
- with
- | :? JsonException -> ()
- | exn as ex -> Expect.isTrue false $"Threw {ex.GetType().Name} ({ex.Message})"
- }
- testTask "succeeds when a field is not removed" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- // This not raising an exception is the test
- do! RemoveFields.byFields SqliteDb.TableName Any [ Field.EQ "NumValue" 17 ] [ "Nothing" ]
- }
- testTask "succeeds when no document is matched" {
- use! db = SqliteDb.BuildDb()
-
- // This not raising an exception is the test
- do! RemoveFields.byFields SqliteDb.TableName Any [ Field.NE "Abracadabra" "apple" ] [ "Value" ]
- }
- ]
- ]
- testList "Delete" [
- testList "byId" [
- testTask "succeeds when a document is deleted" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- do! Delete.byId SqliteDb.TableName "four"
- let! remaining = Count.all SqliteDb.TableName
- Expect.equal remaining 4L "There should have been 4 documents remaining"
- }
- testTask "succeeds when a document is not deleted" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- do! Delete.byId SqliteDb.TableName "thirty"
- let! remaining = Count.all SqliteDb.TableName
- Expect.equal remaining 5L "There should have been 5 documents remaining"
- }
- ]
- testList "byFields" [
- testTask "succeeds when documents are deleted" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- do! Delete.byFields SqliteDb.TableName Any [ Field.NE "Value" "purple" ]
- let! remaining = Count.all SqliteDb.TableName
- Expect.equal remaining 2L "There should have been 2 documents remaining"
- }
- testTask "succeeds when documents are not deleted" {
- use! db = SqliteDb.BuildDb()
- do! loadDocs ()
-
- do! Delete.byFields SqliteDb.TableName Any [ Field.EQ "Value" "crimson" ]
- let! remaining = Count.all SqliteDb.TableName
- Expect.equal remaining 5L "There should have been 5 documents remaining"
- }
- ]
- ]
- test "clean up database" {
- Configuration.useConnectionString "data source=:memory:"
+/// Unit tests for the Query module of the SQLite library
+let queryTests = testList "Query" [
+ testList "whereByFields" [
+ test "succeeds for a single field when a logical operator is passed" {
+ Expect.equal
+ (Query.whereByFields Any [ { Field.GT "theField" 0 with ParameterName = Some "@test" } ])
+ "data->>'theField' > @test"
+ "WHERE clause not correct"
+ }
+ test "succeeds for a single field when an existence operator is passed" {
+ Expect.equal
+ (Query.whereByFields Any [ Field.NEX "thatField" ])
+ "data->>'thatField' IS NULL"
+ "WHERE clause not correct"
+ }
+ test "succeeds for a single field when a between operator is passed" {
+ Expect.equal
+ (Query.whereByFields All [ { Field.BT "aField" 50 99 with ParameterName = Some "@range" } ])
+ "data->>'aField' BETWEEN @rangemin AND @rangemax"
+ "WHERE clause not correct"
+ }
+ test "succeeds for all multiple fields with logical operators" {
+ Expect.equal
+ (Query.whereByFields All [ Field.EQ "theFirst" "1"; Field.EQ "numberTwo" "2" ])
+ "data->>'theFirst' = @field0 AND data->>'numberTwo' = @field1"
+ "WHERE clause not correct"
+ }
+ test "succeeds for any multiple fields with an existence operator" {
+ Expect.equal
+ (Query.whereByFields Any [ Field.NEX "thatField"; Field.GE "thisField" 18 ])
+ "data->>'thatField' IS NULL OR data->>'thisField' >= @field0"
+ "WHERE clause not correct"
+ }
+ test "succeeds for all multiple fields with between operators" {
+ Expect.equal
+ (Query.whereByFields All [ Field.BT "aField" 50 99; Field.BT "anotherField" "a" "b" ])
+ "data->>'aField' BETWEEN @field0min AND @field0max AND data->>'anotherField' BETWEEN @field1min AND @field1max"
+ "WHERE clause not correct"
}
]
- |> testSequenced
+ test "whereById succeeds" {
+ Expect.equal (Query.whereById "@id") "data->>'Id' = @id" "WHERE clause not correct"
+ }
+ test "patch succeeds" {
+ Expect.equal
+ (Query.patch SqliteDb.TableName)
+ $"UPDATE {SqliteDb.TableName} SET data = json_patch(data, json(@data))"
+ "Patch query not correct"
+ }
+ test "removeFields succeeds" {
+ Expect.equal
+ (Query.removeFields SqliteDb.TableName [ SqliteParameter("@a", "a"); SqliteParameter("@b", "b") ])
+ $"UPDATE {SqliteDb.TableName} SET data = json_remove(data, @a, @b)"
+ "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.GT "That" 14 ])
+ "unit WHERE data->>'That' > @field0"
+ "By-Field query not correct"
+ }
+ test "Definition.ensureTable succeeds" {
+ Expect.equal
+ (Query.Definition.ensureTable "tbl")
+ "CREATE TABLE IF NOT EXISTS tbl (data TEXT NOT NULL)"
+ "CREATE TABLE statement not correct"
+ }
+]
-let all = testList "Sqlite" [ unitTests; integrationTests ]
+/// Unit tests for the Parameters module of the SQLite library
+let parametersTests = testList "Parameters" [
+ test "idParam succeeds" {
+ let theParam = idParam 7
+ Expect.equal theParam.ParameterName "@id" "The parameter name is incorrect"
+ Expect.equal theParam.Value "7" "The parameter value is incorrect"
+ }
+ test "jsonParam succeeds" {
+ let theParam = jsonParam "@test" {| Nice = "job" |}
+ Expect.equal theParam.ParameterName "@test" "The parameter name is incorrect"
+ Expect.equal theParam.Value """{"Nice":"job"}""" "The parameter value is incorrect"
+ }
+ testList "addFieldParam" [
+ test "succeeds when adding a parameter" {
+ let paramList = addFieldParam "@field" (Field.EQ "it" 99) []
+ Expect.hasLength paramList 1 "There should have been a parameter added"
+ let theParam = Seq.head paramList
+ Expect.equal theParam.ParameterName "@field" "The parameter name is incorrect"
+ Expect.equal theParam.Value 99 "The parameter value is incorrect"
+ }
+ test "succeeds when not adding a parameter" {
+ let paramList = addFieldParam "@it" (Field.NEX "Coffee") []
+ Expect.isEmpty paramList "There should not have been any parameters added"
+ }
+ ]
+ test "noParams succeeds" {
+ Expect.isEmpty noParams "The parameter list should have been empty"
+ }
+]
+// Results are exhaustively executed in the context of other tests
+
+
+(** INTEGRATION TESTS **)
+
+/// Documents used for integration tests
+let documents = [
+ { Id = "one"; Value = "FIRST!"; NumValue = 0; Sub = None }
+ { Id = "two"; Value = "another"; NumValue = 10; Sub = Some { Foo = "green"; Bar = "blue" } }
+ { Id = "three"; Value = ""; NumValue = 4; Sub = None }
+ { Id = "four"; Value = "purple"; NumValue = 17; Sub = Some { Foo = "green"; Bar = "red" } }
+ { Id = "five"; Value = "purple"; NumValue = 18; Sub = None }
+]
+
+/// Load a table with the test documents
+let loadDocs () = backgroundTask {
+ for doc in documents do do! insert SqliteDb.TableName doc
+}
+
+/// Integration tests for the Configuration module of the SQLite library
+let configurationTests = testList "Configuration" [
+ test "useConnectionString / connectionString succeed" {
+ try
+ Configuration.useConnectionString "Data Source=test.db"
+ Expect.equal
+ Configuration.connectionString
+ (Some "Data Source=test.db;Foreign Keys=True")
+ "Connection string incorrect"
+ finally
+ Configuration.useConnectionString "Data Source=:memory:"
+ }
+ test "useSerializer succeeds" {
+ try
+ Configuration.useSerializer
+ { new IDocumentSerializer with
+ member _.Serialize<'T>(it: 'T) : string = """{"Overridden":true}"""
+ member _.Deserialize<'T>(it: string) : 'T = Unchecked.defaultof<'T>
+ }
+
+ let serialized = Configuration.serializer().Serialize { Foo = "howdy"; Bar = "bye"}
+ Expect.equal serialized """{"Overridden":true}""" "Specified serializer was not used"
+
+ let deserialized = Configuration.serializer().Deserialize """{"Something":"here"}"""
+ Expect.isNull deserialized "Specified serializer should have returned null"
+ finally
+ Configuration.useSerializer DocumentSerializer.``default``
+ }
+ test "serializer returns configured serializer" {
+ Expect.isTrue (obj.ReferenceEquals(DocumentSerializer.``default``, Configuration.serializer ()))
+ "Serializer should have been the same"
+ }
+ test "useIdField / idField succeeds" {
+ Expect.equal (Configuration.idField ()) "Id" "The default configured ID field was incorrect"
+ Configuration.useIdField "id"
+ Expect.equal (Configuration.idField ()) "id" "useIdField did not set the ID field"
+ Configuration.useIdField "Id"
+ }
+]
+
+/// Integration tests for the Custom module of the SQLite library
+let customTests = testList "Custom" [
+ testList "single" [
+ testTask "succeeds when a row is found" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ let! doc =
+ Custom.single
+ $"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id"
+ [ SqliteParameter("@id", "one") ]
+ fromData
+ 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 = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ let! doc =
+ Custom.single
+ $"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id"
+ [ SqliteParameter("@id", "eighty") ]
+ fromData
+ Expect.isNone doc "There should not have been a document returned"
+ }
+ ]
+ testList "list" [
+ testTask "succeeds when data is found" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ let! docs = Custom.list (Query.find SqliteDb.TableName) [] fromData
+ Expect.hasCountOf docs 5u (fun _ -> true) "There should have been 5 documents returned"
+ }
+ testTask "succeeds when data is not found" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ let! docs =
+ Custom.list
+ $"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value"
+ [ SqliteParameter("@value", 100) ]
+ fromData
+ Expect.isEmpty docs "There should have been no documents returned"
+ }
+ ]
+ testList "nonQuery" [
+ testTask "succeeds when operating on data" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ do! Custom.nonQuery $"DELETE FROM {SqliteDb.TableName}" []
+
+ let! remaining = Count.all SqliteDb.TableName
+ Expect.equal remaining 0L "There should be no documents remaining in the table"
+ }
+ testTask "succeeds when no data matches where clause" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ do! Custom.nonQuery
+ $"DELETE FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value"
+ [ SqliteParameter("@value", 100) ]
+
+ let! remaining = Count.all SqliteDb.TableName
+ Expect.equal remaining 5L "There should be 5 documents remaining in the table"
+ }
+ ]
+ testTask "scalar succeeds" {
+ use! db = SqliteDb.BuildDb()
+
+ let! nbr = Custom.scalar "SELECT 5 AS test_value" [] _.GetInt32(0)
+ Expect.equal nbr 5 "The query should have returned the number 5"
+ }
+]
+
+/// Integration tests for the Definition module of the SQLite library
+let definitionTests = testList "Definition" [
+ testTask "ensureTable succeeds" {
+ use! db = SqliteDb.BuildDb()
+ let itExists (name: string) =
+ Custom.scalar
+ $"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = @name) AS it"
+ [ SqliteParameter("@name", name) ]
+ toExists
+
+ let! exists = itExists "ensured"
+ let! alsoExists = itExists "idx_ensured_key"
+ 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' = itExists "ensured"
+ let! alsoExists' = itExists "idx_ensured_key"
+ Expect.isTrue exists' "The table should now exist"
+ Expect.isTrue alsoExists' "The key index should now exist"
+ }
+ testTask "ensureFieldIndex succeeds" {
+ use! db = SqliteDb.BuildDb()
+ let indexExists () =
+ Custom.scalar
+ $"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = '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" [ "Name"; "Age" ]
+ let! exists' = indexExists ()
+ Expect.isTrue exists' "The index should now exist"
+ }
+]
+
+/// Integration tests for the (auto-opened) Document module of the SQLite library
+let documentTests = testList "Document" [
+ testList "insert" [
+ testTask "succeeds" {
+ use! db = SqliteDb.BuildDb()
+ let! before = Find.all SqliteDb.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 SqliteDb.TableName testDoc
+ let! after = Find.all SqliteDb.TableName
+ Expect.equal after [ testDoc ] "There should have been one document inserted"
+ }
+ testTask "fails for duplicate key" {
+ use! db = SqliteDb.BuildDb()
+ do! insert SqliteDb.TableName { emptyDoc with Id = "test" }
+ Expect.throws
+ (fun () ->
+ insert SqliteDb.TableName {emptyDoc with Id = "test" } |> Async.AwaitTask |> Async.RunSynchronously)
+ "An exception should have been raised for duplicate document ID insert"
+ }
+ ]
+ testList "save" [
+ testTask "succeeds when a document is inserted" {
+ use! db = SqliteDb.BuildDb()
+ let! before = Find.all SqliteDb.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 SqliteDb.TableName testDoc
+ let! after = Find.all SqliteDb.TableName
+ Expect.equal after [ testDoc ] "There should have been one document inserted"
+ }
+ testTask "succeeds when a document is updated" {
+ use! db = SqliteDb.BuildDb()
+ let testDoc = { emptyDoc with Id = "test"; Sub = Some { Foo = "a"; Bar = "b" } }
+ do! insert SqliteDb.TableName testDoc
+
+ let! before = Find.byId SqliteDb.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 SqliteDb.TableName upd8Doc
+ let! after = Find.byId SqliteDb.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 SQLite library
+let countTests = testList "Count" [
+ testTask "all succeeds" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ let! theCount = Count.all SqliteDb.TableName
+ Expect.equal theCount 5L "There should have been 5 matching documents"
+ }
+ testList "byFields" [
+ testTask "succeeds for a numeric range" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ let! theCount = Count.byFields SqliteDb.TableName Any [ Field.BT "NumValue" 10 20 ]
+ Expect.equal theCount 3L "There should have been 3 matching documents"
+ }
+ testTask "succeeds for a non-numeric range" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ let! theCount = Count.byFields SqliteDb.TableName Any [ Field.BT "Value" "aardvark" "apple" ]
+ Expect.equal theCount 1L "There should have been 1 matching document"
+ }
+ ]
+]
+
+/// Integration tests for the Exists module of the SQLite library
+let existsTests = testList "Exists" [
+ testList "byId" [
+ testTask "succeeds when a document exists" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ let! exists = Exists.byId SqliteDb.TableName "three"
+ Expect.isTrue exists "There should have been an existing document"
+ }
+ testTask "succeeds when a document does not exist" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ let! exists = Exists.byId SqliteDb.TableName "seven"
+ Expect.isFalse exists "There should not have been an existing document"
+ }
+ ]
+ testList "byFields" [
+ testTask "succeeds when documents exist" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ let! exists = Exists.byFields SqliteDb.TableName Any [ Field.EQ "NumValue" 10 ]
+ Expect.isTrue exists "There should have been existing documents"
+ }
+ testTask "succeeds when no matching documents exist" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ let! exists = Exists.byFields SqliteDb.TableName Any [ Field.LT "Nothing" "none" ]
+ Expect.isFalse exists "There should not have been any existing documents"
+ }
+ ]
+]
+
+/// Integration tests for the Find module of the SQLite library
+let findTests = testList "Find" [
+ testList "all" [
+ testTask "succeeds when there is data" {
+ use! db = SqliteDb.BuildDb()
+
+ do! insert SqliteDb.TableName { Foo = "one"; Bar = "two" }
+ do! insert SqliteDb.TableName { Foo = "three"; Bar = "four" }
+ do! insert SqliteDb.TableName { Foo = "five"; Bar = "six" }
+
+ let! results = Find.all SqliteDb.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 = SqliteDb.BuildDb()
+ let! results = Find.all SqliteDb.TableName
+ Expect.equal results [] "There should have been no documents returned"
+ }
+ ]
+ testList "byId" [
+ testTask "succeeds when a document is found" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ let! doc = Find.byId SqliteDb.TableName "two"
+ Expect.isTrue (Option.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 = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ let! doc = Find.byId SqliteDb.TableName "three hundred eighty-seven"
+ Expect.isFalse (Option.isSome doc) "There should not have been a document returned"
+ }
+ ]
+ testList "byFields" [
+ testTask "succeeds when documents are found" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ let! docs = Find.byFields SqliteDb.TableName Any [ Field.GT "NumValue" 15 ]
+ Expect.equal (List.length docs) 2 "There should have been two documents returned"
+ }
+ testTask "succeeds when documents are not found" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ let! docs = Find.byFields SqliteDb.TableName Any [ Field.GT "NumValue" 100 ]
+ Expect.isTrue (List.isEmpty docs) "There should have been no documents returned"
+ }
+ ]
+ testList "firstByFields" [
+ testTask "succeeds when a document is found" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ let! doc = Find.firstByFields SqliteDb.TableName Any [ Field.EQ "Value" "another" ]
+ Expect.isTrue (Option.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 = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ let! doc = Find.firstByFields SqliteDb.TableName Any [ Field.EQ "Sub.Foo" "green" ]
+ Expect.isTrue (Option.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 = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ let! doc = Find.firstByFields SqliteDb.TableName Any [ Field.EQ "Value" "absent" ]
+ Expect.isFalse (Option.isSome doc) "There should not have been a document returned"
+ }
+ ]
+]
+
+/// Integration tests for the Update module of the SQLite library
+let updateTests = testList "Update" [
+ testList "byId" [
+ testTask "succeeds when a document is updated" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ let testDoc = { emptyDoc with Id = "one"; Sub = Some { Foo = "blue"; Bar = "red" } }
+ do! Update.byId SqliteDb.TableName "one" testDoc
+ let! after = Find.byId SqliteDb.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 = SqliteDb.BuildDb()
+
+ let! before = Find.all SqliteDb.TableName
+ Expect.isEmpty before "There should have been no documents returned"
+
+ // This not raising an exception is the test
+ do! Update.byId
+ SqliteDb.TableName "test" { emptyDoc with Id = "x"; Sub = Some { Foo = "blue"; Bar = "red" } }
+ }
+ ]
+ testList "byFunc" [
+ testTask "succeeds when a document is updated" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ do! Update.byFunc SqliteDb.TableName (_.Id) { Id = "one"; Value = "le un"; NumValue = 1; Sub = None }
+ let! after = Find.byId SqliteDb.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 = SqliteDb.BuildDb()
+
+ let! before = Find.all SqliteDb.TableName
+ Expect.isEmpty before "There should have been no documents returned"
+
+ // This not raising an exception is the test
+ do! Update.byFunc SqliteDb.TableName (_.Id) { Id = "one"; Value = "le un"; NumValue = 1; Sub = None }
+ }
+ ]
+]
+
+/// Integration tests for the Patch module of the SQLite library
+let patchTests = testList "Patch" [
+ testList "byId" [
+ testTask "succeeds when a document is updated" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ do! Patch.byId SqliteDb.TableName "one" {| NumValue = 44 |}
+ let! after = Find.byId SqliteDb.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 = SqliteDb.BuildDb()
+
+ let! before = Find.all SqliteDb.TableName
+ Expect.isEmpty before "There should have been no documents returned"
+
+ // This not raising an exception is the test
+ do! Patch.byId SqliteDb.TableName "test" {| Foo = "green" |}
+ }
+ ]
+ testList "byFields" [
+ testTask "succeeds when a document is updated" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ do! Patch.byFields SqliteDb.TableName Any [ Field.EQ "Value" "purple" ] {| NumValue = 77 |}
+ let! after = Count.byFields SqliteDb.TableName Any [ Field.EQ "NumValue" 77 ]
+ Expect.equal after 2L "There should have been 2 documents returned"
+ }
+ testTask "succeeds when no document is updated" {
+ use! db = SqliteDb.BuildDb()
+
+ let! before = Find.all SqliteDb.TableName
+ Expect.isEmpty before "There should have been no documents returned"
+
+ // This not raising an exception is the test
+ do! Patch.byFields SqliteDb.TableName Any [ Field.EQ "Value" "burgundy" ] {| Foo = "green" |}
+ }
+ ]
+]
+
+/// Integration tests for the RemoveFields module of the SQLite library
+let removeFieldsTests = testList "RemoveFields" [
+ testList "byId" [
+ testTask "succeeds when fields is removed" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ do! RemoveFields.byId SqliteDb.TableName "two" [ "Sub"; "Value" ]
+ try
+ let! _ = Find.byId SqliteDb.TableName "two"
+ Expect.isTrue false "The updated document should have failed to parse"
+ with
+ | :? JsonException -> ()
+ | exn as ex -> Expect.isTrue false $"Threw {ex.GetType().Name} ({ex.Message})"
+ }
+ testTask "succeeds when a field is not removed" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ // This not raising an exception is the test
+ do! RemoveFields.byId SqliteDb.TableName "two" [ "AFieldThatIsNotThere" ]
+ }
+ testTask "succeeds when no document is matched" {
+ use! db = SqliteDb.BuildDb()
+
+ // This not raising an exception is the test
+ do! RemoveFields.byId SqliteDb.TableName "two" [ "Value" ]
+ }
+ ]
+ testList "byFields" [
+ testTask "succeeds when a field is removed" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ do! RemoveFields.byFields SqliteDb.TableName Any [ Field.EQ "NumValue" 17 ] [ "Sub" ]
+ try
+ let! _ = Find.byId SqliteDb.TableName "four"
+ Expect.isTrue false "The updated document should have failed to parse"
+ with
+ | :? JsonException -> ()
+ | exn as ex -> Expect.isTrue false $"Threw {ex.GetType().Name} ({ex.Message})"
+ }
+ testTask "succeeds when a field is not removed" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ // This not raising an exception is the test
+ do! RemoveFields.byFields SqliteDb.TableName Any [ Field.EQ "NumValue" 17 ] [ "Nothing" ]
+ }
+ testTask "succeeds when no document is matched" {
+ use! db = SqliteDb.BuildDb()
+
+ // This not raising an exception is the test
+ do! RemoveFields.byFields SqliteDb.TableName Any [ Field.NE "Abracadabra" "apple" ] [ "Value" ]
+ }
+ ]
+]
+
+/// Integration tests for the Delete module of the SQLite library
+let deleteTests = testList "Delete" [
+ testList "byId" [
+ testTask "succeeds when a document is deleted" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ do! Delete.byId SqliteDb.TableName "four"
+ let! remaining = Count.all SqliteDb.TableName
+ Expect.equal remaining 4L "There should have been 4 documents remaining"
+ }
+ testTask "succeeds when a document is not deleted" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ do! Delete.byId SqliteDb.TableName "thirty"
+ let! remaining = Count.all SqliteDb.TableName
+ Expect.equal remaining 5L "There should have been 5 documents remaining"
+ }
+ ]
+ testList "byFields" [
+ testTask "succeeds when documents are deleted" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ do! Delete.byFields SqliteDb.TableName Any [ Field.NE "Value" "purple" ]
+ let! remaining = Count.all SqliteDb.TableName
+ Expect.equal remaining 2L "There should have been 2 documents remaining"
+ }
+ testTask "succeeds when documents are not deleted" {
+ use! db = SqliteDb.BuildDb()
+ do! loadDocs ()
+
+ do! Delete.byFields SqliteDb.TableName Any [ Field.EQ "Value" "crimson" ]
+ let! remaining = Count.all SqliteDb.TableName
+ Expect.equal remaining 5L "There should have been 5 documents remaining"
+ }
+ ]
+]
+
+/// All tests for the SQLite library
+let all = testList "Sqlite" [
+ testList "Unit" [ queryTests; parametersTests ]
+ testSequenced <| testList "Integration" [
+ configurationTests
+ customTests
+ definitionTests
+ documentTests
+ countTests
+ existsTests
+ findTests
+ updateTests
+ patchTests
+ removeFieldsTests
+ deleteTests
+ test "clean up database" { Configuration.useConnectionString "data source=:memory:" }
+ ]
+]