diff --git a/package.json b/package.json index 23eef13..44e7f00 100644 --- a/package.json +++ b/package.json @@ -18,13 +18,13 @@ "autoprefixer": "^10.4.14", "axios": "^1.6.0", "dayjs": "^1.11.9", - "fuse.js": "^6.6.2", + "fuse.js": "^7.0.0", "highlight.js": "^11.8.0", - "jsdom": "^22.1.0", + "jsdom": "^24.0.0", "lodash": "^4.17.21", "mermaid": "^10.2.4", "playwright": "^1.36.1", - "rehype-mdx-code-props": "^1.0.0", + "rehype-mdx-code-props": "^3.0.0", "rehype-mermaid": "^2.0.1", "sass": "^1.63.6", "tippy.js": "^6.3.7" @@ -34,7 +34,8 @@ "@types/canvas-confetti": "^1.6.0", "@types/jsdom": "^21.1.1", "@types/node": "^20.8.3", + "@types/node-fetch": "^2.6.11", "@types/node-fetch-cache": "^3.0.0", - "node-fetch-cache": "^3.1.3" + "node-fetch-cache": "^4.1.0" } } diff --git a/src/test/header.spec.ts b/src/test/header.spec.ts new file mode 100644 index 0000000..dee875e --- /dev/null +++ b/src/test/header.spec.ts @@ -0,0 +1,29 @@ +import { test, expect } from "@playwright/test"; + +test.describe("Header", () => { + test.beforeEach(async ({ page }) => { + await page.goto("/wiki/"); + }); + + test("Exists", async ({ page }) => { + await expect(page.getByRole("banner")).toBeVisible(); + }); + + test("Home Link", async ({ page, baseURL }) => { + await page.getByRole("link", { name: "house" }).click(); + expect(page.url()).toBe(baseURL); + }); + + test("Wiki Link", async ({ page, baseURL }) => { + await page.getByRole("link", { name: "book" }).click(); + await page.waitForURL("/wiki/"); + expect(page.url()).toBe(baseURL + "wiki/"); + }); + + test("GitHub Link", async ({ page, context }) => { + const href = await page + .getByRole("link", { name: "github" }) + .getAttribute("href"); + expect(href).toBe("https://github.com/luals/lua-language-server"); + }); +}); diff --git a/src/test/index.spec.ts b/src/test/index.spec.ts index a1c80b5..c1a2828 100644 --- a/src/test/index.spec.ts +++ b/src/test/index.spec.ts @@ -1,8 +1,8 @@ -import { test, expect, Locator } from "@playwright/test"; +import { test, expect } from "@playwright/test"; test.describe("Home Page", () => { test.beforeEach(async ({ page }) => { - await page.route( + page.route( "https://api.github.com/repos/LuaLS/lua-language-server", async (route) => { const json = { stargazers_count: 2000 }; @@ -10,7 +10,7 @@ test.describe("Home Page", () => { } ); - await page.route( + page.route( "https://corsproxy.io/?https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery", async (route) => { const json = { @@ -28,108 +28,13 @@ test.describe("Home Page", () => { } ); - await page.goto("/"); + await page.goto("/", { waitUntil: "load", timeout: 3000 }); }); test("Metadata", async ({ page }) => { await expect(page).toHaveTitle("Lua Language Server | Home"); }); - test.describe("Header", () => { - test("Exists", async ({ page }) => { - await expect(page.getByRole("banner")).toBeVisible(); - }); - - test("Home Link", async ({ page, baseURL }) => { - await page.getByRole("link", { name: "house" }).click(); - expect(page.url()).toBe(baseURL); - }); - - test("Wiki Link", async ({ page, baseURL }) => { - await page.getByRole("link", { name: "book" }).click(); - await page.waitForURL("/wiki/"); - expect(page.url()).toBe(baseURL + "wiki/"); - }); - - test.describe("Search", async () => { - let searchInput: Locator; - - test.beforeEach(async ({ page }) => { - searchInput = page.getByPlaceholder("Search..."); - }); - - const isOpen = async () => { - await expect(searchInput).toBeVisible(); - await expect(searchInput).toBeFocused(); - }; - - const isClosed = async () => { - await expect(searchInput).not.toBeVisible(); - }; - - test("Open Search With Button", async ({ page }) => { - await page.getByRole("button", { name: "search" }).click(); - await isOpen(); - }); - - test("Open Search With Keypress", async ({ page }) => { - await page.getByRole("document").press("/"); - await isOpen(); - }); - - test("Close Search With Escape", async ({ page }) => { - await page.getByRole("document").press("/"); - await isOpen(); - await searchInput.press("Escape"); - await isClosed(); - }); - - test("Close Search By Clicking Background", async ({ page }) => { - await page.getByRole("document").press("/"); - await isOpen(); - await page.locator("#site-search").click(); - await isClosed(); - }); - - test("Search Finds Privacy Page", async ({ page, baseURL }) => { - await page.getByRole("document").press("/"); - await searchInput.fill("priva"); - const link = page.getByRole("link", { name: "Privacy /privacy" }); - - await expect(link).toBeVisible(); - await searchInput.press("Enter"); - await page.waitForURL("/privacy/"); - expect(page.url()).toBe(`${baseURL}privacy/`); - await expect(page).toHaveTitle("Lua Language Server | Privacy"); - }); - - test("Search Finds GitHub Repository", async ({ page, context }) => { - await page.getByRole("document").press("/"); - await searchInput.fill("reposit"); - const link = page.getByRole("link", { - name: "GitHub Repository https://github.com/LuaLS/LuaLS.github.io", - }); - - await expect(link).toBeVisible(); - - const pagePromise = context.waitForEvent("page"); - await searchInput.press("Enter"); - const newPage = await pagePromise; - expect(newPage.url()).toBe("https://github.com/LuaLS/LuaLS.github.io"); - }); - }); - - test("GitHub Link", async ({ page, context }) => { - const pagePromise = context.waitForEvent("page"); - await page.getByRole("link", { name: "github" }).click(); - const newPage = await pagePromise; - await newPage.waitForLoadState(); - expect(newPage.url()).toBe( - "https://github.com/luals/lua-language-server" - ); - }); - }); - test.describe("Install Instructions Visible", () => { test("VS Code", async ({ page, baseURL }) => { await page.getByRole("button", { name: "Visual Studio Code" }).click(); diff --git a/src/test/search.spec.ts b/src/test/search.spec.ts new file mode 100644 index 0000000..15f76db --- /dev/null +++ b/src/test/search.spec.ts @@ -0,0 +1,67 @@ +import { test, expect, type Locator } from "@playwright/test"; + +test.describe("Search", async () => { + let searchInput: Locator; + + test.beforeEach(async ({ page }) => { + await page.goto("/wiki/"); + + searchInput = page.getByPlaceholder("Search..."); + }); + + const isOpen = async () => { + await expect(searchInput).toBeVisible(); + await expect(searchInput).toBeFocused(); + }; + + const isClosed = async () => { + await expect(searchInput).not.toBeVisible(); + }; + + test("Open Search With Button", async ({ page }) => { + await page.getByRole("button", { name: "search" }).click(); + await isOpen(); + }); + + test("Open Search With Keypress", async ({ page }) => { + await page.getByRole("document").press("/"); + await isOpen(); + }); + + test("Close Search With Escape", async ({ page }) => { + await page.getByRole("document").press("/"); + await isOpen(); + await searchInput.press("Escape"); + await isClosed(); + }); + + test("Close Search By Clicking Background", async ({ page }) => { + await page.getByRole("document").press("/"); + await isOpen(); + await page.locator("#site-search").click(); + await isClosed(); + }); + + test("Search Finds Privacy Page", async ({ page, baseURL }) => { + await page.getByRole("document").press("/"); + await searchInput.fill("priva"); + const link = page.getByRole("link", { name: "Privacy /privacy" }); + + await expect(link).toBeVisible(); + await searchInput.press("Enter"); + expect(page.url()).toBe(`${baseURL}privacy/`); + }); + + test("Search Finds GitHub Repository", async ({ page, context }) => { + await page.getByRole("document").press("/"); + await searchInput.fill("reposit"); + const link = page.getByRole("link", { + name: "GitHub Repository https://github.com/LuaLS/LuaLS.github.io", + }); + + await expect(link).toBeVisible(); + + const href = await link.getAttribute("href"); + expect(href).toBe("https://github.com/LuaLS/LuaLS.github.io"); + }); +}); diff --git a/src/test/wiki_article.spec.ts b/src/test/wiki_article.spec.ts index ec83f6b..29bffda 100644 --- a/src/test/wiki_article.spec.ts +++ b/src/test/wiki_article.spec.ts @@ -22,7 +22,7 @@ test.describe("Wiki Article", async () => { ).toBeVisible(); }); - test("Article Sidebar", async ({ page, baseURL }) => { + test("Article Sidebar", async ({ page }) => { const sidebar = page.locator("#article-browser"); await page.getByRole("button", { name: "newspaper" }).click(); @@ -32,13 +32,12 @@ test.describe("Wiki Article", async () => { expect(await sidebar.getAttribute("open")).toBe(null); await page.getByRole("button", { name: "newspaper" }).click(); - await page.getByRole("link", { name: "Usage" }).click(); - await page.waitForURL(`${baseURL}wiki/usage/`); - expect(page.url()).toBe(`${baseURL}wiki/usage/`); - await expect(page.getByRole("heading", { name: "Usage" })).toBeVisible(); + const link = page.getByRole("link", { name: "Usage" }); + const href = await link.getAttribute("href"); + expect(href).toBe(`/wiki/usage/`); }); - test("Outline Sidebar", async ({ page, baseURL }) => { + test("Outline Sidebar", async ({ page }) => { const sidebar = page.locator("#outline"); await page.getByRole("button", { name: "list" }).click(); @@ -48,22 +47,18 @@ test.describe("Wiki Article", async () => { expect(await sidebar.getAttribute("open")).toBe(null); await page.getByRole("button", { name: "list" }).click(); - await sidebar.getByRole("link", { name: "Build" }).click(); - await page.waitForURL(`${baseURL}wiki/build/#build`); - expect(page.url()).toBe(`${baseURL}wiki/build/#build`); - await expect(page.getByRole("heading", { name: "Build" })).toBeVisible(); + const link = sidebar.getByRole("link", { name: "Build" }); + const href = await link.getAttribute("href"); + expect(href).toBe(`#build`); }); - test("Edit Page Button", async ({ page, context }) => { + test("Edit Page Button", async ({ page }) => { const link = page.getByRole("link", { name: "pencil Edit this page" }); await expect(link).toBeVisible(); - const pagePromise = context.waitForEvent("page"); - await link.click(); - const newPage = await pagePromise; - await newPage.waitForLoadState(); - expect(newPage.url()).toBe( - "https://github.com/LuaLS/LuaLS.github.io/blob/main/src/content/wiki/build.mdx" + const href = await link.getAttribute("href"); + expect(href).toBe( + "https://github.com/LuaLS/LuaLS.github.io/tree/main/src/content/wiki/build.mdx" ); }); diff --git a/src/util/fetch.ts b/src/util/fetch.ts index a69fcbe..6f97857 100644 --- a/src/util/fetch.ts +++ b/src/util/fetch.ts @@ -1,23 +1,27 @@ -import {fetchBuilder, FileSystemCache } from "node-fetch-cache"; +import NodeFetchCache, { FileSystemCache } from "node-fetch-cache"; import type { default as nodeFetch } from "node-fetch"; import os from "os"; /* Cache location: Windows: C:\Users\USER\AppData\Local\Temp\LuaLS_website_cache + Linux: /tmp/LuaLS_website_cache */ const cacheDir = os.tmpdir() + "/LuaLS_website_cache/"; const cacheDuration = 1800000; // 30 minutes; -const cacheFetch = fetchBuilder.withCache( - new FileSystemCache({ cacheDirectory: cacheDir, ttl: cacheDuration }) -); +const cacheFetch = NodeFetchCache.create({ + cache: new FileSystemCache({ cacheDirectory: cacheDir, ttl: cacheDuration }), +}); /** If in development mode, caches requests to prevent vite from DDOSing api endpoints */ export default async (request: RequestInfo, init?: RequestInit) => { if (import.meta.env.PROD) { return await fetch(request, init); } else { - return await cacheFetch(request as Parameters[0], init as Parameters[1]).then(async (response) => { + return await cacheFetch( + request as Parameters[0], + init as Parameters[1] + ).then(async (response) => { if (!response.ok) { await response.ejectFromCache(); throw new Error(`${response.status}: ${response.statusText}`);