mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
test: cover personal skill API (#25365)
> Mux updated this PR on behalf of Mike. ## Stack Context This PR is the API test coverage slice in the experimental personal skills stack. The storage, schema, permissions, API, and SDK implementation merged in #25363. Stack order: 1. #25362 personal skill resolver 2. #25363 storage, permissions, API, and SDK 3. #25365 API test coverage 4. #25366 chattool and chatd integration 5. #25066 settings UI and docs 6. #25386 personal skills slash menu ## What? Adds API and audit tests for personal skill CRUD, validation failures, limits, authorization, soft-delete cleanup, and audit content tracking. This PR is now test-only. It does not include migrations, generated database code, or API implementation changes. ## Why? The feature touches storage, permissions, and audit behavior. These tests make the server behavior reviewable and protected without re-reviewing the implementation that already merged in #25363. ## Validation - `go test ./coderd -run '^(TestUserSkill|TestPatchUserSkill)' -count=1` - `go test ./enterprise/coderd -run '^TestUserSkillAuditDiffTracksContent$' -count=1` - pre-commit hook via `gt modify --no-edit`
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
package coderd_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/v2/coderd/audit"
|
||||
"github.com/coder/coder/v2/coderd/coderdtest"
|
||||
"github.com/coder/coder/v2/coderd/database"
|
||||
"github.com/coder/coder/v2/coderd/database/dbauthz"
|
||||
"github.com/coder/coder/v2/coderd/database/dbtestutil"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
entaudit "github.com/coder/coder/v2/enterprise/audit"
|
||||
"github.com/coder/coder/v2/enterprise/audit/backends"
|
||||
"github.com/coder/coder/v2/enterprise/coderd/coderdenttest"
|
||||
"github.com/coder/coder/v2/enterprise/coderd/license"
|
||||
"github.com/coder/coder/v2/testutil"
|
||||
)
|
||||
|
||||
func TestUserSkillAuditDiffTracksContent(t *testing.T) {
|
||||
// User skill content is user-authored instruction text, not secret material.
|
||||
// The enterprise auditor needs to be used because it writes actual diffs.
|
||||
t.Parallel()
|
||||
|
||||
db, ps := dbtestutil.NewDB(t)
|
||||
auditor := entaudit.NewAuditor(
|
||||
db,
|
||||
entaudit.DefaultFilter,
|
||||
backends.NewPostgres(db, true),
|
||||
)
|
||||
|
||||
ownerClient, owner := coderdenttest.New(t, &coderdenttest.Options{
|
||||
AuditLogging: true,
|
||||
Options: &coderdtest.Options{
|
||||
Database: db,
|
||||
Pubsub: ps,
|
||||
Auditor: auditor,
|
||||
},
|
||||
LicenseOptions: &coderdenttest.LicenseOptions{
|
||||
Features: license.Features{
|
||||
codersdk.FeatureAuditLog: 1,
|
||||
},
|
||||
},
|
||||
})
|
||||
memberClient, _ := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID)
|
||||
member := codersdk.NewExperimentalClient(memberClient)
|
||||
ctx := testutil.Context(t, testutil.WaitMedium)
|
||||
|
||||
initialContent := userSkillMarkdown("audit-tracking", "initial", "initial body")
|
||||
skill, err := member.CreateUserSkill(ctx, codersdk.Me, codersdk.CreateUserSkillRequest{
|
||||
Content: initialContent,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
newContent := userSkillMarkdown("audit-tracking", "after", "new body")
|
||||
_, err = member.UpdateUserSkill(ctx, codersdk.Me, skill.Name, codersdk.UpdateUserSkillRequest{
|
||||
Content: newContent,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
rows, err := db.GetAuditLogsOffset(
|
||||
dbauthz.AsSystemRestricted(ctx),
|
||||
database.GetAuditLogsOffsetParams{
|
||||
ResourceType: string(database.ResourceTypeUserSkill),
|
||||
LimitOpt: 10,
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, rows, 2, "expected exactly two rows")
|
||||
createLog := rows[1].AuditLog
|
||||
updateLog := rows[0].AuditLog
|
||||
|
||||
var createDiff audit.Map
|
||||
require.NoError(t, json.Unmarshal(createLog.Diff, &createDiff))
|
||||
if assert.Contains(t, createDiff, "description", "tracked field missing from create diff") {
|
||||
assert.Equal(t, "", createDiff["description"].Old)
|
||||
assert.Equal(t, "initial", createDiff["description"].New)
|
||||
assert.False(t, createDiff["description"].Secret)
|
||||
}
|
||||
if assert.Contains(t, createDiff, "content", "content field missing from create diff") {
|
||||
assert.False(t, createDiff["content"].Secret)
|
||||
assert.Equal(t, "", createDiff["content"].Old)
|
||||
assert.Equal(t, initialContent, createDiff["content"].New)
|
||||
}
|
||||
|
||||
var updateDiff audit.Map
|
||||
require.NoError(t, json.Unmarshal(updateLog.Diff, &updateDiff))
|
||||
if assert.Contains(t, updateDiff, "description", "tracked field missing from update diff") {
|
||||
assert.Equal(t, "initial", updateDiff["description"].Old)
|
||||
assert.Equal(t, "after", updateDiff["description"].New)
|
||||
assert.False(t, updateDiff["description"].Secret)
|
||||
}
|
||||
if assert.Contains(t, updateDiff, "content", "content field missing from update diff") {
|
||||
assert.False(t, updateDiff["content"].Secret)
|
||||
assert.Equal(t, initialContent, updateDiff["content"].Old)
|
||||
assert.Equal(t, newContent, updateDiff["content"].New)
|
||||
}
|
||||
assert.NotContains(t, updateDiff, "created_at")
|
||||
assert.NotContains(t, updateDiff, "updated_at")
|
||||
}
|
||||
|
||||
func userSkillMarkdown(name string, description string, body string) string {
|
||||
return fmt.Sprintf("---\nname: %s\ndescription: %s\n---\n\n%s\n", name, description, body)
|
||||
}
|
||||
Reference in New Issue
Block a user