aboutsummaryrefslogtreecommitdiff
path: root/packages/astro/test/units/render/head.test.js
diff options
context:
space:
mode:
Diffstat (limited to 'packages/astro/test/units/render/head.test.js')
-rw-r--r--packages/astro/test/units/render/head.test.js244
1 files changed, 244 insertions, 0 deletions
diff --git a/packages/astro/test/units/render/head.test.js b/packages/astro/test/units/render/head.test.js
new file mode 100644
index 000000000..4c4a9eb77
--- /dev/null
+++ b/packages/astro/test/units/render/head.test.js
@@ -0,0 +1,244 @@
+import * as assert from 'node:assert/strict';
+import { before, describe, it } from 'node:test';
+import * as cheerio from 'cheerio';
+import { RenderContext } from '../../../dist/core/render-context.js';
+import {
+ Fragment,
+ createComponent,
+ maybeRenderHead,
+ render,
+ renderComponent,
+ renderHead,
+ renderSlot,
+} from '../../../dist/runtime/server/index.js';
+import { createBasicPipeline } from '../test-utils.js';
+
+const createAstroModule = (AstroComponent) => ({ default: AstroComponent });
+
+describe('core/render', () => {
+ describe('Injected head contents', () => {
+ let pipeline;
+ before(async () => {
+ pipeline = createBasicPipeline();
+ pipeline.headElements = () => ({
+ links: new Set([
+ { name: 'link', props: { rel: 'stylesheet', href: '/main.css' }, children: '' },
+ ]),
+ scripts: new Set(),
+ styles: new Set(),
+ });
+ });
+
+ it('Multi-level layouts and head injection, with explicit head', async () => {
+ const BaseLayout = createComponent((result, _props, slots) => {
+ return render`<html>
+ <head>
+ ${renderSlot(result, slots['head'])}
+ ${renderHead(result)}
+ </head>
+ ${maybeRenderHead(result)}
+ <body>
+ ${renderSlot(result, slots['default'])}
+ </body>
+ </html>`;
+ });
+
+ const PageLayout = createComponent((result, _props, slots) => {
+ return render`${renderComponent(
+ result,
+ 'Layout',
+ BaseLayout,
+ {},
+ {
+ default: () => render`
+ ${maybeRenderHead(result)}
+ <main>
+ ${renderSlot(result, slots['default'])}
+ </main>
+ `,
+ head: () => render`
+ ${renderComponent(
+ result,
+ 'Fragment',
+ Fragment,
+ { slot: 'head' },
+ {
+ default: () => render`${renderSlot(result, slots['head'])}`,
+ },
+ )}
+ `,
+ },
+ )}
+ `;
+ });
+
+ const Page = createComponent((result) => {
+ return render`${renderComponent(
+ result,
+ 'PageLayout',
+ PageLayout,
+ {},
+ {
+ default: () => render`${maybeRenderHead(result)}<div>hello world</div>`,
+ head: () => render`
+ ${renderComponent(
+ result,
+ 'Fragment',
+ Fragment,
+ { slot: 'head' },
+ {
+ default: () => render`<meta charset="utf-8">`,
+ },
+ )}
+ `,
+ },
+ )}`;
+ });
+
+ const PageModule = createAstroModule(Page);
+ const request = new Request('http://example.com/');
+ const routeData = {
+ type: 'page',
+ pathname: '/index',
+ component: 'src/pages/index.astro',
+ params: {},
+ };
+ const renderContext = await RenderContext.create({ pipeline, request, routeData });
+ const response = await renderContext.render(PageModule);
+
+ const html = await response.text();
+ const $ = cheerio.load(html);
+
+ assert.equal($('head link').length, 1);
+ assert.equal($('body link').length, 0);
+ });
+
+ it('Multi-level layouts and head injection, without explicit head', async () => {
+ const BaseLayout = createComponent((result, _props, slots) => {
+ return render`<html>
+ ${renderSlot(result, slots['head'])}
+ ${maybeRenderHead(result)}
+ <body>
+ ${renderSlot(result, slots['default'])}
+ </body>
+ </html>`;
+ });
+
+ const PageLayout = createComponent((result, _props, slots) => {
+ return render`${renderComponent(
+ result,
+ 'Layout',
+ BaseLayout,
+ {},
+ {
+ default: () => render`
+ ${maybeRenderHead(result)}
+ <main>
+ ${renderSlot(result, slots['default'])}
+ </main>
+ `,
+ head: () => render`
+ ${renderComponent(
+ result,
+ 'Fragment',
+ Fragment,
+ { slot: 'head' },
+ {
+ default: () => render`${renderSlot(result, slots['head'])}`,
+ },
+ )}
+ `,
+ },
+ )}
+ `;
+ });
+
+ const Page = createComponent((result) => {
+ return render`${renderComponent(
+ result,
+ 'PageLayout',
+ PageLayout,
+ {},
+ {
+ default: () => render`${maybeRenderHead(result)}<div>hello world</div>`,
+ head: () => render`
+ ${renderComponent(
+ result,
+ 'Fragment',
+ Fragment,
+ { slot: 'head' },
+ {
+ default: () => render`<meta charset="utf-8">`,
+ },
+ )}
+ `,
+ },
+ )}`;
+ });
+
+ const PageModule = createAstroModule(Page);
+ const request = new Request('http://example.com/');
+ const routeData = {
+ type: 'page',
+ pathname: '/index',
+ component: 'src/pages/index.astro',
+ params: {},
+ };
+ const renderContext = await RenderContext.create({ pipeline, request, routeData });
+ const response = await renderContext.render(PageModule);
+
+ const html = await response.text();
+ const $ = cheerio.load(html);
+
+ assert.equal($('head link').length, 1);
+ assert.equal($('body link').length, 0);
+ });
+
+ it('Multi-level layouts and head injection, without any content in layouts', async () => {
+ const BaseLayout = createComponent((result, _props, slots) => {
+ return render`${renderSlot(result, slots['default'])}`;
+ });
+
+ const PageLayout = createComponent((result, _props, slots) => {
+ return render`${renderComponent(
+ result,
+ 'Layout',
+ BaseLayout,
+ {},
+ {
+ default: () => render`${renderSlot(result, slots['default'])} `,
+ },
+ )}
+ `;
+ });
+
+ const Page = createComponent((result) => {
+ return render`${renderComponent(
+ result,
+ 'PageLayout',
+ PageLayout,
+ {},
+ {
+ default: () => render`${maybeRenderHead(result)}<div>hello world</div>`,
+ },
+ )}`;
+ });
+
+ const PageModule = createAstroModule(Page);
+ const request = new Request('http://example.com/');
+ const routeData = {
+ type: 'page',
+ pathname: '/index',
+ component: 'src/pages/index.astro',
+ params: {},
+ };
+ const renderContext = await RenderContext.create({ pipeline, request, routeData });
+ const response = await renderContext.render(PageModule);
+
+ const html = await response.text();
+ const $ = cheerio.load(html);
+
+ assert.equal($('link').length, 1);
+ });
+ });
+});