diff --git a/.azuredevops/android-build.yml b/.azuredevops/android-build.yml new file mode 100644 index 00000000..5b60dd22 --- /dev/null +++ b/.azuredevops/android-build.yml @@ -0,0 +1,42 @@ +name: $(Date:yyMMdd).00.$(Rev:r) + +trigger: + branches: + include: + - main + paths: + include: + - android/** + +pr: + branches: + include: + - main + paths: + include: + - android/** + +resources: + repositories: + - repository: templates + type: github + name: dkhalife/Pipeline.Templates + endpoint: github + ref: refs/tags/latest + +extends: + template: pipeline.yml@templates + parameters: + stages: + - stage: build + templateContext: + intent: build + jobs: + - job: app + templateContext: + android: + - name: android + jdkVersion: '21' + workingDirectory: android + gradleTasks: assembleDebug + sign: false diff --git a/.azuredevops/api-build.yml b/.azuredevops/api-build.yml new file mode 100644 index 00000000..81896535 --- /dev/null +++ b/.azuredevops/api-build.yml @@ -0,0 +1,48 @@ +name: $(Date:yyMMdd).00.$(Rev:r) + +trigger: + branches: + include: + - main + paths: + include: + - apiserver/** + +pr: + branches: + include: + - main + paths: + include: + - apiserver/** + +resources: + repositories: + - repository: templates + type: github + name: dkhalife/Pipeline.Templates + endpoint: github + ref: refs/tags/latest + +extends: + template: pipeline.yml@templates + parameters: + stages: + - stage: build + templateContext: + intent: build + jobs: + - job: app + templateContext: + go: + - name: api + goVersion: '1.25' + workingDirectory: apiserver + buildArgs: >- + -v + -ldflags "-X dkhalife.com/tasks/core/internal/version.Version=$(Build.BuildNumber) + -X dkhalife.com/tasks/core/internal/version.BuildNumber=0 + -X dkhalife.com/tasks/core/internal/version.CommitHash=$(Build.SourceVersion)" + ./... + testArgs: '-v -coverprofile=coverage.txt ./...' + vet: false diff --git a/.azuredevops/frontend-build.yml b/.azuredevops/frontend-build.yml new file mode 100644 index 00000000..17f1d3ff --- /dev/null +++ b/.azuredevops/frontend-build.yml @@ -0,0 +1,43 @@ +name: $(Date:yyMMdd).00.$(Rev:r) + +trigger: + branches: + include: + - main + paths: + include: + - frontend/** + +pr: + branches: + include: + - main + paths: + include: + - frontend/** + +resources: + repositories: + - repository: templates + type: github + name: dkhalife/Pipeline.Templates + endpoint: github + ref: refs/tags/latest + +extends: + template: pipeline.yml@templates + parameters: + stages: + - stage: build + templateContext: + intent: build + jobs: + - job: app + container: mcr.microsoft.com/playwright:v1.55.1-noble + templateContext: + node: + - name: frontend + nodeVersion: 24.x + workingDirectory: frontend + e2e: true + e2eReportPath: frontend/playwright-report diff --git a/.azuredevops/mcp-build.yml b/.azuredevops/mcp-build.yml new file mode 100644 index 00000000..9ddc2fa9 --- /dev/null +++ b/.azuredevops/mcp-build.yml @@ -0,0 +1,42 @@ +name: $(Date:yyMMdd).00.$(Rev:r) + +trigger: + branches: + include: + - main + paths: + include: + - mcpserver/** + +pr: + branches: + include: + - main + paths: + include: + - mcpserver/** + +resources: + repositories: + - repository: templates + type: github + name: dkhalife/Pipeline.Templates + endpoint: github + ref: refs/tags/latest + +extends: + template: pipeline.yml@templates + parameters: + stages: + - stage: build + templateContext: + intent: build + jobs: + - job: app + templateContext: + dotnet: + - name: mcp + sdkVersion: '9.x' + projects: mcpserver/**/*.csproj + configuration: Release + test: false diff --git a/android/gradlew b/android/gradlew old mode 100644 new mode 100755 diff --git a/apiserver/config/config_test.go b/apiserver/config/config_test.go index 76937731..12f6c38e 100644 --- a/apiserver/config/config_test.go +++ b/apiserver/config/config_test.go @@ -15,8 +15,8 @@ func TestLoadConfig_Success(t *testing.T) { f, err := os.Create("./config/config.yaml") assert.NoError(t, err, "failed to create config.yaml") - defer os.Remove("./config/config.yaml") - defer f.Close() + defer func() { _ = os.Remove("./config/config.yaml") }() + defer func() { _ = f.Close() }() _, err = f.WriteString(`server: port: 1234 log_level: debug @@ -112,8 +112,8 @@ func TestLoadConfig_EntraEnvOverride(t *testing.T) { _ = os.MkdirAll("./config", 0755) f, err := os.Create("./config/config.yaml") assert.NoError(t, err) - defer os.Remove("./config/config.yaml") - defer f.Close() + defer func() { _ = os.Remove("./config/config.yaml") }() + defer func() { _ = f.Close() }() _, err = f.WriteString(`entra: enabled: false @@ -125,10 +125,10 @@ server: `) assert.NoError(t, err) - os.Setenv("TW_ENTRA_ENABLED", "true") - os.Setenv("TW_ENTRA_TENANT_ID", "env-tenant") - os.Setenv("TW_ENTRA_CLIENT_ID", "env-client") - os.Setenv("TW_ENTRA_AUDIENCE", "api://env-client") + _ = os.Setenv("TW_ENTRA_ENABLED", "true") + _ = os.Setenv("TW_ENTRA_TENANT_ID", "env-tenant") + _ = os.Setenv("TW_ENTRA_CLIENT_ID", "env-client") + _ = os.Setenv("TW_ENTRA_AUDIENCE", "api://env-client") viper.Reset() cfg := LoadConfig("./config/config.yaml") @@ -138,56 +138,56 @@ server: assert.Equal(t, "env-client", cfg.Entra.ClientID) assert.Equal(t, "api://env-client", cfg.Entra.Audience) - os.Unsetenv("TW_ENTRA_ENABLED") - os.Unsetenv("TW_ENTRA_TENANT_ID") - os.Unsetenv("TW_ENTRA_CLIENT_ID") - os.Unsetenv("TW_ENTRA_AUDIENCE") + _ = os.Unsetenv("TW_ENTRA_ENABLED") + _ = os.Unsetenv("TW_ENTRA_TENANT_ID") + _ = os.Unsetenv("TW_ENTRA_CLIENT_ID") + _ = os.Unsetenv("TW_ENTRA_AUDIENCE") } func TestLoadConfig_EnvFile(t *testing.T) { f, err := os.Create("envconfig.yaml") assert.NoError(t, err) - defer os.Remove("envconfig.yaml") - defer f.Close() + defer func() { _ = os.Remove("envconfig.yaml") }() + defer func() { _ = f.Close() }() _, err = f.WriteString("server:\n port: 4444\n") assert.NoError(t, err) - os.Setenv("TW_CONFIG_FILE", "envconfig.yaml") + _ = os.Setenv("TW_CONFIG_FILE", "envconfig.yaml") viper.Reset() cfg := LoadConfig("") assert.Equal(t, 4444, cfg.Server.Port) - os.Unsetenv("TW_CONFIG_FILE") + _ = os.Unsetenv("TW_CONFIG_FILE") } func TestLoadConfig_CLIOverridesEnv(t *testing.T) { f1, err := os.Create("env.yaml") assert.NoError(t, err) - defer os.Remove("env.yaml") - defer f1.Close() + defer func() { _ = os.Remove("env.yaml") }() + defer func() { _ = f1.Close() }() _, err = f1.WriteString("server:\n port: 3333\n") assert.NoError(t, err) f2, err := os.Create("cli.yaml") assert.NoError(t, err) - defer os.Remove("cli.yaml") - defer f2.Close() + defer func() { _ = os.Remove("cli.yaml") }() + defer func() { _ = f2.Close() }() _, err = f2.WriteString("server:\n port: 2222\n") assert.NoError(t, err) - os.Setenv("TW_CONFIG_FILE", "env.yaml") + _ = os.Setenv("TW_CONFIG_FILE", "env.yaml") viper.Reset() cfg := LoadConfig("cli.yaml") assert.Equal(t, 2222, cfg.Server.Port) - os.Unsetenv("TW_CONFIG_FILE") + _ = os.Unsetenv("TW_CONFIG_FILE") } func TestLoadConfig_DatabaseEnvOverride(t *testing.T) { _ = os.MkdirAll("./config", 0755) f, err := os.Create("./config/config.yaml") assert.NoError(t, err) - defer os.Remove("./config/config.yaml") - defer f.Close() + defer func() { _ = os.Remove("./config/config.yaml") }() + defer func() { _ = f.Close() }() _, err = f.WriteString(`database: type: sqlite @@ -197,12 +197,12 @@ server: `) assert.NoError(t, err) - os.Setenv("TW_DATABASE_TYPE", "mysql") - os.Setenv("TW_DATABASE_HOST", "localhost") - os.Setenv("TW_DATABASE_PORT", "3307") - os.Setenv("TW_DATABASE_NAME", "taskwizard") - os.Setenv("TW_DATABASE_USERNAME", "dbuser") - os.Setenv("TW_DATABASE_PASSWORD", "dbpass") + _ = os.Setenv("TW_DATABASE_TYPE", "mysql") + _ = os.Setenv("TW_DATABASE_HOST", "localhost") + _ = os.Setenv("TW_DATABASE_PORT", "3307") + _ = os.Setenv("TW_DATABASE_NAME", "taskwizard") + _ = os.Setenv("TW_DATABASE_USERNAME", "dbuser") + _ = os.Setenv("TW_DATABASE_PASSWORD", "dbpass") viper.Reset() cfg := LoadConfig("./config/config.yaml") @@ -214,20 +214,20 @@ server: assert.Equal(t, "dbuser", cfg.Database.Username) assert.Equal(t, "dbpass", cfg.Database.Password) - os.Unsetenv("TW_DATABASE_TYPE") - os.Unsetenv("TW_DATABASE_HOST") - os.Unsetenv("TW_DATABASE_PORT") - os.Unsetenv("TW_DATABASE_NAME") - os.Unsetenv("TW_DATABASE_USERNAME") - os.Unsetenv("TW_DATABASE_PASSWORD") + _ = os.Unsetenv("TW_DATABASE_TYPE") + _ = os.Unsetenv("TW_DATABASE_HOST") + _ = os.Unsetenv("TW_DATABASE_PORT") + _ = os.Unsetenv("TW_DATABASE_NAME") + _ = os.Unsetenv("TW_DATABASE_USERNAME") + _ = os.Unsetenv("TW_DATABASE_PASSWORD") } func TestLoadConfig_MySQLConfig(t *testing.T) { _ = os.MkdirAll("./config", 0755) f, err := os.Create("./config/config.yaml") assert.NoError(t, err) - defer os.Remove("./config/config.yaml") - defer f.Close() + defer func() { _ = os.Remove("./config/config.yaml") }() + defer func() { _ = f.Close() }() _, err = f.WriteString(`database: type: mysql diff --git a/apiserver/internal/migrations/001_initial_schema.go b/apiserver/internal/migrations/001_initial_schema.go index 355ffda4..625faf64 100644 --- a/apiserver/internal/migrations/001_initial_schema.go +++ b/apiserver/internal/migrations/001_initial_schema.go @@ -22,7 +22,7 @@ func (m *InitialSchemaMigration) Name() string { } func (m *InitialSchemaMigration) Up(ctx context.Context, db *gorm.DB) error { - dialect := db.Dialector.Name() + dialect := db.Name() var ( autoInc string diff --git a/apiserver/internal/migrations/002_entra_auth.go b/apiserver/internal/migrations/002_entra_auth.go index 99309529..fbafa400 100644 --- a/apiserver/internal/migrations/002_entra_auth.go +++ b/apiserver/internal/migrations/002_entra_auth.go @@ -24,7 +24,7 @@ func (m *EntraAuthMigration) Name() string { func (m *EntraAuthMigration) Up(ctx context.Context, db *gorm.DB) error { dbCtx := db.WithContext(ctx) migrator := dbCtx.Migrator() - dialect := db.Dialector.Name() + dialect := db.Name() var colType string switch dialect { @@ -88,7 +88,7 @@ func (m *EntraAuthMigration) Up(ctx context.Context, db *gorm.DB) error { func (m *EntraAuthMigration) Down(ctx context.Context, db *gorm.DB) error { dbCtx := db.WithContext(ctx) migrator := dbCtx.Migrator() - dialect := db.Dialector.Name() + dialect := db.Name() if migrator.HasIndex("users", "idx_users_entra_id") { if err := migrator.DropIndex("users", "idx_users_entra_id"); err != nil { diff --git a/apiserver/internal/migrations/003_drop_password.go b/apiserver/internal/migrations/003_drop_password.go index 4f8d3749..6c9484b3 100644 --- a/apiserver/internal/migrations/003_drop_password.go +++ b/apiserver/internal/migrations/003_drop_password.go @@ -37,7 +37,7 @@ func (m *DropPasswordMigration) Up(ctx context.Context, db *gorm.DB) error { func (m *DropPasswordMigration) Down(ctx context.Context, db *gorm.DB) error { dbCtx := db.WithContext(ctx) migrator := dbCtx.Migrator() - dialect := db.Dialector.Name() + dialect := db.Name() if !migrator.HasColumn("users", "password") { var colType string diff --git a/apiserver/internal/migrations/004_drop_app_tokens.go b/apiserver/internal/migrations/004_drop_app_tokens.go index f2e92679..0301c78e 100644 --- a/apiserver/internal/migrations/004_drop_app_tokens.go +++ b/apiserver/internal/migrations/004_drop_app_tokens.go @@ -37,7 +37,7 @@ func (m *DropAppTokensMigration) Up(ctx context.Context, db *gorm.DB) error { func (m *DropAppTokensMigration) Down(ctx context.Context, db *gorm.DB) error { dbCtx := db.WithContext(ctx) migrator := dbCtx.Migrator() - dialect := db.Dialector.Name() + dialect := db.Name() if !migrator.HasTable("app_tokens") { switch dialect { diff --git a/apiserver/internal/migrations/005_drop_email.go b/apiserver/internal/migrations/005_drop_email.go index 6c52b5bf..5221d047 100644 --- a/apiserver/internal/migrations/005_drop_email.go +++ b/apiserver/internal/migrations/005_drop_email.go @@ -23,7 +23,7 @@ func (m *DropPIIMigration) Name() string { func (m *DropPIIMigration) Up(ctx context.Context, db *gorm.DB) error { dbCtx := db.WithContext(ctx) - dialect := db.Dialector.Name() + dialect := db.Name() switch dialect { case "sqlite": @@ -61,7 +61,7 @@ func (m *DropPIIMigration) Up(ctx context.Context, db *gorm.DB) error { func (m *DropPIIMigration) Down(ctx context.Context, db *gorm.DB) error { dbCtx := db.WithContext(ctx) - dialect := db.Dialector.Name() + dialect := db.Name() switch dialect { case "sqlite": diff --git a/apiserver/internal/migrations/006_account_deletion.go b/apiserver/internal/migrations/006_account_deletion.go index 1ec87a31..6201c24f 100644 --- a/apiserver/internal/migrations/006_account_deletion.go +++ b/apiserver/internal/migrations/006_account_deletion.go @@ -23,7 +23,7 @@ func (m *AccountDeletionMigration) Name() string { func (m *AccountDeletionMigration) Up(ctx context.Context, db *gorm.DB) error { dbCtx := db.WithContext(ctx) - dialect := db.Dialector.Name() + dialect := db.Name() switch dialect { case "sqlite": @@ -37,7 +37,7 @@ func (m *AccountDeletionMigration) Up(ctx context.Context, db *gorm.DB) error { func (m *AccountDeletionMigration) Down(ctx context.Context, db *gorm.DB) error { dbCtx := db.WithContext(ctx) - dialect := db.Dialector.Name() + dialect := db.Name() switch dialect { case "sqlite": diff --git a/apiserver/internal/migrations/007_sessions.go b/apiserver/internal/migrations/007_sessions.go index dfd4331d..c6b565ac 100644 --- a/apiserver/internal/migrations/007_sessions.go +++ b/apiserver/internal/migrations/007_sessions.go @@ -23,7 +23,7 @@ func (m *SessionsMigration) Name() string { func (m *SessionsMigration) Up(ctx context.Context, db *gorm.DB) error { dbCtx := db.WithContext(ctx) - dialect := db.Dialector.Name() + dialect := db.Name() switch dialect { case "sqlite": diff --git a/apiserver/internal/migrations/008_unique_label_names.go b/apiserver/internal/migrations/008_unique_label_names.go index 65467776..37501ace 100644 --- a/apiserver/internal/migrations/008_unique_label_names.go +++ b/apiserver/internal/migrations/008_unique_label_names.go @@ -55,7 +55,7 @@ func (m *UniqueLabelNamesMigration) Up(ctx context.Context, db *gorm.DB) error { )`, } - dialect := db.Dialector.Name() + dialect := db.Name() if dialect == "mysql" { dedup = []string{ `INSERT IGNORE INTO task_labels (task_id, label_id) @@ -100,7 +100,7 @@ func (m *UniqueLabelNamesMigration) Up(ctx context.Context, db *gorm.DB) error { func (m *UniqueLabelNamesMigration) Down(ctx context.Context, db *gorm.DB) error { dbCtx := db.WithContext(ctx) - if db.Dialector.Name() == "mysql" { + if db.Name() == "mysql" { return dbCtx.Exec("DROP INDEX idx_labels_created_by_name ON labels").Error } diff --git a/apiserver/internal/migrations/009_task_histories_task_id_id_index.go b/apiserver/internal/migrations/009_task_histories_task_id_id_index.go index 25607f59..6a2a1620 100644 --- a/apiserver/internal/migrations/009_task_histories_task_id_id_index.go +++ b/apiserver/internal/migrations/009_task_histories_task_id_id_index.go @@ -23,7 +23,7 @@ func (m *TaskHistoriesTaskIDIDIndexMigration) Name() string { func (m *TaskHistoriesTaskIDIDIndexMigration) Up(ctx context.Context, db *gorm.DB) error { dbCtx := db.WithContext(ctx) - if db.Dialector.Name() == "mysql" { + if db.Name() == "mysql" { return dbCtx.Exec("CREATE INDEX idx_task_histories_task_id_id ON task_histories(task_id, id)").Error } @@ -33,7 +33,7 @@ func (m *TaskHistoriesTaskIDIDIndexMigration) Up(ctx context.Context, db *gorm.D func (m *TaskHistoriesTaskIDIDIndexMigration) Down(ctx context.Context, db *gorm.DB) error { dbCtx := db.WithContext(ctx) - if db.Dialector.Name() == "mysql" { + if db.Name() == "mysql" { return dbCtx.Exec("DROP INDEX idx_task_histories_task_id_id ON task_histories").Error } diff --git a/apiserver/internal/repos/task/task.go b/apiserver/internal/repos/task/task.go index 61a16e20..9d21a906 100644 --- a/apiserver/internal/repos/task/task.go +++ b/apiserver/internal/repos/task/task.go @@ -249,15 +249,16 @@ func ScheduleNextDueDate(task *models.Task, completedDate time.Time) (*time.Time nextDueDate = baseDate.AddDate(1, 0, 0) } else if freq.Type == "custom" { if freq.On == "interval" { - if freq.Unit == "hours" { + switch freq.Unit { + case "hours": nextDueDate = baseDate.Add(time.Duration(freq.Every) * time.Hour) - } else if freq.Unit == "days" { + case "days": nextDueDate = baseDate.AddDate(0, 0, freq.Every) - } else if freq.Unit == "weeks" { + case "weeks": nextDueDate = baseDate.AddDate(0, 0, 7*freq.Every) - } else if freq.Unit == "months" { + case "months": nextDueDate = baseDate.AddDate(0, freq.Every, 0) - } else if freq.Unit == "years" { + case "years": nextDueDate = baseDate.AddDate(freq.Every, 0, 0) } } else if freq.On == "days_of_the_week" { diff --git a/apiserver/internal/services/notifications/gotify.go b/apiserver/internal/services/notifications/gotify.go index 27b9e654..518bf53e 100644 --- a/apiserver/internal/services/notifications/gotify.go +++ b/apiserver/internal/services/notifications/gotify.go @@ -51,7 +51,7 @@ func SendNotificationViaGotify(c context.Context, provider models.NotificationPr if err != nil { return fmt.Errorf("failed to send HTTP request: %s", err.Error()) } - defer resp.Body.Close() + defer func() { _ = resp.Body.Close() }() if resp.StatusCode != http.StatusOK { return fmt.Errorf("gotify returned non-OK status: %d", resp.StatusCode) diff --git a/apiserver/internal/services/notifications/safehttp_test.go b/apiserver/internal/services/notifications/safehttp_test.go index 166a705f..26d7bd78 100644 --- a/apiserver/internal/services/notifications/safehttp_test.go +++ b/apiserver/internal/services/notifications/safehttp_test.go @@ -115,7 +115,7 @@ func TestSafeClientBlocksLoopback(t *testing.T) { resp, err := client.Do(req) if err == nil { - resp.Body.Close() + _ = resp.Body.Close() t.Fatal("expected loopback connection to be blocked") } diff --git a/apiserver/internal/services/notifications/webhook.go b/apiserver/internal/services/notifications/webhook.go index 4f527f58..5400442c 100644 --- a/apiserver/internal/services/notifications/webhook.go +++ b/apiserver/internal/services/notifications/webhook.go @@ -44,7 +44,7 @@ func SendNotificationViaWebhook(c context.Context, provider models.NotificationP return fmt.Errorf("error sending HTTP request: %s", err.Error()) } - defer resp.Body.Close() + defer func() { _ = resp.Body.Close() }() if resp.StatusCode != http.StatusOK { return fmt.Errorf("received non-OK response: %d", resp.StatusCode) diff --git a/apiserver/internal/services/tasks/task.go b/apiserver/internal/services/tasks/task.go index 88dfc7ca..96730223 100644 --- a/apiserver/internal/services/tasks/task.go +++ b/apiserver/internal/services/tasks/task.go @@ -515,7 +515,7 @@ func (s *TaskService) CompleteTask(ctx context.Context, userID, taskID int, endR return http.StatusNotFound, gin.H{"error": "Task not found"} } - var completedDate time.Time = time.Now().UTC() + completedDate := time.Now().UTC() var nextDueDate *time.Time = nil if !endRecurrence { diff --git a/apiserver/internal/utils/database/database_test.go b/apiserver/internal/utils/database/database_test.go index 555b54c7..4c93bfe2 100644 --- a/apiserver/internal/utils/database/database_test.go +++ b/apiserver/internal/utils/database/database_test.go @@ -36,7 +36,7 @@ func (s *DatabaseTestSuite) TearDownTest() { if s.db != nil { sqlDB, err := s.db.DB() if err == nil { - sqlDB.Close() + _ = sqlDB.Close() } } } diff --git a/apiserver/internal/utils/test/database.go b/apiserver/internal/utils/test/database.go index 43d0af9e..7dc654bb 100644 --- a/apiserver/internal/utils/test/database.go +++ b/apiserver/internal/utils/test/database.go @@ -40,7 +40,7 @@ func (suite *DatabaseTestSuite) TearDownTest() { log.Printf("failed to get database connection: %v", err) return } - db.Close() + _ = db.Close() // Remove the temporary database file created for the test if suite.dbFilePath != "" { diff --git a/apiserver/internal/ws/server_test.go b/apiserver/internal/ws/server_test.go index 4889479c..e234cbe6 100644 --- a/apiserver/internal/ws/server_test.go +++ b/apiserver/internal/ws/server_test.go @@ -81,7 +81,7 @@ func (s *WSServerTestSuite) TestHandleConnection_Unauthorized() { header := http.Header{} conn, _, err := websocket.DefaultDialer.Dial(url, header) if conn != nil { - conn.Close() + _ = conn.Close() } s.Error(err) s.Equal(0, len(s.server.connections)) @@ -97,7 +97,7 @@ func (s *WSServerTestSuite) TestHandleConnection_Authorized() { s.waitForConnections(1) s.Equal(1, len(s.server.userConnections)) - conn.Close() + _ = conn.Close() s.waitForConnections(0) s.Equal(0, len(s.server.userConnections)) } @@ -115,8 +115,8 @@ func (s *WSServerTestSuite) TestMultipleConnectionsAndCleanup() { s.Equal(1, len(s.server.userConnections)) s.Equal(2, len(s.server.userConnections[1])) - conn1.Close() - conn2.Close() + _ = conn1.Close() + _ = conn2.Close() s.waitForConnections(0) s.Equal(0, len(s.server.userConnections)) } @@ -149,7 +149,7 @@ func (s *WSServerTestSuite) TestPingPongKeepsConnectionAlive() { time.Sleep(3 * s.server.pingPeriod) s.Equal(1, len(s.server.connections)) - conn.Close() + _ = conn.Close() <-done s.waitForConnections(0) } @@ -197,7 +197,7 @@ func (s *WSServerTestSuite) TestHandleMessageRoutesResponse() { conn, _, err := s.dial(ts) s.Require().NoError(err) - defer conn.Close() + defer func() { _ = conn.Close() }() s.waitForConnections(1) @@ -217,7 +217,7 @@ func (s *WSServerTestSuite) TestOversizedMessageClosesConnection() { conn, _, err := s.dial(ts) s.Require().NoError(err) - defer conn.Close() + defer func() { _ = conn.Close() }() s.waitForConnections(1) @@ -248,7 +248,7 @@ func (s *WSServerTestSuite) TestRateLimitRejectsFlood() { conn, _, err := s.dial(ts) s.Require().NoError(err) - defer conn.Close() + defer func() { _ = conn.Close() }() s.waitForConnections(1)