Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Unit Tests #110

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ dist/
examples/build/
tmp/
build/
.cache/
.cache/
coverage
3 changes: 3 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
presets: ['@babel/preset-env'],
};
28 changes: 28 additions & 0 deletions lib/__tests__/canvas-sketch.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* @jest-environment jsdom
*/
import canvas from '../canvas-sketch';
import SketchManager from '../core/SketchManager';
import PaperSizes from '../paper-sizes';

describe('canvasSketch', () => {
it('returns a promise', () => {
expect(typeof canvas.canvasSketch().then).toBe('function');
});

it('includes PaperSizes', () => {
expect(canvas.PaperSizes).toBe(PaperSizes);
});

it('returns SketchManager if sketch is not provided', () => {
return canvas.canvasSketch().then(manager => {
expect(manager).toBeInstanceOf(SketchManager);
});
});

it('returns SketchManager if sketch is provided', () => {
return canvas.canvasSketch(() => {}).then(manager => {
expect(manager).toBeInstanceOf(SketchManager);
});
});
});
2 changes: 1 addition & 1 deletion lib/core/SketchManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,7 @@ class SketchManager {
window.removeEventListener('resize', this._resizeHandler);
this._keyboardShortcuts.detach();
}
if (this.props.canvas.parentElement) {
if (this.props.canvas && this.props.canvas.parentElement) {
this.props.canvas.parentElement.removeChild(this.props.canvas);
}
}
Expand Down
231 changes: 231 additions & 0 deletions lib/core/__tests__/SketchManager.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
/**
* @jest-environment jsdom
*/
import SketchManager from '../SketchManager';
import * as utils from '../../util';

utils.isWebGLContext = jest.fn();

let manager;

beforeEach(() => {
utils.isWebGLContext.mockReturnValue(false);
manager = new SketchManager();
});

afterEach(() => {
jest.clearAllMocks();
manager.destroy();
});

describe('SketchManager', () => {
it('basic API', () => {
expect(manager.sketch).toBeUndefined();

expect(manager).toMatchObject({
props: {},
settings: {},

// public methods
run: expect.any(Function),
play: expect.any(Function),
pause: expect.any(Function),
togglePlay: expect.any(Function),
record: expect.any(Function),
stop: expect.any(Function),
endRecord: expect.any(Function),
exportFrame: expect.any(Function),
tick: expect.any(Function),
render: expect.any(Function),
submitDrawCall: expect.any(Function),
update: expect.any(Function),
resize: expect.any(Function),
animate: expect.any(Function),
dispatch: expect.any(Function),
mount: expect.any(Function),
unmount: expect.any(Function),
getTimeProps: expect.any(Function),
setup: expect.any(Function),
loadAndRun: expect.any(Function),
unload: expect.any(Function),
destroy: expect.any(Function),
unload: expect.any(Function),
});
});

describe('setup', () => {
it('merges settings with existing settings', () => {
expect(manager.settings).toEqual({});
manager.setup({ name: 'some-name' });
expect(manager.settings).toEqual({ name: 'some-name' });
manager.setup({ loop: true });
expect(manager.settings).toEqual({ name: 'some-name', loop: true });
});

it('warns for invalid settings', () => {
const originalWarn = console.warn;
console.warn = jest.fn();
manager.setup({ invalidSetting: 'invalid' });
expect(console.warn).toBeCalledWith(
'[canvas-sketch] Could not recognize the setting "invalidSetting"'
);
console.warn = originalWarn;
});

it('sets up props', () => {
const WIDTH = 1024;
const HEIGHT = 768;
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');

const initialSettings = { loop: true, data: {}, canvas, context };
manager.setup(initialSettings);

// Should not have gl prop for a 2d canvas context
expect(manager.props.gl).toBeUndefined();

expect(manager.props).toMatchObject({
canvas,
context,

// time props
playhead: 0,
time: 0,
frame: 0,
duration: Infinity,
totalFrames: Infinity,
fps: 24,
timeScale: 1,

deltaTime: 0,
started: false,
exporting: false,
playing: false,
recording: false,
settings: initialSettings,
data: initialSettings.data,

// resizeCanvas props
bleed: 0,
pixelRatio: 1,
width: WIDTH,
height: HEIGHT,
dimensions: [WIDTH, HEIGHT],
units: 'px',
scaleX: 1,
scaleY: 1,
pixelsPerInch: 72,
viewportWidth: WIDTH,
viewportHeight: HEIGHT,
canvasWidth: WIDTH,
canvasHeight: HEIGHT,
trimWidth: WIDTH,
trimHeight: HEIGHT,
styleWidth: WIDTH,
styleHeight: HEIGHT,

// methods
render: expect.any(Function),
togglePlay: expect.any(Function),
dispatch: expect.any(Function),
tick: expect.any(Function),
resize: expect.any(Function),
update: expect.any(Function),
exportFrame: expect.any(Function),
record: expect.any(Function),
play: expect.any(Function),
pause: expect.any(Function),
stop: expect.any(Function),
});
});

it('adds context as `gl` prop if context is webGL', () => {
utils.isWebGLContext.mockReturnValue(true);
const canvas = document.createElement('canvas');
// `canvas` npm package does not support webgl, so we use
// 2d but mock `isWebGLContext` to return true.
const context = canvas.getContext('2d');

const initialSettings = { loop: true, data: {}, canvas };
manager.setup(initialSettings);

expect(manager.props.gl).toEqual(context);
});

it('throws if SketchManager already has a sketch', () => {
const createSketch = () => ({});
return manager.load(createSketch).then(loaded => {
expect(() => loaded.setup()).toThrow(
'Multiple setup() calls not yet supported.'
);
});
});
});

describe('load', () => {
it('calls createSketch function', () => {
const loaderFn = () => {};
const createSketch = jest.fn(() => loaderFn);
return manager.load(createSketch).then(() => {
expect(createSketch).toBeCalled();
});
});

it('returns SketchManager', () => {
const createSketch = () => ({});
return manager.load(createSketch).then(loaded => {
expect(loaded).toBeInstanceOf(SketchManager);
});
});

it('sets createSketch return value as SketchManager.sketch', () => {
const sketch = 'foo';
const createSketch = () => sketch;
return manager.load(createSketch).then(loaded => {
expect(loaded.sketch).toBe('foo');
});
});

it('sets empty object as SketchManager.sketch if createSketch returns nothing', () => {
const createSketch = () => {};
return manager.load(createSketch).then(loaded => {
expect(loaded.sketch).toEqual({});
});
});

it('unloads existing sketch, adds new sketch to SketchManager', () => {
const unload = jest.fn();
let firstSketch;
const createSketch = () => ({ unload });
return manager
.load(createSketch)
.then(loaded => {
expect(unload).not.toBeCalled();
firstSketch = loaded.sketch;
return manager.load(createSketch);
})
.then(loaded => {
expect(unload).toBeCalled();
expect(loaded.sketch).not.toBe(firstSketch);
expect(loaded.sketch).toEqual(createSketch());
});
});

it('calls sketch.resize on initial load', () => {
const resize = jest.fn();
const createSketch = () => ({ resize });
return manager.load(createSketch).then(loaded => {
expect(resize).toBeCalledWith({});
});
});

it.todo('updates with newSettings if provided');
it.todo('adds event listeners if in browser');

it('throws if no createSketch provided', () => {
expect(() => manager.load()).toThrow(
/must take in a function as the first parameter/i
);
});
});
});
64 changes: 64 additions & 0 deletions lib/core/__tests__/createCanvas.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* @jest-environment jsdom
*/
import createCanvas from '../createCanvas';

