mirror of
https://github.com/brunopostle/ifcurl.git
synced 2026-07-12 02:08:13 +00:00
Extract parseCommitHref, isSimpleTypeSelector, subtractIdMap, and isCommitHash into a new viewer-util.js ES module so they can be tested without a browser. Convert ifcurl.js from an IIFE to an ES module importing from viewer-util.js; update footer.tmpl to type="module". Add node:test suites for viewer-url.js (32 tests) and viewer-util.js (28 tests). Add npm test script and document it in the build section. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
162 lines
5.4 KiB
JavaScript
162 lines
5.4 KiB
JavaScript
// Copyright 2026 The Forgejo Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
import { test, describe } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { parseCommitHref, isSimpleTypeSelector, subtractIdMap, isCommitHash }
|
|
from "../custom/public/assets/viewer-util.js";
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// parseCommitHref
|
|
// ---------------------------------------------------------------------------
|
|
|
|
describe("parseCommitHref", () => {
|
|
test("parses a standard Forgejo browse path", () => {
|
|
const r = parseCommitHref("/org/repo/src/commit/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2/model.ifc");
|
|
assert.equal(r.repoPath, "org/repo");
|
|
assert.equal(r.hash, "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2");
|
|
assert.equal(r.treePath, "model.ifc");
|
|
});
|
|
|
|
test("parses a path with subdirectories", () => {
|
|
const r = parseCommitHref("/org/repo/src/commit/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2/subdir/model.ifc");
|
|
assert.equal(r.treePath, "subdir/model.ifc");
|
|
});
|
|
|
|
test("returns null for non-commit paths", () => {
|
|
assert.equal(parseCommitHref("/org/repo/src/branch/main/model.ifc"), null);
|
|
assert.equal(parseCommitHref("/org/repo"), null);
|
|
assert.equal(parseCommitHref(""), null);
|
|
});
|
|
|
|
test("returns null if hash is not 40 hex chars", () => {
|
|
assert.equal(parseCommitHref("/org/repo/src/commit/abc123/model.ifc"), null);
|
|
});
|
|
|
|
test("is case-insensitive for hex hash", () => {
|
|
const r = parseCommitHref("/org/repo/src/commit/A1B2C3D4E5F6A1B2C3D4E5F6A1B2C3D4E5F6A1B2/model.ifc");
|
|
assert.ok(r !== null);
|
|
assert.equal(r.hash, "A1B2C3D4E5F6A1B2C3D4E5F6A1B2C3D4E5F6A1B2");
|
|
});
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// isSimpleTypeSelector
|
|
// ---------------------------------------------------------------------------
|
|
|
|
describe("isSimpleTypeSelector", () => {
|
|
test("accepts a single IFC type", () => {
|
|
assert.equal(isSimpleTypeSelector("IfcWall"), true);
|
|
});
|
|
|
|
test("accepts multiple types joined by +", () => {
|
|
assert.equal(isSimpleTypeSelector("IfcWall+IfcSlab"), true);
|
|
assert.equal(isSimpleTypeSelector("IfcWall+IfcSlab+IfcBeam"), true);
|
|
});
|
|
|
|
test("accepts subtypes", () => {
|
|
assert.equal(isSimpleTypeSelector("IfcWallStandardCase"), true);
|
|
});
|
|
|
|
test("accepts lowercase ifc prefix", () => {
|
|
assert.equal(isSimpleTypeSelector("ifcWall"), true);
|
|
});
|
|
|
|
test("rejects name filter", () => {
|
|
assert.equal(isSimpleTypeSelector('IfcWall, Name="Core Wall"'), false);
|
|
});
|
|
|
|
test("rejects property set filter", () => {
|
|
assert.equal(isSimpleTypeSelector("IfcWall[Pset_WallCommon.IsExternal=true]"), false);
|
|
});
|
|
|
|
test("rejects bare GlobalId (not an IFC type name)", () => {
|
|
assert.equal(isSimpleTypeSelector("325Q7Fhnf67OZC$$r43uzK"), false);
|
|
});
|
|
|
|
test("rejects empty string", () => {
|
|
assert.equal(isSimpleTypeSelector(""), false);
|
|
});
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// subtractIdMap
|
|
// ---------------------------------------------------------------------------
|
|
|
|
describe("subtractIdMap", () => {
|
|
test("removes ids present in toRemove", () => {
|
|
const all = { m1: [1, 2, 3, 4] };
|
|
const remove = { m1: [2, 4] };
|
|
const result = subtractIdMap(all, remove);
|
|
assert.deepEqual(result, { m1: [1, 3] });
|
|
});
|
|
|
|
test("omits model keys where all ids are removed", () => {
|
|
const all = { m1: [1, 2] };
|
|
const remove = { m1: [1, 2] };
|
|
const result = subtractIdMap(all, remove);
|
|
assert.deepEqual(result, {});
|
|
});
|
|
|
|
test("leaves models untouched that are not in toRemove", () => {
|
|
const all = { m1: [1, 2], m2: [3, 4] };
|
|
const remove = { m1: [1] };
|
|
const result = subtractIdMap(all, remove);
|
|
assert.deepEqual(result, { m1: [2], m2: [3, 4] });
|
|
});
|
|
|
|
test("handles empty toRemove", () => {
|
|
const all = { m1: [1, 2, 3] };
|
|
const result = subtractIdMap(all, {});
|
|
assert.deepEqual(result, { m1: [1, 2, 3] });
|
|
});
|
|
|
|
test("handles multiple models in toRemove", () => {
|
|
const all = { m1: [1, 2], m2: [3, 4] };
|
|
const remove = { m1: [2], m2: [3] };
|
|
const result = subtractIdMap(all, remove);
|
|
assert.deepEqual(result, { m1: [1], m2: [4] });
|
|
});
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// isCommitHash
|
|
// ---------------------------------------------------------------------------
|
|
|
|
describe("isCommitHash", () => {
|
|
test("accepts a full 40-char SHA", () => {
|
|
assert.equal(isCommitHash("a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"), true);
|
|
});
|
|
|
|
test("accepts a 7-char short SHA", () => {
|
|
assert.equal(isCommitHash("a1b2c3d"), true);
|
|
});
|
|
|
|
test("accepts lengths between 7 and 40", () => {
|
|
assert.equal(isCommitHash("a1b2c3d4e5f6"), true);
|
|
});
|
|
|
|
test("rejects heads/ ref", () => {
|
|
assert.equal(isCommitHash("heads/main"), false);
|
|
});
|
|
|
|
test("rejects tags/ ref", () => {
|
|
assert.equal(isCommitHash("tags/v1.0"), false);
|
|
});
|
|
|
|
test("rejects uppercase hex (hashes are lowercase)", () => {
|
|
assert.equal(isCommitHash("A1B2C3D"), false);
|
|
});
|
|
|
|
test("rejects fewer than 7 chars", () => {
|
|
assert.equal(isCommitHash("a1b2c3"), false);
|
|
});
|
|
|
|
test("rejects more than 40 chars", () => {
|
|
assert.equal(isCommitHash("a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2x"), false);
|
|
});
|
|
|
|
test("rejects empty string", () => {
|
|
assert.equal(isCommitHash(""), false);
|
|
});
|
|
});
|