Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 8 additions & 16 deletions src/commands/document/document-list.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Command } from "@cliffy/command"
import { gql } from "../../__codegen__/gql.ts"
import type { DocumentFilter } from "../../__codegen__/graphql.ts"
import { getGraphQLClient } from "../../utils/graphql.ts"
import { getTimeAgo, padDisplay } from "../../utils/display.ts"
import { shouldShowSpinner } from "../../utils/hyperlink.ts"
Expand Down Expand Up @@ -49,23 +50,14 @@ export const listCommand = new Command()
spinner?.start()

try {
// Build filter based on options
// deno-lint-ignore no-explicit-any
let filter: any = undefined

if (project) {
filter = {
...filter,
project: { slugId: { eq: project } },
// Build filter based on options. Stays undefined when neither flag is
// passed so the query sends no filter at all.
const filter: DocumentFilter | undefined = project || issue
? {
project: project ? { slugId: { eq: project } } : undefined,
issue: issue ? { id: { eq: issue.toUpperCase() } } : undefined,
}
}

if (issue) {
filter = {
...filter,
issue: { identifier: { eq: issue.toUpperCase() } },
}
}
: undefined

const client = getGraphQLClient()
const result = await client.request(ListDocuments, {
Expand Down
30 changes: 30 additions & 0 deletions test/commands/document/__snapshots__/document-list.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,36 @@ stderr:
""
`;

snapshot[`Document List Command - Filter By Issue JSON Output 1`] = `
stdout:
'{
"nodes": [
{
"id": "doc-2",
"title": "Migration Runbook",
"slugId": "a1c27f6d8e04",
"url": "https://linear.app/test/document/migration-runbook-a1c27f6d8e04",
"updatedAt": "2026-01-20T14:15:00Z",
"project": null,
"issue": {
"identifier": "TC-123",
"title": "Plan the migration"
},
"creator": {
"name": "Jane Smith"
}
}
],
"pageInfo": {
"hasNextPage": false,
"endCursor": null
}
}
'
stderr:
""
`;

snapshot[`Document List Command - Empty Results 1`] = `
stdout:
"No documents found.
Expand Down
65 changes: 61 additions & 4 deletions test/commands/document/document-list.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ await snapshotTest({
},
})

// NOTE: Tests for "List All Documents", "Filter By Project", and "Filter By Issue"
// have been removed because they display relative timestamps (e.g., "3 days ago")
// which are inherently non-deterministic. The fakeTime solution causes hangs with
// mock servers (see project-list.test.ts for similar issue).
// NOTE: The human-readable table tests for "List All Documents", "Filter By Project",
// and "Filter By Issue" have been removed because they display relative timestamps
// (e.g., "3 days ago") which are inherently non-deterministic. The fakeTime solution
// causes hangs with mock servers (see project-list.test.ts for similar issue).
// Issue filtering is covered below via the --json path, which prints raw timestamps
// and is therefore deterministic.

// Test JSON output (uses raw timestamps, not relative - deterministic)
await snapshotTest({
Expand Down Expand Up @@ -69,6 +71,61 @@ await snapshotTest({
},
})

// Regression test: --issue must filter on IssueFilter.id, not a non-existent
// `identifier` field. The mock declares the exact request variables, so a wrong
// filter shape matches no mock, falls through to the NO_MOCK_CONFIGURED error and
// fails the test rather than quietly producing different output.
await snapshotTest({
name: "Document List Command - Filter By Issue JSON Output",
meta: import.meta,
colors: false,
args: ["--issue", "TC-123", "--json"],
denoArgs: commonDenoArgs,
async fn() {
const server = new MockLinearServer([
{
queryName: "ListDocuments",
variables: {
filter: { issue: { id: { eq: "TC-123" } } },
first: 50,
},
response: {
data: {
documents: {
nodes: [
{
id: "doc-2",
title: "Migration Runbook",
slugId: "a1c27f6d8e04",
url:
"https://linear.app/test/document/migration-runbook-a1c27f6d8e04",
updatedAt: "2026-01-20T14:15:00Z",
project: null,
issue: { identifier: "TC-123", title: "Plan the migration" },
creator: { name: "Jane Smith" },
},
],
pageInfo: { hasNextPage: false, endCursor: null },
},
},
},
},
])

try {
await server.start()
Deno.env.set("LINEAR_GRAPHQL_ENDPOINT", server.getEndpoint())
Deno.env.set("LINEAR_API_KEY", "Bearer test-token")

await listCommand.parse()
} finally {
await server.stop()
Deno.env.delete("LINEAR_GRAPHQL_ENDPOINT")
Deno.env.delete("LINEAR_API_KEY")
}
},
})

// Test empty results
await snapshotTest({
name: "Document List Command - Empty Results",
Expand Down
Loading