docsify/test/e2e/virtual-routes.test.js
Joe Pea 62d756c447 refactor: convert to ES Modules and remove traces of CommonJS except in Rollup config because some dependencies are still CommonJS
BREAKING: The new project layout might break in some tooling setups.

We've added an exports field to `package.json` to specify where
statements like `import ... from 'docsify'` will import from, and left
the `main` and `unpkg` fields as-is for backwards compatibility with the
global <script> import method. Most people who use a non-module
`<script>` tag to import Docsify will not notice a difference. Anyone
else who is importing Docsify into a specilized build setup using
`import` statements has a chance of being broken, so we've marked this
as BREAKING.
2023-06-29 19:02:08 -07:00

296 lines
7.3 KiB
JavaScript

import docsifyInit from '../helpers/docsify-init.js';
import { test, expect } from './fixtures/docsify-init-fixture.js';
/**
* Navigate to a specific route in the site
* @param {import('playwright-core').Page} page the playwright page instance from the test
* @param {string} route the route you want to navigate to
*/
async function navigateToRoute(page, route) {
await page.evaluate(r => (window.location.hash = r), route);
// TODO: playwright eslint now recommends not using networkidle
// eslint-disable-next-line
await page.waitForLoadState('networkidle');
}
test.describe('Virtual Routes - Generate Dynamic Content via Config', () => {
test.describe('Different Types of Virtual Routes', () => {
test('rendering virtual routes specified as string', async ({ page }) => {
const routes = {
'/my-awesome-route': '# My Awesome Route',
};
await docsifyInit({
config: {
routes,
},
});
await navigateToRoute(page, '/my-awesome-route');
const titleElm = page.locator('#main h1');
await expect(titleElm).toContainText('My Awesome Route');
});
test('rendering virtual routes specified as functions', async ({
page,
}) => {
const routes = {
'/my-awesome-function-route': function () {
return '# My Awesome Function Route';
},
};
await docsifyInit({
config: {
routes,
},
});
await navigateToRoute(page, '/my-awesome-function-route');
const titleElm = page.locator('#main h1');
await expect(titleElm).toContainText('My Awesome Function Route');
});
test('rendering virtual routes specified functions that use the "next" callback', async ({
page,
}) => {
const routes = {
'/my-awesome-async-function-route': async function (
route,
matched,
next
) {
setTimeout(() => next('# My Awesome Function Route'), 100);
},
};
await docsifyInit({
config: {
routes,
},
});
await navigateToRoute(page, '/my-awesome-async-function-route');
const titleElm = page.locator('#main h1');
await expect(titleElm).toContainText('My Awesome Function Route');
});
});
test.describe('Routes with Regex Matches', () => {
test('rendering virtual routes with regex matches', async ({ page }) => {
const routes = {
'/items/(.*)': '# Item Page',
};
await docsifyInit({
config: {
routes,
},
});
await navigateToRoute(page, '/items/banana');
const titleElm = page.locator('#main h1');
await expect(titleElm).toContainText('Item Page');
});
test('virtual route functions should get the route as first parameter', async ({
page,
}) => {
const routes = {
'/pets/(.*)': function (route) {
return `# Route: /pets/dog`;
},
};
await docsifyInit({
config: {
routes,
},
});
await navigateToRoute(page, '/pets/dog');
const titleElm = page.locator('#main h1');
await expect(titleElm).toContainText('Route: /pets/dog');
});
test('virtual route functions should get the matched array as second parameter', async ({
page,
}) => {
const routes = {
'/pets/(.*)': function (_, matched) {
return `# Pets Page (${matched[1]})`;
},
};
await docsifyInit({
config: {
routes,
},
});
await navigateToRoute(page, '/pets/cat');
const titleElm = page.locator('#main h1');
await expect(titleElm).toContainText('Pets Page (cat)');
});
});
test.describe('Route Matching Specifics', () => {
test('routes should be exact match if no regex was passed', async ({
page,
}) => {
const routes = {
'/my': '# Incorrect Route - only prefix',
'/route': '# Incorrect Route - only postfix',
'/my/route': '# Correct Route',
};
await docsifyInit({
config: {
routes,
},
});
await navigateToRoute(page, '/my/route');
const titleElm = page.locator('#main h1');
await expect(titleElm).toContainText('Correct Route');
});
test('if there are two routes that match, the first one should be taken', async ({
page,
}) => {
const routes = {
'/multiple/(.+)': '# First Match',
'/multiple/(.*)': '# Second Match',
};
await docsifyInit({
config: {
routes,
},
});
await navigateToRoute(page, '/multiple/matches');
const titleElm = page.locator('#main h1');
await expect(titleElm).toContainText('First Match');
});
test('prefer virtual route over a real file, if a virtual route exists', async ({
page,
}) => {
const routes = {
'/': '# Virtual Homepage',
};
await docsifyInit({
markdown: {
homepage: '# Real File Homepage',
},
config: {
routes,
},
});
const titleElm = page.locator('#main h1');
await expect(titleElm).toContainText('Virtual Homepage');
});
test('fallback to default routing if no route was matched', async ({
page,
}) => {
const routes = {
'/a': '# A',
'/b': '# B',
'/c': '# C',
};
await docsifyInit({
markdown: {
homepage: '# Real File Homepage',
},
config: {
routes,
},
});
await navigateToRoute(page, '/d');
const mainElm = page.locator('#main');
await expect(mainElm).toContainText('404 - Not found');
});
test('skip routes that returned a falsy value that is not a boolean', async ({
page,
}) => {
const routes = {
'/multiple/(.+)': () => null,
'/multiple/(.*)': () => undefined,
'/multiple/.+': () => 0,
'/multiple/.*': () => '# Last Match',
};
await docsifyInit({
config: {
routes,
},
});
await navigateToRoute(page, '/multiple/matches');
const titleElm = page.locator('#main h1');
await expect(titleElm).toContainText('Last Match');
});
test('abort virtual routes and not try the next one, if any matched route returned an explicit "false" boolean', async ({
page,
}) => {
const routes = {
'/multiple/(.+)': () => false,
'/multiple/(.*)': () => "# You Shouldn't See Me",
};
await docsifyInit({
config: {
routes,
},
});
await navigateToRoute(page, '/multiple/matches');
const mainElm = page.locator('#main');
await expect(mainElm).toContainText('404 - Not found');
});
test('skip routes that are not a valid string or function', async ({
page,
}) => {
const routes = {
'/multiple/(.+)': 123,
'/multiple/(.*)': false,
'/multiple/.+': null,
'/multiple/..+': [],
'/multiple/..*': {},
'/multiple/.*': '# Last Match',
};
await docsifyInit({
config: {
routes,
},
});
await navigateToRoute(page, '/multiple/matches');
const titleElm = page.locator('#main h1');
await expect(titleElm).toContainText('Last Match');
});
});
});