Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions example/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { TimeGraphChartGrid } from "timeline-chart/lib/layer/time-graph-chart-gr
import { TimeGraphVerticalScrollbar } from "timeline-chart/lib/layer/time-graph-vertical-scrollbar";
import { TimeGraphChartArrows } from "timeline-chart/lib/layer/time-graph-chart-arrows";
import { TimeGraphRangeEventsLayer } from "timeline-chart/lib/layer/time-graph-range-events-layer";
import { TimeGraphChartRichCursor } from "timeline-chart/lib/layer/time-graph-chart-rich-cursor";

const styleConfig = {
mainWidth: 1000,
Expand Down Expand Up @@ -154,10 +155,11 @@ const timeGraphChartArrows = new TimeGraphChartArrows('timeGraphChartArrows', ro
const timeGraphSelectionRange = new TimeGraphChartSelectionRange('chart-selection-range', { color: styleConfig.cursorColor });
const timeGraphChartCursors = new TimeGraphChartCursors('chart-cursors', timeGraphChart, rowController, { color: styleConfig.cursorColor });
const timeGraphChartRangeEvents = new TimeGraphRangeEventsLayer('timeGraphChartRangeEvents', providers);
const timeGraphRichCursor = new TimeGraphChartRichCursor('chart-rich-cursor', timeGraphChart, rowController);

timeGraphChartContainer.addLayers([timeGraphChartGridLayer, timeGraphChart,
timeGraphChartArrows, timeGraphSelectionRange,
timeGraphChartCursors, timeGraphChartRangeEvents]);
timeGraphChartArrows, timeAxisCursors, timeGraphSelectionRange,
timeGraphChartCursors, timeGraphChartRangeEvents, timeGraphRichCursor]);

