Skip to content

Commit cbca792

Browse files
committed
feat: implement testing infrastructure
1 parent fad7c3a commit cbca792

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/**
2+
* @fileoverview Unit tests for the providers utility module.
3+
* @see {@link file://../../../src/features/connections/utils/providers.ts} - Source module
4+
* @module tests/unit/providers
5+
*/
6+
7+
import { describe, it, expect } from 'vitest';
8+
import { parseConnectionUrl } from '@/features/connections/utils/providers';
9+
10+
describe('parseConnectionUrl', () => {
11+
describe('exact protocol matching', () => {
12+
it('should match postgres protocol exactly', () => {
13+
const result = parseConnectionUrl('postgres://user:pass@localhost:5432/db');
14+
expect(result?.type).toBe('postgres');
15+
});
16+
17+
it('should match postgresql protocol exactly', () => {
18+
const result = parseConnectionUrl('postgresql://user:pass@localhost:5432/db');
19+
expect(result?.type).toBe('postgres');
20+
});
21+
22+
it('should match mysql protocol exactly', () => {
23+
const result = parseConnectionUrl('mysql://user:pass@localhost:3306/db');
24+
expect(result?.type).toBe('mysql');
25+
});
26+
27+
it('should match sqlite protocol exactly', () => {
28+
const result = parseConnectionUrl('sqlite://user:pass@localhost/db');
29+
expect(result?.type).toBe('sqlite');
30+
});
31+
32+
it('should match libsql protocol exactly', () => {
33+
const result = parseConnectionUrl('libsql://db.turso.io');
34+
expect(result?.type).toBe('libsql');
35+
});
36+
});
37+
38+
describe('typo detection with normalized Levenshtein distance', () => {
39+
it('should correct postttgr -> postgres (shares prefix, high distance)', () => {
40+
const result = parseConnectionUrl('postttgr://user:pass@localhost:5432/db');
41+
expect(result?.type).toBe('postgres');
42+
});
43+
44+
it('should correct postgress -> postgres (1 extra char)', () => {
45+
const result = parseConnectionUrl('postgress://user:pass@localhost:5432/db');
46+
expect(result?.type).toBe('postgres');
47+
});
48+
49+
it('should correct postgrse -> postgres (transposition)', () => {
50+
const result = parseConnectionUrl('postgrse://user:pass@localhost:5432/db');
51+
expect(result?.type).toBe('postgres');
52+
});
53+
54+
it('should correct myyql -> mysql (1 substitution)', () => {
55+
const result = parseConnectionUrl('myyql://user:pass@localhost:3306/db');
56+
expect(result?.type).toBe('mysql');
57+
});
58+
59+
it('should correct mysq -> mysql (missing char)', () => {
60+
const result = parseConnectionUrl('mysq://user:pass@localhost:3306/db');
61+
expect(result?.type).toBe('mysql');
62+
});
63+
64+
it('should correct sqlit -> sqlite (missing char)', () => {
65+
const result = parseConnectionUrl('sqlit://user:pass@localhost/db');
66+
expect(result?.type).toBe('sqlite');
67+
});
68+
69+
it('should correct libslq -> libsql (transposition)', () => {
70+
const result = parseConnectionUrl('libslq://db.turso.io');
71+
expect(result?.type).toBe('libsql');
72+
});
73+
});
74+
75+
describe('rejection of unsupported protocols', () => {
76+
it('should reject redis (no match)', () => {
77+
const result = parseConnectionUrl('redis://user:pass@localhost:6379/db');
78+
expect(result).toBeNull();
79+
});
80+
81+
it('should reject mongodb (no match)', () => {
82+
const result = parseConnectionUrl('mongodb://user:pass@localhost/db');
83+
expect(result).toBeNull();
84+
});
85+
86+
it('should reject wildly different protocols', () => {
87+
const result = parseConnectionUrl('verywrongprotocol://user:pass@localhost:5432/db');
88+
expect(result).toBeNull();
89+
});
90+
});
91+
92+
describe('edge cases', () => {
93+
it('should reject protocols shorter than 4 characters', () => {
94+
const result = parseConnectionUrl('po://user:pass@localhost/db');
95+
expect(result).toBeNull();
96+
});
97+
98+
it('should be case insensitive (POSTGRES)', () => {
99+
const result = parseConnectionUrl('POSTGRES://user:pass@localhost:5432/db');
100+
expect(result?.type).toBe('postgres');
101+
});
102+
103+
it('should be case insensitive (PostgreSQL)', () => {
104+
const result = parseConnectionUrl('PostgreSQL://user:pass@localhost:5432/db');
105+
expect(result?.type).toBe('postgres');
106+
});
107+
});
108+
109+
describe('URL component extraction', () => {
110+
it('should extract host, port, user, password, and database', () => {
111+
const result = parseConnectionUrl('postgres://myuser:mypass@myhost.com:5433/mydb');
112+
expect(result).toMatchObject({
113+
type: 'postgres',
114+
host: 'myhost.com',
115+
port: 5433,
116+
user: 'myuser',
117+
password: 'mypass',
118+
database: 'mydb',
119+
});
120+
});
121+
122+
it('should detect SSL from query params', () => {
123+
const result = parseConnectionUrl('postgres://user:pass@localhost:5432/db?sslmode=require');
124+
expect(result?.ssl).toBe(true);
125+
});
126+
});
127+
});

apps/desktop/vitest.config.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { defineConfig } from 'vitest/config';
2+
import path from 'path';
3+
4+
export default defineConfig({
5+
test: {
6+
include: ['tests/**/*.test.ts'],
7+
globals: true,
8+
},
9+
resolve: {
10+
alias: {
11+
'@': path.resolve(__dirname, './src'),
12+
},
13+
},
14+
});

0 commit comments

Comments
 (0)