0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-03-24 23:21:57 -05:00
astro/packages/astro/test/rewrite.test.js
Emanuele Stoppa cb356a5db6
feat(i18n): expand fallback system (#11677)
* feat(i18n): expand fallback system

* rebase

* apply feedback

* better changeset

* update tests too

* apply feedback

* Update .changeset/blue-pens-divide.md

Co-authored-by: Bjorn Lu <bjornlu.dev@gmail.com>

* update docs

* nitpick

* Apply suggestions from code review

Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>

* Update .changeset/blue-pens-divide.md

Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>

* Apply suggestions from code review

Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>

* Update .changeset/blue-pens-divide.md

Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>

* fix regression

---------

Co-authored-by: Bjorn Lu <bjornlu.dev@gmail.com>
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
2024-08-28 12:16:43 +01:00

576 lines
16 KiB
JavaScript

import assert from 'node:assert/strict';
import { after, before, describe, it } from 'node:test';
import { load as cheerioLoad } from 'cheerio';
import testAdapter from './test-adapter.js';
import { loadFixture } from './test-utils.js';
describe('Dev reroute', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
let devServer;
before(async () => {
fixture = await loadFixture({
root: './fixtures/reroute/',
});
devServer = await fixture.startDevServer();
});
after(async () => {
await devServer.stop();
});
it('should render the index page when navigating /reroute ', async () => {
const html = await fixture.fetch('/reroute').then((res) => res.text());
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Index');
});
it('should render the index page when navigating /blog/hello ', async () => {
const html = await fixture.fetch('/blog/hello').then((res) => res.text());
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Index');
});
it('should render the index page when navigating /blog/salut ', async () => {
const html = await fixture.fetch('/blog/salut').then((res) => res.text());
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Index');
});
it('should render the index page when navigating dynamic route /dynamic/[id] ', async () => {
const html = await fixture.fetch('/dynamic/hello').then((res) => res.text());
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Index');
});
it('should render the index page when navigating spread route /spread/[...spread] ', async () => {
const html = await fixture.fetch('/spread/hello').then((res) => res.text());
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Index');
});
it('should return a 404', async () => {
const response = await fixture.fetch('/blog/oops');
assert.equal(response.status, 404);
});
});
describe('Dev rewrite, trailing slash -> never', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
let devServer;
before(async () => {
fixture = await loadFixture({
root: './fixtures/rewrite-trailing-slash-never/',
});
devServer = await fixture.startDevServer();
});
after(async () => {
await devServer.stop();
});
it('should rewrite to the homepage', async () => {
const html = await fixture.fetch('/foo').then((res) => res.text());
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Index');
});
});
describe('Dev rewrite, trailing slash -> never, with base', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
let devServer;
before(async () => {
fixture = await loadFixture({
root: './fixtures/rewrite-trailing-slash-never/',
base: 'base',
});
devServer = await fixture.startDevServer();
});
after(async () => {
await devServer.stop();
});
it('should rewrite to the homepage', async () => {
const html = await fixture.fetch('/base/foo').then((res) => res.text());
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Index');
});
});
describe('Dev rewrite, hybrid/server', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
let devServer;
before(async () => {
fixture = await loadFixture({
root: './fixtures/rewrite-server/',
});
devServer = await fixture.startDevServer();
});
after(async () => {
await devServer.stop();
});
it('should rewrite the [slug]/title ', async () => {
const html = await fixture.fetch('/').then((res) => res.text());
const $ = cheerioLoad(html);
assert.match($('h1').text(), /Title/);
assert.match($('p').text(), /some-slug/);
});
it('should display an error if a rewrite is attempted after the body has been consumed', async () => {
const formData = new FormData();
formData.append('email', 'example@example.com');
const request = new Request('http://example.com/post/post-body-used', {
method: 'POST',
body: formData,
});
const response = await fixture.fetch('/post/post-body-used', request);
const html = await response.text();
const $ = cheerioLoad(html);
assert.equal($('title').text(), 'RewriteWithBodyUsed');
});
});
describe('Build reroute', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
before(async () => {
fixture = await loadFixture({
root: './fixtures/reroute/',
});
await fixture.build();
});
it('should create the index page when navigating /reroute ', async () => {
const html = await fixture.readFile('/reroute/index.html');
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Index');
});
it('should create the index page when navigating /blog/hello ', async () => {
const html = await fixture.readFile('/blog/hello/index.html');
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Index');
});
it('should create the index page when navigating /blog/salut ', async () => {
const html = await fixture.readFile('/blog/salut/index.html');
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Index');
});
it('should create the index page when navigating dynamic route /dynamic/[id] ', async () => {
const html = await fixture.readFile('/dynamic/hello/index.html');
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Index');
});
it('should create the index page when navigating spread route /spread/[...spread] ', async () => {
const html = await fixture.readFile('/spread/hello/index.html');
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Index');
});
it('should create the 404 built-in page', async () => {
try {
await fixture.readFile('/spread/oops/index.html');
assert.fail('Not found');
} catch {
assert.ok;
}
});
});
describe('SSR route', () => {
it("should not build if a user tries to use rewrite('/404') in static pages", async () => {
try {
const fixture = await loadFixture({
root: './fixtures/rewrite-404-invalid/',
});
await fixture.build();
assert.fail('It should fail.');
} catch {
// it passes
assert.equal(true, true);
}
});
});
describe('SSR reroute', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
let app;
before(async () => {
fixture = await loadFixture({
root: './fixtures/reroute/',
output: 'server',
adapter: testAdapter(),
});
await fixture.build();
app = await fixture.loadTestAdapterApp();
});
it('should render the index page when navigating /reroute ', async () => {
const request = new Request('http://example.com/reroute');
const response = await app.render(request);
const html = await response.text();
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Index');
});
it('should render the index page when navigating /blog/hello ', async () => {
const request = new Request('http://example.com/blog/hello');
const response = await app.render(request);
const html = await response.text();
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Index');
});
it('should render the index page when navigating /blog/salut ', async () => {
const request = new Request('http://example.com/blog/salut');
const response = await app.render(request);
const html = await response.text();
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Index');
});
it('should render the index page when navigating dynamic route /dynamic/[id] ', async () => {
const request = new Request('http://example.com/dynamic/hello');
const response = await app.render(request);
const html = await response.text();
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Index');
});
it('should render the index page when navigating spread route /spread/[...spread] ', async () => {
const request = new Request('http://example.com/spread/hello');
const response = await app.render(request);
const html = await response.text();
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Index');
});
it('should render the 404 built-in page', async () => {
const request = new Request('http://example.com/blog/oops');
const response = await app.render(request);
assert.equal(response.status, 404);
});
it('should pass the POST data from one page to another', async () => {
const request = new Request('http://example.com/post/post-a', {
method: 'POST',
body: JSON.stringify({
email: 'example@example.com',
}),
headers: {
'content-type': 'application/json',
},
});
const response = await app.render(request);
const html = await response.text();
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Post B');
assert.match($('h2').text(), /example@example.com/);
});
});
describe('SSR rewrite, hybrid/server', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
let app;
before(async () => {
fixture = await loadFixture({
root: './fixtures/rewrite-server/',
output: 'server',
adapter: testAdapter(),
});
await fixture.build();
app = await fixture.loadTestAdapterApp();
});
it('should rewrite the [slug]/title ', async () => {
const request = new Request('http://example.com/');
const response = await app.render(request);
const html = await response.text();
const $ = cheerioLoad(html);
console.log(html);
assert.match($('h1').text(), /Title/);
assert.match($('p').text(), /some-slug/);
});
it('should return a 500 if a rewrite is attempted after the body has been read', async () => {
const formData = new FormData();
formData.append('email', 'example@example.com');
const request = new Request('http://example.com/post/post-body-used', {
method: 'POST',
body: formData,
});
const response = await app.render(request);
assert.equal(response.status, 500);
});
});
describe('Middleware', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
let devServer;
before(async () => {
fixture = await loadFixture({
root: './fixtures/reroute/',
});
devServer = await fixture.startDevServer();
});
after(async () => {
await devServer.stop();
});
it('should render a locals populated in the third middleware function, because we use next("/")', async () => {
const html = await fixture.fetch('/auth/base').then((res) => res.text());
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Index');
assert.equal($('p').text(), 'Called auth');
});
it('should NOT render locals populated in the third middleware function, because we use ctx.reroute("/")', async () => {
const html = await fixture.fetch('/auth/dashboard').then((res) => res.text());
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Index');
assert.equal($('p').text(), '');
});
it('should render the index when rewriting with params', async () => {
const html = await fixture.fetch('/auth/params').then((res) => res.text());
const $ = cheerioLoad(html);
assert.match($('h1').text(), /Index/);
});
});
describe('Middleware with custom 404.astro and 500.astro', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
let devServer;
before(async () => {
fixture = await loadFixture({
root: './fixtures/rewrite-custom-404/',
});
devServer = await fixture.startDevServer();
});
after(async () => {
await devServer.stop();
});
it('The `next()` function should return a Response with status code 404', async () => {
const html = await fixture.fetch('/about').then((res) => res.text());
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Custom error');
assert.equal($('p').text(), 'Interjected');
});
it('The `next()` function should return a Response with status code 500', async () => {
const html = await fixture.fetch('/about-2').then((res) => res.text());
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Custom error');
assert.equal($('p').text(), 'Interjected');
});
});
describe('Runtime error, default 500', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
let devServer;
before(async () => {
fixture = await loadFixture({
root: './fixtures/rewrite-runtime-error/',
});
devServer = await fixture.startDevServer();
});
after(async () => {
await devServer.stop();
});
it('should return a 500 status code, but not render the custom 500', async () => {
const response = await fixture.fetch('/errors/from');
assert.equal(response.status, 500);
const text = await response.text();
assert.match(text, /@vite\/client/);
});
});
describe('Runtime error in SSR, default 500', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
let app;
before(async () => {
fixture = await loadFixture({
root: './fixtures/rewrite-runtime-error/',
output: 'server',
adapter: testAdapter(),
});
await fixture.build();
app = await fixture.loadTestAdapterApp();
});
it('should return a 500 status code, but not render the custom 500', async () => {
const request = new Request('http://example.com/errors/from');
const response = await app.render(request);
const text = await response.text();
assert.equal(text, '');
});
});
describe('Runtime error in dev, custom 500', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
let devServer;
before(async () => {
fixture = await loadFixture({
root: './fixtures/rewrite-runtime-error-custom500/',
});
devServer = await fixture.startDevServer();
});
after(async () => {
await devServer.stop();
});
it('should render the custom 500 when rewriting a page that throws an error', async () => {
const response = await fixture.fetch('/errors/start');
assert.equal(response.status, 500);
const html = await response.text();
assert.match(html, /I am the custom 500/);
});
});
describe('Runtime error in SSR, custom 500', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
let app;
before(async () => {
fixture = await loadFixture({
root: './fixtures/rewrite-runtime-error-custom500/',
output: 'server',
adapter: testAdapter(),
});
await fixture.build();
app = await fixture.loadTestAdapterApp();
});
it('should render the custom 500 when rewriting a page that throws an error', async () => {
const request = new Request('http://example.com/errors/start');
const response = await app.render(request);
const html = await response.text();
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'I am the custom 500');
});
});
describe('Runtime error in dev, custom 500', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
let devServer;
before(async () => {
fixture = await loadFixture({
root: './fixtures/rewrite-i18n-manual-routing/',
});
devServer = await fixture.startDevServer();
});
after(async () => {
await devServer.stop();
});
it('should return a status 200 when rewriting from the middleware to the homepage', async () => {
const response = await fixture.fetch('/reroute');
assert.equal(response.status, 200);
const html = await response.text();
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Expected http status of index page is 200');
});
});
describe('Runtime error in SSR, custom 500', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
let app;
before(async () => {
fixture = await loadFixture({
root: './fixtures/rewrite-i18n-manual-routing/',
output: 'server',
adapter: testAdapter(),
});
await fixture.build();
app = await fixture.loadTestAdapterApp();
});
it('should return a status 200 when rewriting from the middleware to the homepage', async () => {
const request = new Request('http://example.com/foo');
const response = await app.render(request);
assert.equal(response.status, 200);
const html = await response.text();
const $ = cheerioLoad(html);
assert.equal($('h1').text(), 'Expected http status of index page is 200');
});
});