Repository: sveltejs/kit (js)

Issue:
Redirect in action does not respect status code
### Describe the bug

If a form action redirects, the status code passed into `redirect(status, location)` is always replaced with `303`. 

### Reproduction

https://stackblitz.com/edit/sveltejs-kit-template-default-cq96ae?file=src/routes/+page.server.js

Click the button and look at the console logs. You'll see a 303 redirect even though we passed in "302".

### Logs

```Shell
Status code: 200
Status code: 303
Status code: 200
```


### System Info

```Shell
System:
    OS: macOS 13.0.1
    CPU: (10) arm64 Apple M1 Pro
    Memory: 62.42 MB / 32.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 18.9.0 - /opt/homebrew/bin/node
    Yarn: 1.22.19 - ~/.yarn/bin/yarn
    npm: 9.1.3 - /opt/homebrew/bin/npm
  Browsers:
    Chrome: 108.0.5359.124
    Safari: 16.1
  npmPackages:
    @sveltejs/adapter-auto: ^1.0.0 => 1.0.0
    @sveltejs/kit: ^1.0.0 => 1.0.1
    svelte: ^3.54.0 => 3.55.0
    vite: ^4.0.0 => 4.0.1
```


### Severity

serious, but I can work around it

### Additional Information

I'm guessing this isn't a big deal for most of the client rendered apps out there. But if there are any server rendered apps that rely on non-303 redirects from a form action, e.g. a Permanent redirect, this will be important.

Pull request:
[fix] redirects from actions don't honor the provided status code
Fixes #8209 

### Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
- [x] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
- [x] This message body should clearly illustrate what problems it solves.
- [x] Ideally, include a test that fails without this PR but passes with it.

### Tests
- [x] Run the tests with `pnpm test` and lint the project with `pnpm lint` and `pnpm check`

### Changesets
- [x] If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpm changeset` and following the prompts. All changesets should be `patch` until SvelteKit 1.0


Patch:
diff --git a/.changeset/rare-frogs-crash.md b/.changeset/rare-frogs-crash.md
new file mode 100644
index 000000000..cf0bec2f5
--- /dev/null
+++ b/.changeset/rare-frogs-crash.md
@@ -0,0 +1,5 @@
+---
+"create-svelte": patch
+---
+
+[fix] address flakiness in playwright test
diff --git a/.changeset/tidy-pandas-report.md b/.changeset/tidy-pandas-report.md
new file mode 100644
index 000000000..d328468ff
--- /dev/null
+++ b/.changeset/tidy-pandas-report.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+Fix form action redirect status code
diff --git a/documentation/docs/20-core-concepts/20-load.md b/documentation/docs/20-core-concepts/20-load.md
index 91d244c16..0e7b5ede3 100644
--- a/documentation/docs/20-core-concepts/20-load.md
+++ b/documentation/docs/20-core-concepts/20-load.md
@@ -421,7 +421,7 @@ export function load({ locals }) {
 Top-level promises will be awaited, which makes it easy to return multiple promises without creating a waterfall:
 
 ```js
-/// file: src/routes/+page.server.js
+/// file: src/routes/+page.js
 /** @type {import('./$types').PageServerLoad} */
 export function load() {
 	return {
diff --git a/packages/kit/src/runtime/server/page/index.js b/packages/kit/src/runtime/server/page/index.js
index 84c712d4f..463e72d01 100644
--- a/packages/kit/src/runtime/server/page/index.js
+++ b/packages/kit/src/runtime/server/page/index.js
@@ -62,7 +62,7 @@ export async function render_page(event, route, page, options, state, resolve_op
 			// (this also determines status code)
 			action_result = await handle_action_request(event, leaf_node.server);
 			if (action_result?.type === 'redirect') {
-				return redirect_response(303, action_result.location);
+				return redirect_response(action_result.status, action_result.location);
 			}
 			if (action_result?.type === 'error') {
 				const error = action_result.error;
diff --git a/sites/kit.svelte.dev/src/routes/home/Svelte.svelte b/sites/kit.svelte.dev/src/routes/home/Svelte.svelte
index fa07bcb5e..7f0b44d4c 100644
--- a/sites/kit.svelte.dev/src/routes/home/Svelte.svelte
+++ b/sites/kit.svelte.dev/src/routes/home/Svelte.svelte
@@ -28,9 +28,7 @@
 			<p>
 				SvelteKit is built on Svelte, a UI framework that uses a compiler to let you write
 				breathtakingly concise components that do minimal work in the browser, using languages you
-				already know — HTML, CSS and JavaScript. <strong style="color: var(--sk-theme-2)"
-					>It's a love letter to web development.</strong
-				>
+				already know — HTML, CSS and JavaScript. <strong>It's a love letter to web development.</strong>
 			</p>
 
 			<p>


Test patch:
diff --git a/packages/create-svelte/shared/+playwright+default/tests/test.ts b/packages/create-svelte/shared/+playwright+default/tests/test.ts
index c104fe8eb..38b7f95bd 100644
--- a/packages/create-svelte/shared/+playwright+default/tests/test.ts
+++ b/packages/create-svelte/shared/+playwright+default/tests/test.ts
@@ -2,5 +2,5 @@ import { expect, test } from '@playwright/test';
 
 test('about page has expected h1', async ({ page }) => {
 	await page.goto('/about');
-	expect(await page.textContent('h1')).toBe('About this app');
+	await expect(page.locator('h1')).toHaveText('About this app');
 });
diff --git a/packages/kit/test/apps/basics/test/test.js b/packages/kit/test/apps/basics/test/test.js
index 0193fbbad..0a8476d16 100644
--- a/packages/kit/test/apps/basics/test/test.js
+++ b/packages/kit/test/apps/basics/test/test.js
@@ -2010,12 +2010,25 @@ test.describe('Actions', () => {
 		);
 	});
 
-	test('redirect', async ({ page }) => {
+	test('redirect', async ({ page, javaScriptEnabled }) => {
 		await page.goto('/actions/redirect');
 
 		page.click('button');
 
-		await Promise.all([page.waitForResponse('/actions/redirect'), page.waitForNavigation()]);
+		const [redirect] = await Promise.all([
+			page.waitForResponse('/actions/redirect'),
+			page.waitForNavigation()
+		]);
+		if (javaScriptEnabled) {
+			expect(await redirect.json()).toEqual({
+				type: 'redirect',
+				location: '/actions/enhance',
+				status: 303
+			});
+		} else {
+			expect(redirect.status()).toBe(303);
+			expect(redirect.headers()['location']).toBe('/actions/enhance');
+		}
 
 		expect(page.url()).toContain('/actions/enhance');
 	});