Features: - Add task action buttons to push notifications (complete, view, cancel, etc.) - Add button types logic for different task states (overdue, in_progress, etc.) - Implement Chain of Responsibility pattern for task categorization - Add comprehensive kanban categorization documentation Fixes: - Reset recurring task status to Pending after completion so tasks appear in correct kanban column (was staying in "In Progress") - Fix PostgreSQL EXTRACT function error in overdue notifications query - Update seed data to properly set next_due_date for recurring tasks Admin: - Add tasks list to residence detail page - Fix task edit page to properly handle all fields 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
527 lines
18 KiB
Go
527 lines
18 KiB
Go
package services
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/shopspring/decimal"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/treytartt/casera-api/internal/dto/requests"
|
|
"github.com/treytartt/casera-api/internal/models"
|
|
"github.com/treytartt/casera-api/internal/repositories"
|
|
"github.com/treytartt/casera-api/internal/testutil"
|
|
)
|
|
|
|
func setupTaskService(t *testing.T) (*TaskService, *repositories.TaskRepository, *repositories.ResidenceRepository) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
return service, taskRepo, residenceRepo
|
|
}
|
|
|
|
func TestTaskService_CreateTask(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
|
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
|
|
|
req := &requests.CreateTaskRequest{
|
|
ResidenceID: residence.ID,
|
|
Title: "Fix leaky faucet",
|
|
Description: "Kitchen faucet is dripping",
|
|
}
|
|
|
|
resp, err := service.CreateTask(req, user.ID)
|
|
require.NoError(t, err)
|
|
assert.NotZero(t, resp.ID)
|
|
assert.Equal(t, "Fix leaky faucet", resp.Title)
|
|
assert.Equal(t, "Kitchen faucet is dripping", resp.Description)
|
|
}
|
|
|
|
func TestTaskService_CreateTask_WithOptionalFields(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
|
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
|
|
|
// Get category and priority IDs
|
|
var category models.TaskCategory
|
|
var priority models.TaskPriority
|
|
db.First(&category)
|
|
db.First(&priority)
|
|
|
|
dueDate := requests.FlexibleDate{Time: time.Now().Add(7 * 24 * time.Hour).UTC()}
|
|
cost := decimal.NewFromFloat(150.50)
|
|
|
|
req := &requests.CreateTaskRequest{
|
|
ResidenceID: residence.ID,
|
|
Title: "Fix leaky faucet",
|
|
CategoryID: &category.ID,
|
|
PriorityID: &priority.ID,
|
|
DueDate: &dueDate,
|
|
EstimatedCost: &cost,
|
|
}
|
|
|
|
resp, err := service.CreateTask(req, user.ID)
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, resp.Category)
|
|
assert.NotNil(t, resp.Priority)
|
|
assert.NotNil(t, resp.DueDate)
|
|
assert.NotNil(t, resp.EstimatedCost)
|
|
}
|
|
|
|
func TestTaskService_CreateTask_AccessDenied(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
|
otherUser := testutil.CreateTestUser(t, db, "other", "other@test.com", "password")
|
|
residence := testutil.CreateTestResidence(t, db, owner.ID, "Test House")
|
|
|
|
req := &requests.CreateTaskRequest{
|
|
ResidenceID: residence.ID,
|
|
Title: "Test Task",
|
|
}
|
|
|
|
_, err := service.CreateTask(req, otherUser.ID)
|
|
// When creating a task, residence access is checked first
|
|
assert.ErrorIs(t, err, ErrResidenceAccessDenied)
|
|
}
|
|
|
|
func TestTaskService_GetTask(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
|
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
|
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Test Task")
|
|
|
|
resp, err := service.GetTask(task.ID, user.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, task.ID, resp.ID)
|
|
assert.Equal(t, "Test Task", resp.Title)
|
|
}
|
|
|
|
func TestTaskService_GetTask_AccessDenied(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
|
otherUser := testutil.CreateTestUser(t, db, "other", "other@test.com", "password")
|
|
residence := testutil.CreateTestResidence(t, db, owner.ID, "Test House")
|
|
task := testutil.CreateTestTask(t, db, residence.ID, owner.ID, "Test Task")
|
|
|
|
_, err := service.GetTask(task.ID, otherUser.ID)
|
|
assert.ErrorIs(t, err, ErrTaskAccessDenied)
|
|
}
|
|
|
|
func TestTaskService_ListTasks(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
|
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
|
testutil.CreateTestTask(t, db, residence.ID, user.ID, "Task 1")
|
|
testutil.CreateTestTask(t, db, residence.ID, user.ID, "Task 2")
|
|
testutil.CreateTestTask(t, db, residence.ID, user.ID, "Task 3")
|
|
|
|
resp, err := service.ListTasks(user.ID)
|
|
require.NoError(t, err)
|
|
// ListTasks returns a KanbanBoardResponse with columns
|
|
// Count total tasks across all columns
|
|
totalTasks := 0
|
|
for _, col := range resp.Columns {
|
|
totalTasks += col.Count
|
|
}
|
|
assert.Equal(t, 3, totalTasks)
|
|
}
|
|
|
|
func TestTaskService_UpdateTask(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
|
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
|
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Original Title")
|
|
|
|
newTitle := "Updated Title"
|
|
newDesc := "Updated description"
|
|
req := &requests.UpdateTaskRequest{
|
|
Title: &newTitle,
|
|
Description: &newDesc,
|
|
}
|
|
|
|
resp, err := service.UpdateTask(task.ID, user.ID, req)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "Updated Title", resp.Title)
|
|
assert.Equal(t, "Updated description", resp.Description)
|
|
}
|
|
|
|
func TestTaskService_DeleteTask(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
|
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
|
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Test Task")
|
|
|
|
err := service.DeleteTask(task.ID, user.ID)
|
|
require.NoError(t, err)
|
|
|
|
_, err = service.GetTask(task.ID, user.ID)
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
func TestTaskService_CancelTask(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
|
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
|
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Test Task")
|
|
|
|
resp, err := service.CancelTask(task.ID, user.ID)
|
|
require.NoError(t, err)
|
|
assert.True(t, resp.IsCancelled)
|
|
}
|
|
|
|
func TestTaskService_CancelTask_AlreadyCancelled(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
|
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
|
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Test Task")
|
|
|
|
service.CancelTask(task.ID, user.ID)
|
|
_, err := service.CancelTask(task.ID, user.ID)
|
|
assert.ErrorIs(t, err, ErrTaskAlreadyCancelled)
|
|
}
|
|
|
|
func TestTaskService_UncancelTask(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
|
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
|
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Test Task")
|
|
|
|
service.CancelTask(task.ID, user.ID)
|
|
resp, err := service.UncancelTask(task.ID, user.ID)
|
|
require.NoError(t, err)
|
|
assert.False(t, resp.IsCancelled)
|
|
}
|
|
|
|
func TestTaskService_ArchiveTask(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
|
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
|
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Test Task")
|
|
|
|
resp, err := service.ArchiveTask(task.ID, user.ID)
|
|
require.NoError(t, err)
|
|
assert.True(t, resp.IsArchived)
|
|
}
|
|
|
|
func TestTaskService_UnarchiveTask(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
|
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
|
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Test Task")
|
|
|
|
service.ArchiveTask(task.ID, user.ID)
|
|
resp, err := service.UnarchiveTask(task.ID, user.ID)
|
|
require.NoError(t, err)
|
|
assert.False(t, resp.IsArchived)
|
|
}
|
|
|
|
func TestTaskService_MarkInProgress(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
|
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
|
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Test Task")
|
|
|
|
resp, err := service.MarkInProgress(task.ID, user.ID)
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, resp.Status)
|
|
assert.Equal(t, "In Progress", resp.Status.Name)
|
|
}
|
|
|
|
func TestTaskService_CreateCompletion(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
|
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
|
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Test Task")
|
|
|
|
req := &requests.CreateTaskCompletionRequest{
|
|
TaskID: task.ID,
|
|
Notes: "Completed successfully",
|
|
}
|
|
|
|
resp, err := service.CreateCompletion(req, user.ID)
|
|
require.NoError(t, err)
|
|
assert.NotZero(t, resp.ID)
|
|
assert.Equal(t, task.ID, resp.TaskID)
|
|
assert.Equal(t, "Completed successfully", resp.Notes)
|
|
}
|
|
|
|
func TestTaskService_CreateCompletion_RecurringTask_ResetsStatusToPending(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
|
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
|
|
|
// Get the "In Progress" status (ID=2) and a recurring frequency
|
|
var inProgressStatus models.TaskStatus
|
|
db.Where("name = ?", "In Progress").First(&inProgressStatus)
|
|
|
|
var monthlyFrequency models.TaskFrequency
|
|
db.Where("name = ?", "Monthly").First(&monthlyFrequency)
|
|
|
|
// Create a recurring task with "In Progress" status
|
|
dueDate := time.Now().AddDate(0, 0, 7) // Due in 7 days
|
|
task := &models.Task{
|
|
ResidenceID: residence.ID,
|
|
CreatedByID: user.ID,
|
|
Title: "Recurring Task",
|
|
StatusID: &inProgressStatus.ID,
|
|
FrequencyID: &monthlyFrequency.ID,
|
|
DueDate: &dueDate,
|
|
NextDueDate: &dueDate,
|
|
IsCancelled: false,
|
|
IsArchived: false,
|
|
}
|
|
err := db.Create(task).Error
|
|
require.NoError(t, err)
|
|
|
|
// Complete the task
|
|
req := &requests.CreateTaskCompletionRequest{
|
|
TaskID: task.ID,
|
|
Notes: "Monthly maintenance done",
|
|
}
|
|
|
|
resp, err := service.CreateCompletion(req, user.ID)
|
|
require.NoError(t, err)
|
|
assert.NotZero(t, resp.ID)
|
|
|
|
// Verify the task in the response has status reset to "Pending" (ID=1)
|
|
require.NotNil(t, resp.Task, "Response should include the updated task")
|
|
require.NotNil(t, resp.Task.StatusID, "Task should have a status ID")
|
|
assert.Equal(t, uint(1), *resp.Task.StatusID, "Recurring task status should be reset to Pending (ID=1) after completion")
|
|
|
|
// Verify NextDueDate was updated (should be ~30 days from now for monthly)
|
|
require.NotNil(t, resp.Task.NextDueDate, "Recurring task should have NextDueDate set")
|
|
expectedNextDue := time.Now().AddDate(0, 0, 30) // Monthly = 30 days
|
|
assert.WithinDuration(t, expectedNextDue, *resp.Task.NextDueDate, 24*time.Hour, "NextDueDate should be approximately 30 days from now")
|
|
|
|
// Also verify by reloading from database directly
|
|
var reloadedTask models.Task
|
|
db.Preload("Status").First(&reloadedTask, task.ID)
|
|
require.NotNil(t, reloadedTask.StatusID)
|
|
assert.Equal(t, uint(1), *reloadedTask.StatusID, "Database should show Pending status")
|
|
assert.Equal(t, "Pending", reloadedTask.Status.Name)
|
|
}
|
|
|
|
func TestTaskService_GetCompletion(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
|
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
|
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Test Task")
|
|
|
|
completion := &models.TaskCompletion{
|
|
TaskID: task.ID,
|
|
CompletedByID: user.ID,
|
|
CompletedAt: time.Now().UTC(),
|
|
Notes: "Test notes",
|
|
}
|
|
db.Create(completion)
|
|
|
|
resp, err := service.GetCompletion(completion.ID, user.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, completion.ID, resp.ID)
|
|
assert.Equal(t, "Test notes", resp.Notes)
|
|
}
|
|
|
|
func TestTaskService_DeleteCompletion(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
|
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
|
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Test Task")
|
|
|
|
completion := &models.TaskCompletion{
|
|
TaskID: task.ID,
|
|
CompletedByID: user.ID,
|
|
CompletedAt: time.Now().UTC(),
|
|
}
|
|
db.Create(completion)
|
|
|
|
err := service.DeleteCompletion(completion.ID, user.ID)
|
|
require.NoError(t, err)
|
|
|
|
_, err = service.GetCompletion(completion.ID, user.ID)
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
func TestTaskService_GetCategories(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
categories, err := service.GetCategories()
|
|
require.NoError(t, err)
|
|
assert.Greater(t, len(categories), 0)
|
|
|
|
// Check JSON structure
|
|
for _, cat := range categories {
|
|
assert.NotZero(t, cat.ID)
|
|
assert.NotEmpty(t, cat.Name)
|
|
}
|
|
}
|
|
|
|
func TestTaskService_GetPriorities(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
priorities, err := service.GetPriorities()
|
|
require.NoError(t, err)
|
|
assert.Greater(t, len(priorities), 0)
|
|
|
|
// Check order by level
|
|
for i := 1; i < len(priorities); i++ {
|
|
assert.GreaterOrEqual(t, priorities[i].Level, priorities[i-1].Level)
|
|
}
|
|
}
|
|
|
|
func TestTaskService_GetStatuses(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
statuses, err := service.GetStatuses()
|
|
require.NoError(t, err)
|
|
assert.Greater(t, len(statuses), 0)
|
|
}
|
|
|
|
func TestTaskService_GetFrequencies(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
frequencies, err := service.GetFrequencies()
|
|
require.NoError(t, err)
|
|
assert.Greater(t, len(frequencies), 0)
|
|
}
|
|
|
|
func TestTaskService_SharedUserAccess(t *testing.T) {
|
|
db := testutil.SetupTestDB(t)
|
|
testutil.SeedLookupData(t, db)
|
|
taskRepo := repositories.NewTaskRepository(db)
|
|
residenceRepo := repositories.NewResidenceRepository(db)
|
|
service := NewTaskService(taskRepo, residenceRepo)
|
|
|
|
owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
|
sharedUser := testutil.CreateTestUser(t, db, "shared", "shared@test.com", "password")
|
|
residence := testutil.CreateTestResidence(t, db, owner.ID, "Test House")
|
|
|
|
// Share residence
|
|
residenceRepo.AddUser(residence.ID, sharedUser.ID)
|
|
|
|
// Create task as owner
|
|
task := testutil.CreateTestTask(t, db, residence.ID, owner.ID, "Test Task")
|
|
|
|
// Shared user should be able to see the task
|
|
resp, err := service.GetTask(task.ID, sharedUser.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, task.ID, resp.ID)
|
|
|
|
// Shared user should be able to create tasks
|
|
req := &requests.CreateTaskRequest{
|
|
ResidenceID: residence.ID,
|
|
Title: "Shared User Task",
|
|
}
|
|
_, err = service.CreateTask(req, sharedUser.ID)
|
|
require.NoError(t, err)
|
|
}
|