-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #167 from OneBusAway/more-tests
More tests
- Loading branch information
Showing
5 changed files
with
331 additions
and
2 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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
import { describe, it, expect, vi, beforeEach } from 'vitest'; | ||
import onebusaway from 'onebusaway-sdk'; | ||
import { handleOBAResponse } from '$lib/obaSdk'; | ||
import { error, json } from '@sveltejs/kit'; | ||
|
||
// Mock the onebusaway-sdk | ||
vi.mock('onebusaway-sdk'); | ||
|
||
// Mock @sveltejs/kit error and json functions | ||
vi.mock('@sveltejs/kit', () => ({ | ||
error: vi.fn((status, message) => { | ||
throw new Error(message); | ||
}), | ||
json: vi.fn((data) => ({ | ||
status: 200, | ||
body: data | ||
})) | ||
})); | ||
|
||
// Mock environment variables | ||
vi.mock('$env/static/public', () => ({ | ||
PUBLIC_OBA_SERVER_URL: 'https://test-api.example.com' | ||
})); | ||
|
||
vi.mock('$env/static/private', () => ({ | ||
PRIVATE_OBA_API_KEY: 'test-api-key' | ||
})); | ||
|
||
describe('OneBusAway Client', () => { | ||
beforeEach(() => { | ||
vi.clearAllMocks(); | ||
}); | ||
|
||
describe('OBA Client Initialization', () => { | ||
it('should initialize with correct configuration', () => { | ||
new onebusaway({ | ||
baseURL: 'https://test-api.example.com', | ||
apiKey: 'test-api-key' | ||
}); | ||
|
||
expect(onebusaway).toHaveBeenCalledWith({ | ||
baseURL: 'https://test-api.example.com', | ||
apiKey: 'test-api-key' | ||
}); | ||
}); | ||
}); | ||
|
||
describe('handleOBAResponse', () => { | ||
it('should return JSON response when status code is 200', () => { | ||
const mockResponse = { | ||
code: 200, | ||
data: { | ||
stops: [] | ||
} | ||
}; | ||
|
||
const result = handleOBAResponse(mockResponse, 'stops'); | ||
expect(json).toHaveBeenCalledWith(mockResponse); | ||
expect(result.status).toBe(200); | ||
expect(result.body).toEqual(mockResponse); | ||
}); | ||
|
||
it('should throw error when status code is not 200', () => { | ||
const mockResponse = { | ||
code: 404, | ||
data: null | ||
}; | ||
|
||
expect(() => handleOBAResponse(mockResponse, 'stops')).toThrow(/Unable to fetch stops/); | ||
expect(error).toHaveBeenCalledWith(500, 'Unable to fetch stops.'); | ||
}); | ||
|
||
it('should handle undefined response gracefully', () => { | ||
expect(() => handleOBAResponse(undefined, 'stops')).toThrow(/Unable to fetch stops/); | ||
expect(error).toHaveBeenCalledWith(500, 'Unable to fetch stops.'); | ||
}); | ||
|
||
it('should handle null response gracefully', () => { | ||
expect(() => handleOBAResponse(null, 'stops')).toThrow(/Unable to fetch stops/); | ||
expect(error).toHaveBeenCalledWith(500, 'Unable to fetch stops.'); | ||
}); | ||
|
||
it('should handle response with missing code gracefully', () => { | ||
const mockResponse = { | ||
data: { | ||
stops: [] | ||
} | ||
}; | ||
|
||
expect(() => handleOBAResponse(mockResponse, 'stops')).toThrow(/Unable to fetch stops/); | ||
expect(error).toHaveBeenCalledWith(500, 'Unable to fetch stops.'); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('OBA Client Integration', () => { | ||
let oba; | ||
|
||
beforeEach(() => { | ||
vi.clearAllMocks(); | ||
oba = new onebusaway({ | ||
baseURL: 'https://test-api.example.com', | ||
apiKey: 'test-api-key' | ||
}); | ||
}); | ||
|
||
it('should handle successful API responses', async () => { | ||
const mockApiResponse = { | ||
code: 200, | ||
data: { | ||
stops: [{ id: 1, name: 'Test Stop' }] | ||
} | ||
}; | ||
|
||
// Mock a successful API call | ||
oba.stops = vi.fn().mockResolvedValue(mockApiResponse); | ||
|
||
const response = await oba.stops(); | ||
const result = handleOBAResponse(response, 'stops'); | ||
|
||
expect(json).toHaveBeenCalledWith(mockApiResponse); | ||
expect(result.status).toBe(200); | ||
expect(result.body).toEqual(mockApiResponse); | ||
}); | ||
|
||
it('should handle failed API responses', async () => { | ||
const mockApiResponse = { | ||
code: 500, | ||
data: null | ||
}; | ||
|
||
// Mock a failed API call | ||
oba.stops = vi.fn().mockResolvedValue(mockApiResponse); | ||
|
||
const response = await oba.stops(); | ||
|
||
expect(() => handleOBAResponse(response, 'stops')).toThrow(/Unable to fetch stops/); | ||
expect(error).toHaveBeenCalledWith(500, 'Unable to fetch stops.'); | ||
}); | ||
}); |
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,74 @@ | ||
import { describe, it, expect } from 'vitest'; | ||
import { buildURL } from '$lib/urls'; | ||
|
||
describe('buildURL', () => { | ||
it('should build a basic URL with query parameters', () => { | ||
const result = buildURL('http://example.com', 'api/data', { key: 'value', page: '1' }); | ||
expect(result).toBe('http://example.com/api/data?key=value&page=1'); | ||
}); | ||
|
||
it('should handle trailing slashes in baseURL', () => { | ||
const result = buildURL('http://example.com/', 'api/data', { key: 'value' }); | ||
expect(result).toBe('http://example.com/api/data?key=value'); | ||
}); | ||
|
||
it('should handle leading slashes in path', () => { | ||
const result = buildURL('http://example.com', '/api/data', { key: 'value' }); | ||
expect(result).toBe('http://example.com/api/data?key=value'); | ||
}); | ||
|
||
it('should handle both trailing and leading slashes', () => { | ||
const result = buildURL('http://example.com/', '/api/data', { key: 'value' }); | ||
expect(result).toBe('http://example.com/api/data?key=value'); | ||
}); | ||
|
||
it('should handle multiple trailing slashes in baseURL', () => { | ||
const result = buildURL('http://example.com///', 'api/data', { key: 'value' }); | ||
expect(result).toBe('http://example.com/api/data?key=value'); | ||
}); | ||
|
||
it('should handle multiple leading slashes in path', () => { | ||
const result = buildURL('http://example.com', '///api/data', { key: 'value' }); | ||
expect(result).toBe('http://example.com/api/data?key=value'); | ||
}); | ||
|
||
it('should handle empty query parameters', () => { | ||
const result = buildURL('http://example.com', 'api/data', {}); | ||
expect(result).toBe('http://example.com/api/data?'); | ||
}); | ||
|
||
it('should encode query parameter values', () => { | ||
const result = buildURL('http://example.com', 'api/data', { | ||
key: 'value with spaces', | ||
special: '!@#$%' | ||
}); | ||
expect(result).toBe( | ||
'http://example.com/api/data?key=value+with+spaces&special=%21%40%23%24%25' | ||
); | ||
}); | ||
|
||
it('should convert undefined values to "undefined" string', () => { | ||
const result = buildURL('http://example.com', 'api/data', { key: undefined, value: 'test' }); | ||
expect(result).toBe('http://example.com/api/data?key=undefined&value=test'); | ||
}); | ||
|
||
it('should convert null values to "null" string', () => { | ||
const result = buildURL('http://example.com', 'api/data', { key: null, value: 'test' }); | ||
expect(result).toBe('http://example.com/api/data?key=null&value=test'); | ||
}); | ||
|
||
it('should convert array to comma-separated string', () => { | ||
const result = buildURL('http://example.com', 'api/data', { items: ['a', 'b', 'c'] }); | ||
expect(result).toBe('http://example.com/api/data?items=a%2Cb%2Cc'); | ||
}); | ||
|
||
it('should handle boolean values', () => { | ||
const result = buildURL('http://example.com', 'api/data', { isActive: true, isDeleted: false }); | ||
expect(result).toBe('http://example.com/api/data?isActive=true&isDeleted=false'); | ||
}); | ||
|
||
it('should handle number values', () => { | ||
const result = buildURL('http://example.com', 'api/data', { count: 42, price: 19.99 }); | ||
expect(result).toBe('http://example.com/api/data?count=42&price=19.99'); | ||
}); | ||
}); |
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,107 @@ | ||
import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest'; | ||
import { debounce } from '$lib/utils'; | ||
|
||
describe('debounce', () => { | ||
beforeEach(() => { | ||
vi.useFakeTimers(); | ||
}); | ||
|
||
afterEach(() => { | ||
vi.restoreAllMocks(); | ||
}); | ||
|
||
it('should call the function only once after the wait time', async () => { | ||
const mockFn = vi.fn(); | ||
const debouncedFn = debounce(mockFn, 100); | ||
|
||
debouncedFn(); | ||
expect(mockFn).not.toBeCalled(); | ||
|
||
vi.advanceTimersByTime(50); | ||
expect(mockFn).not.toBeCalled(); | ||
|
||
vi.advanceTimersByTime(50); | ||
expect(mockFn).toBeCalledTimes(1); | ||
}); | ||
|
||
it('should reset the timer when called again before wait time', () => { | ||
const mockFn = vi.fn(); | ||
const debouncedFn = debounce(mockFn, 100); | ||
|
||
debouncedFn(); | ||
vi.advanceTimersByTime(50); | ||
debouncedFn(); | ||
vi.advanceTimersByTime(50); | ||
expect(mockFn).not.toBeCalled(); | ||
|
||
vi.advanceTimersByTime(50); | ||
expect(mockFn).toBeCalledTimes(1); | ||
}); | ||
|
||
it('should pass arguments to the debounced function', () => { | ||
const mockFn = vi.fn(); | ||
const debouncedFn = debounce(mockFn, 100); | ||
|
||
debouncedFn('test', 123); | ||
vi.advanceTimersByTime(100); | ||
|
||
expect(mockFn).toBeCalledWith('test', 123); | ||
}); | ||
|
||
it('should pass the latest arguments when called multiple times', () => { | ||
const mockFn = vi.fn(); | ||
const debouncedFn = debounce(mockFn, 100); | ||
|
||
debouncedFn('first', 1); | ||
vi.advanceTimersByTime(50); | ||
|
||
debouncedFn('second', 2); | ||
vi.advanceTimersByTime(100); | ||
|
||
expect(mockFn).toBeCalledTimes(1); | ||
expect(mockFn).toBeCalledWith('second', 2); | ||
}); | ||
|
||
it('should maintain correct context (this binding)', () => { | ||
const context = { | ||
value: 'test', | ||
method: vi.fn(function () { | ||
return this.value; | ||
}) | ||
}; | ||
|
||
const debouncedMethod = debounce(context.method, 100); | ||
context.debouncedMethod = debouncedMethod; | ||
|
||
context.debouncedMethod(); | ||
vi.advanceTimersByTime(100); | ||
|
||
expect(context.method).toBeCalledTimes(1); | ||
expect(context.method.mock.results[0].value).toBe('test'); | ||
}); | ||
|
||
it('should handle zero wait time', () => { | ||
const mockFn = vi.fn(); | ||
const debouncedFn = debounce(mockFn, 0); | ||
|
||
debouncedFn(); | ||
vi.advanceTimersByTime(0); | ||
|
||
expect(mockFn).toBeCalledTimes(1); | ||
}); | ||
|
||
it('should handle multiple rapid calls', () => { | ||
const mockFn = vi.fn(); | ||
const debouncedFn = debounce(mockFn, 100); | ||
|
||
debouncedFn(); | ||
debouncedFn(); | ||
debouncedFn(); | ||
debouncedFn(); | ||
debouncedFn(); | ||
|
||
vi.advanceTimersByTime(100); | ||
|
||
expect(mockFn).toBeCalledTimes(1); | ||
}); | ||
}); |