133 lines
5.2 KiB
Go
133 lines
5.2 KiB
Go
package httpapi
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"net/http"
|
||
|
|
"testing"
|
||
|
|
)
|
||
|
|
|
||
|
|
// At nævne nogen i en note er at ville have dem til at læse den: omtalen deler
|
||
|
|
// noten, og den, der bliver nævnt, får besked om det.
|
||
|
|
func TestMentioningSomebodySharesTheNote(t *testing.T) {
|
||
|
|
owner := newTestServer(t)
|
||
|
|
owner.bootstrap(t)
|
||
|
|
other := owner.newUser(t, "sofie@example.dk", "Sofie")
|
||
|
|
sofie := userID(t, owner, "sofie@example.dk")
|
||
|
|
|
||
|
|
noteID := owner.createNote(t, "# Aftale om levering\nikke noget endnu")
|
||
|
|
if resp, _ := other.do(t, "GET", "/api/v1/notes/"+noteID, nil); resp.StatusCode != http.StatusNotFound {
|
||
|
|
t.Fatalf("noten var læselig før omtalen: %d", resp.StatusCode)
|
||
|
|
}
|
||
|
|
|
||
|
|
if resp, _ := owner.do(t, "PATCH", "/api/v1/notes/"+noteID,
|
||
|
|
map[string]any{"body": "# Aftale om levering\n@Sofie kan du kigge på det?"}); resp.StatusCode != http.StatusOK {
|
||
|
|
t.Fatalf("ret noten: %d", resp.StatusCode)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Delt, som læser.
|
||
|
|
role, has, err := owner.db.NoteShareRole(t.Context(), noteID, sofie)
|
||
|
|
if err != nil || !has || role != "viewer" {
|
||
|
|
t.Fatalf("deling = %v (findes: %v, fejl: %v), want viewer", role, has, err)
|
||
|
|
}
|
||
|
|
if resp, _ := other.do(t, "GET", "/api/v1/notes/"+noteID, nil); resp.StatusCode != http.StatusOK {
|
||
|
|
t.Fatalf("den omtalte kan ikke læse noten: %d", resp.StatusCode)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Og sagt til — med omtalen som beskeden, ikke "rettede en note". Det er én
|
||
|
|
// handling, og den ene sætning siger mere end den anden.
|
||
|
|
list, unread := notifications(t, other)
|
||
|
|
if len(list) != 1 || unread != 1 {
|
||
|
|
t.Fatalf("Sofie fik %d beskeder (%v ulæste), want 1", len(list), unread)
|
||
|
|
}
|
||
|
|
if n := firstOf(t, list); n["kind"] != "note.mention" || n["note_id"] != noteID {
|
||
|
|
t.Errorf("besked = %v", n)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// En gemning mere med det samme navn i er ikke en omtale mere. En note gemmes ved
|
||
|
|
// hver tastepause, så uden det bliver fem minutters skriveri til tyve beskeder.
|
||
|
|
func TestTheSameMentionOnlyCountsOnce(t *testing.T) {
|
||
|
|
owner := newTestServer(t)
|
||
|
|
owner.bootstrap(t)
|
||
|
|
other := owner.newUser(t, "sofie@example.dk", "Sofie")
|
||
|
|
|
||
|
|
noteID := owner.createNote(t, "# Aftale\n@Sofie kigger")
|
||
|
|
// Omtalen stod i noten fra begyndelsen: den tæller ved oprettelsen.
|
||
|
|
if list, _ := notifications(t, other); len(list) != 1 {
|
||
|
|
t.Fatalf("en omtale i en ny note gav %d beskeder, want 1", len(list))
|
||
|
|
}
|
||
|
|
|
||
|
|
for i := 0; i < 3; i++ {
|
||
|
|
if resp, _ := owner.do(t, "PATCH", "/api/v1/notes/"+noteID,
|
||
|
|
map[string]any{"body": "# Aftale\n@Sofie kigger på linje " + string(rune('a'+i))}); resp.StatusCode != http.StatusOK {
|
||
|
|
t.Fatal("ret noten")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
// Tre gemninger mere: én besked om rettelserne, slået sammen, og ikke tre
|
||
|
|
// omtaler mere.
|
||
|
|
list, _ := notifications(t, other)
|
||
|
|
if len(list) != 2 {
|
||
|
|
t.Fatalf("tre gemninger med det samme navn gav %d beskeder, want 2", len(list))
|
||
|
|
}
|
||
|
|
if firstOf(t, list)["kind"] != "note.changed" {
|
||
|
|
t.Errorf("den nyeste besked = %v, want note.changed", firstOf(t, list))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// En medredaktør må skrive i noten, men ikke give den videre. Ellers kunne den,
|
||
|
|
// ejeren har delt med, skrive et navn og dele ejerens note med en fremmed.
|
||
|
|
func TestAnEditorsMentionDoesNotShareTheNote(t *testing.T) {
|
||
|
|
owner := newTestServer(t)
|
||
|
|
owner.bootstrap(t)
|
||
|
|
editor := owner.newUser(t, "sofie@example.dk", "Sofie")
|
||
|
|
sofie := userID(t, owner, "sofie@example.dk")
|
||
|
|
peterClient := owner.newUser(t, "peter@example.dk", "Peter")
|
||
|
|
peter := userID(t, owner, "peter@example.dk")
|
||
|
|
|
||
|
|
noteID := owner.createNote(t, "# Aftale\nintet")
|
||
|
|
if resp, _ := owner.do(t, "POST", "/api/v1/notes/"+noteID+"/shares",
|
||
|
|
map[string]string{"user_id": sofie, "role": "editor"}); resp.StatusCode != http.StatusOK {
|
||
|
|
t.Fatal("del noten")
|
||
|
|
}
|
||
|
|
|
||
|
|
if resp, _ := editor.do(t, "PATCH", "/api/v1/notes/"+noteID,
|
||
|
|
map[string]any{"body": "# Aftale\n@Peter ved det"}); resp.StatusCode != http.StatusOK {
|
||
|
|
t.Fatal("medredaktøren retter")
|
||
|
|
}
|
||
|
|
|
||
|
|
if _, has, err := owner.db.NoteShareRole(t.Context(), noteID, peter); err != nil || has {
|
||
|
|
t.Errorf("en medredaktørs omtale delte ejerens note (findes: %v, fejl: %v)", has, err)
|
||
|
|
}
|
||
|
|
// Og Peter får ikke besked om en note, han ikke kan åbne.
|
||
|
|
if list, _ := notifications(t, peterClient); len(list) != 0 {
|
||
|
|
t.Errorf("Peter fik %d beskeder om en note, han ikke kan se", len(list))
|
||
|
|
}
|
||
|
|
// Ejeren hører derimod, at der er skrevet i noten — det er stadig en rettelse.
|
||
|
|
if list, _ := notifications(t, owner); len(list) == 0 {
|
||
|
|
t.Error("ejeren hørte ikke, at medredaktøren skrev i noten")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Rollen står. En omtale skal give adgang til den, der ikke har nogen — ikke
|
||
|
|
// sætte en medredaktør ned til læser, fordi ejeren skrev deres navn.
|
||
|
|
func TestAMentionDoesNotLowerAnExistingRole(t *testing.T) {
|
||
|
|
owner := newTestServer(t)
|
||
|
|
owner.bootstrap(t)
|
||
|
|
owner.newUser(t, "sofie@example.dk", "Sofie")
|
||
|
|
sofie := userID(t, owner, "sofie@example.dk")
|
||
|
|
|
||
|
|
noteID := owner.createNote(t, "# Aftale\nintet")
|
||
|
|
if resp, _ := owner.do(t, "POST", "/api/v1/notes/"+noteID+"/shares",
|
||
|
|
map[string]string{"user_id": sofie, "role": "editor"}); resp.StatusCode != http.StatusOK {
|
||
|
|
t.Fatal("del noten")
|
||
|
|
}
|
||
|
|
if resp, _ := owner.do(t, "PATCH", "/api/v1/notes/"+noteID,
|
||
|
|
map[string]any{"body": "# Aftale\n@Sofie retter selv"}); resp.StatusCode != http.StatusOK {
|
||
|
|
t.Fatal("ret noten")
|
||
|
|
}
|
||
|
|
|
||
|
|
role, _, err := owner.db.NoteShareRole(t.Context(), noteID, sofie)
|
||
|
|
if err != nil || role != "editor" {
|
||
|
|
t.Errorf("rolle = %v (%v), want editor uændret", role, err)
|
||
|
|
}
|
||
|
|
}
|