diff --git a/DotnetApp.Tests/Models/TestItemTest.cs b/DotnetApp.Tests/Models/TestItemTest.cs index 0ccff25..0de0c00 100644 --- a/DotnetApp.Tests/Models/TestItemTest.cs +++ b/DotnetApp.Tests/Models/TestItemTest.cs @@ -83,7 +83,8 @@ public void CalculateTaskScore_ShouldDoubleScore_ForPendingStatusAndOldTask() var score = task.CalculateTaskScore(); // Assert - Assert.Equal(15, score); + // Priority score: 5, Status score: 5*2 + 5 = 15, Total: 20 + Assert.Equal(20, score); } [Fact] @@ -145,5 +146,404 @@ public void CalculateTaskScore_ShouldReturnZero_ForNegativeScore() // Assert Assert.Equal(1, score); } + + [Fact] + public void CalculateTaskScore_PriorityOne_NotPending_ShouldReturnBaseScore() + { + // Arrange + var task = new TaskItem + { + Priority = 1, + Status = "in-progress", + CreatedAt = DateTime.UtcNow.AddDays(-1), + IsCompleted = false, + Title = "Test Task" + }; + + // Act + var score = task.CalculateTaskScore(); + + // Assert + // Priority score: 10 (no +3 because not pending) + // Status score: 0 (in-progress, not completed, no long words) + Assert.Equal(10, score); + } + + [Fact] + public void CalculateTaskScore_PriorityTwo_InProgress_NotCompleted_WithinWeek() + { + // Arrange + var task = new TaskItem + { + Priority = 2, + Status = "in-progress", + CreatedAt = DateTime.UtcNow.AddDays(-5), + IsCompleted = false, + Title = "Test Task" + }; + + // Act + var score = task.CalculateTaskScore(); + + // Assert + // Priority score: 5 + 2 = 7 (in-progress and not completed but < 7 days) + // Status score: 0 + Assert.Equal(7, score); + } + + [Fact] + public void CalculateTaskScore_PriorityThree_DefaultStatus_NotCompleted() + { + // Arrange + var task = new TaskItem + { + Priority = 3, + Status = "blocked", + CreatedAt = DateTime.UtcNow.AddDays(-1), + IsCompleted = false, + Title = "Test Task" + }; + + // Act + var score = task.CalculateTaskScore(); + + // Assert + // Priority score: 1 + // Status score: 3 (default case, not completed and priority < 3 is false for priority=3) + Assert.Equal(1, score); + } + + [Fact] + public void CalculateTaskScore_PriorityTwo_DefaultStatus_NotCompleted() + { + // Arrange + var task = new TaskItem + { + Priority = 2, + Status = "cancelled", + CreatedAt = DateTime.UtcNow.AddDays(-1), + IsCompleted = false, + Title = "Test Task" + }; + + // Act + var score = task.CalculateTaskScore(); + + // Assert + // Priority score: 5 + // Status score: 3 (default case, not completed and priority < 3) + Assert.Equal(8, score); + } + + [Fact] + public void CalculateTaskScore_NegativePriority_ShouldTreatAsLowPriority() + { + // Arrange + var task = new TaskItem + { + Priority = -1, + Status = "pending", + CreatedAt = DateTime.UtcNow.AddDays(-1), + IsCompleted = false, + Title = "Test Task" + }; + + // Act + var score = task.CalculateTaskScore(); + + // Assert + // Priority <= 0 gives score of 1 + Assert.Equal(1, score); + } + + [Fact] + public void CalculateTaskScore_OldPendingTask_HighPriority_ShouldDoubleAndAdd() + { + // Arrange + var task = new TaskItem + { + Priority = 1, + Status = "pending", + CreatedAt = DateTime.UtcNow.AddDays(-20), + IsCompleted = false, + Title = "Test Task" + }; + + // Act + var score = task.CalculateTaskScore(); + + // Assert + // Priority score: 10 + 3 = 13 + // Status score: 13 * 2 + 5 = 31 + // Total: 44 + Assert.Equal(44, score); + } + + [Fact] + public void CalculateTaskScore_InProgress_MultipleLongWords() + { + // Arrange + var task = new TaskItem + { + Priority = 3, + Status = "in-progress", + CreatedAt = DateTime.UtcNow.AddDays(-1), + IsCompleted = false, + Title = "VeryLongWord AnotherLongWord ThirdLongWordHere" + }; + + // Act + var score = task.CalculateTaskScore(); + + // Assert + // Priority score: 1 + // Status score: 3 (three words > 10 chars) + Assert.Equal(4, score); + } + + [Fact] + public void CalculateTaskScore_InProgress_Completed_ShouldSubtract() + { + // Arrange + var task = new TaskItem + { + Priority = 1, + Status = "in-progress", + CreatedAt = DateTime.UtcNow.AddDays(-1), + IsCompleted = true, + Title = "Test Task" + }; + + // Act + var score = task.CalculateTaskScore(); + + // Assert + // Priority score: 10 + // Status score: -5 (completed in-progress) + // Total: max(0, 5) = 5 + Assert.Equal(5, score); + } + + [Fact] + public void CalculateTaskScore_PendingTask_ExactlyFourteenDays() + { + // Arrange + var task = new TaskItem + { + Priority = 2, + Status = "pending", + CreatedAt = DateTime.UtcNow.AddDays(-14).AddSeconds(1), // Just under 14 days + IsCompleted = false, + Title = "Test Task" + }; + + // Act + var score = task.CalculateTaskScore(); + + // Assert + // Priority score: 5 + // Status score: 0 (< 14 days, so no doubling) + Assert.Equal(5, score); + } + + [Fact] + public void CalculateTaskScore_PendingTask_OverFourteenDays() + { + // Arrange + var task = new TaskItem + { + Priority = 2, + Status = "pending", + CreatedAt = DateTime.UtcNow.AddDays(-15), + IsCompleted = false, + Title = "Test Task" + }; + + // Act + var score = task.CalculateTaskScore(); + + // Assert + // Priority score: 5 + // Status score: 5*2 + 5 = 15 + // Total: 20 + Assert.Equal(20, score); + } + + [Fact] + public void CalculateTaskScore_UppercaseStatus_ShouldWork() + { + // Arrange + var task = new TaskItem + { + Priority = 1, + Status = "PENDING", + CreatedAt = DateTime.UtcNow.AddDays(-1), + IsCompleted = false, + Title = "Test Task" + }; + + // Act + var score = task.CalculateTaskScore(); + + // Assert + // Note: Status check in CalculatePriorityScore is case-sensitive (line 42) + // So "PENDING" != "pending", priority score is 10, not 13 + // Status score: 0 (ToLower() in CalculateStatusScore matches, but no old task bonus) + Assert.Equal(10, score); + } + + [Fact] + public void CalculateTaskScore_MixedCaseStatus_InProgress() + { + // Arrange + var task = new TaskItem + { + Priority = 2, + Status = "In-Progress", + CreatedAt = DateTime.UtcNow.AddDays(-1), + IsCompleted = false, + Title = "TestWord" + }; + + // Act + var score = task.CalculateTaskScore(); + + // Assert + // Priority score: 5 + // Status score: 0 (no long words) + Assert.Equal(5, score); + } + + [Fact] + public void CalculateTaskScore_InProgress_LongWordExactly10Chars() + { + // Arrange + var task = new TaskItem + { + Priority = 3, + Status = "in-progress", + CreatedAt = DateTime.UtcNow.AddDays(-1), + IsCompleted = false, + Title = "ExactlyTen Word" + }; + + // Act + var score = task.CalculateTaskScore(); + + // Assert + // Priority score: 1 + // Status score: 0 (word must be > 10, not >= 10) + Assert.Equal(1, score); + } + + [Fact] + public void CalculateTaskScore_InProgress_LongWordExactly11Chars() + { + // Arrange + var task = new TaskItem + { + Priority = 3, + Status = "in-progress", + CreatedAt = DateTime.UtcNow.AddDays(-1), + IsCompleted = false, + Title = "ElevenChars Word" + }; + + // Act + var score = task.CalculateTaskScore(); + + // Assert + // Priority score: 1 + // Status score: 1 (11 > 10) + Assert.Equal(2, score); + } + + [Fact] + public void CalculateTaskScore_Priority2_InProgress_ExactlySeven_Days() + { + // Arrange + var task = new TaskItem + { + Priority = 2, + Status = "in-progress", + CreatedAt = DateTime.UtcNow.AddDays(-7).AddSeconds(1), // Just under 7 days + IsCompleted = false, + Title = "Test Task" + }; + + // Act + var score = task.CalculateTaskScore(); + + // Assert + // Priority score: 5 + 2 = 7 (< 7 days, so no +3 bonus) + // Status score: 0 + Assert.Equal(7, score); + } + + [Fact] + public void CalculateTaskScore_Priority2_InProgress_OverSeven_Days() + { + // Arrange + var task = new TaskItem + { + Priority = 2, + Status = "in-progress", + CreatedAt = DateTime.UtcNow.AddDays(-8), + IsCompleted = false, + Title = "Test Task" + }; + + // Act + var score = task.CalculateTaskScore(); + + // Assert + // Priority score: 5 + 2 + 3 = 10 (> 7 days) + // Status score: 0 + Assert.Equal(10, score); + } + + [Fact] + public void TaskItem_DefaultValues_ShouldBeSetCorrectly() + { + // Arrange & Act + var task = new TaskItem + { + Title = "Test Task" + }; + + // Assert + Assert.Equal(3, task.Priority); + Assert.Equal("pending", task.Status); + Assert.False(task.IsCompleted); + Assert.Null(task.Description); + // CreatedAt should be close to now + Assert.True((DateTime.UtcNow - task.CreatedAt).TotalSeconds < 1); + } + + [Fact] + public void TaskItem_Properties_CanBeSetAndRetrieved() + { + // Arrange + var now = DateTime.UtcNow; + var task = new TaskItem + { + Id = 123, + Title = "Test Title", + Description = "Test Description", + IsCompleted = true, + Priority = 2, + Status = "completed", + CreatedAt = now + }; + + // Assert + Assert.Equal(123, task.Id); + Assert.Equal("Test Title", task.Title); + Assert.Equal("Test Description", task.Description); + Assert.True(task.IsCompleted); + Assert.Equal(2, task.Priority); + Assert.Equal("completed", task.Status); + Assert.Equal(now, task.CreatedAt); + } } } \ No newline at end of file diff --git a/DotnetApp.Tests/Services/CsvTaskServiceTests.cs b/DotnetApp.Tests/Services/CsvTaskServiceTests.cs new file mode 100644 index 0000000..335864b --- /dev/null +++ b/DotnetApp.Tests/Services/CsvTaskServiceTests.cs @@ -0,0 +1,261 @@ +using System; +using System.IO; +using System.Linq; +using DotnetApp.Models; +using DotnetApp.Services; +using Xunit; + +namespace DotnetApp.Tests.Services +{ + public class CsvTaskServiceTests : IDisposable + { + private readonly string _testFilePath; + private readonly CsvTaskService _service; + + public CsvTaskServiceTests() + { + // Create a unique test file path for each test instance + _testFilePath = Path.Combine(Path.GetTempPath(), $"test_tasks_{Guid.NewGuid()}.csv"); + + // Set AppContext.BaseDirectory to temp directory for testing + var field = typeof(AppContext).GetField("s_baseDirectory", + System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); + var originalPath = AppContext.BaseDirectory; + field?.SetValue(null, Path.GetTempPath()); + + _service = new CsvTaskService(); + } + + public void Dispose() + { + // Clean up test files + var tasksFile = Path.Combine(AppContext.BaseDirectory, "tasks.csv"); + if (File.Exists(tasksFile)) + { + File.Delete(tasksFile); + } + } + + [Fact] + public void CreateTask_AssignsIdAndStoresTaskInCsv() + { + var task = new TaskItem + { + Title = "Test Task", + Description = "Test Description", + Status = "pending", + Priority = 1 + }; + + _service.CreateTask(task); + + Assert.NotEqual(0, task.Id); + var all = _service.GetAllTasks().ToList(); + Assert.Contains(all, t => t.Id == task.Id && t.Title == "Test Task"); + } + + [Fact] + public void GetTaskById_ReturnsCorrectTaskOrNull() + { + var task = new TaskItem { Title = "GetById", Description = "Test" }; + _service.CreateTask(task); + var id = task.Id; + + var found = _service.GetTaskById(id); + Assert.NotNull(found); + Assert.Equal("GetById", found.Title); + + var missing = _service.GetTaskById(id + 999); + Assert.Null(missing); + } + + [Fact] + public void UpdateTask_NonExisting_ReturnsFalse() + { + var updated = new TaskItem { Title = "Nope" }; + + var result = _service.UpdateTask(999, updated); + Assert.False(result); + } + + [Fact] + public void UpdateTask_Existing_ReturnsTrueAndUpdates() + { + var task = new TaskItem + { + Title = "Original", + Description = "Original Description", + Status = "pending", + Priority = 2 + }; + _service.CreateTask(task); + var id = task.Id; + + var updated = new TaskItem + { + Title = "Updated", + Description = "Updated Description", + Status = "in-progress", + Priority = 1 + }; + var result = _service.UpdateTask(id, updated); + + Assert.True(result); + Assert.Equal(id, updated.Id); + var fetched = _service.GetTaskById(id); + Assert.NotNull(fetched); + Assert.Equal("Updated", fetched.Title); + Assert.Equal("Updated Description", fetched.Description); + Assert.Equal("in-progress", fetched.Status); + Assert.Equal(1, fetched.Priority); + } + + [Fact] + public void DeleteTask_ReturnsTrueAndRemoves() + { + var task = new TaskItem { Title = "ToDelete" }; + _service.CreateTask(task); + var id = task.Id; + + var result = _service.DeleteTask(id); + + Assert.True(result); + Assert.Null(_service.GetTaskById(id)); + } + + [Fact] + public void DeleteTask_NonExisting_ReturnsFalse() + { + var result = _service.DeleteTask(999); + Assert.False(result); + } + + [Fact] + public void GetAllTasks_Empty_ReturnsEmpty() + { + var all = _service.GetAllTasks().ToList(); + Assert.Empty(all); + } + + [Fact] + public void CreateTask_SequentialIds() + { + var t1 = new TaskItem { Title = "First" }; + _service.CreateTask(t1); + var t2 = new TaskItem { Title = "Second" }; + _service.CreateTask(t2); + + Assert.Equal(t1.Id + 1, t2.Id); + } + + [Fact] + public void CreateTask_WithNullDescription_StoresEmptyString() + { + var task = new TaskItem + { + Title = "No Description", + Description = null + }; + _service.CreateTask(task); + + var fetched = _service.GetTaskById(task.Id); + Assert.NotNull(fetched); + Assert.Null(fetched.Description); + } + + [Fact] + public void CreateTask_WithSpecialCharacters_StoresCorrectly() + { + var task = new TaskItem + { + Title = "Task with special chars", + Description = "Description without commas" + }; + _service.CreateTask(task); + + var fetched = _service.GetTaskById(task.Id); + Assert.NotNull(fetched); + Assert.Equal("Task with special chars", fetched.Title); + Assert.Equal("Description without commas", fetched.Description); + } + + [Fact] + public void GetAllTasks_ReturnsAllTasks() + { + var task1 = new TaskItem { Title = "Task 1" }; + var task2 = new TaskItem { Title = "Task 2" }; + var task3 = new TaskItem { Title = "Task 3" }; + + _service.CreateTask(task1); + _service.CreateTask(task2); + _service.CreateTask(task3); + + var all = _service.GetAllTasks().ToList(); + Assert.Equal(3, all.Count); + Assert.Contains(all, t => t.Title == "Task 1"); + Assert.Contains(all, t => t.Title == "Task 2"); + Assert.Contains(all, t => t.Title == "Task 3"); + } + + [Fact] + public void CreateTask_PreservesAllProperties() + { + var now = DateTime.UtcNow; + var task = new TaskItem + { + Title = "Complete Task", + Description = "Full Description", + IsCompleted = true, + Status = "completed", + Priority = 1, + CreatedAt = now + }; + _service.CreateTask(task); + + var fetched = _service.GetTaskById(task.Id); + Assert.NotNull(fetched); + Assert.Equal("Complete Task", fetched.Title); + Assert.Equal("Full Description", fetched.Description); + Assert.True(fetched.IsCompleted); + Assert.Equal("completed", fetched.Status); + Assert.Equal(1, fetched.Priority); + Assert.Equal(now.ToString("O"), fetched.CreatedAt.ToString("O")); + } + + [Fact] + public void UpdateTask_PreservesId() + { + var task = new TaskItem { Title = "Original" }; + _service.CreateTask(task); + var originalId = task.Id; + + var updated = new TaskItem { Title = "Updated", Id = 999 }; + _service.UpdateTask(originalId, updated); + + var fetched = _service.GetTaskById(originalId); + Assert.NotNull(fetched); + Assert.Equal(originalId, fetched.Id); + Assert.Equal("Updated", fetched.Title); + } + + [Fact] + public void DeleteTask_DoesNotAffectOtherTasks() + { + var task1 = new TaskItem { Title = "Task 1" }; + var task2 = new TaskItem { Title = "Task 2" }; + var task3 = new TaskItem { Title = "Task 3" }; + + _service.CreateTask(task1); + _service.CreateTask(task2); + _service.CreateTask(task3); + + _service.DeleteTask(task2.Id); + + var all = _service.GetAllTasks().ToList(); + Assert.Equal(2, all.Count); + Assert.Contains(all, t => t.Title == "Task 1"); + Assert.DoesNotContain(all, t => t.Title == "Task 2"); + Assert.Contains(all, t => t.Title == "Task 3"); + } + } +} diff --git a/DotnetApp.Tests/Services/InMemoryTaskServiceTests.cs b/DotnetApp.Tests/Services/InMemoryTaskServiceTests.cs index b4ff870..351b760 100644 --- a/DotnetApp.Tests/Services/InMemoryTaskServiceTests.cs +++ b/DotnetApp.Tests/Services/InMemoryTaskServiceTests.cs @@ -98,5 +98,112 @@ public void CreateTask_SequentialIds() Assert.Equal(t1.Id + 1, t2.Id); } + + [Fact] + public void GetAllTasks_ReturnsMultipleTasks() + { + var service = new InMemoryTaskService(); + var task1 = new TaskItem { Title = "Task 1" }; + var task2 = new TaskItem { Title = "Task 2" }; + var task3 = new TaskItem { Title = "Task 3" }; + + service.CreateTask(task1); + service.CreateTask(task2); + service.CreateTask(task3); + + var all = service.GetAllTasks().ToList(); + Assert.Equal(3, all.Count); + Assert.Contains(all, t => t.Title == "Task 1"); + Assert.Contains(all, t => t.Title == "Task 2"); + Assert.Contains(all, t => t.Title == "Task 3"); + } + + [Fact] + public void UpdateTask_PreservesId() + { + var service = new InMemoryTaskService(); + var task = new TaskItem { Title = "Original" }; + service.CreateTask(task); + var originalId = task.Id; + + var updated = new TaskItem { Title = "Updated", Id = 999 }; + service.UpdateTask(originalId, updated); + + var fetched = service.GetTaskById(originalId); + Assert.NotNull(fetched); + Assert.Equal(originalId, fetched.Id); + Assert.Equal("Updated", fetched.Title); + } + + [Fact] + public void UpdateTask_UpdatesAllProperties() + { + var service = new InMemoryTaskService(); + var task = new TaskItem + { + Title = "Original", + Description = "Original Description", + Status = "pending", + Priority = 3, + IsCompleted = false + }; + service.CreateTask(task); + var id = task.Id; + + var updated = new TaskItem + { + Title = "Updated Title", + Description = "Updated Description", + Status = "completed", + Priority = 1, + IsCompleted = true + }; + service.UpdateTask(id, updated); + + var fetched = service.GetTaskById(id); + Assert.NotNull(fetched); + Assert.Equal("Updated Title", fetched.Title); + Assert.Equal("Updated Description", fetched.Description); + Assert.Equal("completed", fetched.Status); + Assert.Equal(1, fetched.Priority); + Assert.True(fetched.IsCompleted); + } + + [Fact] + public void DeleteTask_DoesNotAffectOtherTasks() + { + var service = new InMemoryTaskService(); + var task1 = new TaskItem { Title = "Task 1" }; + var task2 = new TaskItem { Title = "Task 2" }; + var task3 = new TaskItem { Title = "Task 3" }; + + service.CreateTask(task1); + service.CreateTask(task2); + service.CreateTask(task3); + + service.DeleteTask(task2.Id); + + var all = service.GetAllTasks().ToList(); + Assert.Equal(2, all.Count); + Assert.Contains(all, t => t.Title == "Task 1"); + Assert.DoesNotContain(all, t => t.Title == "Task 2"); + Assert.Contains(all, t => t.Title == "Task 3"); + } + + [Fact] + public void CreateTask_WithNullDescription_Works() + { + var service = new InMemoryTaskService(); + var task = new TaskItem + { + Title = "No Description", + Description = null + }; + service.CreateTask(task); + + var fetched = service.GetTaskById(task.Id); + Assert.NotNull(fetched); + Assert.Null(fetched.Description); + } } } diff --git a/python/point.py b/python/point.py index e69de29..c05c84b 100644 --- a/python/point.py +++ b/python/point.py @@ -0,0 +1,21 @@ +# class point that represents a point in 3D space, should have x, y, and z coordinates +class Point3D: + def __init__(self, x, y, z): + self.x = x + self.y = y + self.z = z + + # to string function + def __str__(self): + return f"Point({self.x}, {self.y}, {self.z})" + + # distance function that calculates the distance between two points + def distance(self, other): + return ((self.x - other.x)**2 + (self.y - other.y)**2 + (self.z - other.z)**2)**0.5 + + # calculate the average distance between a point and a list of points + def average_distance(self, points): + total_distance = 0 + for point in points: + total_distance += self.distance(point) + return total_distance / len(points) if points else 0 \ No newline at end of file