diff options
| author | stonedDiscord <Tukz@gmx.de> | 2026-01-01 16:56:51 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-01 16:56:51 +0100 |
| commit | 33744e44ceaf3825da451ba38281fd84b255de80 (patch) | |
| tree | e6c080d7e8e6f56652c2269a380eff40b899a065 | |
| parent | e07fe372bc20d16eb590b68ed256007312b3801a (diff) | |
| parent | 01ecb948edb015613e05bc2b6da4021137957745 (diff) | |
Merge pull request #286 from AttorneyOnline/bnnuy
Bnnuy
| -rw-r--r-- | .github/workflows/deploy.yml | 11 | ||||
| -rw-r--r-- | .github/workflows/test.yml | 8 | ||||
| -rw-r--r-- | bunfig.toml | 2 | ||||
| -rw-r--r-- | happydom.ts | 3 | ||||
| -rw-r--r-- | package.json | 57 | ||||
| -rw-r--r-- | webAO/__tests__/aoml.test.ts | 67 | ||||
| -rw-r--r-- | webAO/__tests__/isLowMemory.test.ts | 22 | ||||
| -rw-r--r-- | webAO/__tests__/setEmote.test.js | 140 | ||||
| -rw-r--r-- | webAO/utils/aoml.ts | 22 | ||||
| -rw-r--r-- | webAO/viewport/constants/defaultChatMsg.ts | 4 | ||||
| -rw-r--r-- | webAO/viewport/utils/handleICSpeaking.ts | 15 |
11 files changed, 111 insertions, 240 deletions
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 296323c..1321bdc 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -12,16 +12,15 @@ jobs: - name: Checkout uses: actions/checkout@v6 - name: Setup Node - uses: actions/setup-node@v6 + uses: oven-sh/setup-bun@v2 with: - node-version: 20 - cache: 'npm' + bun-version: latest - name: Install Dependencies - run: npm install + run: bun install - name: Build Project - run: npm run build + run: bun run build - name: Run Tests - run: npm test + run: bun test - name: Deploy 🚀 uses: JamesIves/github-pages-deploy-action@v4.7.6 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5a1a8e7..e7d8e6d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,10 +9,10 @@ jobs: - name: Checkout uses: actions/checkout@v6 - name: Setup Node - uses: actions/setup-node@v6 + uses: oven-sh/setup-bun@v2 with: - node-version: 20 + bun-version: 1.3.5 - name: Install Dependencies - run: npm install + run: bun install - name: Run Tests - run: npm test + run: bun test diff --git a/bunfig.toml b/bunfig.toml new file mode 100644 index 0000000..d20eff3 --- /dev/null +++ b/bunfig.toml @@ -0,0 +1,2 @@ +[test] +preload = "./happydom.ts" diff --git a/happydom.ts b/happydom.ts new file mode 100644 index 0000000..7f712d0 --- /dev/null +++ b/happydom.ts @@ -0,0 +1,3 @@ +import { GlobalRegistrator } from "@happy-dom/global-registrator"; + +GlobalRegistrator.register(); diff --git a/package.json b/package.json index 4cc9d73..92b4549 100644 --- a/package.json +++ b/package.json @@ -25,40 +25,41 @@ }, "homepage": "https://github.com/AttorneyOnline/webAO#readme", "devDependencies": { - "@babel/core": "^7.27.7", - "@babel/plugin-transform-modules-commonjs": "^7.16.8", - "@babel/preset-env": "^7.27.2", - "@babel/preset-typescript": "^7.27.1", - "@types/jest": "^29.4.0", - "@types/node": "^18.0.0", - "@typescript-eslint/eslint-plugin": "^6.7.2", - "@typescript-eslint/parser": "^6.7.2", - "babel-jest": "^30.0.2", - "babel-loader": "^9.1.2", + "@babel/core": "^7.28.5", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/preset-env": "^7.28.5", + "@babel/preset-typescript": "^7.28.5", + "@happy-dom/global-registrator": "^20.0.11", + "@types/jest": "^29.5.14", + "@types/node": "^18.19.130", + "@typescript-eslint/eslint-plugin": "^6.21.0", + "@typescript-eslint/parser": "^6.21.0", + "babel-jest": "^30.2.0", + "babel-loader": "^9.2.1", "copy-webpack-plugin": "^11.0.0", - "dotenv": "^16.0.0", - "eslint": "^8.49.0", + "dotenv": "^16.6.1", + "eslint": "^8.57.1", "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.25.4", - "glob": "^7.2.0", - "html-webpack-plugin": "^5.5.0", + "eslint-plugin-import": "^2.32.0", + "glob": "^7.2.3", + "html-webpack-plugin": "^5.6.5", "husky": "^8.0.3", - "jest": "^29.4.3", - "typescript": "^5.2.2", - "webpack": "^5.94.0", + "jest": "^29.7.0", + "typescript": "^5.9.3", + "webpack": "^5.104.1", "webpack-cli": "^5.1.4", - "webpack-dev-server": "^5.2.1", - "workbox-webpack-plugin": "^7.3.0" + "webpack-dev-server": "^5.2.2", + "workbox-webpack-plugin": "^7.4.0" }, "dependencies": { - "@fingerprintjs/fingerprintjs": "^3.4.0", - "@types/websocket": "^1.0.5", - "core-js": "^3.21.1", - "golden-layout": "^2.5.0", - "jest-environment-jsdom": "^29.5.0", - "regenerator-runtime": "^0.13.9", - "source-map-loader": "^4.0.1", - "ts-loader": "^9.2.8" + "@fingerprintjs/fingerprintjs": "^3.4.2", + "@types/websocket": "^1.0.10", + "core-js": "^3.47.0", + "golden-layout": "^2.6.0", + "jest-environment-jsdom": "^29.7.0", + "regenerator-runtime": "^0.13.11", + "source-map-loader": "^4.0.2", + "ts-loader": "^9.5.4" }, "browserslist": [ "defaults", diff --git a/webAO/__tests__/aoml.test.ts b/webAO/__tests__/aoml.test.ts index b799da6..d612945 100644 --- a/webAO/__tests__/aoml.test.ts +++ b/webAO/__tests__/aoml.test.ts @@ -1,8 +1,4 @@ -import request from "../services/request"; -import mlConfig from "../utils/aoml"; - -jest.mock("../services/request"); -const networkRequest = ` +const configIni = ` c0 = 247, 247, 247 c0_name = White c0_talking = 1 @@ -36,73 +32,56 @@ c6_remove = 0 c6_talking = 0 `; -const mockRequest = request as jest.MockedFunction<typeof request>; -mockRequest.mockReturnValue(Promise.resolve(networkRequest)); - -describe("mlConfig", () => { - beforeEach(() => { - // Clear all instances and calls to constructor and all methods: - mockRequest.mockClear(); - }); +import mlConfig from "../utils/aoml"; - it("Should make a network request", () => { - mlConfig("localhost"); - expect(mockRequest).toHaveBeenCalledTimes(1); - }); -}); describe("applyMarkdown", () => { - const config = mlConfig("localhost"); - - beforeEach(() => { - // Clear all instances and calls to constructor and all methods: - mockRequest.mockClear(); - }); + const config = mlConfig(configIni); - it("Should create an array of spans containing letters", async () => { + it("Should create an array of spans containing letters", () => { const word = `hello`; - const actual = await config.applyMarkdown(`hello`, `blue`); + const actual = config.applyMarkdown(`hello`, `blue`); let index = 0; for (const element of actual) { expect(element.innerHTML).toBe(word[index]); index++; } }); - it("Should add colors based on settings", async () => { - const config = mlConfig("localhost"); - const actual = await config.applyMarkdown(`(heya)`, `blue`); + it("Should add colors based on settings", () => { + const config = mlConfig(configIni); + const actual = config.applyMarkdown(`(heya)`, `blue`); expect(actual[0].getAttribute("style")).toBe("color: rgb(107, 198, 247);"); }); - it("Should keep a letter if remove = 0", async () => { - const config = mlConfig("localhost"); + it("Should keep a letter if remove = 0", () => { + const config = mlConfig(configIni); - const actual = await config.applyMarkdown(`(What())Hey!`, `white`); + const actual = config.applyMarkdown(`(What())Hey!`, `white`); const expected = `(`; expect(actual[5].innerHTML).toBe(expected); }); - it("Should remove a letter if remove = 1", async () => { - const config = mlConfig("localhost"); + it("Should remove a letter if remove = 1", () => { + const config = mlConfig(configIni); - const actual = await config.applyMarkdown(`~What~()Hey!`, `white`); + const actual = config.applyMarkdown(`~What~()Hey!`, `white`); const expected = ``; expect(actual[0].innerHTML).toBe(expected); }); - it("Should remove a letter if remove = 1", async () => { - const config = mlConfig("localhost"); + it("Should remove a letter if remove = 1", () => { + const config = mlConfig(configIni); - const actual = await config.applyMarkdown(`~What~()Hey!`, `white`); + const actual = config.applyMarkdown(`~What~()Hey!`, `white`); const expected = ``; expect(actual[0].innerHTML).toBe(expected); }); - it("Should keep a closing letter if remove = 0", async () => { - const config = mlConfig("localhost"); + it("Should keep a closing letter if remove = 0", () => { + const config = mlConfig(configIni); - const actual = await config.applyMarkdown(`~NO[]~!`, `white`); + const actual = config.applyMarkdown(`~NO[]~!`, `white`); const expected = ``; expect(actual[4].innerHTML).toBe(expected); }); - it("Should remove a closing letter if remove = 1", async () => { - const config = mlConfig("localhost"); - const actual = await config.applyMarkdown(`~NO||~!`, `white`); + it("Should remove a closing letter if remove = 1", () => { + const config = mlConfig(configIni); + const actual = config.applyMarkdown(`~NO||~!`, `white`); const expected = ``; expect(actual[5].innerHTML).toBe(expected); }); diff --git a/webAO/__tests__/isLowMemory.test.ts b/webAO/__tests__/isLowMemory.test.ts index 6428e17..870b40e 100644 --- a/webAO/__tests__/isLowMemory.test.ts +++ b/webAO/__tests__/isLowMemory.test.ts @@ -1,11 +1,31 @@ import { isLowMemory } from '../client/isLowMemory'; import { setOldLoading } from '../client'; +import { AO_HOST, setAOhost } from '../client/aoHost'; -// Mock the setOldLoading function +// Mock the setOldLoading function and prevent any network requests jest.mock('../client', () => ({ setOldLoading: jest.fn(), })); +// Mock any potential network requests +jest.mock('../services/request', () => ({ + __esModule: true, + default: jest.fn().mockResolvedValue(''), + request: jest.fn().mockResolvedValue(''), + requestBuffer: jest.fn().mockResolvedValue(new ArrayBuffer(0)), +})); + +// Mock the fileExists function to prevent network requests +jest.mock('../utils/fileExists', () => ({ + __esModule: true, + default: jest.fn().mockResolvedValue(false), +})); + +// Set AO_HOST to a valid URL before tests run +beforeAll(() => { + setAOhost('https://example.com/'); +}); + describe('isLowMemory', () => { beforeEach(() => { // Reset mock before each test to ensure isolation diff --git a/webAO/__tests__/setEmote.test.js b/webAO/__tests__/setEmote.test.js deleted file mode 100644 index 3a4a521..0000000 --- a/webAO/__tests__/setEmote.test.js +++ /dev/null @@ -1,140 +0,0 @@ -import setEmote from "../client/setEmote.ts"; -import Client from "../client.ts"; -import fileExists from "../utils/fileExists.ts"; -import transparentPng from "../constants/transparentPng.js"; - -jest.mock("../viewport/utils/createMusic"); -jest.mock("../utils/fileExists"); -jest.mock("../viewport/utils/createSfxAudio"); -jest.mock("../viewport/utils/createShoutAudio"); -jest.mock("../viewport/utils/createTestimonyAudio"); -describe("setEmote", () => { - const AO_HOST = ""; - - const client = new Client("127.0.0.1"); - const firstExtension = ".gif"; - - test("Should have a client_def_char_img with a valid source", async () => { - fileExists.mockReturnValue(true); - document.body.innerHTML = ` - <img id="client_def_char_img" /> - `; - await setEmote(AO_HOST, client, "salanto", "coding", "(a)", 0, "def"); - const expected = `http://localhost/characters/salanto/(a)coding${firstExtension}`; - expect(document.getElementById("client_def_char_img").src).toEqual( - expected, - ); - }); - test("Should have a client_pro_char_img to have a valid src", async () => { - document.body.innerHTML = ` - <img id="client_pro_char_img" /> - - `; - await setEmote(AO_HOST, client, "salanto", "coding", "(a)", 0, "pro"); - const expected = `http://localhost/characters/salanto/(a)coding${firstExtension}`; - expect(document.getElementById("client_pro_char_img").src).toEqual( - expected, - ); - }); - test("Should have a client_wit_char_img", async () => { - document.body.innerHTML = ` - <img id="client_wit_char_img" /> - `; - await setEmote(AO_HOST, client, "salanto", "coding", "(a)", 0, "wit"); - const expected = `http://localhost/characters/salanto/(a)coding${firstExtension}`; - - expect(document.getElementById("client_wit_char_img").src).toEqual( - expected, - ); - }); - test("Should have a client_def_pair_img", async () => { - document.body.innerHTML = ` -<img id="client_def_pair_img" /> - -`; - await setEmote(AO_HOST, client, "salanto", "coding", "(a)", 1, "def"); - const expected = `http://localhost/characters/salanto/(a)coding${firstExtension}`; - - expect(document.getElementById("client_def_pair_img").src).toEqual( - expected, - ); - }); - test("Should have a client_pro_pair_img", async () => { - document.body.innerHTML = ` -<img id="client_pro_pair_img" /> - -`; - await setEmote(AO_HOST, client, "salanto", "coding", "(a)", 1, "pro"); - const expected = `http://localhost/characters/salanto/(a)coding${firstExtension}`; - - expect(document.getElementById("client_pro_pair_img").src).toEqual( - expected, - ); - }); - test("Should have a client_wit_pair_img", async () => { - document.body.innerHTML = ` -<img id="client_wit_pair_img" /> - -`; - await setEmote(AO_HOST, client, "salanto", "coding", "(a)", 1, "wit"); - const expected = `http://localhost/characters/salanto/(a)coding${firstExtension}`; - - expect(document.getElementById("client_wit_pair_img").src).toEqual( - expected, - ); - }); - test("Should have a client_char_img", async () => { - document.body.innerHTML = ` - <img id="client_char_img" /> - - `; - await setEmote(AO_HOST, client, "salanto", "coding", "(a)", 0, "notvalid"); - const expected = `http://localhost/characters/salanto/(a)coding${firstExtension}`; - - expect(document.getElementById("client_char_img").src).toEqual(expected); - }); - test("Should have a client_pair_img", async () => { - document.body.innerHTML = ` - <img id="client_pair_img" /> - `; - await setEmote(AO_HOST, client, "salanto", "coding", "(a)", 1, "notvalid"); - const expected = `http://localhost/characters/salanto/(a)coding${firstExtension}`; - - expect(document.getElementById("client_pair_img").src).toEqual(expected); - }); - test("Should handle .png urls differently", async () => { - fileExists.mockReturnValueOnce(false); - document.body.innerHTML = ` - <img id="client_pair_img" /> - `; - await setEmote( - AO_HOST, - client, - "salanto", - "coding", - "prefixNotValid", - 1, - "notvalid", - ); - const expected = "http://localhost/characters/salanto/coding.png"; - - expect(document.getElementById("client_pair_img").src).toEqual(expected); - }); - test("Should replace character if new character responds", async () => { - fileExists.mockReturnValue(false); - document.body.innerHTML = ` - <img id="client_pair_img" /> - `; - await setEmote( - AO_HOST, - client, - "salanto", - "coding", - "prefixNotValid", - 1, - "notvalid", - ); - const expected = transparentPng; - expect(document.getElementById("client_pair_img").src).toEqual(expected); - }); -}); diff --git a/webAO/utils/aoml.ts b/webAO/utils/aoml.ts index f4a6da5..7611399 100644 --- a/webAO/utils/aoml.ts +++ b/webAO/utils/aoml.ts @@ -1,4 +1,3 @@ -import request from "../services/request"; interface Aoml { [key: string]: string | number; @@ -33,15 +32,12 @@ const aomlParser = (text: string) => { return parsed; }; -const mlConfig = (AO_HOST: string) => { - const defaultUrl = `${AO_HOST}themes/default/chat_config.ini`; - const aomlParsed: Promise<{ [key: string]: Aoml }> = request(defaultUrl).then( - (data) => aomlParser(data), - ); +const mlConfig = (iniContent: string) => { + const aomlParsed: { [key: string]: Aoml } = aomlParser(iniContent); - const createIdentifiers = async () => { + const createIdentifiers = () => { const identifiers = new Map<string, Aoml>(); - for (const [ruleName, value] of Object.entries(await aomlParsed)) { + for (const [ruleName, value] of Object.entries(aomlParsed)) { if (value.start && value.end) { identifiers.set(value.start, value); identifiers.set(value.end, value); @@ -49,18 +45,18 @@ const mlConfig = (AO_HOST: string) => { } return identifiers; }; - const createStartIdentifiers = async () => { + const createStartIdentifiers = () => { const startingIdentifiers = new Set<string>(); - for (const [ruleName, value] of Object.entries(await aomlParsed)) { + for (const [ruleName, value] of Object.entries(aomlParsed)) { if (value?.start && value?.end) { startingIdentifiers.add(value.start); } } return startingIdentifiers; }; - const applyMarkdown = async (text: string, defaultColor: string) => { - const identifiers = await createIdentifiers(); - const startIdentifiers = await createStartIdentifiers(); + const applyMarkdown = (text: string, defaultColor: string) => { + const identifiers = createIdentifiers(); + const startIdentifiers = createStartIdentifiers(); const closingStack = []; const colorStack = []; // each value in output will be an html element diff --git a/webAO/viewport/constants/defaultChatMsg.ts b/webAO/viewport/constants/defaultChatMsg.ts index fa25b33..67c60b8 100644 --- a/webAO/viewport/constants/defaultChatMsg.ts +++ b/webAO/viewport/constants/defaultChatMsg.ts @@ -1,6 +1,8 @@ -import { UPDATE_INTERVAL } from "../../client"; import { ChatMsg } from "../interfaces/ChatMsg"; +// Define UPDATE_INTERVAL locally to avoid circular dependency +const UPDATE_INTERVAL = 60; + export const defaultChatMsg = { content: "", objection: 0, diff --git a/webAO/viewport/utils/handleICSpeaking.ts b/webAO/viewport/utils/handleICSpeaking.ts index b037e69..c0a9ae1 100644 --- a/webAO/viewport/utils/handleICSpeaking.ts +++ b/webAO/viewport/utils/handleICSpeaking.ts @@ -11,8 +11,17 @@ import { resizeChatbox } from "../../dom/resizeChatbox"; import transparentPng from "../../constants/transparentPng"; import { COLORS } from "../constants/colors"; import mlConfig from "../../utils/aoml"; +import request from "../../services/request"; -const attorneyMarkdown = mlConfig(AO_HOST); +let attorneyMarkdown: ReturnType<typeof mlConfig> | null = null; + +const initAttorneyMarkdown = async () => { + if (!attorneyMarkdown) { + const iniContent = await request(`${AO_HOST}themes/default/chat_config.ini`); + attorneyMarkdown = mlConfig(iniContent); + } + return attorneyMarkdown; +}; export let startFirstTickCheck: boolean; export const setStartFirstTickCheck = (val: boolean) => { @@ -337,9 +346,9 @@ export const handle_ic_speaking = async (playerChatMsg: ChatMsg) => { } try { - client.viewport.getChatmsg().parsed = await attorneyMarkdown.applyMarkdown( + const markdown = await initAttorneyMarkdown(); + client.viewport.getChatmsg().parsed = markdown.applyMarkdown( client.viewport.getChatmsg().content, - COLORS[client.viewport.getChatmsg().color], ); } catch (error) { |
