mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-10-19 02:43:18 +00:00
fix: use scrollHeight
for rendered iframe if offsetHeight
is unavailable (#9508)
Fixes #9421. Added integration test. Co-authored-by: Gusted <postmaster@gusted.xyz> Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/9508 Reviewed-by: Gusted <gusted@noreply.codeberg.org> Reviewed-by: Michael Kriese <michael.kriese@gmx.de> Co-authored-by: Bojidar Marinov <bojidar.marinov.bg@gmail.com> Co-committed-by: Bojidar Marinov <bojidar.marinov.bg@gmail.com>
This commit is contained in:
parent
e56fdf1ec5
commit
8ed95dc4c6
22 changed files with 125 additions and 6 deletions
|
@ -1921,4 +1921,3 @@
|
|||
is_fsck_enabled: true
|
||||
close_issues_via_commit_in_any_branch: false
|
||||
topics: '[]'
|
||||
|
||||
|
|
|
@ -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("<script>{let postHeight = () => {window.parent.postMessage({frameHeight: document.documentElement.offsetHeight}, '*')}; window.addEventListener('load', postHeight); window.addEventListener('message', (event) => {if (event.source === window.parent && event.data.requestOffsetHeight) postHeight()});}</script>"))
|
||||
_, _ = pw.Write([]byte("<script>{let postHeight = () => {window.parent.postMessage({frameHeight: document.documentElement.offsetHeight || document.documentElement.scrollHeight}, '*')}; window.addEventListener('load', postHeight); window.addEventListener('message', (event) => {if (event.source === window.parent && event.data.requestOffsetHeight) postHeight()});}</script>"))
|
||||
}
|
||||
_ = pw.Close()
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
6
tests/e2e/fixtures/repo_unit.yml
Normal file
6
tests/e2e/fixtures/repo_unit.yml
Normal file
|
@ -0,0 +1,6 @@
|
|||
-
|
||||
id: 1001
|
||||
repo_id: 1002
|
||||
type: 1
|
||||
config: "{}"
|
||||
created_unix: 946684810
|
|
@ -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: '[]'
|
||||
|
|
61
tests/e2e/rendering-iframe.test.e2e.ts
Normal file
61
tests/e2e/rendering-iframe.test.e2e.ts
Normal file
|
@ -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);
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
ref: refs/heads/master
|
|
@ -0,0 +1,4 @@
|
|||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = true
|
|
@ -0,0 +1 @@
|
|||
Unnamed repository; edit this file 'description' to name the repository.
|
|
@ -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]
|
||||
# *~
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
x+)JMU047g040031QHL*но)-IукL+JлMм(имa╦u╖┼-ЩR╨Эеmгv4ЗЩWqь╪ш╙<-13Y╘iЛ?∙и=ЖlK▌╡В/чo⌠z╟╕╙╢8#©╗Y╜Qж╣*rO?тЬ-s╗тo╧ЕUF╗з▓дc╥_J~!\Бx╖Л{╓÷iо√:иsУсK
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
fafaad77cb54665ac800d1bf77e6a55bd355eabc
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue