Skip to content

Commit 9c80cd3

Browse files
authored
fix: handle redacted items on project (#46)
1 parent e2362e0 commit 9c80cd3

26 files changed

+313
-240
lines changed

__tests__/completed-by.test.mts

+10-10
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,11 @@ describe('completedByAction', () => {
137137
{
138138
id: itemId,
139139
content: {
140-
__typename: 'DraftIssue',
141140
id: 'content-id',
142141
body: 'This is the item body',
143142
title: 'Item Title'
144-
}
143+
},
144+
type: 'DRAFT_ISSUE'
145145
}
146146
]);
147147

@@ -168,11 +168,11 @@ describe('completedByAction', () => {
168168
{
169169
id: itemId,
170170
content: {
171-
__typename: 'DraftIssue',
172171
id: 'content-id',
173172
body: `Completed by ${itemUrl}`,
174173
title: 'Item Title'
175-
}
174+
},
175+
type: 'DRAFT_ISSUE'
176176
}
177177
]);
178178
vi.mocked(getPullRequestState).mockResolvedValue('MERGED');
@@ -204,11 +204,11 @@ describe('completedByAction', () => {
204204
{
205205
id: itemId,
206206
content: {
207-
__typename: 'DraftIssue',
208207
id: 'content-id',
209208
body: `Completed by ${itemUrl}`,
210209
title: 'Item Title'
211-
}
210+
},
211+
type: 'DRAFT_ISSUE'
212212
}
213213
]);
214214
vi.mocked(getPullRequestState).mockResolvedValue('OPEN');
@@ -238,14 +238,14 @@ describe('completedByAction', () => {
238238
{
239239
id: itemId,
240240
content: {
241-
__typename: 'DraftIssue',
242241
id: 'content-id',
243242
body: `
244243
Completed by ${itemUrl1}
245244
Completed by ${itemUrl2}
246245
`,
247246
title: 'Item Title'
248-
}
247+
},
248+
type: 'DRAFT_ISSUE'
249249
}
250250
]);
251251
vi.mocked(getPullRequestState)
@@ -278,11 +278,11 @@ describe('completedByAction', () => {
278278
{
279279
id: itemId,
280280
content: {
281-
__typename: 'DraftIssue',
282281
id: 'content-id',
283282
body: `Completed by ${itemUrl}`,
284283
title: 'Item Title'
285-
}
284+
},
285+
type: 'DRAFT_ISSUE'
286286
}
287287
]);
288288
vi.mocked(getPullRequestState).mockRejectedValue(new Error(errorMessage));

__tests__/copy-project.test.mts

+8-8
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,11 @@ describe('copyProjectAction', () => {
235235
{
236236
id: 'item-id',
237237
content: {
238-
__typename: 'DraftIssue',
239238
id: 'content-id',
240239
body: 'This is the item body',
241240
title: 'Item Title'
242-
}
241+
},
242+
type: 'DRAFT_ISSUE'
243243
}
244244
]);
245245

@@ -268,11 +268,11 @@ describe('copyProjectAction', () => {
268268
{
269269
id: itemId,
270270
content: {
271-
__typename: 'DraftIssue',
272271
id: contentId,
273272
body: 'This is the item {{ foo }}',
274273
title: 'Item {{ foo }}'
275-
}
274+
},
275+
type: 'DRAFT_ISSUE'
276276
}
277277
]);
278278

@@ -306,15 +306,15 @@ describe('copyProjectAction', () => {
306306
{
307307
id: itemId,
308308
content: {
309-
__typename: 'DraftIssue',
310309
id: 'content-id',
311310
body: `<!-- fields
312311
{
313312
"${field}": "${fieldValue}"
314313
}
315314
-->`,
316315
title: 'Item Title'
317-
}
316+
},
317+
type: 'DRAFT_ISSUE'
318318
}
319319
]);
320320

