docs: enterprise refactor plan with ralph specs
This commit is contained in:
108
tests/plugins/explorationConfig.test.ts
Normal file
108
tests/plugins/explorationConfig.test.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Unit tests for scope enforcement and auth in PlaywrightAgent.
|
||||
* These tests use the private helper methods indirectly via the agent's behavior
|
||||
* by testing the isExcludedPath, isExternalLink, and isAllowedUrl logic
|
||||
* through subclassing or direct method exposure.
|
||||
*
|
||||
* Since these methods are private, we test observable behavior via
|
||||
* discoverActions and executeAction with mock pages or just verify config logic.
|
||||
*/
|
||||
|
||||
import { ExplorationConfig, DEFAULT_EXPLORATION_CONFIG } from '../../src/core/ExplorationConfig';
|
||||
|
||||
describe('ExplorationConfig', () => {
|
||||
it('has sensible defaults', () => {
|
||||
const cfg = { ...DEFAULT_EXPLORATION_CONFIG };
|
||||
expect(cfg.maxStates).toBe(50);
|
||||
expect(cfg.maxDepth).toBe(5);
|
||||
expect(cfg.actionDelayMs).toBe(500);
|
||||
expect(cfg.sessionTimeoutMs).toBe(300000);
|
||||
expect(cfg.fuzzingEnabled).toBe(true);
|
||||
expect(cfg.fuzzingIntensity).toBe('medium');
|
||||
expect(cfg.auth).toBeNull();
|
||||
expect(cfg.excludedPaths).toEqual([]);
|
||||
expect(cfg.excludedSelectors).toEqual([]);
|
||||
});
|
||||
|
||||
it('accepts cookies auth config', () => {
|
||||
const config: ExplorationConfig = {
|
||||
...DEFAULT_EXPLORATION_CONFIG,
|
||||
auth: {
|
||||
type: 'cookies',
|
||||
cookies: [{ name: 'session', value: 'abc', domain: 'localhost' }],
|
||||
},
|
||||
};
|
||||
expect(config.auth?.type).toBe('cookies');
|
||||
});
|
||||
|
||||
it('accepts headers auth config', () => {
|
||||
const config: ExplorationConfig = {
|
||||
...DEFAULT_EXPLORATION_CONFIG,
|
||||
auth: {
|
||||
type: 'headers',
|
||||
headers: { Authorization: 'Bearer token123' },
|
||||
},
|
||||
};
|
||||
expect(config.auth?.type).toBe('headers');
|
||||
});
|
||||
|
||||
it('accepts login_flow auth config', () => {
|
||||
const config: ExplorationConfig = {
|
||||
...DEFAULT_EXPLORATION_CONFIG,
|
||||
auth: {
|
||||
type: 'login_flow',
|
||||
loginUrl: 'http://app.com/login',
|
||||
usernameSelector: 'input[name="email"]',
|
||||
passwordSelector: 'input[name="password"]',
|
||||
submitSelector: 'button[type="submit"]',
|
||||
username: 'user@test.com',
|
||||
password: 'secret',
|
||||
},
|
||||
};
|
||||
expect(config.auth?.type).toBe('login_flow');
|
||||
});
|
||||
});
|
||||
|
||||
// Helper to test URL-based scope rules (extracted for testability)
|
||||
describe('Scope URL rules', () => {
|
||||
function isExcludedPath(urlOrPath: string, excludedPaths: string[]): boolean {
|
||||
if (excludedPaths.length === 0) return false;
|
||||
try {
|
||||
const parsed = new URL(urlOrPath, 'http://placeholder');
|
||||
return excludedPaths.some((p) => parsed.pathname.startsWith(p));
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function isExternalLink(href: string, currentUrl: string, allowedDomains: string[]): boolean {
|
||||
if (allowedDomains.length === 0) return false;
|
||||
try {
|
||||
const base = new URL(currentUrl);
|
||||
const target = new URL(href, base.origin);
|
||||
return !allowedDomains.includes(target.hostname);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
it('excludes paths correctly', () => {
|
||||
expect(isExcludedPath('http://app.com/logout', ['/logout'])).toBe(true);
|
||||
expect(isExcludedPath('http://app.com/home', ['/logout'])).toBe(false);
|
||||
expect(isExcludedPath('http://app.com/admin/users', ['/admin'])).toBe(true);
|
||||
});
|
||||
|
||||
it('allows paths when no exclusions', () => {
|
||||
expect(isExcludedPath('http://app.com/logout', [])).toBe(false);
|
||||
});
|
||||
|
||||
it('detects external links', () => {
|
||||
expect(isExternalLink('http://external.com/page', 'http://myapp.com', ['myapp.com'])).toBe(true);
|
||||
expect(isExternalLink('/page', 'http://myapp.com', ['myapp.com'])).toBe(false);
|
||||
expect(isExternalLink('http://myapp.com/page', 'http://myapp.com', ['myapp.com'])).toBe(false);
|
||||
});
|
||||
|
||||
it('allows all links when no allowedDomains', () => {
|
||||
expect(isExternalLink('http://external.com/page', 'http://myapp.com', [])).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user