timeGraphChart.registerMouseInteractions({
click: el => {
Expand Down
3 changes: 2 additions & 1 deletion example/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ module.exports = {
{
enforce: "pre",
test: /\.js$/,
loader: "source-map-loader"
loader: "source-map-loader",
exclude: /node_modules\/@pixi/
},
{
test: /\.png$/,
Expand Down
7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@
"devDependencies": {
"@eclipse-dash/nodejs-wrapper": "^0.0.1",
"lerna": "^8.0.0",
"typescript": "^5.2.2"
"typescript": "^5.9.3"
},
"workspaces": [
"timeline-chart",
"example"
],
"dependencies": {
"pixi.js": "^5.0.0"
}
"dependencies": {},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
2 changes: 1 addition & 1 deletion timeline-chart/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"glob": "^7.1.6",
"keyboard-key": "1.1.0",
"lodash.throttle": "^4.1.1",
"pixi.js-legacy": "^5.3.3"
"pixi.js-legacy": "^7.3.2"
},
"devDependencies": {
"@types/enzyme": "^3.10.10",
Expand Down
247 changes: 247 additions & 0 deletions timeline-chart/src/__tests__/pixi-v7-migration.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
import * as PIXI from 'pixi.js-legacy';
import { TimeGraphComponent } from '../components/time-graph-component';
import { TimeGraphContainer } from '../time-graph-container';
import { TimeGraphUnitController } from '../time-graph-unit-controller';
import { FontController } from '../time-graph-font-controller';

// Concrete implementation for testing abstract TimeGraphComponent
class TestComponent extends TimeGraphComponent<any> {
render() {
this.rect({
position: { x: 0, y: 0 },
width: 50,
height: 20,
color: 0xff0000,
opacity: 1
});
}
}

describe('Pixi v7 Migration', () => {
describe('TimeGraphComponent - FederatedPointerEvent', () => {
let component: TestComponent;

beforeEach(() => {
component = new TestComponent('test-comp');
});

afterEach(() => {
component.destroy();
});

it('creates a Graphics display object', () => {
expect(component.displayObject).toBeInstanceOf(PIXI.Graphics);
});

it('renders rect without errors', () => {
expect(() => component.render()).not.toThrow();
});

it('addEvent sets interactive on display object', () => {
const handler = jest.fn();
const target = new PIXI.Graphics();
component.addEvent('click', handler, target);
expect(target.interactive).toBe(true);
});

it('addEvent registers event handler via on()', () => {
const handler = jest.fn();
const target = new PIXI.Graphics();
const onSpy = jest.spyOn(target, 'on');
component.addEvent('mouseover', handler, target);
expect(onSpy).toHaveBeenCalledWith('mouseover', expect.any(Function));
});

it('addEvent handler is callable', () => {
const handler = jest.fn();
const target = new PIXI.Graphics();
component.addEvent('click', handler, target);
// Simulate event emission
target.emit('click', { type: 'click' });
expect(handler).toHaveBeenCalled();
});

it('supports all interaction types', () => {
const types: Array<'mouseover' | 'mouseout' | 'mousemove' | 'mousedown' | 'mouseup' | 'mouseupoutside' | 'rightdown' | 'click'> = [
'mouseover', 'mouseout', 'mousemove', 'mousedown', 'mouseup', 'mouseupoutside', 'rightdown', 'click'
];
types.forEach(type => {
const handler = jest.fn();
const target = new PIXI.Graphics();
expect(() => component.addEvent(type, handler, target)).not.toThrow();
});
});

it('clear() clears graphics without error', () => {
component.render();
expect(() => component.clear()).not.toThrow();
});

it('update() re-renders', () => {
const renderSpy = jest.spyOn(component, 'render');
component.update();
expect(renderSpy).toHaveBeenCalled();
});

it('getPIXIOpacity returns correct values', () => {
expect((component as any).getPIXIOpacity(undefined)).toBe(1);
expect((component as any).getPIXIOpacity(0)).toBe(0.001);
expect((component as any).getPIXIOpacity(0.5)).toBe(0.5);
expect((component as any).getPIXIOpacity(1)).toBe(1);
});
});

describe('TimeGraphContainer - v7 Application options', () => {
it('creates container without transparent option error', () => {
const unitController = new TimeGraphUnitController(BigInt(1000), { start: BigInt(0), end: BigInt(500) });
expect(() => {
const container = new TimeGraphContainer(
{ id: 'test', width: 200, height: 100, transparent: true },
unitController
);
container.destroy();
}).not.toThrow();
});

it('creates container with backgroundColor', () => {
const unitController = new TimeGraphUnitController(BigInt(1000), { start: BigInt(0), end: BigInt(500) });
expect(() => {
const container = new TimeGraphContainer(
{ id: 'test-bg', width: 200, height: 100, backgroundColor: 0x1a1a1a },
unitController
);
container.destroy();
}).not.toThrow();
});

it('canvas property returns HTMLCanvasElement', () => {
const unitController = new TimeGraphUnitController(BigInt(1000), { start: BigInt(0), end: BigInt(500) });
const container = new TimeGraphContainer(
{ id: 'test-canvas', width: 200, height: 100 },
unitController
);
expect(container.canvas).toBeInstanceOf(HTMLCanvasElement);
container.destroy();
});

it('accepts external canvas', () => {
const unitController = new TimeGraphUnitController(BigInt(1000), { start: BigInt(0), end: BigInt(500) });
const extCanvas = document.createElement('canvas');
const container = new TimeGraphContainer(
{ id: 'test-ext', width: 300, height: 150 },
unitController,
extCanvas
);
expect(container.canvas).toBe(extCanvas);
container.destroy();
});

it('updateCanvas resizes without error', () => {
const unitController = new TimeGraphUnitController(BigInt(1000), { start: BigInt(0), end: BigInt(500) });
const container = new TimeGraphContainer(
{ id: 'test-resize', width: 200, height: 100 },
unitController
);
expect(() => container.updateCanvas(400, 200)).not.toThrow();
container.destroy();
});
});

describe('FontController - v7 TextStyle', () => {
it('creates without error', () => {
expect(() => new FontController()).not.toThrow();
});

it('getDefaultFont returns a font name string', () => {
const fc = new FontController();
const { fontName } = fc.getDefaultFont();
expect(typeof fontName).toBe('string');
expect(fontName.length).toBeGreaterThan(0);
});

it('createFont creates bitmap font without error', () => {
const fc = new FontController();
expect(() => fc.createFont('White', 10)).not.toThrow();
expect(() => fc.createFont('Black', 12)).not.toThrow();
});

it('getFont returns correct font for dark background', () => {
const fc = new FontController();
// Dark color (0x000000) should get white font
const { fontName } = fc.getFont(0x000000, 8);
expect(fontName).toContain('White');
});

it('getFont returns correct font for light background', () => {
const fc = new FontController();
// Light color (0xffffff) should get black font
const { fontName } = fc.getFont(0xffffff, 8);
expect(fontName).toContain('Black');
});

it('getFont caches font colors', () => {
const fc = new FontController();
const { fontName: name1 } = fc.getFont(0x123456, 8);
const { fontName: name2 } = fc.getFont(0x123456, 8);
expect(name1).toBe(name2);
});

it('getFont creates new size maps on demand', () => {
const fc = new FontController();
const { fontName } = fc.getFont(0xffffff, 14);
expect(fontName.length).toBeGreaterThan(0);
});

it('respects minimum font size of 6', () => {
const fc = new FontController();
// Size 2 should be clamped to 6
const { fontName } = fc.getFont(0xffffff, 2);
expect(fontName.length).toBeGreaterThan(0);
});

it('accepts custom font family', () => {
expect(() => new FontController('Arial')).not.toThrow();
});
});

describe('DisplayObject event augmentation', () => {
it('Container supports interactive property', () => {
const c = new PIXI.Container();
c.interactive = true;
expect(c.interactive).toBe(true);
});

it('Container supports cursor property', () => {
const c = new PIXI.Container();
c.cursor = 'pointer';
expect(c.cursor).toBe('pointer');
});

it('Container supports on/off', () => {
const c = new PIXI.Container();
const fn = jest.fn();
expect(() => c.on('click', fn)).not.toThrow();
expect(() => c.off('click', fn)).not.toThrow();
});

it('Graphics supports interactive property', () => {
const g = new PIXI.Graphics();
g.interactive = true;
expect(g.interactive).toBe(true);
});

it('Graphics supports on/emit', () => {
const g = new PIXI.Graphics();
const fn = jest.fn();
g.on('click', fn);
g.emit('click');
expect(fn).toHaveBeenCalled();
});

it('Graphics supports cursor property', () => {
const g = new PIXI.Graphics();
g.cursor = 'crosshair';
expect(g.cursor).toBe('crosshair');
});
});
});
Loading
Loading