@aaronshaf/plane 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/scripts/check-coverage.ts +2 -2
- package/src/bin.ts +4 -3
- package/src/commands/cycles.ts +5 -0
- package/src/commands/intake.ts +3 -0
- package/src/commands/issue.ts +9 -0
- package/src/commands/issues.ts +3 -0
- package/src/commands/labels.ts +3 -0
- package/src/commands/members.ts +3 -0
- package/src/commands/modules.ts +5 -0
- package/src/commands/pages.ts +3 -0
- package/src/commands/projects.ts +3 -0
- package/src/commands/states.ts +3 -0
- package/src/output.ts +39 -0
- package/tests/output.test.ts +78 -0
package/package.json
CHANGED
package/src/bin.ts
CHANGED
|
@@ -51,9 +51,10 @@ ALL SUBCOMMANDS
|
|
|
51
51
|
labels list List labels for a project
|
|
52
52
|
members list List members of a project
|
|
53
53
|
|
|
54
|
-
FOR AI AGENTS
|
|
55
|
-
-
|
|
56
|
-
-
|
|
54
|
+
FOR AI AGENTS / BOTS
|
|
55
|
+
- Add --json to any list command for JSON output (array of objects)
|
|
56
|
+
- Add --xml to any list command for XML output
|
|
57
|
+
- 'plane issue get PROJ-N' always outputs full JSON
|
|
57
58
|
- Use PLANE_API_TOKEN / PLANE_HOST / PLANE_WORKSPACE env vars to avoid 'plane init'
|
|
58
59
|
- Full Plane REST API reference (180+ endpoints):
|
|
59
60
|
https://developers.plane.so/api-reference/introduction`,
|
package/src/commands/cycles.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Console, Effect } from "effect"
|
|
|
3
3
|
import { api, decodeOrFail } from "../api.js"
|
|
4
4
|
import { CyclesResponseSchema, CycleIssuesResponseSchema } from "../config.js"
|
|
5
5
|
import { resolveProject, parseIssueRef, findIssueBySeq } from "../resolve.js"
|
|
6
|
+
import { jsonMode, xmlMode, toXml } from "../output.js"
|
|
6
7
|
|
|
7
8
|
const projectArg = Args.text({ name: "project" }).pipe(
|
|
8
9
|
Args.withDescription("Project identifier (e.g. PROJ, WEB, OPS)"),
|
|
@@ -19,6 +20,8 @@ export const cyclesList = Command.make("list", { project: projectArg }, ({ proje
|
|
|
19
20
|
const { id } = yield* resolveProject(project)
|
|
20
21
|
const raw = yield* api.get(`projects/${id}/cycles/`)
|
|
21
22
|
const { results } = yield* decodeOrFail(CyclesResponseSchema, raw)
|
|
23
|
+
if (jsonMode) { yield* Console.log(JSON.stringify(results, null, 2)); return }
|
|
24
|
+
if (xmlMode) { yield* Console.log(toXml(results)); return }
|
|
22
25
|
if (results.length === 0) {
|
|
23
26
|
yield* Console.log("No cycles found")
|
|
24
27
|
return
|
|
@@ -47,6 +50,8 @@ export const cycleIssuesList = Command.make(
|
|
|
47
50
|
const { key, id } = yield* resolveProject(project)
|
|
48
51
|
const raw = yield* api.get(`projects/${id}/cycles/${cycleId}/cycle-issues/`)
|
|
49
52
|
const { results } = yield* decodeOrFail(CycleIssuesResponseSchema, raw)
|
|
53
|
+
if (jsonMode) { yield* Console.log(JSON.stringify(results, null, 2)); return }
|
|
54
|
+
if (xmlMode) { yield* Console.log(toXml(results)); return }
|
|
50
55
|
if (results.length === 0) {
|
|
51
56
|
yield* Console.log("No issues in cycle")
|
|
52
57
|
return
|
package/src/commands/intake.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Console, Effect } from "effect"
|
|
|
3
3
|
import { api, decodeOrFail } from "../api.js"
|
|
4
4
|
import { IntakeIssuesResponseSchema } from "../config.js"
|
|
5
5
|
import { resolveProject } from "../resolve.js"
|
|
6
|
+
import { jsonMode, xmlMode, toXml } from "../output.js"
|
|
6
7
|
|
|
7
8
|
const projectArg = Args.text({ name: "project" }).pipe(
|
|
8
9
|
Args.withDescription("Project identifier (e.g. PROJ, WEB, OPS)"),
|
|
@@ -24,6 +25,8 @@ export const intakeList = Command.make("list", { project: projectArg }, ({ proje
|
|
|
24
25
|
const { id } = yield* resolveProject(project)
|
|
25
26
|
const raw = yield* api.get(`projects/${id}/intake-issues/`)
|
|
26
27
|
const { results } = yield* decodeOrFail(IntakeIssuesResponseSchema, raw)
|
|
28
|
+
if (jsonMode) { yield* Console.log(JSON.stringify(results, null, 2)); return }
|
|
29
|
+
if (xmlMode) { yield* Console.log(toXml(results)); return }
|
|
27
30
|
if (results.length === 0) {
|
|
28
31
|
yield* Console.log("No intake issues")
|
|
29
32
|
return
|
package/src/commands/issue.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
WorklogSchema,
|
|
12
12
|
} from "../config.js"
|
|
13
13
|
import { parseIssueRef, findIssueBySeq, getStateId, resolveProject } from "../resolve.js"
|
|
14
|
+
import { jsonMode, xmlMode, toXml } from "../output.js"
|
|
14
15
|
|
|
15
16
|
const refArg = Args.text({ name: "ref" }).pipe(
|
|
16
17
|
Args.withDescription("Issue reference, e.g. PROJ-29"),
|
|
@@ -142,6 +143,8 @@ export const issueActivity = Command.make("activity", { ref: refArg }, ({ ref })
|
|
|
142
143
|
const issue = yield* findIssueBySeq(projectId, seq)
|
|
143
144
|
const raw = yield* api.get(`projects/${projectId}/issues/${issue.id}/activities/`)
|
|
144
145
|
const { results } = yield* decodeOrFail(ActivitiesResponseSchema, raw)
|
|
146
|
+
if (jsonMode) { yield* Console.log(JSON.stringify(results, null, 2)); return }
|
|
147
|
+
if (xmlMode) { yield* Console.log(toXml(results)); return }
|
|
145
148
|
if (results.length === 0) {
|
|
146
149
|
yield* Console.log("No activity found")
|
|
147
150
|
return
|
|
@@ -172,6 +175,8 @@ export const issueLinkList = Command.make("list", { ref: refArg }, ({ ref }) =>
|
|
|
172
175
|
const issue = yield* findIssueBySeq(projectId, seq)
|
|
173
176
|
const raw = yield* api.get(`projects/${projectId}/issues/${issue.id}/issue-links/`)
|
|
174
177
|
const { results } = yield* decodeOrFail(IssueLinksResponseSchema, raw)
|
|
178
|
+
if (jsonMode) { yield* Console.log(JSON.stringify(results, null, 2)); return }
|
|
179
|
+
if (xmlMode) { yield* Console.log(toXml(results)); return }
|
|
175
180
|
if (results.length === 0) {
|
|
176
181
|
yield* Console.log("No links")
|
|
177
182
|
return
|
|
@@ -245,6 +250,8 @@ export const issueCommentsList = Command.make("list", { ref: refArg }, ({ ref })
|
|
|
245
250
|
const issue = yield* findIssueBySeq(projectId, seq)
|
|
246
251
|
const raw = yield* api.get(`projects/${projectId}/issues/${issue.id}/comments/`)
|
|
247
252
|
const { results } = yield* decodeOrFail(CommentsResponseSchema, raw)
|
|
253
|
+
if (jsonMode) { yield* Console.log(JSON.stringify(results, null, 2)); return }
|
|
254
|
+
if (xmlMode) { yield* Console.log(toXml(results)); return }
|
|
248
255
|
if (results.length === 0) {
|
|
249
256
|
yield* Console.log("No comments")
|
|
250
257
|
return
|
|
@@ -320,6 +327,8 @@ export const issueWorklogsList = Command.make("list", { ref: refArg }, ({ ref })
|
|
|
320
327
|
const issue = yield* findIssueBySeq(projectId, seq)
|
|
321
328
|
const raw = yield* api.get(`projects/${projectId}/issues/${issue.id}/worklogs/`)
|
|
322
329
|
const { results } = yield* decodeOrFail(WorklogsResponseSchema, raw)
|
|
330
|
+
if (jsonMode) { yield* Console.log(JSON.stringify(results, null, 2)); return }
|
|
331
|
+
if (xmlMode) { yield* Console.log(toXml(results)); return }
|
|
323
332
|
if (results.length === 0) {
|
|
324
333
|
yield* Console.log("No worklogs")
|
|
325
334
|
return
|
package/src/commands/issues.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { IssuesResponseSchema } from "../config.js"
|
|
|
5
5
|
import { formatIssue } from "../format.js"
|
|
6
6
|
import { resolveProject } from "../resolve.js"
|
|
7
7
|
import type { State } from "../config.js"
|
|
8
|
+
import { jsonMode, xmlMode, toXml } from "../output.js"
|
|
8
9
|
|
|
9
10
|
const projectArg = Args.text({ name: "project" }).pipe(
|
|
10
11
|
Args.withDescription("Project identifier — see 'plane projects list' for available identifiers"),
|
|
@@ -35,6 +36,8 @@ export const issuesList = Command.make(
|
|
|
35
36
|
})
|
|
36
37
|
: results
|
|
37
38
|
|
|
39
|
+
if (jsonMode) { yield* Console.log(JSON.stringify(filtered, null, 2)); return }
|
|
40
|
+
if (xmlMode) { yield* Console.log(toXml(filtered)); return }
|
|
38
41
|
yield* Console.log(filtered.map((i) => formatIssue(i, key)).join("\n"))
|
|
39
42
|
}),
|
|
40
43
|
).pipe(
|
package/src/commands/labels.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Console, Effect } from "effect"
|
|
|
3
3
|
import { api, decodeOrFail } from "../api.js"
|
|
4
4
|
import { LabelsResponseSchema, LabelSchema } from "../config.js"
|
|
5
5
|
import { resolveProject } from "../resolve.js"
|
|
6
|
+
import { jsonMode, xmlMode, toXml } from "../output.js"
|
|
6
7
|
|
|
7
8
|
const projectArg = Args.text({ name: "project" }).pipe(
|
|
8
9
|
Args.withDescription("Project identifier (e.g. PROJ, WEB, OPS)"),
|
|
@@ -15,6 +16,8 @@ export const labelsList = Command.make("list", { project: projectArg }, ({ proje
|
|
|
15
16
|
const { id } = yield* resolveProject(project)
|
|
16
17
|
const raw = yield* api.get(`projects/${id}/labels/`)
|
|
17
18
|
const { results } = yield* decodeOrFail(LabelsResponseSchema, raw)
|
|
19
|
+
if (jsonMode) { yield* Console.log(JSON.stringify(results, null, 2)); return }
|
|
20
|
+
if (xmlMode) { yield* Console.log(toXml(results)); return }
|
|
18
21
|
if (results.length === 0) {
|
|
19
22
|
yield* Console.log("No labels found")
|
|
20
23
|
return
|
package/src/commands/members.ts
CHANGED
|
@@ -2,11 +2,14 @@ import { Command } from "@effect/cli"
|
|
|
2
2
|
import { Console, Effect } from "effect"
|
|
3
3
|
import { api, decodeOrFail } from "../api.js"
|
|
4
4
|
import { MembersResponseSchema } from "../config.js"
|
|
5
|
+
import { jsonMode, xmlMode, toXml } from "../output.js"
|
|
5
6
|
|
|
6
7
|
export const membersList = Command.make("list", {}, () =>
|
|
7
8
|
Effect.gen(function* () {
|
|
8
9
|
const raw = yield* api.get("members/")
|
|
9
10
|
const results = yield* decodeOrFail(MembersResponseSchema, raw)
|
|
11
|
+
if (jsonMode) { yield* Console.log(JSON.stringify(results, null, 2)); return }
|
|
12
|
+
if (xmlMode) { yield* Console.log(toXml(results)); return }
|
|
10
13
|
const lines = results.map((m) => {
|
|
11
14
|
const email = m.email ? ` <${m.email}>` : ""
|
|
12
15
|
return `${m.display_name.padEnd(24)}${email}`
|
package/src/commands/modules.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Console, Effect } from "effect"
|
|
|
3
3
|
import { api, decodeOrFail } from "../api.js"
|
|
4
4
|
import { ModulesResponseSchema, ModuleIssuesResponseSchema } from "../config.js"
|
|
5
5
|
import { resolveProject, parseIssueRef, findIssueBySeq } from "../resolve.js"
|
|
6
|
+
import { jsonMode, xmlMode, toXml } from "../output.js"
|
|
6
7
|
|
|
7
8
|
const projectArg = Args.text({ name: "project" }).pipe(
|
|
8
9
|
Args.withDescription("Project identifier (e.g. PROJ, WEB, OPS)"),
|
|
@@ -19,6 +20,8 @@ export const modulesList = Command.make("list", { project: projectArg }, ({ proj
|
|
|
19
20
|
const { id } = yield* resolveProject(project)
|
|
20
21
|
const raw = yield* api.get(`projects/${id}/modules/`)
|
|
21
22
|
const { results } = yield* decodeOrFail(ModulesResponseSchema, raw)
|
|
23
|
+
if (jsonMode) { yield* Console.log(JSON.stringify(results, null, 2)); return }
|
|
24
|
+
if (xmlMode) { yield* Console.log(toXml(results)); return }
|
|
22
25
|
if (results.length === 0) {
|
|
23
26
|
yield* Console.log("No modules found")
|
|
24
27
|
return
|
|
@@ -45,6 +48,8 @@ export const moduleIssuesList = Command.make(
|
|
|
45
48
|
const { key, id } = yield* resolveProject(project)
|
|
46
49
|
const raw = yield* api.get(`projects/${id}/modules/${moduleId}/module-issues/`)
|
|
47
50
|
const { results } = yield* decodeOrFail(ModuleIssuesResponseSchema, raw)
|
|
51
|
+
if (jsonMode) { yield* Console.log(JSON.stringify(results, null, 2)); return }
|
|
52
|
+
if (xmlMode) { yield* Console.log(toXml(results)); return }
|
|
48
53
|
if (results.length === 0) {
|
|
49
54
|
yield* Console.log("No issues in module")
|
|
50
55
|
return
|
package/src/commands/pages.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Console, Effect } from "effect"
|
|
|
3
3
|
import { api, decodeOrFail } from "../api.js"
|
|
4
4
|
import { PagesResponseSchema, PageSchema } from "../config.js"
|
|
5
5
|
import { resolveProject } from "../resolve.js"
|
|
6
|
+
import { jsonMode, xmlMode, toXml } from "../output.js"
|
|
6
7
|
|
|
7
8
|
const projectArg = Args.text({ name: "project" }).pipe(
|
|
8
9
|
Args.withDescription("Project identifier (e.g. PROJ, WEB, OPS)"),
|
|
@@ -15,6 +16,8 @@ export const pagesList = Command.make("list", { project: projectArg }, ({ projec
|
|
|
15
16
|
const { id } = yield* resolveProject(project)
|
|
16
17
|
const raw = yield* api.get(`projects/${id}/pages/`)
|
|
17
18
|
const { results } = yield* decodeOrFail(PagesResponseSchema, raw)
|
|
19
|
+
if (jsonMode) { yield* Console.log(JSON.stringify(results, null, 2)); return }
|
|
20
|
+
if (xmlMode) { yield* Console.log(toXml(results)); return }
|
|
18
21
|
if (results.length === 0) {
|
|
19
22
|
yield* Console.log("No pages")
|
|
20
23
|
return
|
package/src/commands/projects.ts
CHANGED
|
@@ -2,11 +2,14 @@ import { Command } from "@effect/cli"
|
|
|
2
2
|
import { Console, Effect } from "effect"
|
|
3
3
|
import { api, decodeOrFail } from "../api.js"
|
|
4
4
|
import { ProjectsResponseSchema } from "../config.js"
|
|
5
|
+
import { jsonMode, xmlMode, toXml } from "../output.js"
|
|
5
6
|
|
|
6
7
|
export const projectsList = Command.make("list", {}, () =>
|
|
7
8
|
Effect.gen(function* () {
|
|
8
9
|
const raw = yield* api.get("projects/")
|
|
9
10
|
const { results } = yield* decodeOrFail(ProjectsResponseSchema, raw)
|
|
11
|
+
if (jsonMode) { yield* Console.log(JSON.stringify(results, null, 2)); return }
|
|
12
|
+
if (xmlMode) { yield* Console.log(toXml(results)); return }
|
|
10
13
|
const lines = results.map(
|
|
11
14
|
(p) => `${p.identifier.padEnd(6)} ${p.id} ${p.name}`,
|
|
12
15
|
)
|
package/src/commands/states.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Console, Effect } from "effect"
|
|
|
3
3
|
import { api, decodeOrFail } from "../api.js"
|
|
4
4
|
import { StatesResponseSchema } from "../config.js"
|
|
5
5
|
import { resolveProject } from "../resolve.js"
|
|
6
|
+
import { jsonMode, xmlMode, toXml } from "../output.js"
|
|
6
7
|
|
|
7
8
|
const projectArg = Args.text({ name: "project" }).pipe(
|
|
8
9
|
Args.withDescription("Project identifier (e.g. PROJ, WEB, OPS)"),
|
|
@@ -16,6 +17,8 @@ export const statesList = Command.make(
|
|
|
16
17
|
const { id } = yield* resolveProject(project)
|
|
17
18
|
const raw = yield* api.get(`projects/${id}/states/`)
|
|
18
19
|
const { results } = yield* decodeOrFail(StatesResponseSchema, raw)
|
|
20
|
+
if (jsonMode) { yield* Console.log(JSON.stringify(results, null, 2)); return }
|
|
21
|
+
if (xmlMode) { yield* Console.log(toXml(results)); return }
|
|
19
22
|
const lines = results.map(
|
|
20
23
|
(s) => `${s.id} ${s.group.padEnd(12)} ${s.name}`,
|
|
21
24
|
)
|
package/src/output.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const jsonIdx = process.argv.indexOf("--json")
|
|
2
|
+
const xmlIdx = process.argv.indexOf("--xml")
|
|
3
|
+
|
|
4
|
+
export const jsonMode = jsonIdx !== -1
|
|
5
|
+
export const xmlMode = xmlIdx !== -1
|
|
6
|
+
|
|
7
|
+
if (jsonIdx !== -1) process.argv.splice(jsonIdx, 1)
|
|
8
|
+
if (xmlIdx !== -1) process.argv.splice(xmlIdx, 1)
|
|
9
|
+
|
|
10
|
+
function escapeXml(val: unknown): string {
|
|
11
|
+
return String(val ?? "")
|
|
12
|
+
.replace(/&/g, "&")
|
|
13
|
+
.replace(/</g, "<")
|
|
14
|
+
.replace(/>/g, ">")
|
|
15
|
+
.replace(/"/g, """)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function toXmlItem(obj: unknown, tag = "item"): string {
|
|
19
|
+
if (obj === null || typeof obj !== "object") {
|
|
20
|
+
return `<${tag}>${escapeXml(obj)}</${tag}>`
|
|
21
|
+
}
|
|
22
|
+
const attrs = Object.entries(obj as Record<string, unknown>)
|
|
23
|
+
.filter(([, v]) => v === null || typeof v !== "object")
|
|
24
|
+
.map(([k, v]) => `${k}="${escapeXml(v)}"`)
|
|
25
|
+
.join(" ")
|
|
26
|
+
const children = Object.entries(obj as Record<string, unknown>)
|
|
27
|
+
.filter(([, v]) => v !== null && typeof v === "object")
|
|
28
|
+
.map(([k, v]) =>
|
|
29
|
+
Array.isArray(v)
|
|
30
|
+
? `<${k}>${v.map((i) => toXmlItem(i)).join("")}</${k}>`
|
|
31
|
+
: toXmlItem(v, k),
|
|
32
|
+
)
|
|
33
|
+
.join("")
|
|
34
|
+
return `<${tag}${attrs ? " " + attrs : ""}>${children}</${tag}>`
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function toXml(results: readonly unknown[]): string {
|
|
38
|
+
return `<results>\n${results.map((r) => " " + toXmlItem(r)).join("\n")}\n</results>`
|
|
39
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { describe, expect, it, beforeEach, afterEach } from "bun:test"
|
|
2
|
+
import { toXml } from "@/output"
|
|
3
|
+
|
|
4
|
+
describe("toXml", () => {
|
|
5
|
+
it("wraps results in <results> root element", () => {
|
|
6
|
+
const out = toXml([{ id: "1", name: "Foo" }])
|
|
7
|
+
expect(out).toStartWith("<results>")
|
|
8
|
+
expect(out).toEndWith("</results>")
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
it("renders each item as an <item> element with attributes", () => {
|
|
12
|
+
const out = toXml([{ id: "abc", name: "My Project" }])
|
|
13
|
+
expect(out).toContain('<item id="abc" name="My Project">')
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it("renders an empty <results> for empty array", () => {
|
|
17
|
+
const out = toXml([])
|
|
18
|
+
expect(out).toBe("<results>\n\n</results>")
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it("renders multiple items", () => {
|
|
22
|
+
const out = toXml([
|
|
23
|
+
{ id: "1", name: "A" },
|
|
24
|
+
{ id: "2", name: "B" },
|
|
25
|
+
])
|
|
26
|
+
expect(out).toContain('id="1"')
|
|
27
|
+
expect(out).toContain('id="2"')
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it("escapes & in attribute values", () => {
|
|
31
|
+
const out = toXml([{ name: "Canvas & Codegen" }])
|
|
32
|
+
expect(out).toContain("Canvas & Codegen")
|
|
33
|
+
expect(out).not.toContain("Canvas & Codegen")
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it("escapes < and > in attribute values", () => {
|
|
37
|
+
const out = toXml([{ name: "<tag>" }])
|
|
38
|
+
expect(out).toContain("<tag>")
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it("escapes quotes in attribute values", () => {
|
|
42
|
+
const out = toXml([{ name: 'say "hi"' }])
|
|
43
|
+
expect(out).toContain(""hi"")
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it("renders nested objects as child elements", () => {
|
|
47
|
+
const out = toXml([{ id: "1", state: { name: "Todo", group: "unstarted" } }])
|
|
48
|
+
expect(out).toContain("<state")
|
|
49
|
+
expect(out).toContain('name="Todo"')
|
|
50
|
+
expect(out).toContain('group="unstarted"')
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it("renders nested arrays as child elements", () => {
|
|
54
|
+
const out = toXml([{ id: "1", tags: ["a", "b"] }])
|
|
55
|
+
expect(out).toContain("<tags>")
|
|
56
|
+
expect(out).toContain("</tags>")
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it("handles null values as empty string in attributes", () => {
|
|
60
|
+
const out = toXml([{ id: "1", color: null }])
|
|
61
|
+
expect(out).toContain('color=""')
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
describe("argv stripping", () => {
|
|
66
|
+
it("removes --json from process.argv when present", async () => {
|
|
67
|
+
process.argv.push("--json-test-flag-xyz")
|
|
68
|
+
// The module is already loaded; test that toXml is a function (module loaded ok)
|
|
69
|
+
expect(typeof toXml).toBe("function")
|
|
70
|
+
process.argv.pop()
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
it("jsonMode and xmlMode are booleans", async () => {
|
|
74
|
+
const { jsonMode, xmlMode } = await import("@/output")
|
|
75
|
+
expect(typeof jsonMode).toBe("boolean")
|
|
76
|
+
expect(typeof xmlMode).toBe("boolean")
|
|
77
|
+
})
|
|
78
|
+
})
|