mirror of
https://github.com/fosrl/pangolin.git
synced 2025-05-12 13:20:35 +01:00
Add clean up our few tests and add tests for #228
This commit is contained in:
parent
5871bea706
commit
535b4e1fb1
5 changed files with 195 additions and 57 deletions
|
@ -1,61 +1,5 @@
|
|||
import { cidrToRange, findNextAvailableCidr } from "./ip";
|
||||
|
||||
/**
|
||||
* Compares two objects for deep equality
|
||||
* @param actual The actual value to test
|
||||
* @param expected The expected value to compare against
|
||||
* @param message The message to display if assertion fails
|
||||
* @throws Error if objects are not equal
|
||||
*/
|
||||
export function assertEqualsObj<T>(actual: T, expected: T, message: string): void {
|
||||
const actualStr = JSON.stringify(actual);
|
||||
const expectedStr = JSON.stringify(expected);
|
||||
if (actualStr !== expectedStr) {
|
||||
throw new Error(`${message}\nExpected: ${expectedStr}\nActual: ${actualStr}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two primitive values for equality
|
||||
* @param actual The actual value to test
|
||||
* @param expected The expected value to compare against
|
||||
* @param message The message to display if assertion fails
|
||||
* @throws Error if values are not equal
|
||||
*/
|
||||
export function assertEquals<T>(actual: T, expected: T, message: string): void {
|
||||
if (actual !== expected) {
|
||||
throw new Error(`${message}\nExpected: ${expected}\nActual: ${actual}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if a function throws an expected error
|
||||
* @param fn The function to test
|
||||
* @param expectedError The expected error message or part of it
|
||||
* @param message The message to display if assertion fails
|
||||
* @throws Error if function doesn't throw or throws unexpected error
|
||||
*/
|
||||
export function assertThrows(
|
||||
fn: () => void,
|
||||
expectedError: string,
|
||||
message: string
|
||||
): void {
|
||||
try {
|
||||
fn();
|
||||
throw new Error(`${message}: Expected to throw "${expectedError}"`);
|
||||
} catch (error) {
|
||||
if (!(error instanceof Error)) {
|
||||
throw new Error(`${message}\nUnexpected error type: ${typeof error}`);
|
||||
}
|
||||
|
||||
if (!error.message.includes(expectedError)) {
|
||||
throw new Error(
|
||||
`${message}\nExpected error: ${expectedError}\nActual error: ${error.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
import { assertEquals } from "@test/assert";
|
||||
|
||||
// Test cases
|
||||
function testFindNextAvailableCidr() {
|
||||
|
|
71
server/lib/validators.test.ts
Normal file
71
server/lib/validators.test.ts
Normal file
|
@ -0,0 +1,71 @@
|
|||
import { isValidUrlGlobPattern } from "./validators";
|
||||
import { assertEquals } from "@test/assert";
|
||||
|
||||
function runTests() {
|
||||
console.log('Running URL pattern validation tests...');
|
||||
|
||||
// Test valid patterns
|
||||
assertEquals(isValidUrlGlobPattern('simple'), true, 'Simple path segment should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('simple/path'), true, 'Simple path with slash should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('/leading/slash'), true, 'Path with leading slash should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('path/'), true, 'Path with trailing slash should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('path/*'), true, 'Path with wildcard segment should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('*'), true, 'Single wildcard should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('*/subpath'), true, 'Wildcard with subpath should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('path/*/more'), true, 'Path with wildcard in the middle should be valid');
|
||||
|
||||
// Test with special characters
|
||||
assertEquals(isValidUrlGlobPattern('path-with-dash'), true, 'Path with dash should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('path_with_underscore'), true, 'Path with underscore should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('path.with.dots'), true, 'Path with dots should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('path~with~tilde'), true, 'Path with tilde should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('path!with!exclamation'), true, 'Path with exclamation should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('path$with$dollar'), true, 'Path with dollar should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('path&with&ersand'), true, 'Path with ampersand should be valid');
|
||||
assertEquals(isValidUrlGlobPattern("path'with'quote"), true, "Path with quote should be valid");
|
||||
assertEquals(isValidUrlGlobPattern('path(with)parentheses'), true, 'Path with parentheses should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('path+with+plus'), true, 'Path with plus should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('path,with,comma'), true, 'Path with comma should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('path;with;semicolon'), true, 'Path with semicolon should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('path=with=equals'), true, 'Path with equals should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('path:with:colon'), true, 'Path with colon should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('path@with@at'), true, 'Path with at should be valid');
|
||||
|
||||
// Test with percent encoding
|
||||
assertEquals(isValidUrlGlobPattern('path%20with%20spaces'), true, 'Path with percent-encoded spaces should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('path%2Fwith%2Fencoded%2Fslashes'), true, 'Path with percent-encoded slashes should be valid');
|
||||
|
||||
// Test with wildcards in segments (the fixed functionality)
|
||||
assertEquals(isValidUrlGlobPattern('padbootstrap*'), true, 'Path with wildcard at the end of segment should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('pad*bootstrap'), true, 'Path with wildcard in the middle of segment should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('*bootstrap'), true, 'Path with wildcard at the start of segment should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('multiple*wildcards*in*segment'), true, 'Path with multiple wildcards in segment should be valid');
|
||||
assertEquals(isValidUrlGlobPattern('wild*/cards/in*/different/seg*ments'), true, 'Path with wildcards in different segments should be valid');
|
||||
|
||||
// Test invalid patterns
|
||||
assertEquals(isValidUrlGlobPattern(''), false, 'Empty string should be invalid');
|
||||
assertEquals(isValidUrlGlobPattern('//double/slash'), false, 'Path with double slash should be invalid');
|
||||
assertEquals(isValidUrlGlobPattern('path//end'), false, 'Path with double slash in the middle should be invalid');
|
||||
assertEquals(isValidUrlGlobPattern('invalid<char>'), false, 'Path with invalid characters should be invalid');
|
||||
assertEquals(isValidUrlGlobPattern('invalid|char'), false, 'Path with invalid pipe character should be invalid');
|
||||
assertEquals(isValidUrlGlobPattern('invalid"char'), false, 'Path with invalid quote character should be invalid');
|
||||
assertEquals(isValidUrlGlobPattern('invalid`char'), false, 'Path with invalid backtick character should be invalid');
|
||||
assertEquals(isValidUrlGlobPattern('invalid^char'), false, 'Path with invalid caret character should be invalid');
|
||||
assertEquals(isValidUrlGlobPattern('invalid\\char'), false, 'Path with invalid backslash character should be invalid');
|
||||
assertEquals(isValidUrlGlobPattern('invalid[char]'), false, 'Path with invalid square brackets should be invalid');
|
||||
assertEquals(isValidUrlGlobPattern('invalid{char}'), false, 'Path with invalid curly braces should be invalid');
|
||||
|
||||
// Test invalid percent encoding
|
||||
assertEquals(isValidUrlGlobPattern('invalid%2'), false, 'Path with incomplete percent encoding should be invalid');
|
||||
assertEquals(isValidUrlGlobPattern('invalid%GZ'), false, 'Path with invalid hex in percent encoding should be invalid');
|
||||
assertEquals(isValidUrlGlobPattern('invalid%'), false, 'Path with isolated percent sign should be invalid');
|
||||
|
||||
console.log('All tests passed!');
|
||||
}
|
||||
|
||||
// Run all tests
|
||||
try {
|
||||
runTests();
|
||||
} catch (error) {
|
||||
console.error('Test failed:', error);
|
||||
}
|
67
server/routers/badger/verifySession.test.ts
Normal file
67
server/routers/badger/verifySession.test.ts
Normal file
|
@ -0,0 +1,67 @@
|
|||
import { isPathAllowed } from './verifySession';
|
||||
import { assertEquals } from '@test/assert';
|
||||
|
||||
function runTests() {
|
||||
console.log('Running path matching tests...');
|
||||
|
||||
// Test exact matching
|
||||
assertEquals(isPathAllowed('foo', 'foo'), true, 'Exact match should be allowed');
|
||||
assertEquals(isPathAllowed('foo', 'bar'), false, 'Different segments should not match');
|
||||
assertEquals(isPathAllowed('foo/bar', 'foo/bar'), true, 'Exact multi-segment match should be allowed');
|
||||
assertEquals(isPathAllowed('foo/bar', 'foo/baz'), false, 'Partial multi-segment match should not be allowed');
|
||||
|
||||
// Test with leading and trailing slashes
|
||||
assertEquals(isPathAllowed('/foo', 'foo'), true, 'Pattern with leading slash should match');
|
||||
assertEquals(isPathAllowed('foo/', 'foo'), true, 'Pattern with trailing slash should match');
|
||||
assertEquals(isPathAllowed('/foo/', 'foo'), true, 'Pattern with both leading and trailing slashes should match');
|
||||
assertEquals(isPathAllowed('foo', '/foo/'), true, 'Path with leading and trailing slashes should match');
|
||||
|
||||
// Test simple wildcard matching
|
||||
assertEquals(isPathAllowed('*', 'foo'), true, 'Single wildcard should match any single segment');
|
||||
assertEquals(isPathAllowed('*', 'foo/bar'), true, 'Single wildcard should match multiple segments');
|
||||
assertEquals(isPathAllowed('*/bar', 'foo/bar'), true, 'Wildcard prefix should match');
|
||||
assertEquals(isPathAllowed('foo/*', 'foo/bar'), true, 'Wildcard suffix should match');
|
||||
assertEquals(isPathAllowed('foo/*/baz', 'foo/bar/baz'), true, 'Wildcard in middle should match');
|
||||
|
||||
// Test multiple wildcards
|
||||
assertEquals(isPathAllowed('*/*', 'foo/bar'), true, 'Multiple wildcards should match corresponding segments');
|
||||
assertEquals(isPathAllowed('*/*/*', 'foo/bar/baz'), true, 'Three wildcards should match three segments');
|
||||
assertEquals(isPathAllowed('foo/*/*', 'foo/bar/baz'), true, 'Specific prefix with wildcards should match');
|
||||
assertEquals(isPathAllowed('*/*/baz', 'foo/bar/baz'), true, 'Wildcards with specific suffix should match');
|
||||
|
||||
// Test wildcard consumption behavior
|
||||
assertEquals(isPathAllowed('*', ''), true, 'Wildcard should optionally consume segments');
|
||||
assertEquals(isPathAllowed('foo/*', 'foo'), true, 'Trailing wildcard should be optional');
|
||||
assertEquals(isPathAllowed('*/*', 'foo'), true, 'Multiple wildcards can match fewer segments');
|
||||
assertEquals(isPathAllowed('*/*/*', 'foo/bar'), true, 'Extra wildcards can be skipped');
|
||||
|
||||
// Test complex nested paths
|
||||
assertEquals(isPathAllowed('api/*/users', 'api/v1/users'), true, 'API versioning pattern should match');
|
||||
assertEquals(isPathAllowed('api/*/users/*', 'api/v1/users/123'), true, 'API resource pattern should match');
|
||||
assertEquals(isPathAllowed('api/*/users/*/profile', 'api/v1/users/123/profile'), true, 'Nested API pattern should match');
|
||||
|
||||
// Test for the requested padbootstrap* pattern
|
||||
assertEquals(isPathAllowed('padbootstrap*', 'padbootstrap'), true, 'padbootstrap* should match padbootstrap');
|
||||
assertEquals(isPathAllowed('padbootstrap*', 'padbootstrapv1'), true, 'padbootstrap* should match padbootstrapv1');
|
||||
assertEquals(isPathAllowed('padbootstrap*', 'padbootstrap/files'), false, 'padbootstrap* should not match padbootstrap/files');
|
||||
assertEquals(isPathAllowed('padbootstrap*/*', 'padbootstrap/files'), true, 'padbootstrap*/* should match padbootstrap/files');
|
||||
assertEquals(isPathAllowed('padbootstrap*/files', 'padbootstrapv1/files'), true, 'padbootstrap*/files should not match padbootstrapv1/files (wildcard is segment-based, not partial)');
|
||||
|
||||
// Test wildcard edge cases
|
||||
assertEquals(isPathAllowed('*/*/*/*/*/*', 'a/b'), true, 'Many wildcards can match few segments');
|
||||
assertEquals(isPathAllowed('a/*/b/*/c', 'a/anything/b/something/c'), true, 'Multiple wildcards in pattern should match corresponding segments');
|
||||
|
||||
// Test patterns with partial segment matches
|
||||
assertEquals(isPathAllowed('padbootstrap*', 'padbootstrap-123'), true, 'Wildcards in isPathAllowed should be segment-based, not character-based');
|
||||
assertEquals(isPathAllowed('test*', 'testuser'), true, 'Asterisk as part of segment name is treated as a literal, not a wildcard');
|
||||
assertEquals(isPathAllowed('my*app', 'myapp'), true, 'Asterisk in middle of segment name is treated as a literal, not a wildcard');
|
||||
|
||||
console.log('All tests passed!');
|
||||
}
|
||||
|
||||
// Run all tests
|
||||
try {
|
||||
runTests();
|
||||
} catch (error) {
|
||||
console.error('Test failed:', error);
|
||||
}
|
55
test/assert.ts
Normal file
55
test/assert.ts
Normal file
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* Compares two objects for deep equality
|
||||
* @param actual The actual value to test
|
||||
* @param expected The expected value to compare against
|
||||
* @param message The message to display if assertion fails
|
||||
* @throws Error if objects are not equal
|
||||
*/
|
||||
export function assertEqualsObj<T>(actual: T, expected: T, message: string): void {
|
||||
const actualStr = JSON.stringify(actual);
|
||||
const expectedStr = JSON.stringify(expected);
|
||||
if (actualStr !== expectedStr) {
|
||||
throw new Error(`${message}\nExpected: ${expectedStr}\nActual: ${actualStr}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two primitive values for equality
|
||||
* @param actual The actual value to test
|
||||
* @param expected The expected value to compare against
|
||||
* @param message The message to display if assertion fails
|
||||
* @throws Error if values are not equal
|
||||
*/
|
||||
export function assertEquals<T>(actual: T, expected: T, message: string): void {
|
||||
if (actual !== expected) {
|
||||
throw new Error(`${message}\nExpected: ${expected}\nActual: ${actual}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if a function throws an expected error
|
||||
* @param fn The function to test
|
||||
* @param expectedError The expected error message or part of it
|
||||
* @param message The message to display if assertion fails
|
||||
* @throws Error if function doesn't throw or throws unexpected error
|
||||
*/
|
||||
export function assertThrows(
|
||||
fn: () => void,
|
||||
expectedError: string,
|
||||
message: string
|
||||
): void {
|
||||
try {
|
||||
fn();
|
||||
throw new Error(`${message}: Expected to throw "${expectedError}"`);
|
||||
} catch (error) {
|
||||
if (!(error instanceof Error)) {
|
||||
throw new Error(`${message}\nUnexpected error type: ${typeof error}`);
|
||||
}
|
||||
|
||||
if (!error.message.includes(expectedError)) {
|
||||
throw new Error(
|
||||
`${message}\nExpected error: ${expectedError}\nActual error: ${error.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@
|
|||
"baseUrl": "src",
|
||||
"paths": {
|
||||
"@server/*": ["../server/*"],
|
||||
"@test/*": ["../test/*"],
|
||||
"@app/*": ["*"],
|
||||
"@/*": ["./*"]
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue