Skip to content
Source
Sign inSign up

pullRequestQuery.test.ts

155 lines6.3 KB

1import { describe, expect, it } from "vite-plus/test";
2import { applyPullRequestDraftFilterChange, parsePullRequestQuery } from "./pullRequestQuery.ts";
3​
4describe("reading qualifiers out of a typed query", () => {
5 it("keeps quoted values whole and separates negation", () => {
6 expect(parsePullRequestQuery('label:"needs design" -label:wip Fix the parser')).toEqual({
7 text: "Fix the parser",
8 filters: { labels: [["needs design"]], excludedLabels: ["wip"] },
9 });
10 });
11​
12 it("keeps the spaces in a quoted name of a list, and drops an empty part", () => {
13 expect(parsePullRequestQuery('label:"needs design","wip"').filters.labels).toEqual([
14 ["needs design", "wip"],
15 ]);
16 expect(parsePullRequestQuery("label:a,,b").filters.labels).toEqual([["a", "b"]]);
17 });
18​
19 it("makes each label qualifier its own group, so the groups are an AND", () => {
20 expect(parsePullRequestQuery("label:bug label:a,b").filters.labels).toEqual([
21 ["bug"],
22 ["a", "b"],
23 ]);
24 });
25​
26 it("reads the scalar qualifiers in GitHub's own spelling", () => {
27 expect(
28 parsePullRequestQuery("author:octocat DRAFT:false review:changes_requested status:failure")
29 .filters,
30 ).toEqual({
31 author: "octocat",
32 draft: "hide",
33 review: "changes-requested",
34 checks: "failing",
35 });
36 expect(parsePullRequestQuery("-draft:true").filters).toEqual({ draft: "hide" });
37 });
38​
39 it("leaves an unknown value and a stray colon as text, and reads an unknown key as a label", () => {
40 const parsed = parsePullRequestQuery("milestone:v2 draft:maybe status: parser");
41 expect(parsed.filters).toEqual({ labels: [["milestone:v2"]] });
42 expect(parsed.text).toBe("draft:maybe status: parser");
43 });
44​
45 it("reads a quoted name holding a comma as the one label it is", () => {
46 expect(parsePullRequestQuery('label:"needs,triage"').filters.labels).toEqual([
47 ["needs,triage"],
48 ]);
49 expect(parsePullRequestQuery('label:"needs,triage",wip').filters.labels).toEqual([
50 ["needs,triage", "wip"],
51 ]);
52 expect(parsePullRequestQuery('-label:"needs,triage"').filters.excludedLabels).toEqual([
53 "needs,triage",
54 ]);
55 });
56​
57 // regression: #30131 a query pasted from github.com lists nothing
58 it("ignores GitHub's own search qualifiers instead of reading them as labels", () => {
59 expect(
60 parsePullRequestQuery(
61 "is:pr state:open archived:false repo:org/repo org:org user:alice sort:updated-desc -repo:org/fork -state:closed fix",
62 ),
63 ).toEqual({ text: "fix", filters: {} });
64 });
65​
66 it("sets no author when the query names more than one", () => {
67 expect(parsePullRequestQuery("author:alice author:bob").filters).toEqual({});
68 expect(parsePullRequestQuery("author:me author:@me").filters).toEqual({ author: "me" });
69 });
70​
71 it("cuts a typed query back to what the contract carries", () => {
72 const many = Array.from({ length: 14 }, (_, index) => `l${index}`).join(",");
73 const long = "x".repeat(240);
74 const parsed = parsePullRequestQuery(`label:${many} label:${long} author:${long}`);
75 expect(parsed.filters.labels?.[0]).toHaveLength(10);
76 expect(parsed.filters.labels?.[1]).toEqual(["x".repeat(200)]);
77 expect(parsed.filters.author).toBe("x".repeat(200));
78 });
79});
80​
81describe("colon-namespaced labels typed as a search", () => {
82 it("reads an unknown key as the label it almost always is", () => {
83 expect(parsePullRequestQuery("size:XXL").filters.labels).toEqual([["size:XXL"]]);
84 expect(parsePullRequestQuery("vouch:trusted").filters.labels).toEqual([["vouch:trusted"]]);
85 expect(parsePullRequestQuery("size:XXL").text).toBe("");
86 });
87​
88 it("reads the key as the namespace of every bare name in its list", () => {
89 expect(parsePullRequestQuery("size:S,XS").filters.labels).toEqual([["size:S", "size:XS"]]);
90 });
91​
92 it("leaves a name that already carries its own namespace alone", () => {
93 expect(parsePullRequestQuery("size:S,size:XS").filters.labels).toEqual([["size:S", "size:XS"]]);
94 });
95​
96 // regression: #19934 negated key:value qualifiers become namespaced label exclusions
97 it("excludes one the same way", () => {
98 expect(parsePullRequestQuery("-size:XXL").filters.excludedLabels).toEqual(["size:XXL"]);
99 expect(parsePullRequestQuery("-size:S,XS").filters.excludedLabels).toEqual([
100 "size:S",
101 "size:XS",
102 ]);
103 });
104​
105 it("keeps a quoted token as text, which is the way back to a literal search", () => {
106 const parsed = parsePullRequestQuery('"size:XXL"');
107 expect(parsed.filters.labels).toBeUndefined();
108 expect(parsed.text).toBe('"size:XXL"');
109 });
110​
111 it("reads a hyphenated namespace as a label too", () => {
112 expect(parsePullRequestQuery("priority-1:high").filters.labels).toEqual([["priority-1:high"]]);
113 expect(parsePullRequestQuery("priority-1:high").text).toBe("");
114 });
115​
116 it("leaves a pasted link alone rather than naming a label after its scheme", () => {
117 const parsed = parsePullRequestQuery("https://github.com/pingdotgg/t3code/pull/1");
118 expect(parsed.filters.labels).toBeUndefined();
119 expect(parsed.text).toBe("https://github.com/pingdotgg/t3code/pull/1");
120 });
121​
122 it("mixes with the keys it does know, and with plain words", () => {
123 const parsed = parsePullRequestQuery("area:web draft:true wizard label:bug");
124 expect(parsed.filters).toEqual({ labels: [["area:web"], ["bug"]], draft: "only" });
125 expect(parsed.text).toBe("wizard");
126 });
127});
128​
129describe("changing the draft menu after typing a qualifier", () => {
130 it("replaces or clears a typed draft qualifier and keeps the rest of the query", () => {
131 expect(
132 applyPullRequestDraftFilterChange(
133 'draft:false fix label:"needs design"',
134 {},
135 { draft: "only" },
136 ),
137 ).toEqual({ query: 'fix label:"needs design"', filters: { draft: "only" } });
138 expect(
139 applyPullRequestDraftFilterChange('draft:true "draft:false" fix', { draft: "only" }, {}),
140 ).toEqual({
141 query: '"draft:false" fix',
142 filters: {},
143 });
144 });
145​
146 it("keeps the typed query and the stored menu draft when another filter changes", () => {
147 expect(
148 applyPullRequestDraftFilterChange(
149 "draft:false fix",
150 { draft: "only" },
151 { draft: "hide", checks: "passing" },
152 ),
153 ).toEqual({ query: "draft:false fix", filters: { draft: "only", checks: "passing" } });
154 });
155});