Skip to content

Commit

Permalink
feat: 🎸 add name to the slides, so you can reference them later
Browse files Browse the repository at this point in the history
Each slide have a name now, that you can specify in SlideBuilder or
SlideDeclaration when creating them in JSON. Having named slides not
only allows to have a possibility to reference slides later but also
make a more better error messaging, so it is easier to debug problems.
  • Loading branch information
ghaiklor committed Apr 4, 2020
1 parent 5001e97 commit f45e55c
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 21 deletions.
25 changes: 13 additions & 12 deletions packages/kittik-slide/spec/Slide.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { TextObject, Text } from 'kittik-shape-text';
import { Print } from 'kittik-animation-print';

const SLIDE_DECLARATION: SlideDeclaration = {
name: 'Testing Slide',
shapes: [{
name: 'Hello',
type: 'Text',
Expand Down Expand Up @@ -71,6 +72,7 @@ const SERIALIZED_ORDER_DECLARATION: OrderDeclaration = {
};

const SERIALIZED_SLIDE_DECLARATION: SlideDeclaration = {
name: 'Testing Slide',
shapes: [SERIALIZED_TEXT_DECLARATION],
animations: [SERIALIZED_ANIMATION_DECLARATION],
order: [SERIALIZED_ORDER_DECLARATION]
Expand All @@ -80,22 +82,22 @@ describe('Core::Slide', () => {
it('Should properly throw an error if shape type is unknown', () => {
const cursor = new Canvas();

expect(() => new Slide(cursor, { shapes: [{ name: 'Test', type: 'unknown' }], order: [{ shape: 'Test' }] }))
expect(() => new Slide(cursor, { name: 'Test', shapes: [{ name: 'Test', type: 'unknown' }], order: [{ shape: 'Test' }] }))
.toThrowError('Shape "Test" (unknown) is unknown for me, maybe you made a typo?');
});

it('Should properly throw an error if animation type is unknown', () => {
const cursor = new Canvas();

expect(() => new Slide(cursor, { shapes: [{ name: 'Test', type: 'Text' }], animations: [{ name: 'Test', type: 'unknown' }], order: [{ shape: 'Test' }] }))
expect(() => new Slide(cursor, { name: 'Test', shapes: [{ name: 'Test', type: 'Text' }], animations: [{ name: 'Test', type: 'unknown' }], order: [{ shape: 'Test' }] }))
.toThrowError('Animation "Test" (unknown) is unknown for me, maybe you made a typo?');
});

it('Should properly throw an error if trying to use shape name in ordering that does not exist', async () => {
const cursor = new Canvas();
const slide = new Slide(cursor, { shapes: [], order: [{ shape: 'Not Exists' }] });
const slide = new Slide(cursor, { name: 'Test', shapes: [], order: [{ shape: 'Not Exists' }] });

await expect(slide.render()).rejects.toThrowError('You specified shape "Not Exists" as part of ordering, but it does not exist in shapes declaration.');
await expect(slide.render()).rejects.toThrowError('You specified shape "Not Exists" in slide "Test" as part of ordering, but it does not exist in shapes declaration.');
});

it('Should properly render the whole slide', async () => {
Expand All @@ -114,14 +116,14 @@ describe('Core::Slide', () => {

it('Should render the slide without animations', async () => {
const cursor = new Canvas();
const slide = Slide.create(cursor, { shapes: [{ name: 'Test', type: 'Text' }], order: [{ shape: 'Test' }] });
const slide = Slide.create(cursor, { name: 'Test', shapes: [{ name: 'Test', type: 'Text' }], order: [{ shape: 'Test' }] });

await expect(slide.render()).resolves.toBeUndefined();
});

it('Should render the slide with unknown animation in ordering', async () => {
const cursor = new Canvas();
const slide = Slide.create(cursor, { shapes: [{ name: 'Test', type: 'Text' }], order: [{ shape: 'Test', animations: ['Not Exists'] }] });
const slide = Slide.create(cursor, { name: 'Test', shapes: [{ name: 'Test', type: 'Text' }], order: [{ shape: 'Test', animations: ['Not Exists'] }] });

await expect(slide.render()).resolves.toBeUndefined();
});
Expand Down Expand Up @@ -164,7 +166,7 @@ describe('Core::Slide', () => {
});

it('Should properly instantiate an empty slide instance when nothing is passed but an empty arrays', () => {
const slide = new Slide(undefined, { order: [], shapes: [] });
const slide = new Slide(undefined, { name: 'Test', order: [], shapes: [] });

expect(slide.cursor).toBeInstanceOf(Canvas);
expect(slide.shapes.size).toBe(0);
Expand All @@ -173,23 +175,22 @@ describe('Core::Slide', () => {
});

it('Should properly throw an error when trying to add shape that is already added', () => {
const slide = new Slide(undefined, { shapes: [{ name: 'Test', type: 'Text' }], order: [] });
const slide = new Slide(undefined, { name: 'Test', shapes: [{ name: 'Test', type: 'Text' }], order: [] });

expect(() => slide.addShape('Test', Text.create())).toThrowError('Shape "Test" already exists in slide');
});

it('Should properly throw an error when trying to add animation that is already added', () => {
const slide = new Slide(undefined, { shapes: [], order: [], animations: [{ name: 'Test', type: 'Print' }] });
const slide = new Slide(undefined, { name: 'Test', shapes: [], order: [], animations: [{ name: 'Test', type: 'Print' }] });

expect(() => slide.addAnimation('Test', Print.create())).toThrowError('Animation "Test" already exists in slide');
});

it('Should properly throw an error when trying to add ordering for the shape that is already added', () => {
const slide = new Slide(undefined, { shapes: [], order: [{ shape: 'Test' }] });
const slide = new Slide(undefined, { name: 'Test', shapes: [], order: [{ shape: 'Test' }] });

expect(() => slide.addOrder('Test')).toThrowError(
'You already have an ordering for "Test"\n' +
'Seems like it was defined somewhere before'
'You already have an ordering for shape "Test" in slide "Test"'
);
});

Expand Down
2 changes: 2 additions & 0 deletions packages/kittik-slide/spec/SlideBuilder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ describe('SlideBuilder', () => {
it('Should properly instantiate slide via builder', () => {
const slide = SlideBuilder
.start()
.withName('Hello, World')
.withCursor(Canvas.create())
.withShape(
'Hello, World',
Expand All @@ -26,6 +27,7 @@ describe('SlideBuilder', () => {
.withOrder('Hello, World', ['Print'])
.end();

expect(slide.name).toBe('Hello, World');
expect(slide.shapes.size).toBe(1);
expect(slide.shapes.get('Hello, World')?.toObject()).toEqual({
type: 'Text',
Expand Down
21 changes: 12 additions & 9 deletions packages/kittik-slide/src/slide/Slide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,17 @@ export class Slide {
readonly animations: Map<string, Animationable> = new Map();
readonly order: OrderDeclaration[] = [];
cursor: Canvas = Canvas.create();
name = 'Untitled Slide'

constructor (cursor?: Canvas, declaration?: SlideDeclaration) {
if (cursor !== undefined) {
this.cursor = cursor;
}

if (declaration?.name !== undefined) {
this.name = declaration.name;
}

if (declaration?.shapes !== undefined) {
this.initShapes(declaration.shapes);
}
Expand Down Expand Up @@ -74,26 +79,23 @@ export class Slide {

addShape (name: string, shape: ShapeRenderable, toOverride = false): void {
if (this.shapes.has(name) && !toOverride) {
throw new Error(`Shape "${name}" already exists in slide`);
throw new Error(`Shape "${name}" already exists in slide "${this.name}"`);
}

this.shapes.set(name, shape);
}

addAnimation (name: string, animation: Animationable, toOverride = false): void {
if (this.animations.has(name) && !toOverride) {
throw new Error(`Animation "${name}" already exists in slide`);
throw new Error(`Animation "${name}" already exists in slide "${this.name}"`);
}

this.animations.set(name, animation);
}

addOrder (shape: string, animations?: string[]): void {
if (this.order.findIndex(decl => decl.shape === shape) !== -1) {
throw new Error(
`You already have an ordering for "${shape}"\n` +
'Seems like it was defined somewhere before'
);
if (this.order.some(order => order.shape === shape)) {
throw new Error(`You already have an ordering for shape "${shape}" in slide "${this.name}"`);
}

this.order.push({ shape, animations });
Expand All @@ -114,7 +116,7 @@ export class Slide {
const shapeToRender = shapes.get(order[i].shape);
if (shapeToRender === undefined) {
throw new Error(
`You specified shape "${order[i].shape}" as part of ordering, but it does not exist in shapes declaration.` +
`You specified shape "${order[i].shape}" in slide "${this.name}" as part of ordering, but it does not exist in shapes declaration.\n` +
'Maybe you forgot to create a shape you want to order or it is a typo in ordering itself.'
);
}
Expand All @@ -140,11 +142,12 @@ export class Slide {
}

toObject (): SlideDeclaration {
const name = this.name;
const shapes = [...this.shapes.entries()].map(([name, shape]) => ({ ...shape.toObject(), name }));
const animations = [...this.animations.entries()].map(([name, animation]) => ({ ...animation.toObject(), name }));
const order = this.order;

return { shapes, animations, order };
return { name, shapes, animations, order };
}

toJSON (): string {
Expand Down
6 changes: 6 additions & 0 deletions packages/kittik-slide/src/slide/SlideBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import { Slide } from './Slide';
export class SlideBuilder {
private readonly slide: Slide = new Slide();

withName (name: string): this {
this.slide.name = name;

return this;
}

withCursor (cursor: Canvas): this {
this.slide.cursor = cursor;

Expand Down
1 change: 1 addition & 0 deletions packages/kittik-slide/src/slide/SlideDeclaration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { OrderDeclaration } from './OrderDeclaration';
import { ShapeDeclaration } from '../shape/ShapeDeclaration';

export interface SlideDeclaration {
name: string
shapes: ShapeDeclaration[]
animations?: AnimationDeclaration[]
order: OrderDeclaration[]
Expand Down

0 comments on commit f45e55c

Please sign in to comment.