gameglue 1.1.1 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,106 @@
1
+ // Test fixtures for GameGlueJS SDK
2
+
3
+ // Helper to create a JWT with custom payload
4
+ function createMockJwt(payload, expiresInSeconds = 3600) {
5
+ const header = { alg: 'RS256', typ: 'JWT' };
6
+ const now = Math.floor(Date.now() / 1000);
7
+ const defaultPayload = {
8
+ sub: 'user-123',
9
+ exp: now + expiresInSeconds,
10
+ iat: now,
11
+ aud: 'gameglue-client',
12
+ iss: 'https://auth.gameglue.gg/realms/GameGlue',
13
+ scope: 'openid gg:broadcast msfs:read',
14
+ ...payload
15
+ };
16
+
17
+ const base64Header = Buffer.from(JSON.stringify(header)).toString('base64url');
18
+ const base64Payload = Buffer.from(JSON.stringify(defaultPayload)).toString('base64url');
19
+ // Fake signature (not cryptographically valid, but works for decoding tests)
20
+ const signature = 'fake_signature_for_testing';
21
+
22
+ return `${base64Header}.${base64Payload}.${signature}`;
23
+ }
24
+
25
+ // Valid access token (expires in 1 hour)
26
+ const validAccessToken = createMockJwt({ sub: 'user-123' }, 3600);
27
+
28
+ // Expired access token
29
+ const expiredAccessToken = createMockJwt({ sub: 'user-123' }, -100);
30
+
31
+ // Valid refresh token
32
+ const validRefreshToken = createMockJwt({ sub: 'user-123', type: 'refresh' }, 86400);
33
+
34
+ // Mock user configuration
35
+ const mockConfig = {
36
+ clientId: 'test-client-id',
37
+ redirect_uri: 'http://localhost:3000/callback',
38
+ scopes: ['msfs:read', 'gg:broadcast']
39
+ };
40
+
41
+ // Mock listener configuration
42
+ const mockListenerConfig = {
43
+ gameId: 'msfs',
44
+ userId: 'user-123',
45
+ fields: ['altitude', 'airspeed', 'heading']
46
+ };
47
+
48
+ // Mock socket instance
49
+ function createMockSocket() {
50
+ const eventHandlers = {};
51
+ const ioEventHandlers = {};
52
+
53
+ return {
54
+ auth: { token: null },
55
+ connected: true,
56
+ on: jest.fn((event, handler) => {
57
+ eventHandlers[event] = handler;
58
+ }),
59
+ emit: jest.fn((event, data, callback) => {
60
+ // Simulate successful responses
61
+ if (callback) {
62
+ if (event === 'listen') {
63
+ callback(null, { status: 'success' });
64
+ } else if (event === 'listen-update') {
65
+ callback(null, { status: 'success' });
66
+ } else if (event === 'set') {
67
+ callback(null, { status: 'success' });
68
+ } else {
69
+ callback(null, { status: 'success' });
70
+ }
71
+ }
72
+ }),
73
+ timeout: jest.fn(function() {
74
+ return this;
75
+ }),
76
+ disconnect: jest.fn(),
77
+ io: {
78
+ on: jest.fn((event, handler) => {
79
+ ioEventHandlers[event] = handler;
80
+ })
81
+ },
82
+ // Helpers for tests to trigger events
83
+ _trigger: (event, data) => {
84
+ if (eventHandlers[event]) {
85
+ eventHandlers[event](data);
86
+ }
87
+ },
88
+ _triggerIo: (event, data) => {
89
+ if (ioEventHandlers[event]) {
90
+ ioEventHandlers[event](data);
91
+ }
92
+ },
93
+ _getHandler: (event) => eventHandlers[event],
94
+ _getIoHandler: (event) => ioEventHandlers[event]
95
+ };
96
+ }
97
+
98
+ module.exports = {
99
+ createMockJwt,
100
+ validAccessToken,
101
+ expiredAccessToken,
102
+ validRefreshToken,
103
+ mockConfig,
104
+ mockListenerConfig,
105
+ createMockSocket
106
+ };
@@ -0,0 +1,50 @@
1
+ // Jest setup file for GameGlueJS SDK
2
+
3
+ // Create a proper localStorage mock with internal store
4
+ let localStore = {};
5
+
6
+ const localStorageMock = {
7
+ getItem: jest.fn((key) => localStore[key] || null),
8
+ setItem: jest.fn((key, value) => {
9
+ localStore[key] = String(value);
10
+ }),
11
+ removeItem: jest.fn((key) => {
12
+ delete localStore[key];
13
+ }),
14
+ clear: jest.fn(() => {
15
+ localStore = {};
16
+ }),
17
+ get length() {
18
+ return Object.keys(localStore).length;
19
+ },
20
+ key: jest.fn((i) => Object.keys(localStore)[i] || null)
21
+ };
22
+
23
+ // Override localStorage on window (jsdom provides window)
24
+ Object.defineProperty(window, 'localStorage', {
25
+ value: localStorageMock,
26
+ writable: true
27
+ });
28
+
29
+ // Also set on global for Node environment
30
+ Object.defineProperty(global, 'localStorage', {
31
+ value: localStorageMock,
32
+ writable: true
33
+ });
34
+
35
+ // Mock window.history.pushState
36
+ window.history.pushState = jest.fn();
37
+
38
+ // Reset mocks and store before each test
39
+ beforeEach(() => {
40
+ localStore = {};
41
+ localStorageMock.getItem.mockClear();
42
+ localStorageMock.setItem.mockClear();
43
+ localStorageMock.removeItem.mockClear();
44
+ localStorageMock.clear.mockClear();
45
+
46
+ // Reset window.location.hash using the proper jsdom approach
47
+ window.location.hash = '';
48
+
49
+ jest.clearAllMocks();
50
+ });
@@ -0,0 +1,64 @@
1
+ const { storage, isBrowser } = require('./utils');
2
+
3
+ describe('utils', () => {
4
+ describe('isBrowser', () => {
5
+ it('should return false in Node.js/Jest environment', () => {
6
+ // In Jest (Node.js), process is defined, so isBrowser returns false
7
+ const result = isBrowser();
8
+ expect(result).toBe(false);
9
+ });
10
+
11
+ it('should return boolean', () => {
12
+ const result = isBrowser();
13
+ expect(typeof result).toBe('boolean');
14
+ });
15
+ });
16
+
17
+ describe('storage', () => {
18
+ describe('in Node.js environment (isBrowser = false)', () => {
19
+ // In Jest, isBrowser() returns false, so storage uses in-memory map
20
+
21
+ beforeEach(() => {
22
+ // Clear storage by setting and getting values
23
+ // The in-memory store persists between tests within a module
24
+ });
25
+
26
+ describe('set', () => {
27
+ it('should store a value', () => {
28
+ storage.set('test-key', 'test-value');
29
+ const result = storage.get('test-key');
30
+ expect(result).toBe('test-value');
31
+ });
32
+
33
+ it('should handle various value types', () => {
34
+ storage.set('string-key', 'string-value');
35
+ storage.set('number-key', '12345');
36
+ storage.set('token-key', 'eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ0ZXN0In0.sig');
37
+
38
+ expect(storage.get('string-key')).toBe('string-value');
39
+ expect(storage.get('number-key')).toBe('12345');
40
+ expect(storage.get('token-key')).toBe('eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ0ZXN0In0.sig');
41
+ });
42
+
43
+ it('should overwrite existing values', () => {
44
+ storage.set('overwrite-key', 'initial');
45
+ storage.set('overwrite-key', 'updated');
46
+ expect(storage.get('overwrite-key')).toBe('updated');
47
+ });
48
+ });
49
+
50
+ describe('get', () => {
51
+ it('should retrieve a stored value', () => {
52
+ storage.set('retrieve-key', 'retrieve-value');
53
+ const result = storage.get('retrieve-key');
54
+ expect(result).toBe('retrieve-value');
55
+ });
56
+
57
+ it('should return undefined for non-existent keys', () => {
58
+ const result = storage.get('definitely-non-existent-key-' + Date.now());
59
+ expect(result).toBeUndefined();
60
+ });
61
+ });
62
+ });
63
+ });
64
+ });