From f470aaad72e0bc55e3ec657f88ce597135d54341 Mon Sep 17 00:00:00 2001 From: M0nkeySan Date: Thu, 31 Oct 2024 15:03:32 +0100 Subject: [PATCH] feat(optimize-project-search): Enhance project search to extract project name from GitLab URLs (#61) - Modify searchProjects function to handle GitLab repository URLs - Extract project name when search input is a full GitLab repository URL - Maintain existing behavior for non-URL search inputs --- __tests__/__fixtures__/projectFixture.ts | 9 +++--- __tests__/project/addProject.test.ts | 39 +++++++++++++++++++++++- __tests__/project/listProjects.test.ts | 4 +-- src/core/services/gitlab.ts | 9 +++++- 4 files changed, 53 insertions(+), 8 deletions(-) diff --git a/__tests__/__fixtures__/projectFixture.ts b/__tests__/__fixtures__/projectFixture.ts index 47d0972..10c9442 100644 --- a/__tests__/__fixtures__/projectFixture.ts +++ b/__tests__/__fixtures__/projectFixture.ts @@ -7,9 +7,9 @@ export const projectFixture: GitlabProjectDetails = { visibility: 'private', ssh_url_to_repo: 'git@example.com:diaspora/diaspora-project-site.git', http_url_to_repo: 'http://example.com/diaspora/diaspora-project-site.git', - web_url: 'http://example.com/diaspora/diaspora-project-site', + web_url: 'https://my-git.domain.com/diaspora/diaspora-project-site', readme_url: - 'http://example.com/diaspora/diaspora-project-site/blob/master/README.md', + 'https://my-git.domain.com/diaspora/diaspora-project-site/blob/master/README.md', tag_list: ['example', 'disapora project'], owner: { id: 3, @@ -64,9 +64,10 @@ export const projectFixture: GitlabProjectDetails = { }, }, archived: false, - avatar_url: 'http://example.com/uploads/project/avatar/3/uploads/avatar.png', + avatar_url: + 'https://my-git.domain.com/uploads/project/avatar/3/uploads/avatar.png', license_url: - 'http://example.com/diaspora/diaspora-client/blob/master/LICENSE', + 'https://my-git.domain.com/diaspora/diaspora-client/blob/master/LICENSE', license: { key: 'lgpl-3.0', name: 'GNU Lesser General Public License v3.0', diff --git a/__tests__/project/addProject.test.ts b/__tests__/project/addProject.test.ts index 9a1a449..f061a9b 100644 --- a/__tests__/project/addProject.test.ts +++ b/__tests__/project/addProject.test.ts @@ -8,7 +8,7 @@ import { getSlackHeaders } from '../utils/getSlackHeaders'; import { mockGitlabCall } from '../utils/mockGitlabCall'; describe('project > addProject', () => { - it('should add project by name', async () => { + it('should add project by search', async () => { // Given const channelId = 'channelId'; const search = 'search'; @@ -45,6 +45,43 @@ describe('project > addProject', () => { }); }); + it('should add project by web_url', async () => { + // Given + const { web_url, path } = projectFixture; + const channelId = 'channelId'; + const userId = 'userId'; + const body = { + channel_id: channelId, + text: `project add ${web_url}`, + user_id: userId, + }; + + mockGitlabCall(`/projects?search=${path}`, [projectFixture]); + + // When + const response = await fetch('/api/v1/homer/command', { + body, + headers: getSlackHeaders(body), + }); + + // Then + const { hasModelEntry } = (await import('sequelize')) as any; + expect(response.status).toEqual(HTTP_STATUS_NO_CONTENT); + expect( + await hasModelEntry('Project', { + channelId, + projectId: projectFixture.id, + }) + ).toEqual(true); + expect(slackBotWebClient.chat.postEphemeral).toHaveBeenNthCalledWith(1, { + channel: channelId, + text: expect.stringContaining( + `\`${projectFixture.path_with_namespace}\` added` + ), + user: userId, + }); + }); + it('should add project by id', async () => { // Given const channelId = 'channelId'; diff --git a/__tests__/project/listProjects.test.ts b/__tests__/project/listProjects.test.ts index 728dcbe..cd6cb94 100644 --- a/__tests__/project/listProjects.test.ts +++ b/__tests__/project/listProjects.test.ts @@ -50,8 +50,8 @@ describe('project > listProjects', () => { { text: { text: slackifyMarkdown(`**Channel projects:** -- [diaspora/diaspora-project-site](http://example.com/diaspora/diaspora-project-site) -- [diaspora/diaspora-project-site](http://example.com/diaspora/diaspora-project-site)`), +- [diaspora/diaspora-project-site](https://my-git.domain.com/diaspora/diaspora-project-site) +- [diaspora/diaspora-project-site](https://my-git.domain.com/diaspora/diaspora-project-site)`), type: 'mrkdwn', }, type: 'section', diff --git a/src/core/services/gitlab.ts b/src/core/services/gitlab.ts index 7a92b9f..fe42419 100644 --- a/src/core/services/gitlab.ts +++ b/src/core/services/gitlab.ts @@ -22,7 +22,8 @@ import type { GitlabTag } from '@/core/typings/GitlabTag'; import type { GitlabUser, GitlabUserDetails } from '@/core/typings/GitlabUser'; import { getEnvVariable } from '@/core/utils/getEnvVariable'; -const BASE_API_URL = `${getEnvVariable('GITLAB_URL')}/api/v4`; +const GITLAB_URL = getEnvVariable('GITLAB_URL'); +const BASE_API_URL = `${GITLAB_URL}/api/v4`; const GITLAB_TOKEN = getEnvVariable('GITLAB_TOKEN'); const MERGE_REQUEST_ID_REGEX = /^!?\d+$/; const MERGE_REQUEST_URL_REGEX = /^http.*\/merge_requests\/(\d+)$/; @@ -401,6 +402,12 @@ async function searchMergeRequestsByText( } export async function searchProjects(search: string): Promise { + if (search.startsWith(GITLAB_URL)) { + const projectName = search.replace(`${GITLAB_URL}/`, '').split('/').pop(); + return callAPI( + `/projects?search=${encodeURIComponent(projectName || search)}` + ); + } return callAPI(`/projects?search=${encodeURIComponent(search)}`); }