0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-02-03 22:29:08 -05:00
astro/packages/astro/test/streaming.test.js
Matthew Phillips 749a7ac967
Fix streaming in Node.js fast path (#11058)
* Fix streaming in Node.js fast path

* Create a new next if the iterator is not done

* Use a flag instead

* Update test

* Add new assertion

* Add explanation of the renderingComplete variable

* Remove flaky assertion
2024-05-16 12:36:28 -04:00

156 lines
4.2 KiB
JavaScript

import assert from 'node:assert/strict';
import { after, before, describe, it } from 'node:test';
import * as cheerio from 'cheerio';
import testAdapter from './test-adapter.js';
import { loadFixture, streamAsyncIterator } from './test-utils.js';
describe('Streaming', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
let decoder = new TextDecoder();
before(async () => {
fixture = await loadFixture({
root: './fixtures/streaming/',
adapter: testAdapter(),
output: 'server',
});
});
describe('Development', () => {
/** @type {import('./test-utils').DevServer} */
let devServer;
before(async () => {
devServer = await fixture.startDevServer();
});
after(async () => {
await devServer.stop();
});
it('Body is chunked', async () => {
let res = await fixture.fetch('/');
let chunks = [];
for await (const bytes of streamAsyncIterator(res.body)) {
let chunk = decoder.decode(bytes);
chunks.push(chunk);
}
assert.equal(chunks.length > 5, true);
});
it('Body of slots is chunked', async () => {
let res = await fixture.fetch('/slot');
let chunks = [];
for await (const bytes of streamAsyncIterator(res.body)) {
let chunk = decoder.decode(bytes);
chunks.push(chunk);
}
assert.ok(chunks.length >= 2);
});
});
describe('Production', () => {
before(async () => {
await fixture.build();
});
it('Can get the full html body', async () => {
const app = await fixture.loadTestAdapterApp();
const request = new Request('http://example.com/');
const response = await app.render(request);
const html = await response.text();
const $ = cheerio.load(html);
assert.equal($('header h1').length, 1);
assert.equal($('ul li').length, 10);
});
it('Body is chunked', async () => {
const app = await fixture.loadTestAdapterApp();
const request = new Request('http://example.com/');
const response = await app.render(request);
let chunks = [];
for await (const bytes of streamAsyncIterator(response.body)) {
let chunk = decoder.decode(bytes);
chunks.push(chunk);
}
assert.equal(chunks.length > 1, true);
});
// if the offshoot promise goes unhandled, this test will pass immediately but fail the test suite
it('Stays alive on failed component renders initiated by failed render templates', async () => {
const app = await fixture.loadTestAdapterApp();
const request = new Request('http://example.com/multiple-errors');
const response = await app.render(request);
assert.equal(response.status, 500);
const text = await response.text();
assert.equal(text, '');
});
});
});
describe('Streaming disabled', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
before(async () => {
fixture = await loadFixture({
root: './fixtures/streaming/',
adapter: testAdapter(),
output: 'server',
server: {
streaming: false,
},
});
});
describe('Development', () => {
/** @type {import('./test-utils').DevServer} */
let devServer;
before(async () => {
devServer = await fixture.startDevServer();
});
after(async () => {
await devServer.stop();
});
it('Body is chunked', async () => {
let res = await fixture.fetch('/');
let chunks = [];
for await (const bytes of streamAsyncIterator(res.body)) {
let chunk = bytes.toString('utf-8');
chunks.push(chunk);
}
assert.equal(chunks.length > 1, true);
});
});
// TODO: find a different solution for the test-adapter,
// currently there's no way to resolve two different versions with one
// having streaming disabled
describe('Production', () => {
before(async () => {
await fixture.build();
});
it('Can get the full html body', async () => {
const app = await fixture.loadTestAdapterApp(false);
const request = new Request('http://example.com/');
const response = await app.render(request);
assert.equal(response.status, 200);
assert.equal(response.headers.get('content-type'), 'text/html');
assert.equal(response.headers.has('content-length'), true);
assert.equal(parseInt(response.headers.get('content-length')) > 0, true);
const html = await response.text();
const $ = cheerio.load(html);
assert.equal($('header h1').length, 1);
assert.equal($('ul li').length, 10);
});
});
});