Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d534247c5a | ||
|
|
75e1b69342 |
+19
-21
@@ -96,9 +96,12 @@ const (
|
|||||||
// be satisfied by the fallback alone and says nothing about the message path. bound the
|
// be satisfied by the fallback alone and says nothing about the message path. bound the
|
||||||
// message-path assertions well under it
|
// message-path assertions well under it
|
||||||
revealTimeout = 5 * time.Second
|
revealTimeout = 5 * time.Second
|
||||||
// generous enough for a cold navigation on a loaded runner, and still well under the
|
// the line the three reveal cases are judged against, measured from the element's creation
|
||||||
// fallback, which is the point of the assertion
|
// and not from anything this process can time. a timer cannot fire early, so below this the
|
||||||
messageRevealBudget = 3 * time.Second
|
// reveal can only have come from the message, and above it only from the fallback. a budget
|
||||||
|
// chosen for how long an engine takes instead would be a bet on the slowest one: webkit has
|
||||||
|
// reported inited 2.6s after creation on a loaded machine
|
||||||
|
revealCutoff = revealTimeout - 500*time.Millisecond
|
||||||
)
|
)
|
||||||
|
|
||||||
// openWithBlockedIframeDoc loads the demo page with the widget document aborted, so the
|
// openWithBlockedIframeDoc loads the demo page with the widget document aborted, so the
|
||||||
@@ -242,21 +245,19 @@ func TestIframe_StaysHiddenUntilTheDocumentReportsInited(t *testing.T) {
|
|||||||
forEachEngine(t, func(t *testing.T, page playwright.Page) {
|
forEachEngine(t, func(t *testing.T, page playwright.Page) {
|
||||||
openWithBlockedIframeDoc(t, page)
|
openWithBlockedIframeDoc(t, page)
|
||||||
|
|
||||||
// unconditional: the loop below is bounded by the frame's own age, and on a slow
|
// hold for almost the whole fallback window. stopping halfway would only prove the
|
||||||
// enough load that bound can already be spent, which would leave the test asserting
|
// fallback is not shorter than that, and a widget that revealed on anything other than
|
||||||
// nothing at all about visibility
|
// `inited` would still pass
|
||||||
require.Equal(t, "hidden", iframeVisibility(t, page))
|
for iframeAge(t, page) < revealCutoff {
|
||||||
|
|
||||||
// then hold it for almost the whole fallback window. stopping halfway would only prove
|
|
||||||
// the fallback is not shorter than that, and a widget that revealed on anything other
|
|
||||||
// than `inited` would still pass. measured from the element's creation, since that is
|
|
||||||
// when the fallback it must not have used starts counting
|
|
||||||
for iframeAge(t, page) < revealTimeout-500*time.Millisecond {
|
|
||||||
require.Equal(t, "hidden", iframeVisibility(t, page))
|
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
}
|
}
|
||||||
_, revealed := revealDelay(t, page)
|
|
||||||
assert.False(t, revealed, "the frame was revealed before its document reported inited")
|
// the mark and not what is visible when the read lands: the two are separated by the
|
||||||
|
// margin above, and an evaluate round trip on a loaded engine outlasts it, which reads
|
||||||
|
// a fallback that fired exactly on time as an early reveal
|
||||||
|
delay, revealed := revealDelay(t, page)
|
||||||
|
assert.False(t, revealed && delay < revealCutoff,
|
||||||
|
"the frame was revealed %v after it was created, before its document reported inited", delay)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,7 +291,7 @@ func TestIframe_IsRevealedByTheInitedMessage(t *testing.T) {
|
|||||||
// whole 5s window without the widget being at fault
|
// whole 5s window without the widget being at fault
|
||||||
delay, ok := revealDelay(t, page)
|
delay, ok := revealDelay(t, page)
|
||||||
require.True(t, ok, "the frame reported no reveal at all")
|
require.True(t, ok, "the frame reported no reveal at all")
|
||||||
assert.Less(t, delay, messageRevealBudget,
|
assert.Less(t, delay, revealCutoff,
|
||||||
"the reveal was slow enough to have come from the fallback and not the message")
|
"the reveal was slow enough to have come from the fallback and not the message")
|
||||||
waitVisible(t, page.Locator("#remark42 iframe"))
|
waitVisible(t, page.Locator("#remark42 iframe"))
|
||||||
})
|
})
|
||||||
@@ -310,12 +311,9 @@ func TestIframe_IsRevealedByTheTimeoutWhenInitedNeverArrives(t *testing.T) {
|
|||||||
// and not before it: without a lower bound, shortening the fallback to a value that
|
// and not before it: without a lower bound, shortening the fallback to a value that
|
||||||
// defeats its purpose would still pass. against the frame's own clock, so that a slow
|
// defeats its purpose would still pass. against the frame's own clock, so that a slow
|
||||||
// navigation cannot be mistaken for the timer having run
|
// navigation cannot be mistaken for the timer having run
|
||||||
// close to the fallback and not three quarters of it: measured in the page there is
|
|
||||||
// no navigation to make room for, and a wider floor tolerates a fallback shortened
|
|
||||||
// enough to defeat its purpose
|
|
||||||
delay, ok := revealDelay(t, page)
|
delay, ok := revealDelay(t, page)
|
||||||
require.True(t, ok, "the frame reported no reveal at all")
|
require.True(t, ok, "the frame reported no reveal at all")
|
||||||
assert.Greater(t, delay, revealTimeout-500*time.Millisecond,
|
assert.Greater(t, delay, revealCutoff,
|
||||||
"the reveal came too early to have been the fallback timer")
|
"the reveal came too early to have been the fallback timer")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"regexp"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -264,3 +265,39 @@ func pauseForWebLimit() {
|
|||||||
}
|
}
|
||||||
lastWebGet = time.Now()
|
lastWebGet = time.Now()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestWeb_NoBundleHardcodesTheWebRoot pins the fix for #2203, which shipped with no test at any
|
||||||
|
// level. The bundler used to bake a fixed public path into every entry, so an instance mounted
|
||||||
|
// under a prefix, which manuals/subdomain documents, asked the domain root for its provider icons
|
||||||
|
// and got nothing. The path is derived from the URL the bundle was loaded from now, which is
|
||||||
|
// correct for both arrangements.
|
||||||
|
//
|
||||||
|
// What separates the two builds is the assignment webpack emits for its runtime public path: a
|
||||||
|
// literal when the path is fixed, and a computed value when it is derived. Asset filenames appear
|
||||||
|
// bare either way, so a case looking for a rooted "/web/name.svg" string finds nothing in either
|
||||||
|
// build and proves nothing; this asserts the assignment instead.
|
||||||
|
//
|
||||||
|
// Every emitted bundle is checked rather than the obvious one: the original defect put fifteen
|
||||||
|
// icons in remark.mjs and one in last-comments.mjs, so a case reading a single entry would have
|
||||||
|
// gone green with half of it still live.
|
||||||
|
func TestWeb_NoBundleHardcodesTheWebRoot(t *testing.T) {
|
||||||
|
names := emittedBundles(t)
|
||||||
|
require.Contains(t, names, "remark.mjs", "listing is not the served web root: %v", names)
|
||||||
|
require.Contains(t, names, "last-comments.mjs",
|
||||||
|
"the entry carrying the second half of #2203 is missing from the listing: %v", names)
|
||||||
|
|
||||||
|
// webpack writes its public path to the `p` property of the runtime object. A baked-in path
|
||||||
|
// is a string literal there; a derived one is an expression
|
||||||
|
baked := regexp.MustCompile("\\.p\\s*=\\s*[\"'`]/web/[\"'`]")
|
||||||
|
|
||||||
|
for _, name := range names {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
body := getWeb(t, "/web/"+name).body
|
||||||
|
require.NotEmpty(t, body, "%s serves nothing, so this asserts nothing", name)
|
||||||
|
|
||||||
|
assert.NotRegexp(t, baked, body,
|
||||||
|
"%s bakes the public path in rather than deriving it, so an instance mounted under "+
|
||||||
|
"a prefix fetches its assets from the domain root", name)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user