@@ -348,11 +348,11 @@ describe('copyProjectAction', () => {
348348
{
349349
id: itemId,
350350
content: {
351-
__typename: 'DraftIssue',
352351
id: contentId,
353352
body: 'This is the item {{ foo }}',
354353
title: 'Item {{ foo }}'
355-
}
354+
},
355+
type: 'DRAFT_ISSUE'
356356
}
357357
]);
358358
vi.mocked(editItem).mockImplementation(() => {

__tests__/delete-project.test.mts

+11
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,15 @@ describe('deleteProjectAction', () => {
7373
expect(core.setFailed).toHaveBeenCalledTimes(1);
7474
expect(core.setFailed).toHaveBeenLastCalledWith('42');
7575
});
76+
77+
it('passes inputs correctly', async () => {
78+
mockGetInput({ owner, 'project-number': projectNumber });
79+
vi.mocked(deleteProject).mockResolvedValue();
80+
81+
await index.deleteProjectAction();
82+
expect(deleteProjectActionSpy).toHaveReturned();
83+
84+
expect(deleteProject).toHaveBeenCalledTimes(1);
85+
expect(deleteProject).toHaveBeenLastCalledWith(owner, projectNumber);
86+
});
7687
});

__tests__/edit-item.test.mts

+25-5
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ describe('editItemAction', () => {
112112
mockGetInput({ owner, 'project-number': projectNumber, item });
113113
vi.mocked(getItem).mockResolvedValue({
114114
id: itemId,
115-
content: { type: 'PullRequest' }
115+
type: 'PULL_REQUEST'
116116
} as ItemDetails);
117117
vi.mocked(editItem).mockImplementation(() => {
118118
throw new ProjectNotFoundError();
@@ -151,6 +151,26 @@ describe('editItemAction', () => {
151151
expect(core.setFailed).toHaveBeenLastCalledWith('42');
152152
});
153153

154+
it('cannot edit redacted items', async () => {
155+
mockGetInput({
156+
owner,
157+
'project-number': projectNumber,
158+
item,
159+
title: 'New Title'
160+
});
161+
vi.mocked(getItem).mockResolvedValue({
162+
type: 'REDACTED'
163+
} as ItemDetails);
164+
165+
await index.editItemAction();
166+
expect(editItemActionSpy).toHaveReturned();
167+
168+
expect(core.setFailed).toHaveBeenCalledTimes(1);
169+
expect(core.setFailed).toHaveBeenLastCalledWith(
170+
'Cannot edit redacted items'
171+
);
172+
});
173+
154174
it('can only set title/body for draft issues', async () => {
155175
mockGetInput({
156176
owner,
@@ -159,7 +179,7 @@ describe('editItemAction', () => {
159179
title: 'New Title'
160180
});
161181
vi.mocked(getItem).mockResolvedValue({
162-
content: { type: 'PullRequest' }
182+
type: 'PULL_REQUEST'
163183
} as ItemDetails);
164184

165185
await index.editItemAction();
@@ -183,7 +203,7 @@ describe('editItemAction', () => {
183203
});
184204
vi.mocked(getItem).mockResolvedValue({
185205
id: itemId,
186-
content: { type: 'PullRequest' },
206+
type: 'PULL_REQUEST',
187207
projectId
188208
} as ItemDetails);
189209
vi.mocked(editItem).mockResolvedValue(itemId);
@@ -209,7 +229,7 @@ describe('editItemAction', () => {
209229
});
210230
vi.mocked(getItem).mockResolvedValue({
211231
id: itemId,
212-
content: { type: 'DraftIssue' },
232+
type: 'DRAFT_ISSUE',
213233
projectId
214234
} as ItemDetails);
215235
vi.mocked(editItem).mockResolvedValue(itemId);
@@ -224,7 +244,7 @@ describe('editItemAction', () => {
224244
mockGetInput({ owner, 'project-number': projectNumber, item });
225245
vi.mocked(getItem).mockResolvedValue({
226246
id: itemId,
227-
content: { type: 'PullRequest' },
247+
type: 'PULL_REQUEST',
228248
projectId
229249
} as ItemDetails);
230250
vi.mocked(editItem).mockResolvedValue(itemId);

__tests__/get-item.test.mts

+31-4
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,10 @@ describe('getItemAction', () => {
128128
});
129129
vi.mocked(getItem).mockResolvedValue({
130130
id: itemId,
131-
content: { id: contentId, type: 'PullRequest', url, title, body },
131+
content: { id: contentId, url, title, body },
132132
field: { id: fieldId, value: fieldValue },
133-
projectId
133+
projectId,
134+
type: 'PULL_REQUEST'
134135
});
135136

136137
await index.getItemAction();
@@ -161,9 +162,10 @@ describe('getItemAction', () => {
161162
});
162163
vi.mocked(getItem).mockResolvedValue({
163164
id: itemId,
164-
content: { id: contentId, type: 'PullRequest', url, title, body },
165+
content: { id: contentId, url, title, body },
165166
field: { id: fieldId, value: null },
166-
projectId
167+
projectId,
168+
type: 'PULL_REQUEST'
167169
});
168170

169171
await index.getItemAction();
@@ -178,4 +180,29 @@ describe('getItemAction', () => {
178180
expect(core.setOutput).toHaveBeenCalledWith('project-id', projectId);
179181
expect(core.setOutput).toHaveBeenCalledWith('field-id', fieldId);
180182
});
183+
184+
it('handles redacted items', async () => {
185+
mockGetInput({
186+
owner,
187+
'project-number': projectNumber,
188+
item,
189+
field: 'Status'
190+
});
191+
vi.mocked(getItem).mockResolvedValue({
192+
id: itemId,
193+
content: null,
194+
projectId,
195+
type: 'REDACTED'
196+
});
197+
198+
await index.getItemAction();
199+
expect(getItemActionSpy).toHaveReturned();
200+
201+
expect(core.setOutput).toHaveBeenCalledTimes(5);
202+
expect(core.setOutput).toHaveBeenCalledWith('id', itemId);
203+
expect(core.setOutput).toHaveBeenCalledWith('body', null);
204+
expect(core.setOutput).toHaveBeenCalledWith('title', null);
205+
expect(core.setOutput).toHaveBeenCalledWith('content-id', null);
206+
expect(core.setOutput).toHaveBeenCalledWith('project-id', projectId);
207+
});
181208
});

__tests__/helpers.test.ts

+25
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
22
import type { Mock } from 'vitest';
33

4+
import * as core from '@actions/core';
45
import * as exec from '@actions/exec';
56
import * as tc from '@actions/tool-cache';
67
import { Octokit } from '@octokit/core';
@@ -108,6 +109,30 @@ describe('helpers', () => {
108109
);
109110
});
110111

112+
it('sets GH_DEBUG if core.isDebug() is true', async () => {
113+
const args = ['project', 'view'];
114+
const stdout = 'output';
115+
const token = 'gh-token';
116+
mockGetInput({ token });
117+
vi.mocked(core.isDebug).mockReturnValue(true);
118+
vi.mocked(exec.getExecOutput).mockResolvedValue({
119+
exitCode: 0,
120+
stdout,
121+
stderr: ''
122+
});
123+
await expect(helpers.execCliCommand(args)).resolves.toEqual(stdout);
124+
expect(exec.getExecOutput).toHaveBeenCalledWith(
125+
expect.anything(),
126+
args,
127+
expect.objectContaining({
128+
env: {
129+
GH_DEBUG: 'api',
130+
GH_TOKEN: token
131+
}
132+
})
133+
);
134+
});
135+
111136
it('throws error on non-zero exit code', async () => {
112137
const args = ['project', 'view'];
113138
const stdout = 'output';

0 commit comments

Comments
 (0)