fix: address code review on #27
- The empty state is about an empty library, not a brand-new Reader:
listView.Fresh becomes EmptyLibrary and moves behind the tab-specific
branches, so "No favourites yet" is no longer shadowed for a Reader whose
library happens to be empty. The action key stays put — hiding it was
never asked for.
- The owner is not a revocable Reader: their row offers no button and
POST /readers/{owner}/revoke is a 404, so the one row where the control
would sign out the tapping browser cannot be reached by a hand-rolled
POST either.
- Modify isolation is asserted in both directions, and the owner's own
sign-in through the OAuth callback is pinned to the seeded row.
- CUTOVER.md and REDEPLOY.md still grepped API_TOKEN out of .env for their
smoke tests, which the last commit deleted; both now take the acting
Reader's derived credential.
- Roster type follows the machine-fact spec (500 10-11px mono, tracked),
and PRODUCT.md names the Readers panel instead of claiming there is no
owner surface at all.
This commit is contained in:
+37
-1
@@ -485,6 +485,23 @@ func TestGuildMemberRegistersOnFirstLoginAndReusesIt(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// The seeded owner signs in through the same path: their row is found, not
|
||||
// created a second time.
|
||||
func TestOwnerLoginReusesTheSeededReader(t *testing.T) {
|
||||
stub, stubSrv := newDiscordStub(t)
|
||||
stub.ownerID = testDiscordID
|
||||
cfg := testConfig()
|
||||
cfg.Discord = discordConfig(stubSrv.URL)
|
||||
router, st := newWebTestServer(t, cfg)
|
||||
|
||||
if got := signedInReader(t, router, st); got != st.OwnerID() {
|
||||
t.Fatalf("owner's sign-in landed on Reader %d, want the seeded %d", got, st.OwnerID())
|
||||
}
|
||||
if n := len(storeReaders(t, st)); n != 1 {
|
||||
t.Fatalf("readers after the owner's login = %d, want 1 (the seed was duplicated)", n)
|
||||
}
|
||||
}
|
||||
|
||||
// A brand-new Reader's page explains how a library gets filled and offers both
|
||||
// install links, and the script it serves carries their credential — not the
|
||||
// owner's.
|
||||
@@ -514,7 +531,7 @@ func TestNewReaderSeesEmptyLibraryAndTheirOwnScript(t *testing.T) {
|
||||
}
|
||||
body := rr.Body.String()
|
||||
for _, want := range []string{
|
||||
"Your library is empty",
|
||||
"Nothing here yet",
|
||||
`href="/install/manga-bookmark.user.js"`,
|
||||
`href="/install/novel-bookmark.user.js"`,
|
||||
} {
|
||||
@@ -570,6 +587,20 @@ func TestOwnerRevokesAnotherReadersSessions(t *testing.T) {
|
||||
t.Fatal("a non-owner's revoke attempt still killed the owner's session")
|
||||
}
|
||||
|
||||
// The owner is not a revocable Reader: the button would sign out the browser
|
||||
// making the request, so both the roster and the endpoint refuse it.
|
||||
req = httptest.NewRequest(http.MethodPost,
|
||||
"/readers/"+strconv.FormatInt(st.OwnerID(), 10)+"/revoke", nil)
|
||||
req.AddCookie(ownerCookie)
|
||||
rr = httptest.NewRecorder()
|
||||
router.ServeHTTP(rr, req)
|
||||
if rr.Code != http.StatusNotFound {
|
||||
t.Fatalf("owner revoking themselves: status = %d, want 404", rr.Code)
|
||||
}
|
||||
if _, ok, _ := st.GetSession(ownerCookie.Value, time.Now()); !ok {
|
||||
t.Fatal("the owner signed themselves out through the revoke endpoint")
|
||||
}
|
||||
|
||||
req = httptest.NewRequest(http.MethodPost,
|
||||
"/readers/"+strconv.FormatInt(theirSession.ReaderID, 10)+"/revoke", nil)
|
||||
req.AddCookie(ownerCookie)
|
||||
@@ -614,6 +645,11 @@ func TestOwnerSeesReadersPanel(t *testing.T) {
|
||||
if !strings.Contains(body, "Revoke sessions") {
|
||||
t.Fatal("the roster offers no revocation control for a signed-in Reader")
|
||||
}
|
||||
// Exactly one revocable row: the other Reader's. The owner's own row carries
|
||||
// the same session count and no button.
|
||||
if n := strings.Count(body, "/revoke"); n != 1 {
|
||||
t.Fatalf("roster has %d revoke controls, want 1 (the owner's own row must have none):\n%s", n, body)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiscordLoginTokenEndpointDown(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user