@@ -1,15 +1,9 @@
|
||||
// @ts-nocheck
|
||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
||||
|
||||
// Stub Application globally before importing ScryingPoolStrip
|
||||
// Stub foundry globals before importing ScryingPoolStrip.
|
||||
// Do NOT include foundry.applications.api.ApplicationV2 so the fallback class is used.
|
||||
beforeEach(() => {
|
||||
vi.stubGlobal('Application', class {
|
||||
static get defaultOptions() { return {}; }
|
||||
constructor() { this.position = { left: 0, top: 0 }; this.rendered = false; }
|
||||
render() {}
|
||||
close() {}
|
||||
activateListeners() {}
|
||||
});
|
||||
vi.stubGlobal('foundry', {
|
||||
utils: {
|
||||
mergeObject: (base, override) => Object.assign({}, base, override),
|
||||
@@ -182,89 +176,208 @@ describe('ScryingPoolStrip', () => {
|
||||
strip = new ScryingPoolStrip(stateStore, controller, avTileAdapter, adapter);
|
||||
});
|
||||
|
||||
describe('defaultOptions', () => {
|
||||
describe('DEFAULT_OPTIONS', () => {
|
||||
it('has correct id', () => {
|
||||
expect(ScryingPoolStrip.defaultOptions.id).toBe('scrying-pool-strip');
|
||||
expect(ScryingPoolStrip.DEFAULT_OPTIONS.id).toBe('scrying-pool-strip');
|
||||
});
|
||||
|
||||
it('has correct template path', () => {
|
||||
expect(ScryingPoolStrip.defaultOptions.template).toContain('roster-strip.hbs');
|
||||
expect(ScryingPoolStrip.PARTS.strip.template).toContain('roster-strip.hbs');
|
||||
});
|
||||
|
||||
it('is not resizable', () => {
|
||||
expect(ScryingPoolStrip.defaultOptions.resizable).toBe(false);
|
||||
expect(ScryingPoolStrip.DEFAULT_OPTIONS.window?.resizable).toBe(false);
|
||||
});
|
||||
|
||||
it('popOut is true', () => {
|
||||
expect(ScryingPoolStrip.defaultOptions.popOut).toBe(true);
|
||||
it('has title set', () => {
|
||||
expect(ScryingPoolStrip.DEFAULT_OPTIONS.window?.title).toBe('Scrying Pool');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getData()', () => {
|
||||
it('returns participants array', () => {
|
||||
const data = strip.getData();
|
||||
describe('_prepareContext()', () => {
|
||||
it('returns participants array', async () => {
|
||||
const data = await strip._prepareContext({});
|
||||
expect(Array.isArray(data.participants)).toBe(true);
|
||||
});
|
||||
|
||||
it('returns isExpanded property', () => {
|
||||
const data = strip.getData();
|
||||
it('returns isExpanded property', async () => {
|
||||
const data = await strip._prepareContext({});
|
||||
expect(typeof data.isExpanded).toBe('boolean');
|
||||
});
|
||||
|
||||
it('returns isEmpty true when no participants', () => {
|
||||
it('returns isEmpty true when no participants', async () => {
|
||||
adapter.users.all.mockReturnValue([]);
|
||||
const data = strip.getData();
|
||||
const data = await strip._prepareContext({});
|
||||
expect(data.isEmpty).toBe(true);
|
||||
});
|
||||
|
||||
it('returns isEmpty false when participants exist', () => {
|
||||
const data = strip.getData();
|
||||
it('returns isEmpty false when participants exist', async () => {
|
||||
const data = await strip._prepareContext({});
|
||||
expect(data.isEmpty).toBe(false);
|
||||
});
|
||||
|
||||
it('returns hasStreamAccess true when webrtc.getMediaStreamForUser is available (Story 5.1)', () => {
|
||||
it('returns hasStreamAccess true when webrtc.getMediaStreamForUser is available (Story 5.1)', async () => {
|
||||
adapter.webrtc = {
|
||||
getMediaStreamForUser: vi.fn(),
|
||||
};
|
||||
const data = strip.getData();
|
||||
const data = await strip._prepareContext({});
|
||||
expect(data.hasStreamAccess).toBe(true);
|
||||
});
|
||||
|
||||
it('returns hasStreamAccess false when webrtc is null (Story 5.1)', () => {
|
||||
it('returns hasStreamAccess false when webrtc is null (Story 5.1)', async () => {
|
||||
adapter.webrtc = null;
|
||||
const data = strip.getData();
|
||||
const data = await strip._prepareContext({});
|
||||
expect(data.hasStreamAccess).toBe(false);
|
||||
});
|
||||
|
||||
it('returns hasStreamAccess false when webrtc has no getMediaStreamForUser (Story 5.1)', () => {
|
||||
it('returns hasStreamAccess false when webrtc has no getMediaStreamForUser (Story 5.1)', async () => {
|
||||
adapter.webrtc = {};
|
||||
const data = strip.getData();
|
||||
const data = await strip._prepareContext({});
|
||||
expect(data.hasStreamAccess).toBe(false);
|
||||
});
|
||||
|
||||
it('includes current user when showGMSelfFeed is true', () => {
|
||||
it('includes current user when showGMSelfFeed is true', async () => {
|
||||
adapter.settings = { get: vi.fn(() => true) };
|
||||
adapter.users.all.mockReturnValue([{ id: 'u1' }, { id: 'u2' }]);
|
||||
const data = strip.getData();
|
||||
const data = await strip._prepareContext({});
|
||||
expect(data.participants.map(p => p.userId)).toContain('u1');
|
||||
expect(data.participants.map(p => p.userId)).toContain('u2');
|
||||
});
|
||||
|
||||
it('excludes current user when showGMSelfFeed is false', () => {
|
||||
it('excludes current user when showGMSelfFeed is false', async () => {
|
||||
adapter.settings = { get: vi.fn(() => false) };
|
||||
adapter.users.all.mockReturnValue([{ id: 'u1' }, { id: 'u2' }]);
|
||||
const data = strip.getData();
|
||||
const data = await strip._prepareContext({});
|
||||
// u1 is the current user (mocked in beforeEach), should be excluded
|
||||
expect(data.participants.map(p => p.userId)).not.toContain('u1');
|
||||
expect(data.participants.map(p => p.userId)).toContain('u2');
|
||||
});
|
||||
|
||||
it('includes all users when settings is unavailable (defaults to true)', () => {
|
||||
it('includes all users when settings is unavailable (defaults to true)', async () => {
|
||||
// no adapter.settings — fallback to true
|
||||
adapter.users.all.mockReturnValue([{ id: 'u1' }, { id: 'u2' }]);
|
||||
const data = strip.getData();
|
||||
const data = await strip._prepareContext({});
|
||||
expect(data.participants.length).toBe(2);
|
||||
});
|
||||
|
||||
it('excludes hidden participants from the strip to keep it compact', async () => {
|
||||
stateStore.getState.mockImplementation(id => id === 'u1' ? 'hidden' : 'active');
|
||||
adapter.users.all.mockReturnValue([{ id: 'u1' }, { id: 'u2' }]);
|
||||
const data = await strip._prepareContext({});
|
||||
expect(data.participants.map(p => p.userId)).not.toContain('u1');
|
||||
expect(data.participants.map(p => p.userId)).toContain('u2');
|
||||
});
|
||||
|
||||
it('returns isEmpty true when all participants are hidden', async () => {
|
||||
stateStore.getState.mockReturnValue('hidden');
|
||||
adapter.users.all.mockReturnValue([{ id: 'u1' }, { id: 'u2' }]);
|
||||
const data = await strip._prepareContext({});
|
||||
expect(data.isEmpty).toBe(true);
|
||||
expect(data.participants.length).toBe(0);
|
||||
});
|
||||
|
||||
it('returns dockLayout from settings (defaults to vertical-sm when setting is not a string)', async () => {
|
||||
// dockLayout non-string → fallback to vertical-sm; no sizeOverride → canonical size 'sm'
|
||||
adapter.settings = { get: vi.fn(key => key === 'dockLayoutExpanded' ? '' : true) };
|
||||
const data = await strip._prepareContext({});
|
||||
expect(data.dockLayout).toBe('vertical-sm');
|
||||
});
|
||||
|
||||
it('returns dockLayout from settings when setting is a valid string', async () => {
|
||||
// No size override → canonical size from world setting ('md') is used
|
||||
adapter.settings = { get: vi.fn(key => key === 'dockLayout' ? 'horizontal-md' : '') };
|
||||
const data = await strip._prepareContext({});
|
||||
expect(data.dockLayout).toBe('horizontal-md');
|
||||
expect(data.isExpanded).toBe(false);
|
||||
expect(data.showName).toBe(true);
|
||||
});
|
||||
|
||||
it('client size override forces sm even when world layout is md', async () => {
|
||||
adapter.settings = { get: vi.fn(key => key === 'dockLayout' ? 'horizontal-md' : key === 'dockLayoutExpanded' ? 'sm' : '') };
|
||||
const data = await strip._prepareContext({});
|
||||
expect(data.dockLayout).toBe('horizontal-sm');
|
||||
expect(data.showName).toBe(false);
|
||||
});
|
||||
|
||||
it('client size override forces md even when world layout is sm', async () => {
|
||||
adapter.settings = { get: vi.fn(key => key === 'dockLayout' ? 'vertical-sm' : key === 'dockLayoutExpanded' ? 'md' : '') };
|
||||
const data = await strip._prepareContext({});
|
||||
expect(data.dockLayout).toBe('vertical-md');
|
||||
expect(data.isExpanded).toBe(true);
|
||||
});
|
||||
|
||||
it('sets isExpanded=true and showName=true only for vertical-md', async () => {
|
||||
adapter.settings = { get: vi.fn(key => key === 'dockLayout' ? 'vertical-md' : '') };
|
||||
const data = await strip._prepareContext({});
|
||||
expect(data.isExpanded).toBe(true);
|
||||
expect(data.showName).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('_computeStripWidth()', () => {
|
||||
it('returns 85 for vertical-sm', () => {
|
||||
expect(strip._computeStripWidth('vertical-sm', 3)).toBe(85);
|
||||
});
|
||||
|
||||
it('returns 242 for vertical-md', () => {
|
||||
expect(strip._computeStripWidth('vertical-md', 3)).toBe(242);
|
||||
});
|
||||
|
||||
it('returns 85 for unknown layout', () => {
|
||||
expect(strip._computeStripWidth('unknown', 3)).toBe(85);
|
||||
});
|
||||
|
||||
it('scales horizontal-sm width with participant count (max 4 cols)', () => {
|
||||
const w2 = strip._computeStripWidth('horizontal-sm', 2);
|
||||
const w4 = strip._computeStripWidth('horizontal-sm', 4);
|
||||
const w6 = strip._computeStripWidth('horizontal-sm', 6);
|
||||
expect(w4).toBeGreaterThan(w2);
|
||||
expect(w6).toBe(w4); // capped at 4 cols
|
||||
});
|
||||
|
||||
it('horizontal-md tiles are wider than horizontal-sm', () => {
|
||||
const wSm = strip._computeStripWidth('horizontal-sm', 4);
|
||||
const wMd = strip._computeStripWidth('horizontal-md', 4);
|
||||
expect(wMd).toBeGreaterThan(wSm);
|
||||
});
|
||||
});
|
||||
|
||||
describe('_computeStripHeight()', () => {
|
||||
const CHROME = 16 + 29; // grip + toolbar (29 = 28px content + 1px border-bottom)
|
||||
const BORDER_H = 2, GAP = 4, TILE_PAD = 8;
|
||||
|
||||
it('returns auto for vertical layouts', () => {
|
||||
expect(strip._computeStripHeight('vertical-sm', 3)).toBe('auto');
|
||||
expect(strip._computeStripHeight('vertical-md', 3)).toBe('auto');
|
||||
expect(strip._computeStripHeight('unknown', 3)).toBe('auto');
|
||||
});
|
||||
|
||||
it('horizontal-sm: 1 row for ≤4 participants', () => {
|
||||
// 4 tiles, 1 row: CHROME + 83 + 8pad + 2border = 138
|
||||
expect(strip._computeStripHeight('horizontal-sm', 4)).toBe(CHROME + 83 + TILE_PAD + BORDER_H);
|
||||
});
|
||||
|
||||
it('horizontal-sm: 2 rows for 5+ participants', () => {
|
||||
// 5 tiles → cols=4, rows=2: CHROME + 2*83 + 1*4 + 8 + 2 = 225
|
||||
expect(strip._computeStripHeight('horizontal-sm', 5)).toBe(CHROME + 2 * 83 + GAP + TILE_PAD + BORDER_H);
|
||||
});
|
||||
|
||||
it('horizontal-md tiles produce taller rows than horizontal-sm', () => {
|
||||
const hSm = strip._computeStripHeight('horizontal-sm', 4);
|
||||
const hMd = strip._computeStripHeight('horizontal-md', 4);
|
||||
expect(hMd).toBeGreaterThan(hSm);
|
||||
});
|
||||
|
||||
it('mosaic-sm: NxN grid', () => {
|
||||
// n=4 → cols=2, rows=2: CHROME + 2*83 + 1*4 + 8 + 2 = 225
|
||||
expect(strip._computeStripHeight('mosaic-sm', 4)).toBe(CHROME + 2 * 83 + GAP + TILE_PAD + BORDER_H);
|
||||
});
|
||||
|
||||
it('mosaic height grows with participant count', () => {
|
||||
const h4 = strip._computeStripHeight('mosaic-sm', 4);
|
||||
const h9 = strip._computeStripHeight('mosaic-sm', 9);
|
||||
expect(h9).toBeGreaterThan(h4);
|
||||
});
|
||||
});
|
||||
|
||||
describe('_attachVideoStream() (Story 5.1)', () => {
|
||||
|
||||
Reference in New Issue
Block a user