Skip to content
Closed
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
16 changes: 15 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Notification, User } from './typesGithub';
import { CheckSuiteStatus, Notification, User } from './typesGithub';

export interface AuthState {
token?: string;
Expand Down Expand Up @@ -56,3 +56,17 @@ export interface AuthTokenResponse {
hostname: string;
token: string;
}

export interface CheckSuiteParts {
workflowName: string;
attemptNumber?: number;
statusDisplayName: string;
statusCode: CheckSuiteStatus | null;
branchName: string;
}

export interface WorkflowRunParts {
user: string;
statusCode: CheckSuiteStatus | null;
statusDisplayName: string;
}
16 changes: 8 additions & 8 deletions src/utils/github-api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,31 +36,31 @@ describe('getNotificationTypeIcon', () => {
getNotificationTypeIcon(
createSubjectMock({
type: 'CheckSuite',
title: 'Workflow cancelled for main branch',
title: 'Demonstration workflow run cancelled for main branch',
}),
).displayName,
).toBe('StopIcon');
expect(
getNotificationTypeIcon(
createSubjectMock({
type: 'CheckSuite',
title: 'Workflow failed for main branch',
title: 'Demonstration workflow run failed for main branch',
}),
).displayName,
).toBe('XIcon');
expect(
getNotificationTypeIcon(
createSubjectMock({
type: 'CheckSuite',
title: 'Workflow skipped for main branch',
title: 'Demonstration workflow run skipped for main branch',
}),
).displayName,
).toBe('SkipIcon');
expect(
getNotificationTypeIcon(
createSubjectMock({
type: 'CheckSuite',
title: 'Workflow succeeded for main branch',
title: 'Demonstration workflow run succeeded for main branch',
}),
).displayName,
).toBe('CheckIcon');
Expand Down Expand Up @@ -172,15 +172,15 @@ describe('getNotificationTypeIconColor', () => {
getNotificationTypeIconColor(
createSubjectMock({
type: 'CheckSuite',
title: 'Workflow cancelled for main branch',
title: 'Demonstration workflow run cancelled for main branch',
}),
),
).toMatchSnapshot();
expect(
getNotificationTypeIconColor(
createSubjectMock({
type: 'CheckSuite',
title: 'Workflow failed for main branch',
title: 'Demonstration workflow run failed for main branch',
}),
),
).toMatchSnapshot();
Expand All @@ -189,15 +189,15 @@ describe('getNotificationTypeIconColor', () => {
getNotificationTypeIconColor(
createSubjectMock({
type: 'CheckSuite',
title: 'Workflow skipped for main branch',
title: 'Demonstration workflow run skipped for main branch',
}),
),
).toMatchSnapshot();
expect(
getNotificationTypeIconColor(
createSubjectMock({
type: 'CheckSuite',
title: 'Workflow succeeded for main branch',
title: 'Demonstration workflow run succeeded for main branch',
}),
),
).toMatchSnapshot();
Expand Down
37 changes: 6 additions & 31 deletions src/utils/github-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import {
TagIcon,
XIcon,
} from '@primer/octicons-react';
import { CheckSuiteStatus, Reason, Subject } from '../typesGithub';
import { Reason, Subject } from '../typesGithub';
import { parseCheckSuiteTitle } from './helpers';

// prettier-ignore
const DESCRIPTIONS = {
Expand Down Expand Up @@ -89,9 +90,8 @@ export function getNotificationTypeIcon(
): React.FC<OcticonProps> {
switch (subject.type) {
case 'CheckSuite':
const checkSuiteState = inferCheckSuiteStatus(subject.title);

switch (checkSuiteState) {
const checkSuiteParts = parseCheckSuiteTitle(subject.title);
switch (checkSuiteParts?.statusCode) {
case 'cancelled':
return StopIcon;
case 'failure':
Expand Down Expand Up @@ -145,9 +145,8 @@ export function getNotificationTypeIcon(

export function getNotificationTypeIconColor(subject: Subject): string {
if (subject.type === 'CheckSuite') {
const checkSuiteState = inferCheckSuiteStatus(subject.title);

switch (checkSuiteState) {
const checkSuiteParts = parseCheckSuiteTitle(subject.title);
switch (checkSuiteParts?.statusCode) {
case 'cancelled':
return 'text-gray-500';
case 'failure':
Expand Down Expand Up @@ -180,27 +179,3 @@ export function getNotificationTypeIconColor(subject: Subject): string {
return 'text-gray-300';
}
}

export function inferCheckSuiteStatus(title: string): CheckSuiteStatus {
if (title) {
const lowerTitle = title.toLowerCase();

if (lowerTitle.includes('cancelled for')) {
return 'cancelled';
}

if (lowerTitle.includes('failed for')) {
return 'failure';
}

if (lowerTitle.includes('skipped for')) {
return 'skipped';
}

if (lowerTitle.includes('succeeded for')) {
return 'success';
}
}

return null;
}
199 changes: 199 additions & 0 deletions src/utils/helpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,138 @@ describe('utils/helpers.ts', () => {
expect(result).toBe(`${mockedHtmlUrl}?${mockedNotificationReferrer}`);
});

it('Check Suite: successful workflow', async () => {
const subject = {
title: 'Demo workflow run succeeded for main branch',
url: null,
latest_comment_url: null,
type: 'CheckSuite' as SubjectType,
};

const result = await generateGitHubWebUrl(
{
...mockedSingleNotification,
subject: subject,
},
mockAccounts,
);

expect(apiRequestAuthMock).toHaveBeenCalledTimes(0);
expect(result).toBe(
`https://github.com/manosim/notifications-test/actions?query=workflow%3A%22Demo%22+is%3Asuccess+branch%3Amain&${mockedNotificationReferrer}`,
);
});

it('Check Suite: failed workflow', async () => {
const subject = {
title: 'Demo workflow run failed for main branch',
url: null,
latest_comment_url: null,
type: 'CheckSuite' as SubjectType,
};

const result = await generateGitHubWebUrl(
{
...mockedSingleNotification,
subject: subject,
},
mockAccounts,
);

expect(apiRequestAuthMock).toHaveBeenCalledTimes(0);
expect(result).toBe(
`https://github.com/manosim/notifications-test/actions?query=workflow%3A%22Demo%22+is%3Afailure+branch%3Amain&${mockedNotificationReferrer}`,
);
});

it('Check Suite: failed workflow multiple attempts', async () => {
const subject = {
title: 'Demo workflow run, Attempt #3 failed for main branch',
url: null,
latest_comment_url: null,
type: 'CheckSuite' as SubjectType,
};

const result = await generateGitHubWebUrl(
{
...mockedSingleNotification,
subject: subject,
},
mockAccounts,
);

expect(apiRequestAuthMock).toHaveBeenCalledTimes(0);
expect(result).toBe(
`https://github.com/manosim/notifications-test/actions?query=workflow%3A%22Demo%22+is%3Afailure+branch%3Amain&${mockedNotificationReferrer}`,
);
});

it('Check Suite: skipped workflow', async () => {
const subject = {
title: 'Demo workflow run skipped for main branch',
url: null,
latest_comment_url: null,
type: 'CheckSuite' as SubjectType,
};

const result = await generateGitHubWebUrl(
{
...mockedSingleNotification,
subject: subject,
},
mockAccounts,
);

expect(apiRequestAuthMock).toHaveBeenCalledTimes(0);
expect(result).toBe(
`https://github.com/manosim/notifications-test/actions?query=workflow%3A%22Demo%22+is%3Askipped+branch%3Amain&${mockedNotificationReferrer}`,
);
});

it('Check Suite: unhandled workflow scenario', async () => {
const subject = {
title: 'unhandled workflow scenario',
url: null,
latest_comment_url: null,
type: 'CheckSuite' as SubjectType,
};

const result = await generateGitHubWebUrl(
{
...mockedSingleNotification,
subject: subject,
},
mockAccounts,
);

expect(apiRequestAuthMock).toHaveBeenCalledTimes(0);
expect(result).toBe(
`https://github.com/manosim/notifications-test/actions?${mockedNotificationReferrer}`,
);
});

it('Check Suite: unhandled status scenario', async () => {
const subject = {
title: 'Demo workflow run unhandled-status for main branch',
url: null,
latest_comment_url: null,
type: 'CheckSuite' as SubjectType,
};

const result = await generateGitHubWebUrl(
{
...mockedSingleNotification,
subject: subject,
},
mockAccounts,
);

expect(apiRequestAuthMock).toHaveBeenCalledTimes(0);
expect(result).toBe(
`https://github.com/manosim/notifications-test/actions?query=workflow%3A%22Demo%22+branch%3Amain&${mockedNotificationReferrer}`,
);
});

it('Discussions: when no subject urls and no discussions found via query, default to linking to repository discussions', async () => {
const subject = {
title: 'generate github web url unit tests',
Expand Down Expand Up @@ -310,6 +442,73 @@ describe('utils/helpers.ts', () => {
);
});

it('Workflow Run: approval requested', async () => {
const subject = {
title: 'some-user requested your review to deploy to an environment',
url: null,
latest_comment_url: null,
type: 'WorkflowRun' as SubjectType,
};

const result = await generateGitHubWebUrl(
{
...mockedSingleNotification,
subject: subject,
},
mockAccounts,
);

expect(apiRequestAuthMock).toHaveBeenCalledTimes(0);
expect(result).toBe(
`https://github.com/manosim/notifications-test/actions?query=is%3Awaiting&${mockedNotificationReferrer}`,
);
});

it('Workflow Run: unhandled status/action scenario', async () => {
const subject = {
title:
'some-user requested your unhandled-action to deploy to an environment',
url: null,
latest_comment_url: null,
type: 'WorkflowRun' as SubjectType,
};

const result = await generateGitHubWebUrl(
{
...mockedSingleNotification,
subject: subject,
},
mockAccounts,
);

expect(apiRequestAuthMock).toHaveBeenCalledTimes(0);
expect(result).toBe(
`https://github.com/manosim/notifications-test/actions?${mockedNotificationReferrer}`,
);
});

it('Workflow Run: unhandled workflow scenario', async () => {
const subject = {
title: 'some unhandled scenario',
url: null,
latest_comment_url: null,
type: 'WorkflowRun' as SubjectType,
};

const result = await generateGitHubWebUrl(
{
...mockedSingleNotification,
subject: subject,
},
mockAccounts,
);

expect(apiRequestAuthMock).toHaveBeenCalledTimes(0);
expect(result).toBe(
`https://github.com/manosim/notifications-test/actions?${mockedNotificationReferrer}`,
);
});

it('defaults to repository url', async () => {
const subject = {
title: 'generate github web url unit tests',
Expand Down
Loading