Skip to content

Commit

Permalink
Fix and improve storybook/react definitions (#2645)
Browse files Browse the repository at this point in the history
  • Loading branch information
pascalduez authored and villesau committed Sep 19, 2018
1 parent 82d206c commit 35108fa
Show file tree
Hide file tree
Showing 5 changed files with 294 additions and 32 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
type NodeModule = typeof module;

declare module '@storybook/react' {
declare type Context = { kind: string, story: string };
declare type Renderable = React$Element<*>;
declare type RenderCallback = (
context: Context
) => Renderable | Array<Renderable>;
declare type RenderFunction = () => Renderable | Array<Renderable>;

declare type StoryDecorator = (
story: RenderFunction,
context: Context
) => Renderable | null;

declare interface Story {
+kind: string;
add(storyName: string, callback: RenderCallback): Story;
addDecorator(decorator: StoryDecorator): Story;
}

declare interface StoryObject {
name: string;
render: RenderFunction;
}

declare interface StoryBucket {
kind: string;
filename: string;
stories: Array<StoryObject>;
}

declare function addDecorator(decorator: StoryDecorator): void;
declare function configure(fn: () => void, module: NodeModule): void;
declare function setAddon(addon: Object): void;
declare function storiesOf(name: string, module: NodeModule): Story;
declare function forceReRender(): void;

declare function getStorybook(): Array<StoryBucket>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// @flow

import { describe, it } from 'flow-typed-test';
import React from 'react';
import {
storiesOf,
addDecorator,
getStorybook,
forceReRender,
configure,
} from '@storybook/react';

const Button = props => <button {...props} />;

const Decorator = story => <div>{story()}</div>;

describe('The `storiesOf` function', () => {
it('should validate on default usage', () => {
storiesOf('', module);
});

it('should error on invalid options', () => {
// $ExpectError
storiesOf([], module);
// $ExpectError
storiesOf('', 123);
});

it('should error on invalid method call', () => {
// $ExpectError
storiesOf('', module).foo('', () => <div />);
});
});

describe('The `add` method', () => {
it('should validate on default usage (element)', () => {
storiesOf('', module).add('', () => <div />);
});

it('should validate on default usage (component)', () => {
storiesOf('', module).add('', () => <Button>test</Button>);
});

it('should validate on default usage (array)', () => {
storiesOf('', module).add('', () => [
<Button>test</Button>,
<Button>test</Button>,
<Button>test</Button>,
]);
});

it('should error on invalid default usage', () => {
// $ExpectError
storiesOf('', module).add('', () => '');
// $ExpectError
storiesOf('', module).add('', () => null);
});

it('should validate when unwrapping arguments', () => {
storiesOf('', module).add('', ({ kind, story }) => (
<div>
{kind} {story}
</div>
));
});

it('should error when unwrapping invalid arguments', () => {
// $ExpectError
storiesOf('', module).add('', ({ kind, story, foo }) => (
<div>
{kind} {story} {foo}
</div>
));
});
});

describe('The `addDecorator` function', () => {
it('should validate on default usage (local)', () => {
storiesOf('', module)
.addDecorator(Decorator)
.add('', () => <div />);
});

it('should validate on default usage (global)', () => {
addDecorator(Decorator);
});
});

describe('The `getStorybook` function', () => {
it('should validate on default usage', () => {
getStorybook().forEach(({ kind, stories }) =>
stories.forEach(({ name, render }) => render())
);
});
});

describe('The `forceReRender` function', () => {
it('should validate on default usage', () => {
forceReRender();
});
});

describe('The `configure` function', () => {
it('should validate on default usage', () => {
configure(() => undefined, module);
});
});
Original file line number Diff line number Diff line change
@@ -1,28 +1,33 @@
type NodeModule = typeof module;

declare module '@storybook/react' {
declare type Renderable = React$Node;
declare type RenderFunction = (context: Context) => Renderable;
declare type Context = { kind: string, story: string };
declare type Renderable = React$Element<*>;
declare type RenderCallback = (
context: Context
) => Renderable | Array<Renderable>;
declare type RenderFunction = () => Renderable | Array<Renderable>;

declare type StoryDecorator = (
story: RenderFunction,
context: Context
) => Renderable;
) => Renderable | null;

declare interface Story {
add(storyName: string, callback: RenderFunction): Story,
addDecorator(decorator: StoryDecorator): Story,
+kind: string;
add(storyName: string, callback: RenderCallback): Story;
addDecorator(decorator: StoryDecorator): Story;
}

declare interface StoryObject {
name: string,
render: RenderFunction,
name: string;
render: RenderFunction;
}

declare interface StoryBucket {
kind: string,
stories: Array<StoryObject>,
kind: string;
filename: string;
stories: Array<StoryObject>;
}

declare function addDecorator(decorator: StoryDecorator): void;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// @flow

import { describe, it } from 'flow-typed-test';
import React from 'react';
import {
storiesOf,
addDecorator,
getStorybook,
forceReRender,
configure,
setAddon,
type RenderFunction,
type Story,
} from '@storybook/react';

const Button = props => <button {...props} />;

const Decorator = story => <div>{story()}</div>;

describe('The `storiesOf` function', () => {
it('should validate on default usage', () => {
storiesOf('', module);
});

it('should error on invalid options', () => {
// $ExpectError
storiesOf([], module);
// $ExpectError
storiesOf('', 123);
});

it('should error on invalid method call', () => {
// $ExpectError
storiesOf('', module).foo('', () => <div />);
});
});

describe('The `add` method', () => {
it('should validate on default usage (element)', () => {
storiesOf('', module).add('', () => <div />);
});

it('should validate on default usage (component)', () => {
storiesOf('', module).add('', () => <Button>test</Button>);
});

it('should validate on default usage (array)', () => {
storiesOf('', module).add('', () => [
<Button>test</Button>,
<Button>test</Button>,
<Button>test</Button>,
]);
});

it('should error on invalid default usage', () => {
// $ExpectError
storiesOf('', module).add('', () => '');
// $ExpectError
storiesOf('', module).add('', () => null);
});

it('should validate when unwrapping arguments', () => {
storiesOf('', module).add('', ({ kind, story }) => (
<div>
{kind} {story}
</div>
));
});

it('should error when unwrapping invalid arguments', () => {
// $ExpectError
storiesOf('', module).add('', ({ kind, story, foo }) => (
<div>
{kind} {story} {foo}
</div>
));
});
});

describe('The `addDecorator` function', () => {
it('should validate on default usage (local)', () => {
storiesOf('', module)
.addDecorator(Decorator)
.add('', () => <div />);
});

it('should validate on default usage (global)', () => {
addDecorator(Decorator);
});
});

describe('The `getStorybook` function', () => {
it('should validate on default usage', () => {
getStorybook().forEach(({ kind, stories }) =>
stories.forEach(({ name, render }) => render())
);
});
});

describe('The `forceReRender` function', () => {
it('should validate on default usage', () => {
forceReRender();
});
});

describe('The `configure` function', () => {
it('should validate on default usage', () => {
configure(() => undefined, module);
});
});

describe('The `setAddon` function', () => {
it('should validate on default usage', () => {
interface Addon {
test<T>(name: string, story: RenderFunction): Story & T;
}

const TestAddon: Addon = {
test(name, story) {
console.log(this.kind === 'TestAddon');
return this.add(name, story);
},
};

setAddon(TestAddon);

storiesOf<Addon>('TestAddon', module)
.test('', () => <div />)
.test('', () => <div />)
.add('', () => <div />)
.test('', () => <div />);
});
});
23 changes: 0 additions & 23 deletions definitions/npm/@storybook/react_v3.x.x/test_react_v3.x.x.js

This file was deleted.

0 comments on commit 35108fa

Please sign in to comment.