-
-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
♻️ refactor: refactor global and share service
- Loading branch information
1 parent
820c15e
commit dd6f00e
Showing
8 changed files
with
196 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { Mock, beforeEach, describe, expect, it, vi } from 'vitest'; | ||
|
||
import { globalService } from '../global'; | ||
|
||
global.fetch = vi.fn(); | ||
|
||
beforeEach(() => { | ||
vi.clearAllMocks(); | ||
}); | ||
|
||
describe('GlobalService', () => { | ||
it('should return the latest version when fetch is successful', async () => { | ||
// Arrange | ||
const mockVersion = '1.0.0'; | ||
(fetch as Mock).mockResolvedValue({ | ||
json: () => Promise.resolve({ 'dist-tags': { latest: mockVersion } }), | ||
}); | ||
|
||
// Act | ||
const version = await globalService.getLatestVersion(); | ||
|
||
// Assert | ||
expect(fetch).toHaveBeenCalledWith('https://registry.npmmirror.com/@lobehub/chat'); | ||
expect(version).toBe(mockVersion); | ||
}); | ||
|
||
it('should return undefined if the latest version is not found in the response', async () => { | ||
// Arrange | ||
(fetch as Mock).mockResolvedValue({ | ||
json: () => Promise.resolve({}), | ||
}); | ||
|
||
// Act | ||
const version = await globalService.getLatestVersion(); | ||
|
||
// Assert | ||
expect(version).toBeUndefined(); | ||
}); | ||
|
||
it('should throw an error when the fetch call fails', async () => { | ||
// Arrange | ||
(fetch as Mock).mockRejectedValue(new Error('Network error')); | ||
|
||
// Act & Assert | ||
await expect(globalService.getLatestVersion()).rejects.toThrow('Network error'); | ||
}); | ||
|
||
it('should handle non-JSON responses gracefully', async () => { | ||
// Arrange | ||
(fetch as Mock).mockResolvedValue({ | ||
json: () => Promise.reject(new SyntaxError('Unexpected token < in JSON at position 0')), | ||
}); | ||
|
||
// Act & Assert | ||
await expect(globalService.getLatestVersion()).rejects.toThrow(SyntaxError); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { Mock, afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; | ||
|
||
import { ShareGPTConversation } from '@/types/share'; | ||
import { parseMarkdown } from '@/utils/parseMarkdown'; | ||
|
||
import { SHARE_GPT_URL, shareGPTService } from '../share'; | ||
|
||
// Mock dependencies | ||
vi.mock('@/utils/parseMarkdown', () => ({ | ||
parseMarkdown: vi.fn(), | ||
})); | ||
|
||
global.fetch = vi.fn(); | ||
|
||
describe('ShareGPTService', () => { | ||
beforeEach(() => { | ||
vi.clearAllMocks(); | ||
}); | ||
|
||
it('should create and return a ShareGPT URL when fetch is successful', async () => { | ||
// Arrange | ||
const mockId = '123abc'; | ||
const conversation: ShareGPTConversation = { | ||
items: [ | ||
{ from: 'human', value: 'Hello' }, | ||
{ from: 'gpt', value: 'Hi there!' }, | ||
], | ||
}; | ||
(parseMarkdown as Mock).mockResolvedValue('Parsed markdown'); | ||
(fetch as Mock).mockResolvedValue({ | ||
json: () => Promise.resolve({ id: mockId }), | ||
}); | ||
|
||
// Act | ||
const url = await shareGPTService.createShareGPTUrl(conversation); | ||
|
||
// Assert | ||
expect(parseMarkdown).toHaveBeenCalledWith('Hi there!'); | ||
expect(fetch).toHaveBeenCalledWith(SHARE_GPT_URL, expect.anything()); | ||
expect(url).toBe(`https://shareg.pt/${mockId}`); | ||
}); | ||
|
||
it('should throw an error when the fetch call fails', async () => { | ||
// Arrange | ||
const conversation: ShareGPTConversation = { | ||
items: [{ from: 'human', value: 'Hello' }], | ||
}; | ||
(fetch as Mock).mockRejectedValue(new Error('Network error')); | ||
|
||
// Act & Assert | ||
await expect(shareGPTService.createShareGPTUrl(conversation)).rejects.toThrow('Network error'); | ||
}); | ||
|
||
it('should not parse markdown for items not from gpt', async () => { | ||
// Arrange | ||
const mockId = '123abc'; | ||
const conversation: ShareGPTConversation = { | ||
items: [ | ||
{ from: 'human', value: 'Hello' }, | ||
{ from: 'human', value: 'How are you?' }, | ||
], | ||
}; | ||
(fetch as Mock).mockResolvedValue({ | ||
json: () => Promise.resolve({ id: mockId }), | ||
}); | ||
|
||
// Act | ||
await shareGPTService.createShareGPTUrl(conversation); | ||
|
||
// Assert | ||
expect(parseMarkdown).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('should throw an error if the response does not contain an id', async () => { | ||
// Arrange | ||
const conversation: ShareGPTConversation = { | ||
items: [{ from: 'human', value: 'Hello' }], | ||
}; | ||
(fetch as Mock).mockResolvedValue({ | ||
json: () => Promise.resolve({}), | ||
}); | ||
|
||
// Act & Assert | ||
await expect(shareGPTService.createShareGPTUrl(conversation)).rejects.toThrow(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
const VERSION_URL = 'https://registry.npmmirror.com/@lobehub/chat'; | ||
|
||
class GlobalService { | ||
/** | ||
* get latest version from npm | ||
*/ | ||
getLatestVersion = async (): Promise<string> => { | ||
const res = await fetch(VERSION_URL); | ||
const data = await res.json(); | ||
|
||
return data['dist-tags']?.latest; | ||
}; | ||
} | ||
|
||
export const globalService = new GlobalService(); |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { ShareGPTConversation } from '@/types/share'; | ||
import { parseMarkdown } from '@/utils/parseMarkdown'; | ||
|
||
export const SHARE_GPT_URL = 'https://sharegpt.com/api/conversations'; | ||
|
||
class ShareGPTService { | ||
public async createShareGPTUrl(conversation: ShareGPTConversation) { | ||
const items = []; | ||
|
||
for (const item of conversation.items) { | ||
items.push({ | ||
from: item.from, | ||
value: item.from === 'gpt' ? await parseMarkdown(item.value) : item.value, | ||
}); | ||
} | ||
|
||
const res = await fetch(SHARE_GPT_URL, { | ||
body: JSON.stringify({ ...conversation, items }), | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
method: 'POST', | ||
}); | ||
|
||
const { id } = await res.json(); | ||
|
||
if (!id) throw new Error('Failed to create ShareGPT URL'); | ||
|
||
// short link to the ShareGPT post | ||
return `https://shareg.pt/${id}`; | ||
} | ||
} | ||
|
||
export const shareGPTService = new ShareGPTService(); |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters