Story 4.1 completed

This commit is contained in:
2026-05-23 23:00:07 +02:00
parent fd0a7868f3
commit de1b33c453
10 changed files with 574 additions and 25 deletions
+33 -2
View File
@@ -28,8 +28,39 @@ const SOCKET_STUB = {
};
/** A representative user object. */
const GM_USER = Object.freeze({ id: 'gm-user-1', name: 'GM', isGM: true });
const PLAYER_USER = Object.freeze({ id: 'player-user-1', name: 'Player', isGM: false });
const createUserWithFlags = (id, name, isGM, flags = {}) => {
const flagStore = { ...flags };
return Object.freeze({
id,
name,
isGM,
/**
* Get a flag value for this user.
* @param {string} scope - The flag scope/namespace
* @param {string} key - The flag key
* @returns {unknown|null} The flag value or null if not found
*/
getFlag: (scope, key) => {
const scopeKey = `${scope}.${key}`;
return flagStore[scopeKey] ?? null;
},
/**
* Set a flag value for this user.
* @param {string} scope - The flag scope/namespace
* @param {string} key - The flag key
* @param {unknown} value - The value to set
* @returns {Promise<unknown>} Resolves when set
*/
setFlag: (scope, key, value) => {
const scopeKey = `${scope}.${key}`;
flagStore[scopeKey] = value;
return Promise.resolve(value);
},
});
};
const GM_USER = createUserWithFlags('gm-user-1', 'GM', true);
const PLAYER_USER = createUserWithFlags('player-user-1', 'Player', false);
/** Minimal game.users map-like stub. */
const USERS_STUB = {
+54
View File
@@ -321,6 +321,60 @@ describe('FoundryAdapter surface delegation', () => {
it('users.current() returns game.user', () => {
expect(adapter.users.current()).toEqual({ id: GM_USER.id, name: GM_USER.name, isGM: true });
});
describe('user flag methods', () => {
it('users.getFlag returns flag value for valid user, scope, and key', () => {
// First set a flag on the GM user
GM_USER.setFlag('video-view-manager', 'testFlag', 'testValue');
const result = adapter.users.getFlag(GM_USER.id, 'video-view-manager', 'testFlag');
expect(result).toBe('testValue');
expect(USERS_STUB.get).toHaveBeenCalledWith(GM_USER.id);
});
it('users.getFlag returns null when flag does not exist', () => {
const result = adapter.users.getFlag(GM_USER.id, 'video-view-manager', 'nonExistentFlag');
expect(result).toBeNull();
});
it('users.getFlag returns null when user does not exist', () => {
const result = adapter.users.getFlag('unknown-user-id', 'video-view-manager', 'testFlag');
expect(result).toBeNull();
expect(USERS_STUB.get).toHaveBeenCalledWith('unknown-user-id');
});
it('users.setFlag sets flag value for valid user', async () => {
const promise = adapter.users.setFlag(PLAYER_USER.id, 'video-view-manager', 'reactionCamEnabled', true);
expect(promise).not.toBeNull();
await promise;
expect(USERS_STUB.get).toHaveBeenCalledWith(PLAYER_USER.id);
// Verify the flag was set
expect(PLAYER_USER.getFlag('video-view-manager', 'reactionCamEnabled')).toBe(true);
});
it('users.setFlag returns null when user does not exist', () => {
const promise = adapter.users.setFlag('unknown-user-id', 'video-view-manager', 'testFlag', true);
expect(promise).toBeNull();
expect(USERS_STUB.get).toHaveBeenCalledWith('unknown-user-id');
});
it('users.getFlagModule returns module-scoped flag', () => {
GM_USER.setFlag('video-view-manager', 'hpReactiveCamStylingEnabled', false);
const result = adapter.users.getFlagModule(GM_USER.id, 'hpReactiveCamStylingEnabled');
expect(result).toBe(false);
});
it('users.getFlagModule returns null when flag does not exist', () => {
const result = adapter.users.getFlagModule(GM_USER.id, 'nonExistentFlag');
expect(result).toBeNull();
});
it('users.setFlagModule sets module-scoped flag', async () => {
const promise = adapter.users.setFlagModule(PLAYER_USER.id, 'reactionCamEnabled', true);
expect(promise).not.toBeNull();
await promise;
expect(PLAYER_USER.getFlag('video-view-manager', 'reactionCamEnabled')).toBe(true);
});
});
});
describe('scenes surface', () => {