- NUnit2046: `Assert.That(x.Count, Is.EqualTo(n))` → `Assert.That(x, Has.Count.EqualTo(n))` (or `Is.Empty` when n==0)
- NUnit2011: `Assert.That(s.Contains(x))` → `Assert.That(s, Does.Contain(x))` for richer failure messages
- CA1866: `.StartsWith("$"|"@"|":")` → `.StartsWith('$'|'@'|':')` char overload
Driven by `dotnet format analyzers --diagnostics NUnit2046 NUnit2011 CA1866`
for the cases the Roslyn fixer handles, plus a regex sweep for the remaining
`Count == n` (n>0) cases which the fixer doesn't address. CA1866 had no
associated code fix and was edited by hand (3 sites in 2 files). All tests
green (1180 passing).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
344 lines
8.8 KiB
C#
344 lines
8.8 KiB
C#
using Strata.SqlTools.Breakdowns.PostgreSql;
|
|
|
|
namespace Strata.SqlTools.SqlBreakdown.Tests.PostgreSql;
|
|
|
|
[TestFixture]
|
|
public class QueryBreakdownCollectionTests
|
|
{
|
|
private QueryBreakdownCollection _collection = null!;
|
|
|
|
[SetUp]
|
|
public void Setup()
|
|
{
|
|
_collection = new QueryBreakdownCollection();
|
|
}
|
|
|
|
#region Constructor Tests
|
|
|
|
[Test]
|
|
public void Constructor_Default_CreatesEmptyCollection()
|
|
{
|
|
// Arrange & Act
|
|
var collection = new QueryBreakdownCollection();
|
|
|
|
// Assert
|
|
Assert.That(collection, Is.Empty);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Add Tests
|
|
|
|
[Test]
|
|
public void Add_SingleQueryBreakdown_AddsSuccessfully()
|
|
{
|
|
// Arrange
|
|
var query = new QueryBreakdown("id, name", "users");
|
|
|
|
// Act
|
|
_collection.Add(query);
|
|
|
|
// Assert
|
|
Assert.That(_collection.Count, Is.GreaterThan(0));
|
|
}
|
|
|
|
[Test]
|
|
public void Add_MultipleQueryBreakdowns_AddsMultiple()
|
|
{
|
|
// Arrange
|
|
var query1 = new QueryBreakdown("id, name", "users");
|
|
var query2 = new QueryBreakdown("order_id, amount", "orders");
|
|
var query3 = new QueryBreakdown("product_id, price", "products");
|
|
|
|
// Act
|
|
_collection.Add(query1);
|
|
_collection.Add(query2);
|
|
_collection.Add(query3);
|
|
|
|
// Assert
|
|
Assert.That(_collection, Has.Count.EqualTo(3));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetPostgreSqlBatch Tests
|
|
|
|
[Test]
|
|
public void GetPostgreSqlBatch_EmptyCollection_ReturnsEmptyString()
|
|
{
|
|
// Arrange - empty collection created in SetUp
|
|
|
|
// Act
|
|
var sql = _collection.GetPostgreSqlBatch();
|
|
|
|
// Assert
|
|
Assert.That(sql, Is.Not.Null);
|
|
}
|
|
|
|
[Test]
|
|
public void GetPostgreSqlBatch_SingleQuery_GeneratesValidSql()
|
|
{
|
|
// Arrange
|
|
var query = new QueryBreakdown("id, name", "users");
|
|
_collection.Add(query);
|
|
|
|
// Act
|
|
var sql = _collection.GetPostgreSqlBatch();
|
|
|
|
// Assert
|
|
Assert.That(sql, Is.Not.Null);
|
|
Assert.That(sql, Does.Contain("SELECT").Or.Contain("select"));
|
|
}
|
|
|
|
[Test]
|
|
public void GetPostgreSqlBatch_MultipleQueries_SeparatesWithSemicolon()
|
|
{
|
|
// Arrange
|
|
var query1 = new QueryBreakdown("id", "users");
|
|
var query2 = new QueryBreakdown("id", "orders");
|
|
_collection.Add(query1);
|
|
_collection.Add(query2);
|
|
|
|
// Act
|
|
var sql = _collection.GetPostgreSqlBatch();
|
|
|
|
// Assert
|
|
Assert.That(sql, Is.Not.Null);
|
|
// PostgreSQL batch should contain semicolons separating statements
|
|
Assert.That(sql, Does.Contain(";"));
|
|
}
|
|
|
|
[Test]
|
|
public void GetPostgreSqlBatch_WithWhereClause_IncludesConditions()
|
|
{
|
|
// Arrange
|
|
var query = new QueryBreakdown("id, name", "users");
|
|
query.WhereClause.Clause = "active = true";
|
|
_collection.Add(query);
|
|
|
|
// Act
|
|
var sql = _collection.GetPostgreSqlBatch();
|
|
|
|
// Assert
|
|
Assert.That(sql, Does.Contain("active"));
|
|
}
|
|
|
|
[Test]
|
|
public void GetPostgreSqlBatch_WithOrderBy_IncludesOrderBy()
|
|
{
|
|
// Arrange
|
|
var query = new QueryBreakdown("id, name", "users");
|
|
query.OrderByClause.Clause = "name ASC";
|
|
_collection.Add(query);
|
|
|
|
// Act
|
|
var sql = _collection.GetPostgreSqlBatch();
|
|
|
|
// Assert
|
|
Assert.That(sql, Does.Contain("ORDER BY").Or.Contain("order by"));
|
|
}
|
|
|
|
[Test]
|
|
public void GetPostgreSqlBatch_WithGroupBy_IncludesGroupBy()
|
|
{
|
|
// Arrange
|
|
var query = new QueryBreakdown("category, COUNT(*) as count", "products");
|
|
query.GroupByClause.Clause = "category";
|
|
_collection.Add(query);
|
|
|
|
// Act
|
|
var sql = _collection.GetPostgreSqlBatch();
|
|
|
|
// Assert
|
|
Assert.That(sql, Does.Contain("GROUP BY").Or.Contain("group by"));
|
|
}
|
|
|
|
[Test]
|
|
public void GetPostgreSqlBatch_WithHaving_IncludesHaving()
|
|
{
|
|
// Arrange
|
|
var query = new QueryBreakdown("category, COUNT(*) as count", "products");
|
|
query.GroupByClause.Clause = "category";
|
|
query.HavingClause.Clause = "COUNT(*) > 5";
|
|
_collection.Add(query);
|
|
|
|
// Act
|
|
var sql = _collection.GetPostgreSqlBatch();
|
|
|
|
// Assert
|
|
Assert.That(sql, Does.Contain("HAVING").Or.Contain("having"));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ParseBatch Tests
|
|
|
|
[Test]
|
|
public void ParseBatch_WithValidSql_Succeeds()
|
|
{
|
|
// Arrange
|
|
var batchSql = "SELECT id, name FROM users WHERE active = true; SELECT order_id FROM orders;";
|
|
|
|
// Act
|
|
var result = _collection.ParseBatch(batchSql);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.True);
|
|
Assert.That(_collection.Count, Is.GreaterThan(0));
|
|
}
|
|
|
|
[Test]
|
|
public void ParseBatch_WithMultipleStatements_ParsesAllQueries()
|
|
{
|
|
// Arrange
|
|
var batchSql = @"
|
|
SELECT id, name FROM users WHERE active = true;
|
|
SELECT order_id, amount FROM orders WHERE user_id = $1;
|
|
";
|
|
|
|
// Act
|
|
var result = _collection.ParseBatch(batchSql);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.True);
|
|
Assert.That(_collection.Count, Is.GreaterThan(0));
|
|
}
|
|
|
|
[Test]
|
|
public void ParseBatch_WithSingleStatement_ParsesSingleQuery()
|
|
{
|
|
// Arrange
|
|
var batchSql = "SELECT id, name FROM users";
|
|
|
|
// Act
|
|
var result = _collection.ParseBatch(batchSql);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.True);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Complex Query Tests
|
|
|
|
[Test]
|
|
public void GetPostgreSqlBatch_ComplexQueryWithMultipleClauses_GeneratesValidBatch()
|
|
{
|
|
// Arrange
|
|
var query1 = new QueryBreakdown("id, name", "users");
|
|
query1.WhereClause.Clause = "id = $1";
|
|
|
|
var query2 = new QueryBreakdown("order_id, amount", "orders");
|
|
query2.WhereClause.Clause = "user_id = $1";
|
|
query2.OrderByClause.Clause = "created_at DESC";
|
|
|
|
_collection.Add(query1);
|
|
_collection.Add(query2);
|
|
|
|
// Act
|
|
var sql = _collection.GetPostgreSqlBatch();
|
|
|
|
// Assert
|
|
Assert.That(sql, Does.Contain(";"));
|
|
Assert.That(sql, Does.Contain("SELECT"));
|
|
Assert.That(sql, Does.Contain("WHERE"));
|
|
}
|
|
|
|
[Test]
|
|
public void GetPostgreSqlBatch_WithParameters_IncludesParameterValues()
|
|
{
|
|
// Arrange
|
|
var query = new QueryBreakdown("id, name", "users");
|
|
query.AddParameter("userId", 123);
|
|
_collection.Add(query);
|
|
|
|
// Act
|
|
var sql = _collection.GetPostgreSqlBatch();
|
|
|
|
// Assert
|
|
Assert.That(sql, Does.Contain("SELECT"));
|
|
Assert.That(sql, Is.Not.Null);
|
|
}
|
|
|
|
[Test]
|
|
public void GetPostgreSqlBatch_MultipleQueriesWithDifferentClauses_GeneratesValidBatch()
|
|
{
|
|
// Arrange
|
|
var query1 = new QueryBreakdown("id, name", "users");
|
|
query1.WhereClause.Clause = "active = true";
|
|
|
|
var query2 = new QueryBreakdown("order_id, total", "orders");
|
|
query2.WhereClause.Clause = "status = 'pending'";
|
|
query2.OrderByClause.Clause = "created_at DESC";
|
|
|
|
var query3 = new QueryBreakdown("product_id, price", "products");
|
|
query3.WhereClause.Clause = "in_stock = true";
|
|
query3.OrderByClause.Clause = "price ASC";
|
|
|
|
_collection.Add(query1);
|
|
_collection.Add(query2);
|
|
_collection.Add(query3);
|
|
|
|
// Act
|
|
var sql = _collection.GetPostgreSqlBatch();
|
|
|
|
// Assert
|
|
Assert.That(sql, Does.Contain("SELECT"));
|
|
Assert.That(sql, Does.Contain(";"));
|
|
Assert.That(_collection, Has.Count.EqualTo(3));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Edge Cases
|
|
|
|
[Test]
|
|
public void GetPostgreSqlBatch_MultipleQueriesWithJoins_GeneratesValidBatch()
|
|
{
|
|
// Arrange
|
|
var query = new QueryBreakdown("u.id, u.name, o.order_id", "users u LEFT JOIN orders o ON u.id = o.user_id");
|
|
query.WhereClause.Clause = "u.active = true";
|
|
_collection.Add(query);
|
|
|
|
// Act
|
|
var sql = _collection.GetPostgreSqlBatch();
|
|
|
|
// Assert
|
|
Assert.That(sql, Does.Contain("JOIN"));
|
|
}
|
|
|
|
[Test]
|
|
public void GetPostgreSqlBatch_WithDoubleQuotedIdentifiers_PreservesQuotes()
|
|
{
|
|
// Arrange
|
|
var query = new QueryBreakdown("\"Id\", \"Name\"", "\"Users\"");
|
|
_collection.Add(query);
|
|
|
|
// Act
|
|
var sql = _collection.GetPostgreSqlBatch();
|
|
|
|
// Assert
|
|
Assert.That(sql, Does.Contain("\""));
|
|
}
|
|
|
|
[Test]
|
|
public void ParseBatch_WithComments_IgnoresComments()
|
|
{
|
|
// Arrange
|
|
var batchSql = @"
|
|
-- This is a user query
|
|
SELECT id, name FROM users;
|
|
-- This is an orders query
|
|
SELECT order_id FROM orders;
|
|
";
|
|
|
|
// Act
|
|
var result = _collection.ParseBatch(batchSql);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.True);
|
|
}
|
|
|
|
#endregion
|
|
}
|