debian-mirror-gitlab/spec/frontend/streaming/render_html_streams_spec.js
2023-05-27 22:25:52 +05:30

96 lines
2.9 KiB
JavaScript

import { ReadableStream } from 'node:stream/web';
import { renderHtmlStreams } from '~/streaming/render_html_streams';
import { HtmlStream } from '~/streaming/html_stream';
import waitForPromises from 'helpers/wait_for_promises';
jest.mock('~/streaming/html_stream');
jest.mock('~/streaming/constants', () => {
return {
HIGH_FRAME_TIME: 0,
LOW_FRAME_TIME: 0,
MAX_CHUNK_SIZE: 1,
MIN_CHUNK_SIZE: 1,
};
});
const firstStreamContent = 'foobar';
const secondStreamContent = 'bazqux';
describe('renderHtmlStreams', () => {
let htmlWriter;
const encoder = new TextEncoder();
const createSingleChunkStream = (chunk) => {
const encoded = encoder.encode(chunk);
const stream = new ReadableStream({
pull(controller) {
controller.enqueue(encoded);
controller.close();
},
});
return [stream, encoded];
};
beforeEach(() => {
htmlWriter = {
write: jest.fn(),
close: jest.fn(),
abort: jest.fn(),
};
jest.spyOn(HtmlStream.prototype, 'withChunkWriter').mockReturnValue(htmlWriter);
});
it('renders a single stream', async () => {
const [stream, encoded] = createSingleChunkStream(firstStreamContent);
await renderHtmlStreams([Promise.resolve(stream)], document.body);
expect(htmlWriter.write).toHaveBeenCalledWith(encoded);
expect(htmlWriter.close).toHaveBeenCalledTimes(1);
});
it('renders stream sequence', async () => {
const [stream1, encoded1] = createSingleChunkStream(firstStreamContent);
const [stream2, encoded2] = createSingleChunkStream(secondStreamContent);
await renderHtmlStreams([Promise.resolve(stream1), Promise.resolve(stream2)], document.body);
expect(htmlWriter.write.mock.calls).toMatchObject([[encoded1], [encoded2]]);
expect(htmlWriter.close).toHaveBeenCalledTimes(1);
});
it("doesn't wait for the whole sequence to resolve before streaming", async () => {
const [stream1, encoded1] = createSingleChunkStream(firstStreamContent);
const [stream2, encoded2] = createSingleChunkStream(secondStreamContent);
let res;
const delayedStream = new Promise((resolve) => {
res = resolve;
});
renderHtmlStreams([Promise.resolve(stream1), delayedStream], document.body);
await waitForPromises();
expect(htmlWriter.write.mock.calls).toMatchObject([[encoded1]]);
expect(htmlWriter.close).toHaveBeenCalledTimes(0);
res(stream2);
await waitForPromises();
expect(htmlWriter.write.mock.calls).toMatchObject([[encoded1], [encoded2]]);
expect(htmlWriter.close).toHaveBeenCalledTimes(1);
});
it('closes HtmlStream on error', async () => {
const [stream1] = createSingleChunkStream(firstStreamContent);
const error = new Error();
try {
await renderHtmlStreams([Promise.resolve(stream1), Promise.reject(error)], document.body);
} catch (err) {
expect(err).toBe(error);
}
expect(htmlWriter.abort).toHaveBeenCalledTimes(1);
});
});