diff --git a/bskyweb/cmd/bskyweb/render_test.go b/bskyweb/cmd/bskyweb/render_test.go
index 30b27a53d5..902476709f 100644
--- a/bskyweb/cmd/bskyweb/render_test.go
+++ b/bskyweb/cmd/bskyweb/render_test.go
@@ -43,6 +43,13 @@ func extractJSONLD(t *testing.T, html string) string {
return strings.TrimSpace(m[1])
}
+func TestRenderBase_NoindexMeta(t *testing.T) {
+ html := renderTemplate(t, "base.html", pongo2.Context{"noindex": true, "nofollow": true})
+ if !strings.Contains(html, ``) {
+ t.Errorf("expected combined noindex,nofollow meta; got:\n%s", html)
+ }
+}
+
func TestRenderPost_EmitsJSONLD(t *testing.T) {
pv := makePostView("alice.bsky.social", "did:plc:alice", "abc123", "hello")
ld, err := buildPostJSONLD(pv, nil, "https://bsky.app/profile/alice.bsky.social/post/abc123", hideEmbedLabels, hideReplyLabels)
@@ -243,3 +250,50 @@ func TestRenderPost_VideoWithoutThumbnailEmitsOGVideo(t *testing.T) {
t.Errorf("og:video:type should emit even without imgThumbUrls; got:\n%s", html)
}
}
+
+// Auth-required posts must emit noindex,nofollow so the stub page (no body
+// text, no comments) is not indexed.
+func TestRenderPost_AuthRequiredNoindex(t *testing.T) {
+ html := renderTemplate(t, "post.html", pongo2.Context{
+ "requiresAuth": true,
+ "profileHandle": "alice.bsky.social",
+ "requestURI": "https://bsky.app/profile/alice.bsky.social/post/abc123",
+ "canonicalURL": "https://bsky.app/profile/alice.bsky.social/post/abc123",
+ "noindex": true,
+ "nofollow": true,
+ })
+ if !strings.Contains(html, ``) {
+ t.Errorf("auth-required post should emit noindex,nofollow; got:\n%s", html)
+ }
+}
+
+// Auth-required profiles must emit noindex,nofollow.
+func TestRenderProfile_AuthRequiredNoindex(t *testing.T) {
+ pv := newProfileViewDetailed()
+ html := renderTemplate(t, "profile.html", pongo2.Context{
+ "profileView": pv,
+ "requestURI": "https://bsky.app/profile/alice.bsky.social",
+ "requiresAuth": true,
+ "noindex": true,
+ "nofollow": true,
+ })
+ if !strings.Contains(html, ``) {
+ t.Errorf("auth-required profile should emit noindex,nofollow; got:\n%s", html)
+ }
+}
+
+// Public posts must NOT emit a robots meta tag. Guards against an accidental
+// flip of the noindex flag for indexable pages.
+func TestRenderPost_PublicNoNoindex(t *testing.T) {
+ pv := makePostView("alice.bsky.social", "did:plc:alice", "abc123", "hello")
+ ld, _ := buildPostJSONLD(pv, nil, "https://bsky.app/profile/alice.bsky.social/post/abc123", hideEmbedLabels, hideReplyLabels)
+ html := renderTemplate(t, "post.html", pongo2.Context{
+ "postView": pv,
+ "requestURI": "https://bsky.app/profile/alice.bsky.social/post/abc123",
+ "canonicalURL": "https://bsky.app/profile/alice.bsky.social/post/abc123",
+ "postJSONLD": ld,
+ })
+ if strings.Contains(html, `
+ {% if noindex %}{% endif %}