Skip to content

Commit

Permalink
feat: 🎸 DeckBuilder allows to create the whole decks via API
Browse files Browse the repository at this point in the history
  • Loading branch information
ghaiklor committed Apr 4, 2020
1 parent 70c2b64 commit fc1eb56
Show file tree
Hide file tree
Showing 7 changed files with 239 additions and 13 deletions.
45 changes: 45 additions & 0 deletions packages/kittik-deck/examples/builder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { DeckBuilder, SlideBuilder, AnimationBuilder, ShapeBuilder } from '..';

DeckBuilder
.start()
.withSlide(
SlideBuilder
.start()
.withShape(
'Local Shape',
ShapeBuilder
.start('Rectangle')
.withText('Local Shape Here!')
.withY('bottom')
.withX('right')
.withBackground('white')
.withForeground('black')
.end()
)
.withAnimation(
'Local Animation',
AnimationBuilder
.start('Slide')
.end()
)
.withOrder('Global Shape', ['Global Animation'])
.withOrder('Local Shape', ['Local Animation'])
.end()
)
.withShape(
'Global Shape',
ShapeBuilder
.start('FigText')
.withText('Hello, World!')
.end()
)
.withAnimation(
'Global Animation',
AnimationBuilder
.start('Print')
.withDuration(5000)
.end()
)
.end()
.renderSlide()
.catch(e => console.error(e));
15 changes: 13 additions & 2 deletions packages/kittik-deck/examples/complex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const ThanksArtShapeOptions: Partial<FigTextOptions> = {

new Deck({
shapes: [{
name: 'Text',
name: 'Shape: Text',
type: 'Text',
options: {
text: 'Shape: Text',
Expand Down Expand Up @@ -93,6 +93,7 @@ new Deck({
options: FocusAnimationOptions
}],
slides: [{
name: 'Hello, Kittik',
shapes: [{
name: 'Kittik',
type: 'FigText',
Expand All @@ -103,6 +104,7 @@ new Deck({
animations: ['Print']
}]
}, {
name: 'Demo #1',
shapes: [{
name: 'Demo',
type: 'Text',
Expand All @@ -117,30 +119,35 @@ new Deck({
animations: ['Print']
}]
}, {
name: 'Demo #2',
shapes: [],
order: [{
shape: 'Text',
shape: 'Shape: Text',
animations: ['Print']
}]
}, {
name: 'Demo #3',
shapes: [],
order: [{
shape: 'Rectangle',
animations: ['Slide In', 'Focus']
}]
}, {
name: 'Demo #4',
shapes: [],
order: [{
shape: 'FigText',
animations: ['Slide In', 'Focus']
}]
}, {
name: 'Demo #5',
shapes: [],
order: [{
shape: 'Code',
animations: ['Slide In']
}]
}, {
name: 'Demo #6',
shapes: [{
name: 'Text',
type: 'FigText',
Expand All @@ -151,6 +158,7 @@ new Deck({
animations: ['Print']
}]
}, {
name: 'Demo #7',
shapes: [{
name: 'Text',
type: 'Text',
Expand All @@ -165,6 +173,7 @@ new Deck({
animations: ['Print']
}]
}, {
name: 'Demo #8',
shapes: [{
name: 'Text',
type: 'Text',
Expand All @@ -179,6 +188,7 @@ new Deck({
animations: ['Print']
}]
}, {
name: 'Demo #9',
shapes: [{
name: 'Text',
type: 'Text',
Expand All @@ -193,6 +203,7 @@ new Deck({
animations: ['Print']
}]
}, {
name: 'Demo #10',
shapes: [{
name: 'Text',
type: 'FigText',
Expand Down
2 changes: 2 additions & 0 deletions packages/kittik-deck/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,10 @@
"eslint-plugin-promise": "4.2.1",
"eslint-plugin-standard": "4.0.1",
"jest": "25.2.7",
"kittik-animation-basic": "0.0.0",
"kittik-animation-focus": "0.0.0",
"kittik-animation-slide": "0.0.0",
"kittik-shape-basic": "0.0.0",
"kittik-shape-code": "0.0.0",
"kittik-shape-fig-text": "0.0.0",
"rimraf": "3.0.2",
Expand Down
69 changes: 66 additions & 3 deletions packages/kittik-deck/spec/Deck.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Animationable } from 'kittik-animation-basic';
import { Canvas } from 'terminal-canvas';
import { Deck, DeckDeclaration } from '../src/Deck';
import { ShapeRenderable } from 'kittik-shape-basic';

const DECK_DECLARATION: DeckDeclaration = {
cursor: Canvas.create(),
Expand All @@ -23,6 +25,7 @@ const DECK_DECLARATION: DeckDeclaration = {
],
slides: [
{
name: 'Global Animation',
shapes: [],
order: [{
shape: 'Global Shape',
Expand All @@ -32,6 +35,7 @@ const DECK_DECLARATION: DeckDeclaration = {
}]
},
{
name: 'Global Animation 2',
shapes: [],
order: [{
shape: 'Global Shape',
Expand All @@ -54,6 +58,8 @@ describe('Deck', () => {
expect(renderSpy).toBeCalledTimes(2);
expect(renderSpy).toBeCalledWith(1);
expect(renderSpy).toBeCalledWith(0);

deck.exit();
});

it('Should properly handle the key press for next slide', async () => {
Expand All @@ -65,6 +71,8 @@ describe('Deck', () => {

expect(renderSpy).toBeCalledTimes(1);
expect(renderSpy).toBeCalledWith(1);

deck.exit();
});

it('Should properly handle the key press for exit', () => {
Expand All @@ -74,6 +82,8 @@ describe('Deck', () => {
process.stdin.emit('keypress', 'q');

expect(exitSpy).toBeCalledTimes(1);

deck.exit();
});

it('Should properly render next and previous slides', async () => {
Expand All @@ -88,6 +98,8 @@ describe('Deck', () => {
expect(renderSpy).toBeCalledTimes(2);
expect(renderSpy).toBeCalledWith(0);
expect(renderSpy).toBeCalledWith(1);

deck.exit();
});

it('Should properly render slides without custom cursor', async () => {
Expand All @@ -102,10 +114,12 @@ describe('Deck', () => {
expect(renderSpy).toBeCalledTimes(2);
expect(renderSpy).toBeCalledWith(0);
expect(renderSpy).toBeCalledWith(1);

deck.exit();
});

it('Should properly render minimal slide without global shapes/animations', async () => {
const deck = new Deck({ slides: [{ shapes: [], order: [] }, { shapes: [], order: [], animations: [] }] });
const deck = new Deck({ slides: [{ name: 'Test', shapes: [], order: [] }, { name: 'Test 2', shapes: [], order: [], animations: [] }] });
const renderSpy = jest.spyOn(deck, 'renderSlide').mockResolvedValue();

await deck.nextSlide();
Expand All @@ -116,10 +130,12 @@ describe('Deck', () => {
expect(renderSpy).toBeCalledTimes(2);
expect(renderSpy).toBeCalledWith(0);
expect(renderSpy).toBeCalledWith(1);

deck.exit();
});

it('Should not call slide renderer many times if slide is already rendering', () => {
const deck = new Deck({ slides: [{ shapes: [], order: [] }] });
const deck = new Deck({ slides: [{ name: 'Test', shapes: [], order: [] }] });

// Though, slides is a private property, I need to access it anyway in sake of the tests
// This is done to test if slides render() behaves as expected
Expand All @@ -131,8 +147,55 @@ describe('Deck', () => {
deck.renderSlide(); // eslint-disable-line @typescript-eslint/no-floating-promises
deck.renderSlide(); // eslint-disable-line @typescript-eslint/no-floating-promises
deck.renderSlide(); // eslint-disable-line @typescript-eslint/no-floating-promises
deck.exit();

expect(renderSpy).toBeCalledTimes(1);

deck.exit();
});

it('Should properly add a shape to all the slides in the deck', () => {
const deck = new Deck({ slides: [{ name: 'Test', shapes: [{ name: 'Shape', type: 'Text' }], order: [] }] });
const shape = {} as ShapeRenderable;

deck.addShape('Shape 2', shape);

// I am accessing the private property to check if there is actually a new shape exists
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
expect(deck.slides[0].shapes.size).toBe(2);

deck.exit();
});

it('Should properly throw an error if shape already exists in other slides', () => {
const deck = new Deck({ slides: [{ name: 'Test', shapes: [{ name: 'Shape', type: 'Text' }], order: [] }] });
const shape = {} as ShapeRenderable;

expect(() => deck.addShape('Shape', shape)).toThrowError('Slides [Test] already have a shape with the name "Shape"');

deck.exit();
});

it('Should properly add an animation to all the slides in the deck', () => {
const deck = new Deck({ slides: [{ name: 'Test', shapes: [], order: [], animations: [{ name: 'Animation', type: 'Print' }] }] });
const animation = {} as Animationable;

deck.addAnimation('Animation 2', animation);

// I am accessing the private property to check if there is actually a new animation exists
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
expect(deck.slides[0].animations.size).toBe(2);

deck.exit();
});

it('Should properly throw an error if animation already exists in other slides', () => {
const deck = new Deck({ slides: [{ name: 'Test', shapes: [], order: [], animations: [{ name: 'Animation', type: 'Print' }] }] });
const animation = {} as Animationable;

expect(() => deck.addAnimation('Animation', animation)).toThrowError('Slides [Test] already have an animation with the name "Animation"');

deck.exit();
});
});
33 changes: 33 additions & 0 deletions packages/kittik-deck/spec/DeckBuilder.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { AnimationBuilder, ShapeBuilder, SlideBuilder } from '../src/Deck';
import { Canvas } from 'terminal-canvas';
import { DeckBuilder } from '../src/DeckBuilder';

describe('DeckBuilder', () => {
it('Should properly create deck using DeckBuilder', () => {
const deck = DeckBuilder
.start()
.withCursor(Canvas.create())
.withAnimation(
'Test Animation',
AnimationBuilder
.start('Focus')
.end()
)
.withShape(
'Test Shape',
ShapeBuilder
.start('Text')
.end()
)
.withSlide(
SlideBuilder
.start()
.end()
)
.end();

expect(deck.cursor).toBeInstanceOf(Canvas);

deck.exit();
});
});
Loading

0 comments on commit fc1eb56

Please sign in to comment.