diff --git a/models/fixtures/repository.yml b/models/fixtures/repository.yml
index eaa5f07ba5..f537ee02d5 100644
--- a/models/fixtures/repository.yml
+++ b/models/fixtures/repository.yml
@@ -1921,4 +1921,3 @@
is_fsck_enabled: true
close_issues_via_commit_in_any_branch: false
topics: '[]'
-
diff --git a/modules/markup/renderer.go b/modules/markup/renderer.go
index ceaf435684..05dd512815 100644
--- a/modules/markup/renderer.go
+++ b/modules/markup/renderer.go
@@ -326,7 +326,7 @@ func render(ctx *RenderContext, renderer Renderer, input io.Reader, output io.Wr
if r, ok := renderer.(ExternalRenderer); ok && r.DisplayInIFrame() {
// Append a short script to the iframe's contents, which will communicate the scroll height of the embedded document via postMessage, either once loaded (in case the containing page loads first) in response to a postMessage from external.js, in case the iframe loads first
// We use '*' as a target origin for postMessage, because can be certain we are embedded on the same domain, due to X-Frame-Options configured elsewhere. (Plus, the offsetHeight of an embedded document is likely not sensitive data anyway.)
- _, _ = pw.Write([]byte(""))
+ _, _ = pw.Write([]byte(""))
}
_ = pw.Close()
diff --git a/services/repository/adopt_test.go b/services/repository/adopt_test.go
index a66b4c5ac0..79e4fc0023 100644
--- a/services/repository/adopt_test.go
+++ b/services/repository/adopt_test.go
@@ -69,7 +69,7 @@ func TestCheckUnadoptedRepositories(t *testing.T) {
func TestListUnadoptedRepositories_ListOptions(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
username := "user2"
- unadoptedList := []string{path.Join(username, "unadopted1"), path.Join(username, "unadopted2")}
+ unadoptedList := []string{path.Join(username, "rendering-test"), path.Join(username, "unadopted1"), path.Join(username, "unadopted2")}
for _, unadopted := range unadoptedList {
_ = os.Mkdir(path.Join(setting.RepoRootPath, unadopted+".git"), 0o755)
}
@@ -77,13 +77,13 @@ func TestListUnadoptedRepositories_ListOptions(t *testing.T) {
opts := db.ListOptions{Page: 1, PageSize: 1}
repoNames, count, err := ListUnadoptedRepositories(db.DefaultContext, "", &opts)
require.NoError(t, err)
- assert.Equal(t, 2, count)
+ assert.Equal(t, 3, count)
assert.Equal(t, unadoptedList[0], repoNames[0])
opts = db.ListOptions{Page: 2, PageSize: 1}
repoNames, count, err = ListUnadoptedRepositories(db.DefaultContext, "", &opts)
require.NoError(t, err)
- assert.Equal(t, 2, count)
+ assert.Equal(t, 3, count)
assert.Equal(t, unadoptedList[1], repoNames[0])
}
@@ -97,7 +97,7 @@ func TestAdoptRepository(t *testing.T) {
path.Join(setting.RepoRootPath, username, unadopted+".git"),
))
- opts := db.ListOptions{Page: 1, PageSize: 1}
+ opts := db.ListOptions{Page: 2, PageSize: 1}
repoNames, _, err := ListUnadoptedRepositories(db.DefaultContext, "", &opts)
require.NoError(t, err)
require.Contains(t, repoNames, path.Join(username, unadopted))
diff --git a/tests/e2e/fixtures/repo_unit.yml b/tests/e2e/fixtures/repo_unit.yml
new file mode 100644
index 0000000000..df727bbc08
--- /dev/null
+++ b/tests/e2e/fixtures/repo_unit.yml
@@ -0,0 +1,6 @@
+-
+ id: 1001
+ repo_id: 1002
+ type: 1
+ config: "{}"
+ created_unix: 946684810
diff --git a/tests/e2e/fixtures/repository.yml b/tests/e2e/fixtures/repository.yml
index 6afbd138e8..153e6e7752 100644
--- a/tests/e2e/fixtures/repository.yml
+++ b/tests/e2e/fixtures/repository.yml
@@ -11,3 +11,18 @@
status: 0
lfs_size: 8192
topics: '[]'
+
+
+-
+ id: 1002
+ owner_id: 2
+ owner_name: user2
+ lower_name: rendering-test
+ name: rendering-test
+ default_branch: master
+ is_empty: false
+ is_archived: false
+ is_private: false
+ status: 0
+ num_issues: 0
+ topics: '[]'
diff --git a/tests/e2e/rendering-iframe.test.e2e.ts b/tests/e2e/rendering-iframe.test.e2e.ts
new file mode 100644
index 0000000000..507d63705c
--- /dev/null
+++ b/tests/e2e/rendering-iframe.test.e2e.ts
@@ -0,0 +1,61 @@
+// Copyright 2025 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+// @watch start
+// web_src/js/markup/external.js
+// @watch end
+
+import {expect} from '@playwright/test';
+import {test} from './utils_e2e.ts';
+
+test('iframe renderer shrinks to shorter page', async ({page}, _workerInfo) => {
+ const previewPath = '/user2/rendering-test/src/branch/master/short.iframehtml';
+
+ const response = await page.goto(previewPath, {waitUntil: 'domcontentloaded'});
+ expect(response?.status()).toBe(200);
+
+ const preview = page.locator('iframe.external-render');
+ await expect.poll(async () => {
+ const boundingBox = await preview.boundingBox();
+ return boundingBox.height;
+ }).toBeLessThan(300);
+});
+
+test('iframe renderer expands to taller page', async ({page}, _workerInfo) => {
+ const previewPath = '/user2/rendering-test/src/branch/master/tall.iframehtml';
+
+ const response = await page.goto(previewPath, {waitUntil: 'domcontentloaded'});
+ expect(response?.status()).toBe(200);
+
+ const preview = page.locator('iframe.external-render');
+ await expect.poll(async () => {
+ const boundingBox = await preview.boundingBox();
+ return boundingBox.height;
+ }).toBeGreaterThan(300);
+});
+
+test('iframe renderer expands to taller page with absolutely-positioned body', async ({page}, _workerInfo) => {
+ const previewPath = '/user2/rendering-test/src/branch/master/absolute.iframehtml';
+
+ const response = await page.goto(previewPath, {waitUntil: 'domcontentloaded'});
+ expect(response?.status()).toBe(200);
+
+ const preview = page.locator('iframe.external-render');
+ await expect.poll(async () => {
+ const boundingBox = await preview.boundingBox();
+ return boundingBox.height;
+ }).toBeGreaterThan(300);
+});
+
+test('iframe renderer remains at default height if script breaks', async ({page}, _workerInfo) => {
+ const previewPath = '/user2/rendering-test/src/branch/master/fail.iframehtml';
+
+ const response = await page.goto(previewPath, {waitUntil: 'domcontentloaded'});
+ expect(response?.status()).toBe(200);
+
+ const preview = page.locator('iframe.external-render');
+ await expect.poll(async () => {
+ const boundingBox = await preview.boundingBox();
+ return boundingBox.height;
+ }).toBeCloseTo(300, 0.5);
+});
diff --git a/tests/gitea-repositories-meta/user2/rendering-test.git/HEAD b/tests/gitea-repositories-meta/user2/rendering-test.git/HEAD
new file mode 100644
index 0000000000..cb089cd89a
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/rendering-test.git/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/master
diff --git a/tests/gitea-repositories-meta/user2/rendering-test.git/config b/tests/gitea-repositories-meta/user2/rendering-test.git/config
new file mode 100644
index 0000000000..07d359d07c
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/rendering-test.git/config
@@ -0,0 +1,4 @@
+[core]
+ repositoryformatversion = 0
+ filemode = true
+ bare = true
diff --git a/tests/gitea-repositories-meta/user2/rendering-test.git/description b/tests/gitea-repositories-meta/user2/rendering-test.git/description
new file mode 100644
index 0000000000..498b267a8c
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/rendering-test.git/description
@@ -0,0 +1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff --git a/tests/gitea-repositories-meta/user2/rendering-test.git/info/exclude b/tests/gitea-repositories-meta/user2/rendering-test.git/info/exclude
new file mode 100644
index 0000000000..a5196d1be8
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/rendering-test.git/info/exclude
@@ -0,0 +1,6 @@
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
diff --git a/tests/gitea-repositories-meta/user2/rendering-test.git/objects/29/262fe430e92c957b5d6945df90570d85725dfd b/tests/gitea-repositories-meta/user2/rendering-test.git/objects/29/262fe430e92c957b5d6945df90570d85725dfd
new file mode 100644
index 0000000000..184f27bb65
Binary files /dev/null and b/tests/gitea-repositories-meta/user2/rendering-test.git/objects/29/262fe430e92c957b5d6945df90570d85725dfd differ
diff --git a/tests/gitea-repositories-meta/user2/rendering-test.git/objects/32/6ad6b850d0786dcbe128fb1cc2754ea739d501 b/tests/gitea-repositories-meta/user2/rendering-test.git/objects/32/6ad6b850d0786dcbe128fb1cc2754ea739d501
new file mode 100644
index 0000000000..6d9a33fdcf
Binary files /dev/null and b/tests/gitea-repositories-meta/user2/rendering-test.git/objects/32/6ad6b850d0786dcbe128fb1cc2754ea739d501 differ
diff --git a/tests/gitea-repositories-meta/user2/rendering-test.git/objects/35/5dfe24938c3f06a4c5078fa3bd5f3c65c17c8f b/tests/gitea-repositories-meta/user2/rendering-test.git/objects/35/5dfe24938c3f06a4c5078fa3bd5f3c65c17c8f
new file mode 100644
index 0000000000..d275362b93
Binary files /dev/null and b/tests/gitea-repositories-meta/user2/rendering-test.git/objects/35/5dfe24938c3f06a4c5078fa3bd5f3c65c17c8f differ
diff --git a/tests/gitea-repositories-meta/user2/rendering-test.git/objects/4d/26f069992909b3ff6e52c027f781d0a9eb655c b/tests/gitea-repositories-meta/user2/rendering-test.git/objects/4d/26f069992909b3ff6e52c027f781d0a9eb655c
new file mode 100644
index 0000000000..9a2230ae80
Binary files /dev/null and b/tests/gitea-repositories-meta/user2/rendering-test.git/objects/4d/26f069992909b3ff6e52c027f781d0a9eb655c differ
diff --git a/tests/gitea-repositories-meta/user2/rendering-test.git/objects/aa/ee434b5dbfce8a1fa9a0e21e7fa4743d7d5c9a b/tests/gitea-repositories-meta/user2/rendering-test.git/objects/aa/ee434b5dbfce8a1fa9a0e21e7fa4743d7d5c9a
new file mode 100644
index 0000000000..87ff244ebb
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/rendering-test.git/objects/aa/ee434b5dbfce8a1fa9a0e21e7fa4743d7d5c9a
@@ -0,0 +1 @@
+x+)JMU047g040031QHL*ÎÏ)-IÕËL+JÌMÍ(ÉÍa¸u§Š-ýRºüÅmÇv4úýWqؼ۪<-13Y©iì?•É=ölK޲÷/Þo“z°¦ª´8#¿¨YQÖµ*rO?Ôø-s¨Ôo¹åUF¨Ú’Äc·_J~!\âx§ì{¤ŸiÏ–:ÉsõÓK
\ No newline at end of file
diff --git a/tests/gitea-repositories-meta/user2/rendering-test.git/objects/b7/d263e8137441dc76f7594e358cb47e19ce7fe1 b/tests/gitea-repositories-meta/user2/rendering-test.git/objects/b7/d263e8137441dc76f7594e358cb47e19ce7fe1
new file mode 100644
index 0000000000..02776c78f1
Binary files /dev/null and b/tests/gitea-repositories-meta/user2/rendering-test.git/objects/b7/d263e8137441dc76f7594e358cb47e19ce7fe1 differ
diff --git a/tests/gitea-repositories-meta/user2/rendering-test.git/objects/da/dc7a0667d2671fd1b6c6b8814eff2440b3bb3b b/tests/gitea-repositories-meta/user2/rendering-test.git/objects/da/dc7a0667d2671fd1b6c6b8814eff2440b3bb3b
new file mode 100644
index 0000000000..0fdf4f9019
Binary files /dev/null and b/tests/gitea-repositories-meta/user2/rendering-test.git/objects/da/dc7a0667d2671fd1b6c6b8814eff2440b3bb3b differ
diff --git a/tests/gitea-repositories-meta/user2/rendering-test.git/objects/fa/faad77cb54665ac800d1bf77e6a55bd355eabc b/tests/gitea-repositories-meta/user2/rendering-test.git/objects/fa/faad77cb54665ac800d1bf77e6a55bd355eabc
new file mode 100644
index 0000000000..e91b9e0912
Binary files /dev/null and b/tests/gitea-repositories-meta/user2/rendering-test.git/objects/fa/faad77cb54665ac800d1bf77e6a55bd355eabc differ
diff --git a/tests/gitea-repositories-meta/user2/rendering-test.git/refs/heads/master b/tests/gitea-repositories-meta/user2/rendering-test.git/refs/heads/master
new file mode 100644
index 0000000000..69d0f8e29c
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/rendering-test.git/refs/heads/master
@@ -0,0 +1 @@
+fafaad77cb54665ac800d1bf77e6a55bd355eabc
diff --git a/tests/mysql.ini.tmpl b/tests/mysql.ini.tmpl
index 055cc091c5..e50d5c4792 100644
--- a/tests/mysql.ini.tmpl
+++ b/tests/mysql.ini.tmpl
@@ -125,3 +125,11 @@ ENABLED = false
[cron.check_repo_stats]
ENABLED = false
+
+# For iframe rendering tests
+[markup.iframehtml]
+ENABLED = true
+FILE_EXTENSIONS = .iframehtml
+RENDER_COMMAND = cat
+RENDER_CONTENT_MODE = iframe
+NEED_POSTPROCESS = false
diff --git a/tests/pgsql.ini.tmpl b/tests/pgsql.ini.tmpl
index 0293817c6e..4c494941c3 100644
--- a/tests/pgsql.ini.tmpl
+++ b/tests/pgsql.ini.tmpl
@@ -139,3 +139,11 @@ ENABLED = false
[cron.check_repo_stats]
ENABLED = false
+
+# For iframe rendering tests
+[markup.iframehtml]
+ENABLED = true
+FILE_EXTENSIONS = .iframehtml
+RENDER_COMMAND = cat
+RENDER_CONTENT_MODE = iframe
+NEED_POSTPROCESS = false
diff --git a/tests/sqlite.ini.tmpl b/tests/sqlite.ini.tmpl
index 6a08bce8ea..0514c684e6 100644
--- a/tests/sqlite.ini.tmpl
+++ b/tests/sqlite.ini.tmpl
@@ -126,3 +126,11 @@ ENABLED = false
[cron.check_repo_stats]
ENABLED = false
+
+# For iframe rendering tests
+[markup.iframehtml]
+ENABLED = true
+FILE_EXTENSIONS = .iframehtml
+RENDER_COMMAND = cat
+RENDER_CONTENT_MODE = iframe
+NEED_POSTPROCESS = false