Spaces:
Sleeping
Sleeping
File size: 5,972 Bytes
e0e1da7 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | // Setup testing database environment variables BEFORE any imports
process.env.DB_MODE = 'sqlite';
process.env.SQLITE_DB_PATH = './test_database.db';
// Clear Supabase keys to force SQLite mode
process.env.SUPABASE_URL = '';
process.env.SUPABASE_KEY = '';
process.env.SUPABASE_SERVICE_ROLE_KEY = '';
// Mock environment variables for Twitch client
process.env.TWITCH_CLIENT_ID = 'mocked_client_id';
process.env.TWITCH_CLIENT_SECRET = 'mocked_client_secret';
import Database from 'better-sqlite3';
import fs from 'fs';
import axios from 'axios';
// Clean up test database
if (fs.existsSync('./test_database.db')) {
fs.unlinkSync('./test_database.db');
}
const sqliteDb = new Database('./test_database.db');
// Create settings table
sqliteDb.exec(`
CREATE TABLE IF NOT EXISTS settings (
key TEXT PRIMARY KEY,
value TEXT NOT NULL
);
`);
// Insert initial expired token and refresh token
sqliteDb.prepare(`
INSERT INTO settings (key, value)
VALUES ('twitch_streamer_access_token', 'expired_token_value')
`).run();
sqliteDb.prepare(`
INSERT INTO settings (key, value)
VALUES ('twitch_streamer_refresh_token', 'valid_refresh_token_value')
`).run();
// Mock Axios methods
let validateCalls = 0;
let refreshCalls = 0;
let refreshParamsReceived = null;
axios.get = async (url, config) => {
if (url === 'https://id.twitch.tv/oauth2/validate') {
validateCalls++;
const authHeader = config?.headers?.Authorization;
if (authHeader === 'Bearer valid_mocked_token') {
// Mock success for valid token
return { data: { client_id: 'mocked_client_id' } };
} else {
// Mock expiration/invalid token error
const err = new Error('Unauthorized');
err.response = { status: 401, data: { message: 'invalid oauth token' } };
throw err;
}
}
throw new Error(`Unexpected GET request to ${url}`);
};
axios.post = async (url, data, config) => {
if (url === 'https://id.twitch.tv/oauth2/token') {
refreshCalls++;
refreshParamsReceived = config?.params;
return {
data: {
access_token: 'new_refreshed_access_token',
refresh_token: 'new_refreshed_refresh_token'
}
};
}
throw new Error(`Unexpected POST request to ${url}`);
};
// Dynamically import db.js and eventsub.js so they read correct environment variables and use the mocked axios
const { getSetting } = await import('../db.js');
const { getOrRefreshAccessToken } = await import('../eventsub.js');
async function runTest() {
console.log('--- STARTING TOKEN REFRESH TEST ---');
// Scenario 1: Initial call with expired token. Should fail validate, call refresh, and return new token.
console.log('Scenario 1: Testing token validation failure and refresh flow...');
const token = await getOrRefreshAccessToken();
console.log('Returned token:', token);
console.log('Validate calls:', validateCalls);
console.log('Refresh calls:', refreshCalls);
console.log('Params received on refresh:', refreshParamsReceived);
// Assertions
if (token !== 'new_refreshed_access_token') {
console.error('FAIL: Expected new refreshed access token, got:', token);
process.exit(1);
}
if (validateCalls !== 1) {
console.error('FAIL: Expected 1 validate call, got:', validateCalls);
process.exit(1);
}
if (refreshCalls !== 1) {
console.error('FAIL: Expected 1 refresh call, got:', refreshCalls);
process.exit(1);
}
if (!refreshParamsReceived || refreshParamsReceived.refresh_token !== 'valid_refresh_token_value') {
console.error('FAIL: Incorrect refresh token sent in params:', refreshParamsReceived);
process.exit(1);
}
// Verify DB updated settings
const dbAccessToken = sqliteDb.prepare("SELECT value FROM settings WHERE key = 'twitch_streamer_access_token'").get()?.value;
const dbRefreshToken = sqliteDb.prepare("SELECT value FROM settings WHERE key = 'twitch_streamer_refresh_token'").get()?.value;
console.log('DB Access Token:', dbAccessToken);
console.log('DB Refresh Token:', dbRefreshToken);
if (dbAccessToken !== 'new_refreshed_access_token' || dbRefreshToken !== 'new_refreshed_refresh_token') {
console.error('FAIL: Settings not updated in database correctly');
process.exit(1);
}
// Scenario 2: Subsequent call with the now valid token. Should validate successfully and not call refresh.
console.log('Scenario 2: Testing valid token bypasses refresh...');
// Update mock token validation check to succeed for this new token
axios.get = async (url, config) => {
if (url === 'https://id.twitch.tv/oauth2/validate') {
validateCalls++;
const authHeader = config?.headers?.Authorization;
if (authHeader === 'Bearer new_refreshed_access_token') {
return { data: { client_id: 'mocked_client_id' } };
}
const err = new Error('Unauthorized');
err.response = { status: 401 };
throw err;
}
throw new Error(`Unexpected GET request to ${url}`);
};
const tokenScenario2 = await getOrRefreshAccessToken();
console.log('Scenario 2 Returned token:', tokenScenario2);
console.log('Scenario 2 Validate calls total:', validateCalls);
console.log('Scenario 2 Refresh calls total:', refreshCalls);
if (tokenScenario2 !== 'new_refreshed_access_token') {
console.error('FAIL: Expected token to remain new_refreshed_access_token, got:', tokenScenario2);
process.exit(1);
}
if (validateCalls !== 2) {
console.error('FAIL: Expected validate calls to increment to 2, got:', validateCalls);
process.exit(1);
}
if (refreshCalls !== 1) {
console.error('FAIL: Expected refresh calls to remain 1, got:', refreshCalls);
process.exit(1);
}
console.log('SUCCESS: Token refresh flow successfully verified and tested!');
// Clean up
sqliteDb.close();
if (fs.existsSync('./test_database.db')) {
fs.unlinkSync('./test_database.db');
}
}
runTest().catch(err => {
console.error('Test crashed:', err);
process.exit(1);
});
|