/
githubmirror
/
pixijs
Обзор
Документация
Войти
/
githubmirror
/
pixijs
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
dev
src/app/__tests__/Application.test.ts
315 строк
9 KB
Zyie
fix: enable proper application reinitialization (#11759)
13 ноя 2025, 16:00
Не верифицирован
13 ноя 2025, 16:00
3e52ac7
Код
Авторство
О чём код?
import { Application } from '../Application'; import { basePath, getApp, nextTick } from '@test-utils'; import { Assets } from '~/assets'; import { extensions, ExtensionType } from '~/extensions'; import { Container, Graphics, Sprite, Text } from '~/scene'; import { GlobalResourceRegistry } from '~/utils'; import type { ApplicationOptions } from '../Application'; describe('Application', () => { describe('LifeCycle', () => { it('should generate application', async () => { expect(Application).toBeInstanceOf(Function); const app = await getApp(); expect(app.stage).toBeInstanceOf(Container); expect(app.renderer).toBeTruthy(); app.destroy(); expect(app.stage).toBeNull(); expect(app.renderer).toBeNull(); }); it('should allow for application to be reinitialized after destroy', async () => { const app = await getApp(); expect(app.stage).toBeInstanceOf(Container); expect(app.renderer).toBeTruthy(); app.destroy(); expect(app.stage).toBeNull(); expect(app.renderer).toBeNull(); await app.init(); expect(app.stage).toBeInstanceOf(Container); expect(app.renderer).toBeTruthy(); app.destroy(); expect(app.stage).toBeNull(); expect(app.renderer).toBeNull(); }); it('register a new plugin, then destroy it', async () => { const plugin = { init: jest.fn(), destroy: jest.fn(), }; const extension = { type: ExtensionType.Application, ref: plugin }; extensions.add(extension); const app = await getApp(); app.destroy(); expect(plugin.init).toHaveBeenCalledOnce(); expect(plugin.destroy).toHaveBeenCalledOnce(); extensions.remove(extension); }); it('should remove canvas when destroyed', async () => { const app = await getApp(); const view = app.canvas as HTMLCanvasElement; expect(view).toBeInstanceOf(HTMLCanvasElement); document.body.appendChild(view); expect(document.body.contains(view)).toBe(true); app.destroy(true); expect(document.body.contains(view)).toBe(false); }); it('should not destroy children by default', async () => { const app = await getApp(); const stage = app.stage; const child = new Container(); stage.addChild(child); app.destroy(); expect(child.destroyed).toBeFalse(); }); it('should destroy children when option passed', async () => { const app = await getApp(); const stage = app.stage; const child = new Container(); stage.addChild(child); app.destroy(true, true); expect(child.destroyed).toBeTrue(); }); it('should destroy all children when option passed', async () => { const app = await getApp(); await Assets.init({ basePath }); const bunny = await Assets.load('textures/bunny.png'); const stage = app.stage; const child = new Container(); const graphics = new Graphics().rect(0, 0, 10, 10).fill('red'); const graphics2 = new Graphics().rect(0, 0, 10, 10).fill('red'); const sprite = new Sprite(bunny); const text = new Text({ text: 'Hello, world!' }); graphics.mask = sprite; stage.addChild(child, graphics, graphics2, sprite, text); const spy = jest.spyOn(GlobalResourceRegistry, 'release'); app.render(); app.destroy(true, true); expect(child.destroyed).toBeTrue(); expect(graphics.destroyed).toBeTrue(); expect(sprite.destroyed).toBeTrue(); expect(text.destroyed).toBeTrue(); expect(spy).toHaveBeenCalled(); Assets.reset(); }); }); describe('resizeTo', () => { const getAppWithDiv = async (options?: Partial<ApplicationOptions>) => { const div: HTMLDivElement = document.createElement('div'); div.style.width = '100px'; div.style.height = '200px'; document.body.appendChild(div); const app = await getApp({ resizeTo: div, ...options, }); const forceResizeApp = (width: number, height: number, queue = false) => { div.style.width = `${width}px`; div.style.height = `${height}px`; if (queue) { app.queueResize(); } else { app.resize(); } }; const forceQueueResizeApp = (width: number, height: number) => forceResizeApp(width, height, true); const cleanup = (destroy = true) => { destroy && app.destroy(); div.parentNode.removeChild(div); }; return { app, div, forceResizeApp, forceQueueResizeApp, cleanup, }; }; it('should assign resizeTo', async () => { const { app, div, cleanup } = await getAppWithDiv(); expect(app.resizeTo).toEqual(div); expect(app.canvas.width).toEqual(100); expect(app.canvas.height).toEqual(200); cleanup(); }); it('should force multiple immediate resizes', async () => { const spy = jest.fn(); const { app, forceResizeApp, cleanup } = await getAppWithDiv(); app.renderer.view.texture.source.on('resize', spy); forceResizeApp(200, 400); forceResizeApp(300, 500); expect(spy).toHaveBeenCalledTimes(2); cleanup(); }); // eslint-disable-next-line jest/no-done-callback it('should throttle multiple resizes', async (done) => { const { app, forceQueueResizeApp, cleanup } = await getAppWithDiv(); const onResize = () => { // eslint-disable-next-line @typescript-eslint/no-floating-promises nextTick().then(() => { // give the canvas a chance to be resized before we check it expect(app.canvas.width).toEqual(300); expect(app.canvas.height).toEqual(500); cleanup(); done(); }); }; app.renderer.view.texture.source.on('resize', onResize); forceQueueResizeApp(200, 400); forceQueueResizeApp(300, 500); }); // eslint-disable-next-line jest/no-done-callback it('should cancel resize on destroy', async (done) => { const spy = jest.fn(); const { app, forceQueueResizeApp, cleanup } = await getAppWithDiv(); app.renderer.view.texture.source.on('resize', spy); forceQueueResizeApp(200, 400); app.destroy(); requestAnimationFrame(() => { expect(spy).not.toHaveBeenCalled(); cleanup(false); // don't destroy, we already did done(); }); }); // eslint-disable-next-line jest/no-done-callback it('should resize cancel resize queue', async (done) => { const spy = jest.fn(); const { app, forceQueueResizeApp, forceResizeApp, cleanup } = await getAppWithDiv(); app.renderer.view.texture.source.on('resize', spy); forceQueueResizeApp(200, 400); forceResizeApp(300, 500); app.destroy(); requestAnimationFrame(() => { expect(spy).toHaveBeenCalledTimes(1); cleanup(false); // don't destroy, we already did done(); }); }); it('should resizeTo with resolution', async () => { const { app, cleanup } = await getAppWithDiv({ resolution: 2 }); expect(app.canvas.width).toEqual(200); expect(app.canvas.height).toEqual(400); cleanup(); }); it('should resizeTo with resolution and autoDensity', async () => { const { app, div, cleanup } = await getAppWithDiv({ resolution: 2, autoDensity: true, }); expect(app.canvas.width).toEqual(200); expect(app.canvas.height).toEqual(400); expect(app.canvas.style.width).toEqual(div.style.width); expect(app.canvas.style.height).toEqual(div.style.height); cleanup(); }); }); describe('Offscreen Canvas', () => { it('should support OffscreenCanvas', async () => { const view = new OffscreenCanvas(1, 1); const app = await getApp({ canvas: view, width: 1, height: 1, }); expect(app.canvas).toBeInstanceOf(OffscreenCanvas); app.destroy(); }); }); });