mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-11-13 12:13:42 +01:00
Test the plugin's copy of the template tag scanner (#711)
This commit is contained in:
1 parent
34815f327a
commit
411aa262c7
3 files changed
+127
-54
No files matched your search
@@ -0,0 +1,79 @@
|
||||
/* oxlint-disable no-template-curly-in-string */
|
||||
|
||||
/*
|
||||
* Shared expectations for `resolvedModelName`.
|
||||
*
|
||||
* The request template function plugin carries a hand-copied `resolvedModelName` and template-tag
|
||||
* scanner, because importing this module into the plugin bundle fails to build on Windows in CI.
|
||||
* Both `resolvedModelName.test.ts` here and `plugins/template-function-request/tests/
|
||||
* resolvedModelName.test.ts` iterate these cases, so changing an expectation on this side
|
||||
* automatically exercises the plugin's copy and a drifting copy fails its own suite.
|
||||
*
|
||||
* Keep this file dependency-free — the plugin test imports it by relative path, so anything it
|
||||
* pulls in would have to resolve from both packages.
|
||||
*/
|
||||
|
||||
export interface ResolvedModelNameCase {
|
||||
/** Test name, used as the `test.each` title on both sides. */
|
||||
name: string;
|
||||
/** `url` of the `http_request` under test. */
|
||||
url: string;
|
||||
/** `name` of the `http_request`, when the case is about an explicit name. */
|
||||
requestName?: string;
|
||||
/** What `resolvedModelName` must return. */
|
||||
expected: string;
|
||||
}
|
||||
|
||||
export const resolvedModelNameCases: ResolvedModelNameCase[] = [
|
||||
{
|
||||
name: "returns the name when there is one",
|
||||
url: "https://example.com",
|
||||
requestName: "My Request",
|
||||
expected: "My Request",
|
||||
},
|
||||
{
|
||||
name: "replaces a simple tag with its contents",
|
||||
url: "${[ base_url ]}/users",
|
||||
expected: "base_url/users",
|
||||
},
|
||||
{
|
||||
name: "replaces a tag containing a quoted argument with a space",
|
||||
url: "${[ fn(arg='my key') ]}/users",
|
||||
expected: "fn(arg='my key')/users",
|
||||
},
|
||||
{
|
||||
name: "replaces each tag in a multi-tag string",
|
||||
url: "${[ fn(arg='my key') ]}/a/${[ other(b='x y') ]}/b",
|
||||
expected: "fn(arg='my key')/a/other(b='x y')/b",
|
||||
},
|
||||
{
|
||||
name: "keeps a quoted `]}` inside the tag",
|
||||
url: "${[ fn(arg='x]}y') ]}/users",
|
||||
expected: "fn(arg='x]}y')/users",
|
||||
},
|
||||
{
|
||||
name: "keeps an escaped quote inside the tag",
|
||||
url: "${[ fn(arg='it\\'s ]}') ]}/users",
|
||||
expected: "fn(arg='it\\'s ]}')/users",
|
||||
},
|
||||
{
|
||||
name: "closes at the first `]}` when a quote is left unterminated",
|
||||
url: "${[ fn(arg='oops ]}/users",
|
||||
expected: "fn(arg='oops/users",
|
||||
},
|
||||
{
|
||||
name: "stops each tag at its first closing bracket",
|
||||
url: "${[ a ]}${[ b ]}",
|
||||
expected: "ab",
|
||||
},
|
||||
{
|
||||
name: "strips the protocol",
|
||||
url: "https://example.com/${[ path ]}",
|
||||
expected: "example.com/path",
|
||||
},
|
||||
{
|
||||
name: "falls back to a generic name when the url is empty",
|
||||
url: "",
|
||||
expected: "HTTP Request",
|
||||
},
|
||||
];
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { HttpRequest } from "@yaakapp-internal/models";
|
||||
import { describe, expect, test, vi } from "vite-plus/test";
|
||||
import { resolvedModelNameCases } from "./resolvedModelName.cases";
|
||||
|
||||
// resolvedModelName only reads plain model fields, but its module imports pull in the
|
||||
// platform singleton, which needs a browser. Stub them out to keep this a pure unit test.
|
||||
@@ -8,62 +9,13 @@ vi.mock("./jotai", () => ({ jotaiStore: { get: () => [] } }));
|
||||
|
||||
const { resolvedModelName } = await import("./resolvedModelName");
|
||||
|
||||
function httpRequest(url: string): HttpRequest {
|
||||
return { id: "rq_test", model: "http_request", name: "", url } as HttpRequest;
|
||||
function httpRequest(url: string, name = ""): HttpRequest {
|
||||
return { id: "rq_test", model: "http_request", name, url } as HttpRequest;
|
||||
}
|
||||
|
||||
describe("resolvedModelName", () => {
|
||||
test("returns the name when there is one", () => {
|
||||
expect(
|
||||
resolvedModelName({ ...httpRequest("https://example.com"), name: "My Request" }),
|
||||
).toEqual("My Request");
|
||||
});
|
||||
|
||||
test("replaces a simple tag with its contents", () => {
|
||||
expect(resolvedModelName(httpRequest("${[ base_url ]}/users"))).toEqual("base_url/users");
|
||||
});
|
||||
|
||||
test("replaces a tag containing a quoted argument with a space", () => {
|
||||
expect(resolvedModelName(httpRequest("${[ fn(arg='my key') ]}/users"))).toEqual(
|
||||
"fn(arg='my key')/users",
|
||||
);
|
||||
});
|
||||
|
||||
test("replaces each tag in a multi-tag string", () => {
|
||||
expect(
|
||||
resolvedModelName(httpRequest("${[ fn(arg='my key') ]}/a/${[ other(b='x y') ]}/b")),
|
||||
).toEqual("fn(arg='my key')/a/other(b='x y')/b");
|
||||
});
|
||||
|
||||
test("keeps a quoted `]}` inside the tag", () => {
|
||||
expect(resolvedModelName(httpRequest("${[ fn(arg='x]}y') ]}/users"))).toEqual(
|
||||
"fn(arg='x]}y')/users",
|
||||
);
|
||||
});
|
||||
|
||||
test("keeps an escaped quote inside the tag", () => {
|
||||
expect(resolvedModelName(httpRequest("${[ fn(arg='it\\'s ]}') ]}/users"))).toEqual(
|
||||
"fn(arg='it\\'s ]}')/users",
|
||||
);
|
||||
});
|
||||
|
||||
test("closes at the first `]}` when a quote is left unterminated", () => {
|
||||
expect(resolvedModelName(httpRequest("${[ fn(arg='oops ]}/users"))).toEqual(
|
||||
"fn(arg='oops/users",
|
||||
);
|
||||
});
|
||||
|
||||
test("stops each tag at its first closing bracket", () => {
|
||||
expect(resolvedModelName(httpRequest("${[ a ]}${[ b ]}"))).toEqual("ab");
|
||||
});
|
||||
|
||||
test("strips the protocol", () => {
|
||||
expect(resolvedModelName(httpRequest("https://example.com/${[ path ]}"))).toEqual(
|
||||
"example.com/path",
|
||||
);
|
||||
});
|
||||
|
||||
test("falls back to a generic name when the url is empty", () => {
|
||||
expect(resolvedModelName(httpRequest(""))).toEqual("HTTP Request");
|
||||
// Shared with the plugin's hand-copied scanner. See `resolvedModelName.cases.ts`.
|
||||
test.each(resolvedModelNameCases)("$name", ({ url, requestName, expected }) => {
|
||||
expect(resolvedModelName(httpRequest(url, requestName))).toEqual(expected);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* This plugin carries its own copy of the template-tag scanner, because importing the client's
|
||||
* copy into the plugin bundle fails to build on Windows in CI.
|
||||
*
|
||||
* Rather than copying the expectations too — copied expectations can't detect drift — this
|
||||
* imports the client's `resolvedModelName.cases.ts` and runs the plugin's copy against it, then
|
||||
* asserts the plugin's output matches the client's own `resolvedModelName` for every case. A
|
||||
* change to the client scanner or its cases therefore fails here until the copy is updated. The
|
||||
* import is test-only and never reaches the plugin bundle, so the Windows problem doesn't apply.
|
||||
*/
|
||||
|
||||
import type { HttpRequest } from "@yaakapp-internal/models";
|
||||
import { describe, expect, test, vi } from "vite-plus/test";
|
||||
import { resolvedModelNameCases } from "../../../apps/yaak-client/lib/resolvedModelName.cases";
|
||||
|
||||
// `resolvedModelName` reads plain model fields, but the two modules under test pull in sibling
|
||||
// plugins that only resolve once they're built, plus the client's platform singleton, which
|
||||
// needs a browser. Stub them all out to keep this a pure unit test.
|
||||
vi.mock("../../template-function-json", () => ({ filterJSONPath: () => null }));
|
||||
vi.mock("../../template-function-xml", () => ({ filterXPath: () => null }));
|
||||
vi.mock("@yaakapp-internal/models", () => ({ foldersAtom: {} }));
|
||||
vi.mock("../../../apps/yaak-client/lib/jotai", () => ({ jotaiStore: { get: () => [] } }));
|
||||
|
||||
const { resolvedModelName } = await import("../src");
|
||||
const { resolvedModelName: clientResolvedModelName } = await import(
|
||||
"../../../apps/yaak-client/lib/resolvedModelName"
|
||||
);
|
||||
|
||||
function httpRequest(url: string, name = ""): HttpRequest {
|
||||
return { id: "rq_test", model: "http_request", name, url } as HttpRequest;
|
||||
}
|
||||
|
||||
describe("resolvedModelName", () => {
|
||||
test.each(resolvedModelNameCases)("$name", ({ url, requestName, expected }) => {
|
||||
expect(resolvedModelName(httpRequest(url, requestName))).toEqual(expected);
|
||||
});
|
||||
|
||||
test.each(resolvedModelNameCases)("matches the client for: $name", ({ url, requestName }) => {
|
||||
const request = httpRequest(url, requestName);
|
||||
expect(resolvedModelName(request)).toEqual(clientResolvedModelName(request));
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user