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.Multiple(() => { // 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.Multiple(() => { // 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.Multiple(() => { // 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.Multiple(() => { // 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.Multiple(() => { // 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.Multiple(() => { // 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.Multiple(() => { // 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.Multiple(() => { // 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.Multiple(() => { // 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.Multiple(() => { // Assert Assert.That(query.IsUsingWithClause, Is.True); Assert.That(query.WithClauses, Has.Count.EqualTo(1)); }); Assert.Multiple(() => { 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.Multiple(() => { // Assert Assert.That(query.IsUsingWithClause, Is.True); Assert.That(query.WithClauses, Has.Count.EqualTo(2)); }); Assert.Multiple(() => { 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.Multiple(() => { // 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.Multiple(() => { // 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.Multiple(() => { 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.Multiple(() => { // 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(() => query!.Select("*")); } [Test] public void From_WithNullQuery_ThrowsArgumentNullException() { // Arrange QueryBreakdown? query = null; // Act & Assert Assert.Throws(() => query!.From("users")); } [Test] public void Where_WithNullQuery_ThrowsArgumentNullException() { // Arrange QueryBreakdown? query = null; // Act & Assert Assert.Throws(() => query!.Where("active = 1")); } [Test] public void WithCte_WithNullQuery_ThrowsArgumentNullException() { // Arrange QueryBreakdown? query = null; // Act & Assert Assert.Throws(() => query!.WithCte("test", cte => cte.Select("*").From("users"))); } [Test] public void WithCte_WithEmptyTableName_ThrowsArgumentException() { // Arrange var query = new QueryBreakdown(); // Act & Assert Assert.Throws(() => query.WithCte("", cte => cte.Select("*").From("users"))); } [Test] public void WithCte_WithNullConfigureAction_ThrowsArgumentNullException() { // Arrange var query = new QueryBreakdown(); // Act & Assert Assert.Throws(() => query.WithCte("test", (Action)null!)); } [Test] public void WithCte_WithColumnList_WithEmptyColumns_ThrowsArgumentException() { // Arrange var query = new QueryBreakdown(); // Act & Assert Assert.Throws(() => query.WithCte("test", Array.Empty(), cte => cte.Select("*").From("users"))); } [Test] public void WithCte_WithIQueryBreakdown_WithNullCteQuery_ThrowsArgumentNullException() { // Arrange var query = new QueryBreakdown(); // Act & Assert Assert.Throws(() => 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.Multiple(() => { // 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.Multiple(() => { // 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.Multiple(() => { // Assert Assert.That(query.SelectClause.Clause, Is.EqualTo(" id, name ")); Assert.That(query.FromClause.Clause, Is.EqualTo(" users ")); }); } #endregion }