0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-23 21:53:55 -05:00
astro/packages/integrations/markdoc/test/headings.test.js
Ben Holmes fb84622af0
[Markdoc] headings and heading IDs (#7095)
* deps: markdown-remark

* wip: heading-ids function

* chore: add `@astrojs/markdoc` to external

* feat: `headings` support

* fix: allow `render` config on headings

* fix: nonexistent `userConfig`

* test: headings, toc, astro component render

* docs: README

* chore: changeset

* refactor: expose Markdoc helpers from runtime

* fix: bad named exports (commonjsssss)

* refactor: defaultNodes -> nodes

* deps: github-slugger

* fix: reset slugger cache on each render

* fix: bad astroNodes import

* docs: explain headingSlugger export

* docs: add back double stringify comment

* chore: bump to minor for internal exports change
2023-05-17 09:13:10 -04:00

192 lines
4.3 KiB
JavaScript

import { parseHTML } from 'linkedom';
import { expect } from 'chai';
import { loadFixture } from '../../../astro/test/test-utils.js';
async function getFixture(name) {
return await loadFixture({
root: new URL(`./fixtures/${name}/`, import.meta.url),
});
}
describe('Markdoc - Headings', () => {
let fixture;
before(async () => {
fixture = await getFixture('headings');
});
describe('dev', () => {
let devServer;
before(async () => {
devServer = await fixture.startDevServer();
});
after(async () => {
await devServer.stop();
});
it('applies IDs to headings', async () => {
const res = await fixture.fetch('/');
const html = await res.text();
const { document } = parseHTML(html);
idTest(document);
});
it('generates a TOC with correct info', async () => {
const res = await fixture.fetch('/');
const html = await res.text();
const { document } = parseHTML(html);
tocTest(document);
});
});
describe('build', () => {
before(async () => {
await fixture.build();
});
it('applies IDs to headings', async () => {
const html = await fixture.readFile('/index.html');
const { document } = parseHTML(html);
idTest(document);
});
it('generates a TOC with correct info', async () => {
const html = await fixture.readFile('/index.html');
const { document } = parseHTML(html);
tocTest(document);
});
});
});
describe('Markdoc - Headings with custom Astro renderer', () => {
let fixture;
before(async () => {
fixture = await getFixture('headings-custom');
});
describe('dev', () => {
let devServer;
before(async () => {
devServer = await fixture.startDevServer();
});
after(async () => {
await devServer.stop();
});
it('applies IDs to headings', async () => {
const res = await fixture.fetch('/');
const html = await res.text();
const { document } = parseHTML(html);
idTest(document);
});
it('generates a TOC with correct info', async () => {
const res = await fixture.fetch('/');
const html = await res.text();
const { document } = parseHTML(html);
tocTest(document);
});
it('renders Astro component for each heading', async () => {
const res = await fixture.fetch('/');
const html = await res.text();
const { document } = parseHTML(html);
astroComponentTest(document);
});
});
describe('build', () => {
before(async () => {
await fixture.build();
});
it('applies IDs to headings', async () => {
const html = await fixture.readFile('/index.html');
const { document } = parseHTML(html);
idTest(document);
});
it('generates a TOC with correct info', async () => {
const html = await fixture.readFile('/index.html');
const { document } = parseHTML(html);
tocTest(document);
});
it('renders Astro component for each heading', async () => {
const html = await fixture.readFile('/index.html');
const { document } = parseHTML(html);
astroComponentTest(document);
});
});
});
const depthToHeadingMap = {
1: {
slug: 'level-1-heading',
text: 'Level 1 heading',
},
2: {
slug: 'level-2-heading',
text: 'Level 2 heading',
},
3: {
slug: 'level-3-heading',
text: 'Level 3 heading',
},
4: {
slug: 'level-4-heading',
text: 'Level 4 heading',
},
5: {
slug: 'id-override',
text: 'Level 5 heading with override',
},
6: {
slug: 'level-6-heading',
text: 'Level 6 heading',
},
};
/** @param {Document} document */
function idTest(document) {
for (const [depth, info] of Object.entries(depthToHeadingMap)) {
expect(document.querySelector(`h${depth}`)?.getAttribute('id')).to.equal(info.slug);
}
}
/** @param {Document} document */
function tocTest(document) {
const toc = document.querySelector('[data-toc] > ul');
expect(toc.children).to.have.lengthOf(Object.keys(depthToHeadingMap).length);
for (const [depth, info] of Object.entries(depthToHeadingMap)) {
const linkEl = toc.querySelector(`a[href="#${info.slug}"]`);
expect(linkEl).to.exist;
expect(linkEl.getAttribute('data-depth')).to.equal(depth);
expect(linkEl.textContent.trim()).to.equal(info.text);
}
}
/** @param {Document} document */
function astroComponentTest(document) {
const headings = document.querySelectorAll('h1, h2, h3, h4, h5, h6');
for (const heading of headings) {
expect(heading.hasAttribute('data-custom-heading')).to.be.true;
}
}