Skip to content
This repository has been archived by the owner on Aug 13, 2023. It is now read-only.

Update inputProvider to toggle on serviceName not language #674

Merged
20 commits merged into from
Jun 26, 2019
Merged
Show file tree
Hide file tree
Changes from 17 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
1 change: 1 addition & 0 deletions packages/utilities/psammead-storybook-helpers/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<!-- prettier-ignore -->
| Version | Description |
|---------|-------------|
| 3.0.0 | [PR#674](https://github.com/bbc/psammead/pull/674) Update inputProvider to pass an object with script, service, dir and slotTexts |
| 2.1.1 | [PR#512](https://github.com/bbc/psammead/pull/512) Pass script and dir to storybook function |
| 2.1.0 | [PR#496](https://github.com/bbc/psammead/pull/496) Add dir storybook decorator |
| 2.0.0 | [PR#468](https://github.com/bbc/psammead/pull/468) Rewrite of inputProvider |
Expand Down
17 changes: 10 additions & 7 deletions packages/utilities/psammead-storybook-helpers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ This package provides a collection of common values that are used in storybook b
- `slot`: Object containing configuration for this slot.
- `name`: String uniquely identifying this slot in the story. Required.
- `defaultText`: String to use when the story is showing English text. Optional.
- `renderFn`: `function(slotTexts, script, dir)` Required.
- `renderFn`: `function({slotTexts, script, dir, service})` Required.
- `slotTexts`: Array of strings to insert into the story. Length and order corresponds to the provided `slots`.
- `script`: A [script](https://github.com/bbc/psammead/tree/latest/packages/utilities/gel-foundations#script-support) corresponding to the language selected by the storybook user.
- `script`: A [script](https://github.com/bbc/psammead/tree/latest/packages/utilities/gel-foundations#script-support) corresponding to the service selected by the storybook user.
- `dir`: Either `'ltr'` or `'rtl'`, corresponding to the language currently selected by the storybook user.
- `service`: The service selected by the storybook user.

`dirDecorator` - A storybook decorator function that uses `inputProvider` internally to provide direction control. It calls the storybook function with an object containing `dir` and `script`.
`dirDecorator` - A storybook decorator function that uses `inputProvider` internally to provide direction control. It calls the storybook function with an object containing `dir`, `script` and the `service` name.

## Installation

Expand All @@ -39,7 +40,7 @@ const defaultValue = 'This is a caption';
const groupIdentifier = 'CAPTION VARIANTS';

<Caption>
{select(label, LANGUAGE_VARIANTS, LANGUAGE_VARIANTS.english, groupIdentifier).text}
{select(label, LANGUAGE_VARIANTS, LANGUAGE_VARIANTS.news, groupIdentifier).text}
</Caption>;
```

Expand All @@ -62,8 +63,8 @@ storiesOf('Caption', module)
{ name: 'caption', defaultText: 'Students sitting an examination' },
{ name: 'offscreen text', defaultText: 'Image Caption, ' },
],
([captionText, offscreenText], script, dir) => (
<Caption script={script} dir={dir}>
({ slotTexts: [captionText, offscreenText], script, dir, service }) => (
<Caption script={script} dir={dir} service={service}>
<VisuallyHiddenText>{offscreenText}</VisuallyHiddenText>
{captionText}
</Caption>
Expand All @@ -84,7 +85,9 @@ import { dirDecorator } from '@bbc/psammead-storybook-helpers';
storiesOf('Example', module)
.addDecorator(withKnobs)
.addDecorator(dirDecorator)
.add('default', ({ dir }) => <h1 dir={dir}>Lorem Ipsum</h1>);
.add('default', ({ dir, service }) => (
<h1 dir={dir}>Lorem Ipsum ${service}</h1>
));
```

## Contributing
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/utilities/psammead-storybook-helpers/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@bbc/psammead-storybook-helpers",
"version": "2.1.1",
"version": "3.0.0",
"main": "dist/index.js",
"description": "A collection of common values that are used in storybook by the Psammead components.",
"repository": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import inputProvider from './input-provider';

/* eslint-disable import/prefer-default-export */
export const dirDecorator = storyFn => {
const renderFn = (slotTexts, script, dir) => storyFn({ script, dir });
const renderFn = ({ script, dir, service }) =>
storyFn({ script, dir, service });

const decoratedComponent = inputProvider(null, renderFn);
return decoratedComponent();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ storiesOf('Utilities|Input Provider', module)
{
name: 'first slot',
defaultText:
"this slot overwrites the English default; the next one doesn't",
"this slot overwrites the news default; the next one doesn't",
},
{ name: 'second slot' },
],
([first, second], script, dir) => (
({ slotTexts: [first, second], script, dir, service }) => (
<ul>
<li>{first}</li>
<li>{second}</li>
This conversation was marked as resolved.
Show resolved Hide resolved
<li>{service}</li>
<li>Selected direction: {dir}</li>
<li>
Content of selected script:
Expand Down
145 changes: 60 additions & 85 deletions packages/utilities/psammead-storybook-helpers/src/index.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,45 +53,40 @@ describe('Psammead storybook helpers', () => {
});

it('always calls the render function with a script and direction', () => {
const english = {
text: 'Could a computer ever create better art than a human?',
script: 'latin',
dir: 'ltr',
};
select.mockReturnValueOnce(english);
select.mockReturnValueOnce('news');

underTest.inputProvider([], renderFn)();

expect(renderFn).toHaveBeenCalledTimes(1);
expect(renderFn).toHaveBeenCalledWith([], 'LATIN SCRIPT OBJECT', 'ltr');
expect(renderFn).toHaveBeenCalledWith({
dir: 'ltr',
slotTexts: [],
script: 'LATIN SCRIPT OBJECT',
service: 'news',
});
expect(select).toHaveBeenCalledTimes(1);
expect(text).toHaveBeenCalledTimes(0);
});

it('handles scenario where config is null', () => {
const english = {
text: 'Could a computer ever create better art than a human?',
script: 'latin',
dir: 'ltr',
};
select.mockReturnValueOnce(english);
select.mockReturnValueOnce('news');

underTest.inputProvider(null, renderFn)();

expect(renderFn).toHaveBeenCalledTimes(1);
expect(renderFn).toHaveBeenCalledWith([], 'LATIN SCRIPT OBJECT', 'ltr');
expect(renderFn).toHaveBeenCalledWith({
dir: 'ltr',
slotTexts: [],
script: 'LATIN SCRIPT OBJECT',
service: 'news',
});
expect(select).toHaveBeenCalledTimes(1);
expect(text).toHaveBeenCalledTimes(0);
});

describe('calls the render function with slot default text when displaying english', () => {
describe('calls the render function with slot default text when displaying news', () => {
it('for a single slot', () => {
const english = {
text: 'Could a computer ever create better art than a human?',
script: 'latin',
dir: 'ltr',
};
select.mockReturnValueOnce(english);
select.mockReturnValueOnce('news');
text.mockImplementation((_, displayText) => displayText);

underTest.inputProvider(
Expand All @@ -100,23 +95,19 @@ describe('Psammead storybook helpers', () => {
)();

expect(renderFn).toHaveBeenCalledTimes(1);
expect(renderFn).toHaveBeenCalledWith(
['Sole input'],
'LATIN SCRIPT OBJECT',
'ltr',
);
expect(renderFn).toHaveBeenCalledWith({
slotTexts: ['Sole input'],
script: 'LATIN SCRIPT OBJECT',
dir: 'ltr',
service: 'news',
});

expect(select).toHaveBeenCalledTimes(1);
expect(text).toHaveBeenCalledTimes(1);
});

it('for multiple slots', () => {
const english = {
text: 'Could a computer ever create better art than a human?',
script: 'latin',
dir: 'ltr',
};
select.mockReturnValueOnce(english);
select.mockReturnValueOnce('news');
text.mockImplementation((_, displayText) => displayText);

underTest.inputProvider(
Expand All @@ -128,47 +119,38 @@ describe('Psammead storybook helpers', () => {
)();

expect(renderFn).toHaveBeenCalledTimes(1);
expect(renderFn).toHaveBeenCalledWith(
['First input', 'Second input'],
'LATIN SCRIPT OBJECT',
'ltr',
);
expect(renderFn).toHaveBeenCalledWith({
slotTexts: ['First input', 'Second input'],
script: 'LATIN SCRIPT OBJECT',
dir: 'ltr',
service: 'news',
});

expect(select).toHaveBeenCalledTimes(1);
expect(text).toHaveBeenCalledTimes(2);
});
});

it('displays english snippet when no slot default text provided', () => {
const english = {
text: 'Could a computer ever create better art than a human?',
script: 'latin',
dir: 'ltr',
};
select.mockReturnValueOnce(english);
select.mockReturnValueOnce('news');
text.mockImplementation((_, displayText) => displayText);

underTest.inputProvider([{ name: 'first' }], renderFn)();

expect(renderFn).toHaveBeenCalledTimes(1);
expect(renderFn).toHaveBeenCalledWith(
['Could a computer ever create better art than a human?'],
'LATIN SCRIPT OBJECT',
'ltr',
);
expect(renderFn).toHaveBeenCalledWith({
slotTexts: ['Could a computer ever create better art than a human?'],
script: 'LATIN SCRIPT OBJECT',
dir: 'ltr',
service: 'news',
});

expect(select).toHaveBeenCalledTimes(1);
expect(text).toHaveBeenCalledTimes(1);
});

it('defaults to language text for non-english languages', () => {
const russian = {
text:
'Мнение Назарбаева будет иметь приоритетное значение при принятии важных для страны решений, сказал Токаев',
script: 'cyrillic',
dir: 'ltr',
};
select.mockReturnValueOnce(russian);
it('defaults to service text for non-news services', () => {
select.mockReturnValueOnce('russian');
text.mockImplementation((_, displayText) => displayText);

underTest.inputProvider(
Expand All @@ -177,66 +159,59 @@ describe('Psammead storybook helpers', () => {
)();

expect(renderFn).toHaveBeenCalledTimes(1);
expect(renderFn).toHaveBeenCalledWith(
[
expect(renderFn).toHaveBeenCalledWith({
slotTexts: [
'Мнение Назарбаева будет иметь приоритетное значение при принятии важных для страны решений, сказал Токаев',
],
'CYRILLIC SCRIPT OBJECT',
'ltr',
);
script: 'CYRILLIC SCRIPT OBJECT',
dir: 'ltr',
service: 'russian',
});
});

describe('text direction', () => {
it('defaults to ltr when not specified', () => {
const russian = {
script: 'cyrillic',
};
select.mockReturnValueOnce(russian);
select.mockReturnValueOnce('russian');
text.mockImplementation((textKnobName, displayText) => displayText);

underTest.inputProvider([], renderFn)();

expect(renderFn).toHaveBeenCalledTimes(1);
expect(renderFn).toHaveBeenCalledWith(
[],
'CYRILLIC SCRIPT OBJECT',
'ltr',
);
expect(renderFn).toHaveBeenCalledWith({
slotTexts: [],
script: 'CYRILLIC SCRIPT OBJECT',
dir: 'ltr',
service: 'russian',
});
});

it('returns value when specified', () => {
const arabic = {
script: 'arabic',
dir: 'rtl',
};
select.mockReturnValueOnce(arabic);
select.mockReturnValueOnce('arabic');
text.mockImplementation((_, displayText) => displayText);

underTest.inputProvider([], renderFn)();

expect(renderFn).toHaveBeenCalledTimes(1);
expect(renderFn).toHaveBeenCalledWith(
[],
'ARABIC SCRIPT OBJECT',
'rtl',
);
expect(renderFn).toHaveBeenCalledWith({
slotTexts: [],
script: 'ARABIC SCRIPT OBJECT',
dir: 'rtl',
service: 'arabic',
});
});
});

describe('dirDecorator', () => {
it('calls the story function with dir and script', () => {
const storyFn = jest.fn();
const english = {
script: 'latin',
dir: 'ltr',
};
select.mockReturnValueOnce(english);
select.mockReturnValueOnce('news');

underTest.dirDecorator(storyFn);

expect(storyFn).toHaveBeenCalledWith({
dir: 'ltr',
script: 'LATIN SCRIPT OBJECT',
service: 'news',
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,13 @@ import scripts from '@bbc/gel-foundations/scripts';
import LANGUAGE_VARIANTS from './text-variants';

const inputProvider = (slots, componentFunction) => () => {
const lang = select(
'Select a language',
LANGUAGE_VARIANTS,
LANGUAGE_VARIANTS.english,
);
const serviceNames = Object.keys(LANGUAGE_VARIANTS);
const serviceName = select('Select a service', serviceNames, 'news');

// `select` doesn't return name of language selected, so test if selection
// is English by comparing `text` to English's `text`
const isEnglish = lang.text === LANGUAGE_VARIANTS.english.text;
const service = LANGUAGE_VARIANTS[serviceName];
const isNews = serviceName === 'news';

const inputs = (slots || []).map(({ name, defaultText }) =>
const slotTexts = (slots || []).map(({ name, defaultText }) =>
text(
`Content for ${name}`,
// Expect defaultText to be in English. When it is provided and we're
Expand All @@ -24,17 +20,17 @@ const inputProvider = (slots, componentFunction) => () => {
// When we switch to a language other than English, set the default
// text for the knob to the snippet from LANGUAGE_VARIANTS for that
// language.
defaultText && isEnglish ? defaultText : lang.text,
defaultText && isNews ? defaultText : service.text,
),
);

const script = scripts[lang.script];
const dir = lang.dir || 'ltr';
const script = scripts[service.script];
const dir = service.dir || 'ltr';

return (
<Fragment>
<Helmet htmlAttributes={{ dir }} />
{componentFunction(inputs, script, dir)}
{componentFunction({ slotTexts, script, dir, service: serviceName })}
</Fragment>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const LANGUAGE_VARIANTS = {
},
chineseSimp: { text: '家长们在学校门口维权。', script: 'chinese' },
chineseTrad: { text: '家長們在學校門口維權。', script: 'chinese' },
english: {
news: {
text: 'Could a computer ever create better art than a human?',
script: 'latin',
},
Expand Down