diff --git a/package.json b/package.json index 4572039e..76aa78a7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hawk.api", - "version": "1.4.3", + "version": "1.4.4", "main": "index.ts", "license": "BUSL-1.1", "scripts": { diff --git a/src/integrations/github/routes.ts b/src/integrations/github/routes.ts index f000ca24..8144ec34 100644 --- a/src/integrations/github/routes.ts +++ b/src/integrations/github/routes.ts @@ -522,15 +522,15 @@ export function createGitHubRouter(factories: ContextFactories): express.Router * just log query parameters and respond with 200 without signature validation. */ if (req.method !== 'POST') { + // eslint-disable-next-line @typescript-eslint/camelcase, camelcase const { code, installation_id, setup_action, state, ...restQuery } = req.query as Record; + // eslint-disable-next-line @typescript-eslint/camelcase, camelcase if (code || installation_id || state || setup_action) { - // eslint-disable-next-line @typescript-eslint/camelcase, camelcase log('info', `${WEBHOOK_LOG_PREFIX}Received non-POST request on /webhook with OAuth-like params`, { - // eslint-disable-next-line @typescript-eslint/camelcase, camelcase code, - installation_id, - setup_action, + installation_id, // eslint-disable-line @typescript-eslint/camelcase, camelcase + setup_action, // eslint-disable-line @typescript-eslint/camelcase, camelcase state, query: restQuery, }); diff --git a/src/resolvers/project.js b/src/resolvers/project.js index aa16734e..c1a2767c 100644 --- a/src/resolvers/project.js +++ b/src/resolvers/project.js @@ -421,7 +421,7 @@ module.exports = { */ const taskManager = project.taskManager; - if (taskManager && taskManager.type === 'github' && taskManager.config?.installationId) { + if (taskManager && taskManager.type === 'github' && taskManager.config && taskManager.config.installationId) { const githubService = new GitHubService(); await githubService.deleteInstallation(taskManager.config.installationId); diff --git a/src/typeDefs/event.ts b/src/typeDefs/event.ts index c2ac3a2d..c200de96 100644 --- a/src/typeDefs/event.ts +++ b/src/typeDefs/event.ts @@ -116,29 +116,6 @@ type EventUser { photo: String } -""" -Breadcrumb severity level -""" -enum BreadcrumbLevel { - fatal - error - warning - info - debug -} - -""" -Breadcrumb type - controls categorization and UI appearance -""" -enum BreadcrumbType { - default - request - ui - navigation - logic - error -} - """ Single breadcrumb entry - represents an event that occurred before the error """ @@ -149,9 +126,11 @@ type Breadcrumb { timestamp: Float! """ - Type of breadcrumb - controls UI categorization + Type of breadcrumb - controls UI categorization. + Common values: default, request, ui, navigation, logic, error. + Accepts any string since SDK users may send custom types. """ - type: BreadcrumbType + type: String """ Category of the event - more specific than type @@ -164,9 +143,11 @@ type Breadcrumb { message: String """ - Severity level of the breadcrumb + Severity level of the breadcrumb. + Common values: fatal, error, warning, info, debug. + Accepts any string since SDK users may send custom levels. """ - level: BreadcrumbLevel + level: String """ Arbitrary key-value data associated with the breadcrumb diff --git a/test/__mocks__/github-service.ts b/test/__mocks__/github-service.ts new file mode 100644 index 00000000..04ff8529 --- /dev/null +++ b/test/__mocks__/github-service.ts @@ -0,0 +1,5 @@ +export const deleteInstallationMock = jest.fn().mockResolvedValue(undefined); + +export const GitHubService = jest.fn().mockImplementation(() => ({ + deleteInstallation: deleteInstallationMock, +})); diff --git a/test/integrations/github-routes.test.ts b/test/integrations/github-routes.test.ts index 81094183..03eacc94 100644 --- a/test/integrations/github-routes.test.ts +++ b/test/integrations/github-routes.test.ts @@ -480,7 +480,7 @@ describe('GitHub Routes - /integration/github/connect', () => { expect(response.status).toBe(302); expect(response.body).toContain('http://localhost:8080/'); - expect(response.body).toContain('error=Missing+or+invalid+OAuth+code'); + expect(response.body).toContain('apiError=Missing+or+invalid+OAuth+code'); }); it('should redirect with error when state is missing', async () => { @@ -501,7 +501,7 @@ describe('GitHub Routes - /integration/github/connect', () => { expect(response.status).toBe(302); expect(response.body).toContain('http://localhost:8080/'); - expect(response.body).toContain('error=Missing+or+invalid+state'); + expect(response.body).toContain('apiError=Missing+or+invalid+state'); }); it('should redirect with error when state is invalid or expired', async () => { @@ -525,7 +525,7 @@ describe('GitHub Routes - /integration/github/connect', () => { expect(response.status).toBe(302); expect(response.body).toContain('http://localhost:8080/'); - expect(response.body).toContain('error=Invalid+or+expired+state'); + expect(response.body).toContain('apiError=Invalid+or+expired+state'); expect(mockGetState).toHaveBeenCalledWith(state); }); diff --git a/test/resolvers/project.test.ts b/test/resolvers/project.test.ts index bda54a40..8f50acbc 100644 --- a/test/resolvers/project.test.ts +++ b/test/resolvers/project.test.ts @@ -3,6 +3,11 @@ import { ObjectId } from 'mongodb'; import { ProjectDBScheme, ProjectTaskManagerConfig } from '@hawk.so/types'; import { ResolverContextWithUser } from '../../src/types/graphql'; import { ApolloError, UserInputError } from 'apollo-server-express'; + +jest.mock('../../src/integrations/github/service', () => require('../__mocks__/github-service')); +// eslint-disable-next-line @typescript-eslint/no-var-requires +import { deleteInstallationMock, GitHubService } from '../__mocks__/github-service'; + // @ts-expect-error - CommonJS module, TypeScript can't infer types properly import projectResolverModule from '../../src/resolvers/project'; @@ -141,6 +146,8 @@ describe('Project Resolver - Task Manager Mutations', () => { )) as { taskManager: ProjectTaskManagerConfig | null }; expect(context.factories.projectsFactory.findById).toHaveBeenCalledWith(mockProject._id.toString()); + expect(GitHubService).toHaveBeenCalledTimes(1); + expect(deleteInstallationMock).toHaveBeenCalledWith('123456'); expect(mockProject.updateProject).toHaveBeenCalledWith({ taskManager: null, }); @@ -217,6 +224,8 @@ describe('Project Resolver - Task Manager Mutations', () => { context )) as { taskManager: ProjectTaskManagerConfig | null }; + expect(GitHubService).not.toHaveBeenCalled(); + expect(deleteInstallationMock).not.toHaveBeenCalled(); expect(mockProject.updateProject).toHaveBeenCalledWith({ taskManager: null, });