BitBadger.Documents/src/Tests.CSharp/SqliteCSharpTests.cs

802 lines
35 KiB
C#

using Expecto.CSharp;
using Expecto;
using Microsoft.FSharp.Core;
using BitBadger.Documents.Sqlite;
namespace BitBadger.Documents.Tests.CSharp;
using static Runner;
/// <summary>
/// C# tests for the SQLite implementation of <tt>BitBadger.Documents</tt>
/// </summary>
public static class SqliteCSharpTests
{
/// <summary>
/// Unit tests for the Query module of the SQLite library
/// </summary>
private static readonly Test QueryTests = TestList("Query",
[
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", () =>
{
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");
})
]);
/// <summary>
/// Unit tests for the Parameters module of the SQLite library
/// </summary>
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
/// <summary>
/// Documents used for integration tests
/// </summary>
private static readonly List<JsonDocument> TestDocuments =
[
new() { Id = "one", Value = "FIRST!", NumValue = 0 },
new() { Id = "two", Value = "another", NumValue = 10, Sub = new() { Foo = "green", Bar = "blue" } },
new() { Id = "three", Value = "", NumValue = 4 },
new() { Id = "four", Value = "purple", NumValue = 17, Sub = new() { Foo = "green", Bar = "red" } },
new() { Id = "five", Value = "purple", NumValue = 18 }
];
/// <summary>
/// Add the test documents to the database
/// </summary>
internal static async Task LoadDocs()
{
foreach (var doc in TestDocuments) await Document.Insert(SqliteDb.TableName, doc);
}
/// <summary>
/// Integration tests for the Configuration module of the SQLite library
/// </summary>
private static readonly Test ConfigurationTests = TestCase("Configuration.UseConnectionString succeeds", () =>
{
try
{
Sqlite.Configuration.UseConnectionString("Data Source=test.db");
Expect.equal(Sqlite.Configuration.connectionString,
new FSharpOption<string>("Data Source=test.db;Foreign Keys=True"), "Connection string incorrect");
}
finally
{
Sqlite.Configuration.UseConnectionString("Data Source=:memory:");
}
});
/// <summary>
/// Integration tests for the Custom module of the SQLite library
/// </summary>
private static readonly Test CustomTests = TestList("Custom",
[
TestList("Single",
[
TestCase("succeeds when a row is found", async () =>
{
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<JsonDocument>);
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 doc = await Custom.Single($"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id",
[Parameters.Id("eighty")], Results.FromData<JsonDocument>);
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<JsonDocument>);
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<JsonDocument>);
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");
})
]);
/// <summary>
/// Integration tests for the Definition module of the SQLite library
/// </summary>
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<bool> ItExists(string name)
{
return await Custom.Scalar($"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = @name) AS it",
[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", ["Id", "Category"]);
exists = await IndexExists();
Expect.isTrue(exists, "The index should now exist");
return;
Task<bool> IndexExists() => Custom.Scalar(
$"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = 'idx_ensured_test') AS it",
Parameters.None, Results.ToExists);
})
]);
/// <summary>
/// Integration tests for the Document module of the SQLite library
/// </summary>
private static readonly Test DocumentTests = TestList("Document",
[
TestList("Insert",
[
TestCase("succeeds", async () =>
{
await using var db = await SqliteDb.BuildDb();
var before = await Find.All<SubDocument>(SqliteDb.TableName);
Expect.isEmpty(before, "There should be no documents in the table");
await Document.Insert(SqliteDb.TableName,
new JsonDocument { Id = "turkey", Sub = new() { Foo = "gobble", Bar = "gobble" } });
var after = await Find.All<JsonDocument>(SqliteDb.TableName);
Expect.equal(after.Count, 1, "There should have been one document inserted");
}),
TestCase("fails for duplicate key", async () =>
{
await using var db = await SqliteDb.BuildDb();
await Document.Insert(SqliteDb.TableName, new JsonDocument { Id = "test" });
try
{
await Document.Insert(SqliteDb.TableName, new JsonDocument { Id = "test" });
Expect.isTrue(false, "An exception should have been raised for duplicate document ID insert");
}
catch (Exception)
{
// This is what is supposed to happen
}
})
]),
TestList("Document.Save",
[
TestCase("succeeds when a document is inserted", async () =>
{
await using var db = await SqliteDb.BuildDb();
var before = await Find.All<JsonDocument>(SqliteDb.TableName);
Expect.isEmpty(before, "There should be no documents in the table");
await Document.Save(SqliteDb.TableName,
new JsonDocument { Id = "test", Sub = new() { Foo = "a", Bar = "b" } });
var after = await Find.All<JsonDocument>(SqliteDb.TableName);
Expect.equal(after.Count, 1, "There should have been one document inserted");
}),
TestCase("succeeds when a document is updated", async () =>
{
await using var db = await SqliteDb.BuildDb();
await Document.Insert(SqliteDb.TableName,
new JsonDocument { Id = "test", Sub = new() { Foo = "a", Bar = "b" } });
var before = await Find.ById<string, JsonDocument>(SqliteDb.TableName, "test");
Expect.isNotNull(before, "There should have been a document returned");
Expect.equal(before!.Id, "test", "The document is not correct");
Expect.isNotNull(before.Sub, "There should have been a sub-document");
Expect.equal(before.Sub!.Foo, "a", "The document is not correct");
Expect.equal(before.Sub.Bar, "b", "The document is not correct");
await Document.Save(SqliteDb.TableName, new JsonDocument { Id = "test" });
var after = await Find.ById<string, JsonDocument>(SqliteDb.TableName, "test");
Expect.isNotNull(after, "There should have been a document returned post-update");
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");
})
])
]);
/// <summary>
/// Integration tests for the Count module of the SQLite library
/// </summary>
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("succeeds for 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");
})
])
]);
/// <summary>
/// Integration tests for the Exists module of the SQLite library
/// </summary>
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");
})
])
]);
/// <summary>
/// Integration tests for the Find module of the SQLite library
/// </summary>
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<JsonDocument>(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<SubDocument>(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<string, JsonDocument>(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<string, JsonDocument>(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<JsonDocument>(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<JsonDocument>(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<JsonDocument>(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<JsonDocument>(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<JsonDocument>(SqliteDb.TableName, FieldMatch.Any,
[Field.EQ("Value", "absent")]);
Expect.isNull(doc, "There should not have been a document returned");
})
])
]);
/// <summary>
/// Integration tests for the Update module of the SQLite library
/// </summary>
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<string, JsonDocument>(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<JsonDocument>(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<string, JsonDocument>(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<JsonDocument>(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 });
})
]),
]);
/// <summary>
/// Integration tests for the Patch module of the SQLite library
/// </summary>
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<string, JsonDocument>(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<JsonDocument>(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<SubDocument>(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" });
})
])
]);
/// <summary>
/// Integration tests for the RemoveFields module of the SQLite library
/// </summary>
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<string, JsonDocument>(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<string, JsonDocument>(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"]);
})
])
]);
/// <summary>
/// Integration tests for the Delete module of the SQLite library
/// </summary>
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");
})
])
]);
/// <summary>
/// All tests for SQLite C# functions and methods
/// </summary>
[Tests]
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:"))
]))
]);
}