describe('createCanvas', () => {
it('returns values by default', () => {
const { canvas, context, ownsCanvas } = createCanvas();
expect(canvas).toBeInstanceOf(HTMLCanvasElement);
expect(context.canvas).toEqual(canvas);
expect(typeof context.createPattern).toBe('function');
expect(typeof context.drawImage).toBe('function');
// ownsCanvas is true if no canvas is provided
expect(ownsCanvas).toBe(true);
});

it('uses canvas element if provided', () => {
const myCanvas = document.createElement('canvas');
const { canvas, context, ownsCanvas } = createCanvas({ canvas: myCanvas });
expect(canvas).toBeInstanceOf(HTMLCanvasElement);
expect(context.canvas).toEqual(canvas);
expect(typeof context.createPattern).toBe('function');
expect(typeof context.drawImage).toBe('function');
expect(ownsCanvas).toBe(false);
});

it('assigns attributes to canvas', () => {
const attributes = { height: 50, width: 50 };
const { canvas, context, ownsCanvas } = createCanvas({ attributes });
expect(canvas.height).toEqual(50);
expect(canvas.width).toEqual(50);
});

it('returns empty values if settings.canvas === false', () => {
const { canvas, context, ownsCanvas } = createCanvas({ canvas: false });
expect(canvas).toBeUndefined();
expect(context).toBeUndefined();
expect(ownsCanvas).toBe(false);
});

it('returns pixelated canvas if settings.pixelated is true', () => {
const { canvas, context, ownsCanvas } = createCanvas({ pixelated: true });
expect(context.imageSmoothingEnabled).toBe(false);
expect(context.mozImageSmoothingEnabled).toBe(false);
expect(context.oImageSmoothingEnabled).toBe(false);
expect(context.webkitImageSmoothingEnabled).toBe(false);
expect(context.msImageSmoothingEnabled).toBe(false);
expect(canvas.style['image-rendering']).toBe('pixelated');
});

describe('Error cases', () => {
it('throws if invalid context type', () => {
expect(() => createCanvas({ canvas: 'invalid-canvas' })).toThrow(
'The specified { canvas } element does not have a getContext() function'
);
});

it('throws if invalid context type', () => {
expect(() => createCanvas({ context: 'invalid-type' })).toThrow(
"Failed at canvas.getContext('invalid-type')"
);
});
});
});
Loading