Files
sql-utilities/tests/Strata.SqlTools.SqlBreakdown.Tests/Extensions/QueryBreakdownExtensionsTests.cs
T
Thom LambandClaude Opus 4.7 505ada5017 chore(sonar): adopt Has.Count, Is.Empty, Does.Contain, char overloads in tests (NUnit2046, NUnit2011, CA1866)
- 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>
2026-05-27 11:58:00 -05:00

505 lines
15 KiB
C#

using Strata.SqlTools.Breakdowns.SqlServer;
using Strata.SqlTools.Extensions;
namespace Strata.SqlTools.SqlBreakdown.Tests.Extensions;
[TestFixture]
public class QueryBreakdownExtensionsTests
{
#region Basic Clause Tests
[Test]
public void Select_SetsSelectClause()
{
// Arrange
var query = new QueryBreakdown();
// Act
var result = query.Select("id, name");
// Assert
Assert.That(result, Is.SameAs(query));
Assert.That(query.SelectClause.Clause, Is.EqualTo("id, name"));
}
[Test]
public void From_SetsFromClause()
{
// Arrange
var query = new QueryBreakdown();
// Act
var result = query.From("users");
// Assert
Assert.That(result, Is.SameAs(query));
Assert.That(query.FromClause.Clause, Is.EqualTo("users"));
}
[Test]
public void Where_SetsWhereClause()
{
// Arrange
var query = new QueryBreakdown();
// Act
var result = query.Where("active = 1");
// Assert
Assert.That(result, Is.SameAs(query));
Assert.That(query.WhereClause.Clause, Is.EqualTo("active = 1"));
}
[Test]
public void GroupBy_SetsGroupByClause()
{
// Arrange
var query = new QueryBreakdown();
// Act
var result = query.GroupBy("department");
// Assert
Assert.That(result, Is.SameAs(query));
Assert.That(query.GroupByClause.Clause, Is.EqualTo("department"));
}
[Test]
public void Having_SetsHavingClause()
{
// Arrange
var query = new QueryBreakdown();
// Act
var result = query.Having("COUNT(*) > 5");
// Assert
Assert.That(result, Is.SameAs(query));
Assert.That(query.HavingClause.Clause, Is.EqualTo("COUNT(*) > 5"));
}
[Test]
public void OrderBy_SetsOrderByClause()
{
// Arrange
var query = new QueryBreakdown();
// Act
var result = query.OrderBy("name ASC");
// Assert
Assert.That(result, Is.SameAs(query));
Assert.That(query.OrderByClause.Clause, Is.EqualTo("name ASC"));
}
[Test]
public void AddWhere_AppendsToWhereClause()
{
// Arrange
var query = new QueryBreakdown().Where("active = 1");
// Act
var result = query.AddWhere("AND age > 18");
// Assert
Assert.That(result, Is.SameAs(query));
Assert.That(query.WhereClause.Clause, Does.Contain("active = 1"));
Assert.That(query.WhereClause.Clause, Does.Contain("AND age > 18"));
}
#endregion
#region Method Chaining Tests
[Test]
public void FluentAPI_CanChainSelectFromWhere()
{
// Act
var query = new QueryBreakdown()
.Select("id, name")
.From("users")
.Where("active = 1");
// Assert
Assert.That(query.SelectClause.Clause, Is.EqualTo("id, name"));
Assert.That(query.FromClause.Clause, Is.EqualTo("users"));
Assert.That(query.WhereClause.Clause, Is.EqualTo("active = 1"));
}
[Test]
public void FluentAPI_CanChainAllClauses()
{
// Act
var query = new QueryBreakdown()
.Select("department, COUNT(*) as employee_count")
.From("employees")
.Where("salary > 50000")
.GroupBy("department")
.Having("COUNT(*) > 5")
.OrderBy("employee_count DESC");
// Assert
Assert.That(query.SelectClause.Clause, Is.EqualTo("department, COUNT(*) as employee_count"));
Assert.That(query.FromClause.Clause, Is.EqualTo("employees"));
Assert.That(query.WhereClause.Clause, Is.EqualTo("salary > 50000"));
Assert.That(query.GroupByClause.Clause, Is.EqualTo("department"));
Assert.That(query.HavingClause.Clause, Is.EqualTo("COUNT(*) > 5"));
Assert.That(query.OrderByClause.Clause, Is.EqualTo("employee_count DESC"));
}
[Test]
public void FluentAPI_GeneratesCorrectSQL()
{
// Arrange & Act
var query = new QueryBreakdown()
.Select("id, name, email")
.From("users")
.Where("active = 1")
.OrderBy("name ASC");
var sql = query.GetSql();
// Assert
Assert.That(sql, Does.Contain("SELECT"));
Assert.That(sql, Does.Contain("id, name, email"));
Assert.That(sql, Does.Contain("FROM"));
Assert.That(sql, Does.Contain("users"));
Assert.That(sql, Does.Contain("WHERE"));
Assert.That(sql, Does.Contain("active = 1"));
Assert.That(sql, Does.Contain("ORDER BY"));
Assert.That(sql, Does.Contain("name ASC"));
}
#endregion
#region WithCte Tests
[Test]
public void WithCte_WithConfigureAction_AddsCtesToQuery()
{
// Arrange & Act
var query = new QueryBreakdown()
.WithCte("active_users", cte => cte
.Select("id, name")
.From("users")
.Where("active = 1"))
.Select("*")
.From("active_users");
// Assert
Assert.That(query.IsUsingWithClause, Is.True);
Assert.That(query.WithClauses, Has.Count.EqualTo(1));
Assert.That(query.WithClauses[0].TableName, Is.EqualTo("active_users"));
Assert.That(query.SelectClause.Clause, Is.EqualTo("*"));
Assert.That(query.FromClause.Clause, Is.EqualTo("active_users"));
}
[Test]
public void WithCte_GeneratesCorrectSQL()
{
// Arrange & Act
var query = new QueryBreakdown()
.WithCte("active_users", cte => cte
.Select("id, name")
.From("users")
.Where("active = 1"))
.Select("*")
.From("active_users");
var sql = query.GetSql();
// Assert
Assert.That(sql, Does.Contain("WITH"));
Assert.That(sql, Does.Contain("active_users AS"));
Assert.That(sql, Does.Contain("SELECT"));
Assert.That(sql, Does.Contain("id, name"));
Assert.That(sql, Does.Contain("FROM"));
Assert.That(sql, Does.Contain("users"));
Assert.That(sql, Does.Contain("WHERE"));
Assert.That(sql, Does.Contain("active = 1"));
}
[Test]
public void WithCte_SupportsMultipleCTEs()
{
// Arrange & Act
var query = new QueryBreakdown()
.WithCte("active_users", cte => cte
.Select("id, name")
.From("users")
.Where("active = 1"))
.WithCte("recent_orders", cte => cte
.Select("order_id, user_id, total")
.From("orders")
.Where("created_date > '2024-01-01'"))
.Select("u.name, COUNT(o.order_id) as order_count")
.From("active_users u LEFT JOIN recent_orders o ON u.id = o.user_id")
.GroupBy("u.id, u.name");
// Assert
Assert.That(query.IsUsingWithClause, Is.True);
Assert.That(query.WithClauses, Has.Count.EqualTo(2));
Assert.That(query.WithClauses[0].TableName, Is.EqualTo("active_users"));
Assert.That(query.WithClauses[1].TableName, Is.EqualTo("recent_orders"));
}
private static readonly string[] columns = new[] { "id", "name", "email" };
[Test]
public void WithCte_WithColumnList_AddsCtesWithColumns()
{
// Arrange & Act
var query = new QueryBreakdown()
.WithCte("active_users", columns, cte => cte
.Select("user_id, user_name, user_email")
.From("users")
.Where("status = 'active'"))
.Select("*")
.From("active_users");
var sql = query.GetSql();
// Assert
Assert.That(query.IsUsingWithClause, Is.True);
Assert.That(query.WithClauses, Has.Count.EqualTo(1));
Assert.That(sql, Does.Contain("active_users (id, name, email)"));
}
[Test]
public void WithCte_WithIQueryBreakdown_AddsCte()
{
// Arrange
var cteQuery = new QueryBreakdown()
.Select("id, name")
.From("users")
.Where("active = 1");
// Act
var query = new QueryBreakdown()
.WithCte("active_users", cteQuery)
.Select("*")
.From("active_users");
// Assert
Assert.That(query.IsUsingWithClause, Is.True);
Assert.That(query.WithClauses, Has.Count.EqualTo(1));
Assert.That(query.WithClauses[0].TableName, Is.EqualTo("active_users"));
}
#endregion
#region Complex Query Tests
[Test]
public void FluentAPI_ComplexQueryWithGrouping()
{
// Arrange & Act
var query = new QueryBreakdown()
.Select("department, AVG(salary) as avg_salary, COUNT(*) as emp_count")
.From("employees")
.Where("hire_date >= '2020-01-01'")
.GroupBy("department")
.Having("COUNT(*) >= 10")
.OrderBy("avg_salary DESC");
var sql = query.GetSql();
// Assert
Assert.That(sql, Does.Contain("SELECT"));
Assert.That(sql, Does.Contain("department, AVG(salary) as avg_salary, COUNT(*) as emp_count"));
Assert.That(sql, Does.Contain("GROUP BY"));
Assert.That(sql, Does.Contain("HAVING"));
Assert.That(sql, Does.Contain("COUNT(*) >= 10"));
}
[Test]
public void FluentAPI_RealWorldExample_SalesSummaryReport()
{
// Arrange & Act - Build a sales summary report with CTE
var query = new QueryBreakdown()
.WithCte("monthly_sales", cte => cte
.Select("YEAR(order_date) as year, MONTH(order_date) as month, SUM(total_amount) as total_sales")
.From("orders")
.Where("status = 'completed'")
.GroupBy("YEAR(order_date), MONTH(order_date)"))
.Select("year, month, total_sales, LAG(total_sales) OVER (ORDER BY year, month) as prev_month_sales")
.From("monthly_sales")
.OrderBy("year DESC, month DESC");
var sql = query.GetSql();
// Assert
Assert.That(sql, Does.Contain("WITH"));
Assert.That(sql, Does.Contain("monthly_sales AS"));
Assert.That(sql, Does.Contain("LAG(total_sales)"));
Assert.That(query.IsUsingWithClause, Is.True);
}
[Test]
public void FluentAPI_RealWorldExample_ActiveUserHierarchy()
{
// Arrange & Act - Build a hierarchical user/order report
var query = new QueryBreakdown()
.WithCte("active_users", cte => cte
.Select("id, name, email")
.From("users")
.Where("active = 1 AND last_login > DATEADD(month, -3, GETDATE())"))
.WithCte("user_orders", cte => cte
.Select("u.id as user_id, u.name, COUNT(o.id) as order_count, SUM(o.total) as total_spent")
.From("active_users u LEFT JOIN orders o ON u.id = o.user_id")
.GroupBy("u.id, u.name"))
.Select("name, order_count, total_spent, CASE WHEN total_spent > 1000 THEN 'VIP' ELSE 'Regular' END as customer_tier")
.From("user_orders")
.Where("order_count > 0")
.OrderBy("total_spent DESC");
var sql = query.GetSql();
// Assert
Assert.That(query.WithClauses, Has.Count.EqualTo(2));
Assert.That(sql, Does.Contain("active_users AS"));
Assert.That(sql, Does.Contain("user_orders AS"));
Assert.That(sql, Does.Contain("customer_tier"));
}
#endregion
#region Validation Tests
[Test]
public void Select_WithNullQuery_ThrowsArgumentNullException()
{
// Arrange
QueryBreakdown? query = null;
// Act & Assert
Assert.Throws<ArgumentNullException>(() => query!.Select("*"));
}
[Test]
public void From_WithNullQuery_ThrowsArgumentNullException()
{
// Arrange
QueryBreakdown? query = null;
// Act & Assert
Assert.Throws<ArgumentNullException>(() => query!.From("users"));
}
[Test]
public void Where_WithNullQuery_ThrowsArgumentNullException()
{
// Arrange
QueryBreakdown? query = null;
// Act & Assert
Assert.Throws<ArgumentNullException>(() => query!.Where("active = 1"));
}
[Test]
public void WithCte_WithNullQuery_ThrowsArgumentNullException()
{
// Arrange
QueryBreakdown? query = null;
// Act & Assert
Assert.Throws<ArgumentNullException>(() =>
query!.WithCte("test", cte => cte.Select("*").From("users")));
}
[Test]
public void WithCte_WithEmptyTableName_ThrowsArgumentException()
{
// Arrange
var query = new QueryBreakdown();
// Act & Assert
Assert.Throws<ArgumentException>(() =>
query.WithCte("", cte => cte.Select("*").From("users")));
}
[Test]
public void WithCte_WithNullConfigureAction_ThrowsArgumentNullException()
{
// Arrange
var query = new QueryBreakdown();
// Act & Assert
Assert.Throws<ArgumentNullException>(() =>
query.WithCte("test", (Action<QueryBreakdown>)null!));
}
[Test]
public void WithCte_WithColumnList_WithEmptyColumns_ThrowsArgumentException()
{
// Arrange
var query = new QueryBreakdown();
// Act & Assert
Assert.Throws<ArgumentException>(() =>
query.WithCte("test", Array.Empty<string>(), cte => cte.Select("*").From("users")));
}
[Test]
public void WithCte_WithIQueryBreakdown_WithNullCteQuery_ThrowsArgumentNullException()
{
// Arrange
var query = new QueryBreakdown();
// Act & Assert
Assert.Throws<ArgumentNullException>(() =>
query.WithCte("test", (QueryBreakdown)null!));
}
#endregion
#region Edge Case Tests
[Test]
public void FluentAPI_CanOverwriteClauses()
{
// Arrange
var query = new QueryBreakdown()
.Select("*")
.From("users")
.Where("active = 1");
// Act - Overwrite clauses
query.Select("id, name").Where("active = 0");
// Assert
Assert.That(query.SelectClause.Clause, Is.EqualTo("id, name"));
Assert.That(query.WhereClause.Clause, Is.EqualTo("active = 0"));
}
[Test]
public void FluentAPI_HandlesEmptyStrings()
{
// Arrange & Act
var query = new QueryBreakdown()
.Select("")
.From("")
.Where("");
// Assert
Assert.That(query.SelectClause.Clause, Is.EqualTo(""));
Assert.That(query.FromClause.Clause, Is.EqualTo(""));
Assert.That(query.WhereClause.Clause, Is.EqualTo(""));
}
[Test]
public void FluentAPI_PreservesWhitespace()
{
// Arrange & Act
var query = new QueryBreakdown()
.Select(" id, name ")
.From(" users ");
// Assert
Assert.That(query.SelectClause.Clause, Is.EqualTo(" id, name "));
Assert.That(query.FromClause.Clause, Is.EqualTo(" users "));
}
#endregion
}