/** * wechatTokenManager.test.js * Unit tests for WeChat Access Token management. */ const { describe, it, before, after } = require('node:test'); const assert = require('node:assert/strict'); // Mock wx environment for WeChat mini game server // The wechatTokenManager uses wx APIs on client, but on server it uses // HTTPS requests to WeChat API. We test the server-side module. const WechatTokenManager = require('../services/wechatTokenManager'); describe('WechatTokenManager', () => { let manager; before(() => { manager = new WechatTokenManager(); }); after(() => { // Clean up any timers if (manager._refreshTimer) { clearInterval(manager._refreshTimer); } }); it('should initialize with no token', () => { assert.strictEqual(manager._accessToken, ''); assert.strictEqual(manager._expiresAt, 0); assert.strictEqual(manager._isAvailable, false); }); it('should report unavailable when no token is set', () => { const available = manager.isAvailable(); assert.strictEqual(available, false); }); it('should report available when valid token is set', () => { manager._accessToken = 'test_token_123'; manager._expiresAt = Date.now() + 7000 * 1000; // 7000 seconds from now manager._isAvailable = true; assert.strictEqual(manager.isAvailable(), true); }); it('should return token when available', () => { manager._accessToken = 'test_token_456'; manager._expiresAt = Date.now() + 7000 * 1000; manager._isAvailable = true; const token = manager.getAccessToken(); assert.strictEqual(token, 'test_token_456'); }); it('should return empty string when token is expired', () => { manager._accessToken = 'expired_token'; manager._expiresAt = Date.now() - 1000; // expired manager._isAvailable = false; const token = manager.getAccessToken(); assert.strictEqual(token, ''); }); it('should handle token refresh failure gracefully', async () => { // Create a manager with invalid appid/secret to test failure const failManager = new WechatTokenManager(); failManager.appId = 'invalid_appid'; failManager.appSecret = 'invalid_secret'; // Override retry delays to speed up test failManager._isRefreshing = false; // The _refreshToken will attempt with retries, but should not throw. // Use a short timeout to avoid long waits. const result = await Promise.race([ failManager._refreshToken(), new Promise((resolve) => setTimeout(() => resolve(false), 5000)), ]); assert.strictEqual(failManager.isAvailable(), false); // Clean up any pending timers failManager.destroy(); }); it('should not leak token in toString', () => { manager._accessToken = 'sensitive_token_xyz'; const str = manager.toString(); assert.strictEqual(str.includes('sensitive_token_xyz'), false); }); });