Skip to content

Commit

Permalink
fix(render): pass Text props (x, y, text, style) via instantiation
Browse files Browse the repository at this point in the history
  • Loading branch information
remarkablemark committed Jan 10, 2024
1 parent 8e1dd99 commit 9ea0815
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 47 deletions.
74 changes: 57 additions & 17 deletions src/render/gameobject.test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import Phaser from 'phaser';
import type { JSX } from 'react';

import { Container } from '..';
import { createGameObject } from './gameobject';
import { Container, Text } from '..';
import { createGameObject } from '.';

jest.mock('phaser', () => {
const GameObject = jest.fn();
Expand All @@ -11,6 +11,7 @@ jest.mock('phaser', () => {
Container: GameObject,
GameObject,
Particles: {},
Text: GameObject,
},
Scene: jest.fn(),
};
Expand All @@ -32,29 +33,34 @@ function Children(props: { children: JSX.Element[] }) {
return <Container {...props} />;
}

it('logs warning for invalid element', () => {
const spy = jest.spyOn(console, 'warn').mockImplementation();
const element = {} as JSX.Element;
const container = new Phaser.GameObjects.Container(scene);
expect(createGameObject(element, scene, container)).toBe(undefined);
expect(spy).toBeCalledWith(
'Invalid JSX type. Expected a class or function but got: undefined',
);
spy.mockRestore();
let container: Phaser.GameObjects.Container;

beforeEach(() => {
jest.clearAllMocks();
container = new Phaser.GameObjects.Container(scene);
container.add = jest.fn();
});

describe('invalid element', () => {
it('logs warning', () => {
const spy = jest.spyOn(console, 'warn').mockImplementation();
const element = {} as JSX.Element;
expect(createGameObject(element, scene, container)).toBe(undefined);
expect(spy).toBeCalledWith(
'Invalid JSX type. Expected a class or function but got: undefined',
);
spy.mockRestore();
});
});

it('creates game object from element', () => {
const element = <Container />;
const container = new Phaser.GameObjects.Container(scene);
container.add = jest.fn();
expect(createGameObject(element, scene, container)).toBeInstanceOf(Object);
expect(container.add).toBeCalledTimes(1);
});

it('creates game object from component', () => {
const element = <Component />;
const container = new Phaser.GameObjects.Container(scene);
container.add = jest.fn();
expect(createGameObject(element, scene, container)).toBeInstanceOf(Object);
expect(container.add).toBeCalledTimes(1);
});
Expand All @@ -66,8 +72,42 @@ it('creates game object with children', () => {
<Container />
</Children>
);
const container = new Phaser.GameObjects.Container(scene);
container.add = jest.fn();
expect(createGameObject(element, scene, container)).toBeInstanceOf(Object);
expect(container.add).toBeCalledTimes(1);
});

describe('Text', () => {
it('creates text with no props', () => {
const element = <Text />;
expect(createGameObject(element, scene, container)).toBeInstanceOf(Object);
expect(container.add).toBeCalledTimes(1);
expect(Phaser.GameObjects.Text).toBeCalledWith(
scene,
undefined,
undefined,
undefined,
undefined,
);
});

it('creates text with props', () => {
const props = {
x: 1,
y: 2,
text: 'a',
style: {
fontSize: '42px',
},
};
const element = <Text {...props} />;
expect(createGameObject(element, scene, container)).toBeInstanceOf(Object);
expect(container.add).toBeCalledTimes(1);
expect(Phaser.GameObjects.Text).toBeCalledWith(
scene,
props.x,
props.y,
props.text,
props.style,
);
});
});
24 changes: 20 additions & 4 deletions src/render/gameobject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,31 @@ export function createGameObject(
return;
}

const gameObject: Phaser.GameObjects.GameObject = new element.type(scene);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { children, key, ref, ...props } = element.props;

let gameObject: Phaser.GameObjects.GameObject;

switch (element.type) {
case Phaser.GameObjects.Text:
gameObject = new element.type(
scene,
props.x,
props.y,
props.text,
props.style,
);
break;

default:
gameObject = new element.type(scene);
break;
}

if (!(gameObject instanceof Phaser.GameObjects.GameObject)) {
return createGameObject(new element.type(element.props), scene, container);
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { children, key, ref, ...props } = element.props;

setProps(gameObject, props, scene);
attachRef(gameObject, ref);

Expand Down
17 changes: 0 additions & 17 deletions src/render/props.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,6 @@ it('does not set invalid props', () => {
expect(JSON.stringify(gameObject)).toBe('{}');
});

it('sets prop style', () => {
const gameObject = new Phaser.GameObjects.Text(scene, 1, 2, 'text', {
fontFamily: 'Arial',
});
const props = {
style: {
fontSize: '42px',
},
};

gameObject.setStyle = jest.fn();
expect(setProps(gameObject, props, scene)).toBe(undefined);

expect(gameObject.setStyle).toBeCalledTimes(1);
expect(gameObject.setStyle).toBeCalledWith(props.style);
});

it('sets prop onPointerDown', () => {
const gameObject = new Phaser.GameObjects.Container(scene);
const props = {
Expand Down
9 changes: 0 additions & 9 deletions src/render/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,6 @@ export function setProps(
for (const key in props) {
const value = props[key];

if (
key === 'style' &&
value instanceof Object &&
gameObject instanceof Phaser.GameObjects.Text
) {
gameObject.setStyle(value);
continue;
}

if (events[key] && typeof value === 'function') {
gameObject.setInteractive();
gameObject.on(key.slice(2).toLowerCase(), value, scene);
Expand Down

0 comments on commit 9ea0815

Please sign in to comment.