-
Notifications
You must be signed in to change notification settings - Fork 516
fix: fix failing CI/CD on dev branch #1473
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e4cfba7
8cbe5db
bfab68f
b056d92
05ccfee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,34 @@ import { StackClientApp } from "@stackframe/js"; | |
| import { afterEach, vi } from "vitest"; | ||
| import { it, localRedirectUrl } from "../helpers"; | ||
|
|
||
| function createMockDocument(): Document { | ||
| const cookieJar = new Map<string, string>(); | ||
| return { | ||
| get cookie() { | ||
| return [...cookieJar.entries()].map(([k, v]) => `${k}=${v}`).join('; '); | ||
| }, | ||
| set cookie(str: string) { | ||
| const parts = str.split(';'); | ||
| const [nameValue] = parts; | ||
| const eqIndex = nameValue.indexOf('='); | ||
| if (eqIndex >= 0) { | ||
| const name = nameValue.slice(0, eqIndex).trim(); | ||
| const isExpired = parts.some(p => { | ||
| const trimmed = p.trim().toLowerCase(); | ||
| if (!trimmed.startsWith('expires=')) return false; | ||
| return new Date(trimmed.slice('expires='.length)) <= new Date(); | ||
| }); | ||
| if (isExpired) { | ||
| cookieJar.delete(name); | ||
| } else { | ||
| cookieJar.set(name, nameValue.slice(eqIndex + 1).trim()); | ||
| } | ||
| } | ||
| }, | ||
| createElement: () => ({}), | ||
| } as any; | ||
|
Comment on lines
+5
to
+30
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The Prompt To Fix With AIThis is a comment left during a code review.
Path: apps/e2e/tests/js/cross-domain-auth.test.ts
Line: 5-19
Comment:
**Cookie deletion not supported in mock**
The `createMockDocument` setter only handles writing cookies but never removes them: if any code path under test calls `document.cookie = "name=; expires=Thu, 01 Jan 1970 00:00:00 GMT"` (the standard deletion pattern), the mock will silently store an empty string value instead of evicting the key. This won't break the two tests being fixed here, but the same mock is now shared infrastructure — any future test that relies on cookie expiry/deletion will see stale values and get a confusing false-positive pass.
How can I resolve this? If you propose a fix, please make it concise.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Addressed in 8cbe5db — the setter now parses |
||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| const withHostedDomainSuffix = async (callback: () => Promise<void>) => { | ||
| const oldHostedHandlerDomainSuffix = process.env.NEXT_PUBLIC_STACK_HOSTED_HANDLER_DOMAIN_SUFFIX; | ||
| const oldHostedHandlerUrlTemplate = process.env.NEXT_PUBLIC_STACK_HOSTED_HANDLER_URL_TEMPLATE; | ||
|
|
@@ -48,7 +76,7 @@ it("adds secure cross-domain handoff parameters when redirecting to hosted sign- | |
| const previousDocument = globalThis.document; | ||
| let redirectedUrl = ""; | ||
|
|
||
| globalThis.document = { cookie: "", createElement: () => ({}) } as any; | ||
| globalThis.document = createMockDocument(); | ||
| globalThis.window = { | ||
| location: { | ||
| href: `${localRedirectUrl}/private-page?foo=bar`, | ||
|
|
@@ -90,7 +118,7 @@ it("returns static app.urls.signIn for hosted flows", async ({ expect }) => { | |
|
|
||
| const previousWindow = globalThis.window; | ||
| const previousDocument = globalThis.document; | ||
| globalThis.document = { cookie: "", createElement: () => ({}) } as any; | ||
| globalThis.document = createMockDocument(); | ||
| globalThis.window = { | ||
| location: { | ||
| href: currentHref, | ||
|
|
@@ -121,7 +149,7 @@ it("returns static app.urls.signOut for hosted flows", async ({ expect }) => { | |
|
|
||
| const previousWindow = globalThis.window; | ||
| const previousDocument = globalThis.document; | ||
| globalThis.document = { cookie: "", createElement: () => ({}) } as any; | ||
| globalThis.document = createMockDocument(); | ||
| globalThis.window = { | ||
| location: { | ||
| href: currentHref, | ||
|
|
@@ -156,7 +184,7 @@ it("strips stale OAuth callback params from hosted current-page redirect URIs", | |
| currentUrl.searchParams.set("message", "Known message"); | ||
| currentUrl.searchParams.set("details", "{}"); | ||
|
|
||
| globalThis.document = { cookie: "", createElement: () => ({}) } as any; | ||
| globalThis.document = createMockDocument(); | ||
| globalThis.window = { | ||
| location: { | ||
| href: currentUrl.toString(), | ||
|
|
@@ -178,7 +206,7 @@ it("only treats hosted OAuth callback URLs as Stack callbacks when the matching | |
| const previousWindow = globalThis.window; | ||
| const previousDocument = globalThis.document; | ||
|
|
||
| globalThis.document = { cookie: "", createElement: () => ({}) } as any; | ||
| globalThis.document = createMockDocument(); | ||
| globalThis.window = { | ||
| location: { | ||
| href: `${localRedirectUrl}/callback-page?code=oauth-code&state=oauth-state`, | ||
|
|
@@ -221,7 +249,7 @@ it("does not await pending auth resolutions when post-callback redirect mints a | |
| redirectBackUrl.searchParams.set("stack_cross_domain_auth", "1"); | ||
| redirectBackUrl.searchParams.set("stack_cross_domain_state", "state"); | ||
| redirectBackUrl.searchParams.set("stack_cross_domain_code_challenge", "challenge"); | ||
| redirectBackUrl.searchParams.set("stack_cross_domain_after_callback_redirect_url", `${localRedirectUrl}/after`); | ||
| redirectBackUrl.searchParams.set("stack_cross_domain_after_callback_redirect_url", `https://${projectId}.example-stack-hosted.test/after`); | ||
| currentUrl.searchParams.set("after_auth_return_to", redirectBackUrl.toString()); | ||
|
|
||
| const previousWindow = globalThis.window; | ||
|
|
@@ -230,7 +258,7 @@ it("does not await pending auth resolutions when post-callback redirect mints a | |
| .spyOn(clientApp as any, "_createCrossDomainAuthRedirectUrl") | ||
| .mockResolvedValue(`https://${projectId}.example-stack-hosted.test/handler/final`); | ||
|
|
||
| globalThis.document = { cookie: "", createElement: () => ({}) } as any; | ||
| globalThis.document = createMockDocument(); | ||
| globalThis.window = { | ||
| location: { | ||
| href: currentUrl.toString(), | ||
|
|
@@ -271,7 +299,7 @@ it("does not await pending auth resolutions when post-callback redirect adds nes | |
|
|
||
| const previousWindow = globalThis.window; | ||
| const previousDocument = globalThis.document; | ||
| globalThis.document = { cookie: "", createElement: () => ({}) } as any; | ||
| globalThis.document = createMockDocument(); | ||
| globalThis.window = { | ||
| location: { | ||
| href: `${localRedirectUrl}/callback-page`, | ||
|
|
@@ -326,7 +354,7 @@ it("keeps cross-domain handoff working when top-level params are dropped before | |
| .spyOn(clientApp as any, "_createCrossDomainAuthRedirectUrl") | ||
| .mockResolvedValue(crossDomainAuthorizeRedirect); | ||
|
|
||
| globalThis.document = { cookie: "", createElement: () => ({}) } as any; | ||
| globalThis.document = createMockDocument(); | ||
| globalThis.window = { | ||
| location: { | ||
| href: hostedAfterSignInCallbackUrl.toString(), | ||
|
|
@@ -382,7 +410,7 @@ it("keeps cross-domain handoff working when after_auth_return_to is rewritten to | |
| .spyOn(clientApp as any, "_createCrossDomainAuthRedirectUrl") | ||
| .mockResolvedValue(crossDomainAuthorizeRedirect); | ||
|
|
||
| globalThis.document = { cookie: "", createElement: () => ({}) } as any; | ||
| globalThis.document = createMockDocument(); | ||
| globalThis.window = { | ||
| location: { | ||
| href: hostedAfterSignInCallbackUrl.toString(), | ||
|
|
@@ -423,7 +451,7 @@ it("adds nested cross-domain auth params when redirecting signed-in users to hos | |
| const previousWindow = globalThis.window; | ||
| const previousDocument = globalThis.document; | ||
| let redirectedUrl = ""; | ||
| globalThis.document = { cookie: "", createElement: () => ({}) } as any; | ||
| globalThis.document = createMockDocument(); | ||
| globalThis.window = { | ||
| location: { | ||
| href: currentHref, | ||
|
|
@@ -461,7 +489,7 @@ it("adds nested cross-domain auth params for other cross-domain handler redirect | |
| const previousWindow = globalThis.window; | ||
| const previousDocument = globalThis.document; | ||
| let redirectedUrl = ""; | ||
| globalThis.document = { cookie: "", createElement: () => ({}) } as any; | ||
| globalThis.document = createMockDocument(); | ||
| globalThis.window = { | ||
| location: { | ||
| href: currentHref, | ||
|
|
@@ -502,7 +530,7 @@ it("starts nested cross-domain auth from the target domain", async ({ expect }) | |
| codeChallenge: "nested-code-challenge", | ||
| }); | ||
|
|
||
| globalThis.document = { cookie: "", createElement: () => ({}) } as any; | ||
| globalThis.document = createMockDocument(); | ||
| globalThis.window = { | ||
| location: { | ||
| href: currentHref, | ||
|
|
@@ -554,7 +582,7 @@ it("continues nested cross-domain auth on the source domain", async ({ expect }) | |
| .mockResolvedValue(crossDomainRedirect); | ||
| vi.spyOn(clientApp as any, "_getCurrentRefreshTokenIdIfSignedIn").mockResolvedValue(sourceRefreshTokenId); | ||
|
|
||
| globalThis.document = { cookie: "", createElement: () => ({}) } as any; | ||
| globalThis.document = createMockDocument(); | ||
| globalThis.window = { | ||
| location: { | ||
| href: currentUrl.toString(), | ||
|
|
@@ -598,7 +626,7 @@ it("rejects nested cross-domain auth when the source redirect URI is untrusted", | |
| const createCrossDomainAuthRedirectUrlSpy = vi.spyOn(clientApp as any, "_createCrossDomainAuthRedirectUrl"); | ||
| vi.spyOn(clientApp as any, "_isTrusted").mockResolvedValue(false); | ||
|
|
||
| globalThis.document = { cookie: "", createElement: () => ({}) } as any; | ||
| globalThis.document = createMockDocument(); | ||
| globalThis.window = { | ||
| location: { | ||
| href: currentUrl.toString(), | ||
|
|
@@ -627,7 +655,7 @@ it("rejects nested cross-domain auth when the callback URL is untrusted", async | |
| vi.spyOn(clientApp as any, "_getCurrentRefreshTokenIdIfSignedIn").mockResolvedValue(null); | ||
| vi.spyOn(clientApp as any, "_isTrusted").mockResolvedValue(false); | ||
|
|
||
| globalThis.document = { cookie: "", createElement: () => ({}) } as any; | ||
| globalThis.document = createMockDocument(); | ||
| globalThis.window = { | ||
| location: { | ||
| href: currentHref, | ||
|
|
@@ -658,7 +686,7 @@ it("rejects nested cross-domain auth when the source session does not match", as | |
| const createCrossDomainAuthRedirectUrlSpy = vi.spyOn(clientApp as any, "_createCrossDomainAuthRedirectUrl"); | ||
| vi.spyOn(clientApp as any, "_getCurrentRefreshTokenIdIfSignedIn").mockResolvedValue("different-source-session"); | ||
|
|
||
| globalThis.document = { cookie: "", createElement: () => ({}) } as any; | ||
| globalThis.document = createMockDocument(); | ||
| globalThis.window = { | ||
| location: { | ||
| href: currentUrl.toString(), | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.