Skip to content
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

Update single fetch headers approach to use response stub API #9142

Merged
merged 12 commits into from
Mar 27, 2024
Prev Previous commit
Next Next commit
Switch to proxied headers approach
  • Loading branch information
brophdawg11 committed Mar 26, 2024
commit 392ab0f7d908ae0a19e7ec8e2192f015f6282680
113 changes: 112 additions & 1 deletion integration/single-fetch-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ test.describe("single-fetch", () => {
expect(urls).toEqual([]);
});

test("merges headers correctly for loader and action calls", async () => {
test("returns headers correctly for singular loader and action calls", async () => {
let fixture = await createFixture({
config: {
future: {
Expand Down Expand Up @@ -500,6 +500,117 @@ test.describe("single-fetch", () => {
expect(dataResponse.headers.get("x-action-error")).toEqual("true");
});

test("merges headers from nested route loaders", async () => {
let fixture = await createFixture({
config: {
future: {
unstable_singleFetch: true,
},
},
files: {
...files,
"app/routes/a.tsx": js`
export function loader({ request, response }) {
response.headers.set('x-one', 'a set');
response.headers.append('x-one', 'a append');
response.headers.set('x-two', 'a set');
response.headers.append('x-three', 'a append');
response.headers.set('x-four', 'a set');
return null;
}

export default function Comp() {
return null;
}
`,
"app/routes/a.b.tsx": js`
export function loader({ request, response }) {
response.headers.set('x-one', 'b set');
response.headers.append('x-one', 'b append');
response.headers.set('x-two', 'b set');
response.headers.append('x-three', 'b append');
response.headers.delete('x-four');
return null;
}

export default function Comp() {
return null;
}
`,
"app/routes/a.b.c.tsx": js`
export function loader({ request, response }) {
response.headers.set('x-one', 'c set');
response.headers.append('x-one', 'c append');
response.headers.set('x-two', 'c set');
response.headers.append('x-three', 'c append');
return null;
}

export default function Comp() {
return null;
}
`,
},
});

// x-one used both set and append
// x-two only uses set
// x-three only uses append
// x-four deletes
async function assertHeaders(
method: "requestDocument" | "requestSingleFetchData"
) {
let res = await fixture[method]("/a.data");
expect(res.headers.get("x-one")).toEqual("a set, a append");
expect(res.headers.get("x-two")).toEqual("a set");
expect(res.headers.get("x-three")).toEqual("a append");
expect(res.headers.get("x-four")).toEqual("a set");

res = await fixture[method]("/a/b.data");
expect(res.headers.get("x-one")).toEqual("b set, b append");
expect(res.headers.get("x-two")).toEqual("b set");
expect(res.headers.get("x-three")).toEqual("a append, b append");
expect(res.headers.get("x-four")).toEqual(null);

res = await fixture[method]("/a/b/c.data");
expect(res.headers.get("x-one")).toEqual("c set, c append");
expect(res.headers.get("x-two")).toEqual("c set");
expect(res.headers.get("x-three")).toEqual(
"a append, b append, c append"
);
expect(res.headers.get("x-four")).toEqual(null);

res = await fixture[method]("/a/b/c.data?_routes=routes%2Fa");
expect(res.headers.get("x-one")).toEqual("a set, a append");
expect(res.headers.get("x-two")).toEqual("a set");
expect(res.headers.get("x-three")).toEqual("a append");
expect(res.headers.get("x-four")).toEqual("a set");

res = await fixture[method]("/a/b.data?_routes=routes%2Fa,routes%2Fa.b");
expect(res.headers.get("x-one")).toEqual("b set, b append");
expect(res.headers.get("x-two")).toEqual("b set");
expect(res.headers.get("x-three")).toEqual("a append, b append");
expect(res.headers.get("x-four")).toEqual(null);

res = await fixture[method]("/a/b/c.data?_routes=routes%2Fa.b.c");
expect(res.headers.get("x-one")).toEqual("c set, c append");
expect(res.headers.get("x-two")).toEqual("c set");
expect(res.headers.get("x-three")).toEqual("c append");
expect(res.headers.get("x-four")).toEqual(null);

res = await fixture[method](
"/a/b/c.data?_routes=routes%2Fa,routes%2Fa.b.c"
);
expect(res.headers.get("x-one")).toEqual("c set, c append");
expect(res.headers.get("x-two")).toEqual("c set");
expect(res.headers.get("x-three")).toEqual("a append, c append");
expect(res.headers.get("x-four")).toEqual("a set");
}

assertHeaders("requestDocument");
assertHeaders("requestSingleFetchData");
});

test("processes loader redirects", async ({ page }) => {
let fixture = await createFixture({
config: {
Expand Down
12 changes: 8 additions & 4 deletions packages/remix-server-runtime/routeModules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,20 @@ export type DataFunctionArgs = RRActionFunctionArgs<AppLoadContext> &
context: AppLoadContext;
};

export const ResponseStubSymbol = Symbol("ResponseStub");

export const ResponseStubOperationsSymbol = Symbol("ResponseStubOperations");
export type ResponseStubOperation = [
"set" | "append" | "delete",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only track "write" operations

string,
string?
];
/**
* A stubbed response to let you set the status/headers of your response from
* loader/action functions
*/
export type ResponseStub = {
status: number;
status: number | undefined;
headers: Headers;
[ResponseStubSymbol]: boolean;
[ResponseStubOperationsSymbol]: ResponseStubOperation[];
};

/**
Expand Down
Loading