285 lines
8.3 KiB
TypeScript
285 lines
8.3 KiB
TypeScript
import { describe, test, expect, beforeEach } from 'vitest';
|
|
import { SessionCookieStore } from '@gridpilot/automation/infrastructure//automation/auth/SessionCookieStore';
|
|
import type { Cookie } from 'playwright';
|
|
|
|
const logger = console as any;
|
|
|
|
describe('SessionCookieStore - Cookie Validation', () => {
|
|
let cookieStore: SessionCookieStore;
|
|
|
|
beforeEach(() => {
|
|
cookieStore = new SessionCookieStore('test-user-data', logger);
|
|
});
|
|
|
|
describe('validateCookieConfiguration()', () => {
|
|
const targetUrl = 'https://members-ng.iracing.com/jjwtauth/success';
|
|
|
|
test('should succeed when all cookies are valid for target URL', async () => {
|
|
const cookies: Cookie[] = [
|
|
{
|
|
name: 'irsso_members',
|
|
value: 'valid_sso_token',
|
|
domain: '.iracing.com',
|
|
path: '/',
|
|
expires: Date.now() / 1000 + 3600,
|
|
httpOnly: true,
|
|
secure: true,
|
|
sameSite: 'Lax',
|
|
},
|
|
{
|
|
name: 'authtoken_members',
|
|
value: 'valid_auth_token',
|
|
domain: 'members-ng.iracing.com',
|
|
path: '/',
|
|
expires: Date.now() / 1000 + 3600,
|
|
httpOnly: true,
|
|
secure: true,
|
|
sameSite: 'Lax',
|
|
},
|
|
];
|
|
|
|
await cookieStore.write({ cookies, origins: [] });
|
|
const result = cookieStore.validateCookieConfiguration(targetUrl);
|
|
|
|
expect(result.isOk()).toBe(true);
|
|
});
|
|
|
|
test('should fail when cookie domain mismatches target', async () => {
|
|
const cookies: Cookie[] = [
|
|
{
|
|
name: 'irsso_members',
|
|
value: 'valid_token',
|
|
domain: 'example.com',
|
|
path: '/',
|
|
expires: Date.now() / 1000 + 3600,
|
|
httpOnly: true,
|
|
secure: true,
|
|
sameSite: 'Lax',
|
|
},
|
|
];
|
|
|
|
await cookieStore.write({ cookies, origins: [] });
|
|
const result = cookieStore.validateCookieConfiguration(targetUrl);
|
|
|
|
expect(result.isErr()).toBe(true);
|
|
expect(result.unwrapErr().message).toMatch(/domain mismatch/i);
|
|
});
|
|
|
|
test('should fail when cookie path is invalid for target', async () => {
|
|
const cookies: Cookie[] = [
|
|
{
|
|
name: 'irsso_members',
|
|
value: 'valid_token',
|
|
domain: '.iracing.com',
|
|
path: '/invalid/path',
|
|
expires: Date.now() / 1000 + 3600,
|
|
httpOnly: true,
|
|
secure: true,
|
|
sameSite: 'Lax',
|
|
},
|
|
];
|
|
|
|
await cookieStore.write({ cookies, origins: [] });
|
|
const result = cookieStore.validateCookieConfiguration(targetUrl);
|
|
|
|
expect(result.isErr()).toBe(true);
|
|
expect(result.unwrapErr().message).toMatch(/path.*not valid/i);
|
|
});
|
|
|
|
test('should fail when required irsso_members cookie is missing', async () => {
|
|
const cookies: Cookie[] = [
|
|
{
|
|
name: 'authtoken_members',
|
|
value: 'valid_auth_token',
|
|
domain: 'members-ng.iracing.com',
|
|
path: '/',
|
|
expires: Date.now() / 1000 + 3600,
|
|
httpOnly: true,
|
|
secure: true,
|
|
sameSite: 'Lax',
|
|
},
|
|
];
|
|
|
|
await cookieStore.write({ cookies, origins: [] });
|
|
const result = cookieStore.validateCookieConfiguration(targetUrl);
|
|
|
|
expect(result.isErr()).toBe(true);
|
|
expect(result.unwrapErr().message).toMatch(/required.*irsso_members/i);
|
|
});
|
|
|
|
test('should fail when required authtoken_members cookie is missing', async () => {
|
|
const cookies: Cookie[] = [
|
|
{
|
|
name: 'irsso_members',
|
|
value: 'valid_sso_token',
|
|
domain: '.iracing.com',
|
|
path: '/',
|
|
expires: Date.now() / 1000 + 3600,
|
|
httpOnly: true,
|
|
secure: true,
|
|
sameSite: 'Lax',
|
|
},
|
|
];
|
|
|
|
await cookieStore.write({ cookies, origins: [] });
|
|
const result = cookieStore.validateCookieConfiguration(targetUrl);
|
|
|
|
expect(result.isErr()).toBe(true);
|
|
expect(result.unwrapErr().message).toMatch(/required.*authtoken_members/i);
|
|
});
|
|
|
|
test('should fail when no cookies are stored', () => {
|
|
const result = cookieStore.validateCookieConfiguration(targetUrl);
|
|
|
|
expect(result.isErr()).toBe(true);
|
|
expect(result.unwrapErr().message).toMatch(/no cookies/i);
|
|
});
|
|
|
|
test('should validate cookies for members-ng.iracing.com domain', async () => {
|
|
const cookies: Cookie[] = [
|
|
{
|
|
name: 'irsso_members',
|
|
value: 'valid_token',
|
|
domain: 'members-ng.iracing.com',
|
|
path: '/',
|
|
expires: Date.now() / 1000 + 3600,
|
|
httpOnly: true,
|
|
secure: true,
|
|
sameSite: 'Lax',
|
|
},
|
|
{
|
|
name: 'authtoken_members',
|
|
value: 'valid_auth_token',
|
|
domain: 'members-ng.iracing.com',
|
|
path: '/',
|
|
expires: Date.now() / 1000 + 3600,
|
|
httpOnly: true,
|
|
secure: true,
|
|
sameSite: 'Lax',
|
|
},
|
|
];
|
|
|
|
await cookieStore.write({ cookies, origins: [] });
|
|
const result = cookieStore.validateCookieConfiguration(targetUrl);
|
|
|
|
expect(result.isOk()).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('getValidCookiesForUrl()', () => {
|
|
const targetUrl = 'https://members-ng.iracing.com/jjwtauth/success';
|
|
|
|
test('should return only cookies valid for target URL', async () => {
|
|
const cookies: Cookie[] = [
|
|
{
|
|
name: 'valid_cookie',
|
|
value: 'valid_value',
|
|
domain: '.iracing.com',
|
|
path: '/',
|
|
expires: Date.now() / 1000 + 3600,
|
|
httpOnly: true,
|
|
secure: true,
|
|
sameSite: 'Lax',
|
|
},
|
|
{
|
|
name: 'invalid_cookie',
|
|
value: 'invalid_value',
|
|
domain: 'example.com',
|
|
path: '/',
|
|
expires: Date.now() / 1000 + 3600,
|
|
httpOnly: true,
|
|
secure: true,
|
|
sameSite: 'Lax',
|
|
},
|
|
];
|
|
|
|
await cookieStore.write({ cookies, origins: [] });
|
|
const validCookies = cookieStore.getValidCookiesForUrl(targetUrl);
|
|
|
|
expect(validCookies).toHaveLength(1);
|
|
expect(validCookies[0]!.name).toBe('valid_cookie');
|
|
});
|
|
|
|
test('should filter out cookies with mismatched domains', async () => {
|
|
const cookies: Cookie[] = [
|
|
{
|
|
name: 'cookie1',
|
|
value: 'value1',
|
|
domain: '.iracing.com',
|
|
path: '/',
|
|
expires: Date.now() / 1000 + 3600,
|
|
httpOnly: true,
|
|
secure: true,
|
|
sameSite: 'Lax',
|
|
},
|
|
{
|
|
name: 'cookie2',
|
|
value: 'value2',
|
|
domain: '.example.com',
|
|
path: '/',
|
|
expires: Date.now() / 1000 + 3600,
|
|
httpOnly: true,
|
|
secure: true,
|
|
sameSite: 'Lax',
|
|
},
|
|
];
|
|
|
|
await cookieStore.write({ cookies, origins: [] });
|
|
const validCookies = cookieStore.getValidCookiesForUrl(targetUrl);
|
|
|
|
expect(validCookies).toHaveLength(1);
|
|
expect(validCookies[0]!.name).toBe('cookie1');
|
|
});
|
|
|
|
test('should filter out cookies with invalid paths', async () => {
|
|
const cookies: Cookie[] = [
|
|
{
|
|
name: 'valid_path_cookie',
|
|
value: 'value',
|
|
domain: '.iracing.com',
|
|
path: '/',
|
|
expires: Date.now() / 1000 + 3600,
|
|
httpOnly: true,
|
|
secure: true,
|
|
sameSite: 'Lax',
|
|
},
|
|
{
|
|
name: 'invalid_path_cookie',
|
|
value: 'value',
|
|
domain: '.iracing.com',
|
|
path: '/wrong/path',
|
|
expires: Date.now() / 1000 + 3600,
|
|
httpOnly: true,
|
|
secure: true,
|
|
sameSite: 'Lax',
|
|
},
|
|
];
|
|
|
|
await cookieStore.write({ cookies, origins: [] });
|
|
const validCookies = cookieStore.getValidCookiesForUrl(targetUrl);
|
|
|
|
expect(validCookies).toHaveLength(1);
|
|
expect(validCookies[0]!.name).toBe('valid_path_cookie');
|
|
});
|
|
|
|
test('should return empty array when no cookies are valid', async () => {
|
|
const cookies: Cookie[] = [
|
|
{
|
|
name: 'invalid_cookie',
|
|
value: 'value',
|
|
domain: 'example.com',
|
|
path: '/',
|
|
expires: Date.now() / 1000 + 3600,
|
|
httpOnly: true,
|
|
secure: true,
|
|
sameSite: 'Lax',
|
|
},
|
|
];
|
|
|
|
await cookieStore.write({ cookies, origins: [] });
|
|
const validCookies = cookieStore.getValidCookiesForUrl(targetUrl);
|
|
|
|
expect(validCookies).toHaveLength(0);
|
|
});
|
|
});
|
|
}); |