Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / internal/modules/collab/service_test.go |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 720d47fae476b0d38477ae4401697d372b1ea2bc |
| Branch | feature/opportunity-to-outcome |
| Path or archive member | internal/modules/collab/service_test.go |
| Original SHA-256 | 04b533ae99ecbadc0f1e4b554f8e3e4acc3b7e30533280aa2e02e46bdf03e3ce |
| Git blob SHA | 1fbf1045ac08dc40a9208d51e84d627794c8b791 |
| Reading-copy SHA-256 | 04b533ae99ecbadc0f1e4b554f8e3e4acc3b7e30533280aa2e02e46bdf03e3ce |
Recovered source transcript
Download complete source text ↓157 lines · 6.0 KB
package collab
import (
"os"
"strings"
"testing"
)
// The entity vocabulary must match the CHECK constraint in migration 0087 exactly. If the two drift, a type
// the handler accepts is refused by the database at insert time, which surfaces as a 500 on a claim rather
// than a 404 on an unknown type.
func TestEntityVocabularyMatchesTheMigration(t *testing.T) {
sql, err := os.ReadFile("../../../db/migrations/0087_org_settings.sql")
if err != nil {
t.Fatalf("read migration: %v", err)
}
// Both work_claims and work_touches declare the same list; checking against the file catches a change to
// either without needing a database.
for _, typ := range EntityTypes() {
if !strings.Contains(string(sql), "'"+typ+"'") {
t.Errorf("entity type %q is accepted by the module but is not in the migration's CHECK", typ)
}
}
// And the reverse: nothing in the migration's list may be missing here, or a record type exists in the
// schema that no route can reach.
for _, typ := range []string{"candidate", "requisition", "opportunity", "proposal", "client"} {
if !ValidEntityType(typ) {
t.Errorf("the migration allows %q and the module does not", typ)
}
}
}
// The table name is interpolated into SQL, so the map it comes from is the only thing standing between this
// and an injection. This asserts the shape rather than the behaviour: every value must be a bare identifier.
func TestEntityTableNamesAreBareIdentifiers(t *testing.T) {
for typ, table := range entityTables {
if table == "" {
t.Errorf("%q maps to an empty table name", typ)
}
for _, r := range table {
if (r < 'a' || r > 'z') && r != '_' {
t.Errorf("table name %q for %q is not a bare lowercase identifier, it must never reach SQL", table, typ)
}
}
}
for typ, col := range ownerColumns {
if !ValidEntityType(typ) {
t.Errorf("ownerColumns names %q which is not a valid entity type", typ)
}
for _, r := range col {
if (r < 'a' || r > 'z') && r != '_' {
t.Errorf("owner column %q for %q is not a bare lowercase identifier", col, typ)
}
}
}
}
// An unknown type must be refused BEFORE any query is built, which is what makes the interpolation safe.
func TestUnknownEntityTypeRefused(t *testing.T) {
for _, bad := range []string{"", "user", "organization", "candidates", "CANDIDATE",
"candidate; drop table users", "candidate'"} {
if ValidEntityType(bad) {
t.Errorf("%q must not be a valid entity type", bad)
}
}
}
// The activity vocabulary must also match the migration, for the same reason as the entity vocabulary.
func TestActivityVocabularyMatchesTheMigration(t *testing.T) {
sql, err := os.ReadFile("../../../db/migrations/0087_org_settings.sql")
if err != nil {
t.Fatalf("read migration: %v", err)
}
for a := range validActivities {
if !strings.Contains(string(sql), "'"+a+"'") {
t.Errorf("activity %q is accepted by the module but is not in the migration's CHECK", a)
}
}
}
func TestEntityTypesIsSortedAndComplete(t *testing.T) {
got := EntityTypes()
if len(got) != len(entityTables) {
t.Fatalf("EntityTypes returned %d of %d types", len(got), len(entityTables))
}
for i := 1; i < len(got); i++ {
if got[i] < got[i-1] {
t.Errorf("EntityTypes is not sorted: %q came before %q", got[i-1], got[i])
}
}
if !strings.Contains(typeList(), "candidate") {
t.Error("the human readable type list is missing candidate")
}
}
// THE STRUCTURAL GUARANTEE. activityTx is the ONLY place the visibility rule is applied, and every read path
// must funnel through it. A future read that queried work_claims directly would return another recruiter's
// activity to somebody the organization said must not see it.
func TestEveryReadGoesThroughActivityTx(t *testing.T) {
src, err := os.ReadFile("service.go")
if err != nil {
t.Fatalf("read source: %v", err)
}
s := string(src)
if !strings.Contains(s, "security.CanSeeOthersWork(role, st.WorkVisibility)") {
t.Fatal("activityTx no longer consults the visibility rule")
}
// Exactly one call site. More than one means the decision has been copied, and a copy is a place to
// forget.
if n := strings.Count(s, "security.CanSeeOthersWork("); n != 1 {
t.Errorf("the visibility rule is consulted in %d places, it must be exactly one", n)
}
// MyClaims is the deliberate exception and says so: it returns only the caller's own claims.
body := s[strings.Index(s, "func (s *Service) MyClaims("):]
if i := strings.Index(body, "\nfunc "); i > 0 {
body = body[:i]
}
if !strings.Contains(body, "c.user_id = $1") {
t.Error("MyClaims must filter to the caller's own claims, it is the one read that skips the visibility rule")
}
}
// Presence must be an upsert, never an append. An append generates a row per page view per recruiter per
// candidate and turns a presence feature into a browsing history of a named employee.
func TestPresenceIsAnUpsertNotAnAppend(t *testing.T) {
src, err := os.ReadFile("service.go")
if err != nil {
t.Fatalf("read source: %v", err)
}
s := string(src)
if !strings.Contains(s, "ON CONFLICT (organization_id, entity_type, entity_id, user_id)") {
t.Error("work_touches is no longer upserted; presence would accumulate a row per view")
}
if !strings.Contains(s, "st.ShowActivityPresence") {
t.Error("presence is recorded without checking whether the organization wants it")
}
}
// An expired claim must be released before a new one is attempted, or the partial unique index makes an
// abandoned claim own a record permanently.
func TestExpiredClaimsAreReleasedBeforeClaiming(t *testing.T) {
src, err := os.ReadFile("service.go")
if err != nil {
t.Fatalf("read source: %v", err)
}
body := string(src)[strings.Index(string(src), "func (s *Service) TakeClaim("):]
if i := strings.Index(body, "\nfunc "); i > 0 {
body = body[:i]
}
if !strings.Contains(body, "released_at IS NULL AND expires_at <= now()") {
t.Error("TakeClaim does not release expired claims first; an abandoned claim would own a record forever")
}
if !strings.Contains(body, "assertExists(ctx, tx, entityType, entityID)") {
t.Error("TakeClaim does not prove the record exists in this tenant before writing about it")
}
}