diff --git a/packages/shared/package.json b/packages/shared/package.json index a15ef6d..b3b3ac7 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -7,9 +7,11 @@ "types": "./src/index.ts", "scripts": { "lint": "eslint src/", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit", + "test": "vitest run" }, "devDependencies": { - "typescript": "^5.4.0" + "typescript": "^5.4.0", + "vitest": "^2.0.0" } } diff --git a/packages/shared/src/platforms.test.ts b/packages/shared/src/platforms.test.ts new file mode 100644 index 0000000..d1ff86b --- /dev/null +++ b/packages/shared/src/platforms.test.ts @@ -0,0 +1,76 @@ +import { describe, it, expect } from 'vitest'; +import { + PLATFORMS, + getAllPlatforms, + getPlatform, + getProfileUrl, + getWebViewUrl, + getDeepLinkUrl, +} from './platforms'; + +// ─── StackOverflow Platform Tests ─── + +describe('stackoverflow platform', () => { + it('should exist in PLATFORMS registry', () => { + expect(PLATFORMS.stackoverflow).toBeDefined(); + }); + + it('should have correct platform definition', () => { + const so = PLATFORMS.stackoverflow; + expect(so.id).toBe('stackoverflow'); + expect(so.name).toBe('Stack Overflow'); + expect(so.icon).toBe('stackoverflow'); + expect(so.color).toBe('#F58025'); + expect(so.urlPattern).toBe('https://stackoverflow.com/users/{username}'); + expect(so.followStrategy).toBe('link'); + expect(so.deepLinkPattern).toBeNull(); + expect(so.webViewUrlPattern).toBeNull(); + expect(so.oauthScopes).toEqual([]); + expect(so.usesFullUrl).toBe(false); + expect(so.usernamePlaceholder).toBeTruthy(); + }); + + it('should be included in getAllPlatforms()', () => { + const all = getAllPlatforms(); + const so = all.find((p) => p.id === 'stackoverflow'); + expect(so).toBeDefined(); + expect(so!.name).toBe('Stack Overflow'); + }); + + it('should be retrievable via getPlatform()', () => { + const so = getPlatform('stackoverflow'); + expect(so).toBeDefined(); + expect(so!.id).toBe('stackoverflow'); + }); +}); + +// ─── getProfileUrl Tests for StackOverflow ─── + +describe('getProfileUrl – stackoverflow', () => { + it('should generate correct URL with user ID and display name', () => { + const url = getProfileUrl('stackoverflow', '1234/user'); + expect(url).toBe('https://stackoverflow.com/users/1234/user'); + }); + + it('should generate correct URL with numeric ID only', () => { + const url = getProfileUrl('stackoverflow', '56789'); + expect(url).toBe('https://stackoverflow.com/users/56789'); + }); + + it('should return empty string for unknown platform', () => { + const url = getProfileUrl('nonexistent', '1234'); + expect(url).toBe(''); + }); +}); + +// ─── getWebViewUrl / getDeepLinkUrl for StackOverflow ─── + +describe('getWebViewUrl / getDeepLinkUrl – stackoverflow', () => { + it('should return null for webViewUrl (not supported)', () => { + expect(getWebViewUrl('stackoverflow', '1234/user')).toBeNull(); + }); + + it('should return null for deepLinkUrl (not supported)', () => { + expect(getDeepLinkUrl('stackoverflow', '1234/user')).toBeNull(); + }); +}); diff --git a/packages/shared/src/platforms.ts b/packages/shared/src/platforms.ts index 52b07aa..a218957 100644 --- a/packages/shared/src/platforms.ts +++ b/packages/shared/src/platforms.ts @@ -175,6 +175,19 @@ export const PLATFORMS: Record = { usernamePlaceholder: 'e.g. hacker', usesFullUrl: false, }, + stackoverflow: { + id: 'stackoverflow', + name: 'Stack Overflow', + icon: 'stackoverflow', + color: '#F58025', + urlPattern: 'https://stackoverflow.com/users/{username}', + deepLinkPattern: null, + webViewUrlPattern: null, + followStrategy: 'link', + oauthScopes: [], + usernamePlaceholder: 'e.g. 1234/username', + usesFullUrl: false, + }, discord: { id: 'discord', name: 'Discord', diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2637abe..f7b0958 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -221,6 +221,9 @@ importers: typescript: specifier: ^5.4.0 version: 5.9.3 + vitest: + specifier: ^2.0.0 + version: 2.1.9(@types/node@22.19.15)(terser@5.46.0) packages: