diff --git a/src/__tests__/authenticate-gitee.ts b/src/__tests__/authenticate-gitee.ts new file mode 100644 index 0000000..d5ccd21 --- /dev/null +++ b/src/__tests__/authenticate-gitee.ts @@ -0,0 +1,25 @@ +import { StartTest } from "./helper/start-test"; + +describe('Test Authenticate Gitee', () => { + test('Test Authenticate Gitee', async () => { + const request = StartTest.createGiteeRequest(); + const res = await request.authenticate(); + expect(Object.keys(res)).toEqual([ + 'id', 'login', + 'name', 'avatar_url', + 'url', 'html_url', + 'remark', 'followers_url', + 'following_url', 'gists_url', + 'starred_url', 'subscriptions_url', + 'organizations_url', 'repos_url', + 'events_url', 'received_events_url', + 'type', 'blog', + 'weibo', 'bio', + 'public_repos', 'public_gists', + 'followers', 'following', + 'stared', 'watched', + 'created_at', 'updated_at', + 'email' + ]) + }); +}); \ No newline at end of file diff --git a/src/__tests__/authenticate-github.ts b/src/__tests__/authenticate-github.ts new file mode 100644 index 0000000..e6a2873 --- /dev/null +++ b/src/__tests__/authenticate-github.ts @@ -0,0 +1,26 @@ +import { StartTest } from "./helper/start-test"; + +describe('Test Authenticate Github', () => { + test('Test Authenticate Github', async () => { + const request = StartTest.createGithubRequest(); + const res = await request.authenticate(); + expect(Object.keys(res)).toEqual([ + 'login', 'id', + 'node_id', 'avatar_url', + 'gravatar_id', 'url', + 'html_url', 'followers_url', + 'following_url', 'gists_url', + 'starred_url', 'subscriptions_url', + 'organizations_url', 'repos_url', + 'events_url', 'received_events_url', + 'type', 'site_admin', + 'name', 'company', + 'blog', 'location', + 'email', 'hireable', + 'bio', 'twitter_username', + 'public_repos', 'public_gists', + 'followers', 'following', + 'created_at', 'updated_at' + ]); + }); +}); \ No newline at end of file diff --git a/src/__tests__/authenticate-gitlab.ts b/src/__tests__/authenticate-gitlab.ts new file mode 100644 index 0000000..252b59b --- /dev/null +++ b/src/__tests__/authenticate-gitlab.ts @@ -0,0 +1,50 @@ +import { StartTest } from "./helper/start-test"; + +describe('Test Authenticate Gitlab', () => { + test('Test Authenticate Gitlab', async () => { + const request = StartTest.createGitlabRequest(); + const res = await request.authenticate(); + expect(Object.keys(res)).toEqual([ + 'id', + 'username', + 'name', + 'state', + 'locked', + 'avatar_url', + 'web_url', + 'created_at', + 'bio', + 'location', + 'public_email', + 'skype', + 'linkedin', + 'twitter', + 'discord', + 'website_url', + 'organization', + 'job_title', + 'pronouns', + 'bot', + 'work_information', + 'local_time', + 'last_sign_in_at', + 'confirmed_at', + 'last_activity_on', + 'email', + 'theme_id', + 'color_scheme_id', + 'projects_limit', + 'current_sign_in_at', + 'identities', + 'can_create_group', + 'can_create_project', + 'two_factor_enabled', + 'external', + 'private_profile', + 'commit_email', + 'shared_runners_minutes_limit', + 'extra_shared_runners_minutes_limit', + 'scim_identities' + ]); + }); +}); \ No newline at end of file diff --git a/src/__tests__/authenticate.test.ts b/src/__tests__/authenticate.test.ts deleted file mode 100644 index 672542c..0000000 --- a/src/__tests__/authenticate.test.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { StartTest } from "./helper/start-test"; - -describe('Test Authenticate Function', () => { - test('Test Authenticate Gitee', async () => { - const request = StartTest.createGiteeRequest(); - const res = await request.authenticate(); - expect(Object.keys(res)).toEqual([ - 'id', 'login', - 'name', 'avatar_url', - 'url', 'html_url', - 'remark', 'followers_url', - 'following_url', 'gists_url', - 'starred_url', 'subscriptions_url', - 'organizations_url', 'repos_url', - 'events_url', 'received_events_url', - 'type', 'blog', - 'weibo', 'bio', - 'public_repos', 'public_gists', - 'followers', 'following', - 'stared', 'watched', - 'created_at', 'updated_at', - 'email' - ]) - }); - - test('Test Authenticate Github', async () => { - const request = StartTest.createGithubRequest(); - const res = await request.authenticate(); - expect(Object.keys(res)).toEqual([ - 'login', 'id', - 'node_id', 'avatar_url', - 'gravatar_id', 'url', - 'html_url', 'followers_url', - 'following_url', 'gists_url', - 'starred_url', 'subscriptions_url', - 'organizations_url', 'repos_url', - 'events_url', 'received_events_url', - 'type', 'site_admin', - 'name', 'company', - 'blog', 'location', - 'email', 'hireable', - 'bio', 'twitter_username', - 'public_repos', 'public_gists', - 'followers', 'following', - 'created_at', 'updated_at' - ]); - }); - - test('Test Authenticate Gitlab', async () => { - const request = StartTest.createGitlabRequest(); - const res = await request.authenticate(); - expect(Object.keys(res)).toEqual([ - 'id', - 'username', - 'name', - 'state', - 'locked', - 'avatar_url', - 'web_url', - 'created_at', - 'bio', - 'location', - 'public_email', - 'skype', - 'linkedin', - 'twitter', - 'discord', - 'website_url', - 'organization', - 'job_title', - 'pronouns', - 'bot', - 'work_information', - 'local_time', - 'last_sign_in_at', - 'confirmed_at', - 'last_activity_on', - 'email', - 'theme_id', - 'color_scheme_id', - 'projects_limit', - 'current_sign_in_at', - 'identities', - 'can_create_group', - 'can_create_project', - 'two_factor_enabled', - 'external', - 'private_profile', - 'commit_email', - 'shared_runners_minutes_limit', - 'extra_shared_runners_minutes_limit', - 'scim_identities' - ]); - }); -}); \ No newline at end of file diff --git a/src/__tests__/chat-storage.test.ts b/src/__tests__/chat-storage.test.ts new file mode 100644 index 0000000..6e96e59 --- /dev/null +++ b/src/__tests__/chat-storage.test.ts @@ -0,0 +1,88 @@ +import { ChatStorage } from "./helper/chat-storage"; + +describe('Use Gitlab Test Chat Storage', () => { + const chatStorage = new ChatStorage(); + + test('Test deleteAll Chat', async () => { + await chatStorage.deleteAll(); + const detail = await chatStorage.find(); + expect(detail.length).toEqual(0); + }); + + test('Test create & findById Chat', async () => { + await chatStorage.create({ + participants: ['test-user', 'test-user-update'], + messages: [ + { + from: 'test-user', + to: 'test-user-update', + message: 'hello' + } + ] + }); + const findResult = await chatStorage.find(); + expect(findResult.length).toEqual(1); + + const findByIdResult = await chatStorage.findById(findResult[0].id); + expect(findByIdResult).toEqual(findResult[0]); + }); + + test('Test updateById Chat', async () => { + const findResult = await chatStorage.find(); + const updateResult = await chatStorage.updateById(findResult[0].id, { + participants: ['test-user', 'test-user-update'], + messages: [ + { + from: 'test-user', + to: 'test-user-update', + message: 'hello world' + } + ] + }); + const findByIdResult = await chatStorage.findById(findResult[0].id); + expect(updateResult.participants).toEqual(findByIdResult.participants); + expect(updateResult.messages).toEqual(findByIdResult.messages); + expect(updateResult.id).toEqual(findByIdResult.id); + expect(updateResult.created_at).toEqual(findByIdResult.created_at); + expect(updateResult.updated_at).toEqual(findByIdResult.updated_at); + }); + + test('Test deleteById Chat failed', async () => { + try { + await chatStorage.deleteById(123); + } catch (error: any) { + expect(error.response.data).toEqual({ + "message": "404 Not found" + }); + } + }); + + test('Test updateById Chat failed', async () => { + try { + await chatStorage.updateById(123, { + participants: ['test-user', 'test-user-update'], + messages: [ + { + from: 'test-user', + to: 'test-user-update', + message: 'hello world' + } + ] + }); + } catch (error: any) { + expect(error.response.data).toEqual({ + "message": "404 Not found" + }); + } + }); + + test('Test findById Chat failed', async () => { + try { + await chatStorage.findById(123); + } catch (error: any) { + expect(error.response.data).toEqual({ + "message": "404 Not found" + }); + } + }); +}); \ No newline at end of file diff --git a/src/__tests__/helper/chat-model.ts b/src/__tests__/helper/chat-model.ts new file mode 100644 index 0000000..d7a2784 --- /dev/null +++ b/src/__tests__/helper/chat-model.ts @@ -0,0 +1,6 @@ +import { BaseModel } from "../../storage-lib"; + +export interface ChatModel extends BaseModel { + participants: string[]; + messages: Array<{from: string; to: string; message: string}>; +} \ No newline at end of file diff --git a/src/__tests__/helper/chat-storage.ts b/src/__tests__/helper/chat-storage.ts new file mode 100644 index 0000000..cfd428f --- /dev/null +++ b/src/__tests__/helper/chat-storage.ts @@ -0,0 +1,13 @@ +import { GitlabStorage } from "../../storage-lib"; +import { ChatModel } from "./chat-model"; +import { StartTest } from "./start-test"; + +const options = { + request: StartTest.createGitlabRequest(), + issueNumber: StartTest.GITLAB_NUMBER +} +export class ChatStorage extends GitlabStorage { + constructor() { + super(options); + } +} \ No newline at end of file diff --git a/src/__tests__/helper/start-test.ts b/src/__tests__/helper/start-test.ts index e31b6f0..5e4deca 100644 --- a/src/__tests__/helper/start-test.ts +++ b/src/__tests__/helper/start-test.ts @@ -9,6 +9,8 @@ export class StartTest { static GITHUB_NUMBER = process.env.TEST_GITHUB_NUMBER as string; + static GITLAB_NUMBER = process.env.TEST_GITLAB_NUMBER as string; + static ENCRYPT_KEY = "MySecretPassphrase"; constructor() { @@ -50,7 +52,7 @@ export class StartTest { request: axios, accessToken: process.env.TEST_GITLAB_TOKEN as string, platform: 'gitlab', - projectId: '' + projectId: process.env.TEST_GITLAB_PROJECT_ID as string }); } } \ No newline at end of file diff --git a/src/request-lib/base/base-request.ts b/src/request-lib/base/base-request.ts index 0e26dff..bcc8bac 100644 --- a/src/request-lib/base/base-request.ts +++ b/src/request-lib/base/base-request.ts @@ -39,6 +39,10 @@ export abstract class BaseRequest { return this.sendRequest('PATCH', url, body); } + put(url: string, body: string): Promise { + return this.sendRequest('PUT', url, body); + } + async authenticate() { switch(this.options.platform) { case StoragePlatform.gitee: @@ -72,7 +76,7 @@ export abstract class BaseRequest { case StoragePlatform.github: return `${this.baseUrl}/repos/${this.options.owner}/${this.options.repo}`; case StoragePlatform.gitlab: - return `${this.baseUrl}/api/v4/user`; + return `${this.baseUrl}/api/v4/projects/${this.options.projectId}`; default: throw new Error('Unsupported Platform'); } diff --git a/src/storage-lib/gitlab/gitlab-storage.ts b/src/storage-lib/gitlab/gitlab-storage.ts index e69de29..fd8df2a 100644 --- a/src/storage-lib/gitlab/gitlab-storage.ts +++ b/src/storage-lib/gitlab/gitlab-storage.ts @@ -0,0 +1,91 @@ +import { BaseRequest } from "../../request-lib"; +import { BaseComment } from "../base/base-comment"; +import { BaseModel } from "../base/base-model"; +import { BaseOptions } from "../base/base-options"; +import { BaseStorage } from "../base/base-storage"; +import { PlainObject } from "../base/plain-object"; + +export class GitlabStorage extends BaseStorage { + private endpoint: string; + private request: BaseRequest; + private issueNumber: string; + + constructor(baseOptions: BaseOptions) { + super(baseOptions); + + const { request, issueNumber } = baseOptions; + this.request = request; + this.issueNumber = issueNumber; + this.endpoint = request.getEndpoint(); + + } + + /** + * Retrieves a list of items from the GitLab storage. + * @returns A promise that resolves to an array of items. + */ + async find(): Promise { + const url = `${this.endpoint}/issues/${this.issueNumber}/notes`; + const response = await this.request.get(url); + return response.map((item) => this.deserialize(item)); + } + + /** + * Finds a record by its ID. + * @param id - The ID of the record to find. + * @returns A promise that resolves to the found record. + */ + async findById(id: number): Promise { + const url = `${this.endpoint}/issues/${this.issueNumber}/notes/${id}`; + const response = await this.request.get(url); + return this.deserialize(response); + } + + /** + * Creates a new entry in the GitLab storage. + * + * @param data The data to be stored. + * @returns A promise that resolves to the created entry. + */ + async create(data: PlainObject): Promise { + const url = `${this.endpoint}/issues/${this.issueNumber}/notes`; + const body = this.serialize>(data); + const response = await this.request.post(url, body); + return this.deserialize(response); + } + + /** + * Updates a record by its ID. + * + * @param id - The ID of the record to update. + * @param data - The updated data for the record. + * @returns A promise that resolves to the updated record. + */ + async updateById(id: number, data: PlainObject): Promise { + const url = `${this.endpoint}/issues/${this.issueNumber}/notes/${id}`; + const body = this.serialize>(data); + const response = await this.request.put(url, body); + return this.deserialize(response); + } + + /** + * Deletes a note by its ID. + * @param id - The ID of the note to delete. + * @returns A Promise that resolves when the note is successfully deleted. + */ + async deleteById(id: number): Promise { + const url = `${this.endpoint}/issues/${this.issueNumber}/notes/${id}`; + await this.request.delete(url); + } + + /** + * Deletes all comments associated with the GitLab storage. + * @returns A Promise that resolves when all comments are deleted. + */ + async deleteAll(): Promise { + const findUrl = `${this.endpoint}/issues/${this.issueNumber}/notes`; + const findResult = await this.request.get(findUrl); + await Promise.all(findResult.map((item) => this.deleteById(item.id))); + } + +} \ No newline at end of file diff --git a/src/storage-lib/index.ts b/src/storage-lib/index.ts index 08f4117..8cb7772 100644 --- a/src/storage-lib/index.ts +++ b/src/storage-lib/index.ts @@ -9,4 +9,5 @@ export { GithubOptions } from './github/github-options'; export { GithubStorage } from './github/github-storage'; /** Gitlab */ export { GitlabUser } from './gitlab/gitlab-user'; -export { GitlabOptions } from './gitlab/gitlab-options'; \ No newline at end of file +export { GitlabOptions } from './gitlab/gitlab-options'; +export { GitlabStorage } from './gitlab/gitlab-storage'; \ No newline at end of file