mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-29 18:27:56 +02:00
fix(theme-classic): allow tabs with number as value (#5732)
This commit is contained in:
parent
2398943c17
commit
c2eda4aac1
3 changed files with 73 additions and 53 deletions
|
@ -41,6 +41,6 @@ module.exports = {
|
|||
// Maybe point to a fixture?
|
||||
'@generated/.*': '<rootDir>/jest/emptyModule.js',
|
||||
// TODO maybe use "projects" + multiple configs if we plan to add tests to another theme?
|
||||
'@theme/(.*)': '@docusaurus/theme-classic/lib-next/theme/$1',
|
||||
'@theme/(.*)': '@docusaurus/theme-classic/src/theme/$1',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -9,6 +9,8 @@ import React from 'react';
|
|||
import renderer from 'react-test-renderer';
|
||||
import Tabs from '../index';
|
||||
import TabItem from '../../TabItem';
|
||||
import UserPreferencesProvider from '@theme/UserPreferencesProvider';
|
||||
import {ScrollControllerProvider} from '@docusaurus/theme-common';
|
||||
|
||||
describe('Tabs', () => {
|
||||
test('Should reject bad Tabs child', () => {
|
||||
|
@ -54,53 +56,74 @@ describe('Tabs', () => {
|
|||
test('Should accept valid Tabs config', () => {
|
||||
expect(() => {
|
||||
renderer.create(
|
||||
<>
|
||||
<Tabs>
|
||||
<TabItem value="v1">Tab 1</TabItem>
|
||||
<TabItem value="v2">Tab 2</TabItem>
|
||||
</Tabs>
|
||||
<Tabs>
|
||||
<TabItem value="v1">Tab 1</TabItem>
|
||||
<TabItem value="v2" default>
|
||||
Tab 2
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
<Tabs defaultValue="v1">
|
||||
<TabItem value="v1" label="V1">
|
||||
Tab 1
|
||||
</TabItem>
|
||||
<TabItem value="v2" label="V2">
|
||||
Tab 2
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
<Tabs
|
||||
defaultValue="v1"
|
||||
values={[
|
||||
{value: 'v1', label: 'V1'},
|
||||
{value: 'v2', label: 'V2'},
|
||||
]}>
|
||||
<TabItem>Tab 1</TabItem>
|
||||
<TabItem>Tab 2</TabItem>
|
||||
</Tabs>
|
||||
<Tabs
|
||||
defaultValue={null}
|
||||
values={[
|
||||
{value: 'v1', label: 'V1'},
|
||||
{value: 'v2', label: 'V2'},
|
||||
]}>
|
||||
<TabItem>Tab 1</TabItem>
|
||||
<TabItem>Tab 2</TabItem>
|
||||
</Tabs>
|
||||
<Tabs defaultValue={null}>
|
||||
<TabItem value="v1" label="V1">
|
||||
Tab 1
|
||||
</TabItem>
|
||||
<TabItem value="v2" label="V2">
|
||||
Tab 2
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
</>,
|
||||
<ScrollControllerProvider>
|
||||
<UserPreferencesProvider>
|
||||
<Tabs>
|
||||
<TabItem value="v1">Tab 1</TabItem>
|
||||
<TabItem value="v2">Tab 2</TabItem>
|
||||
</Tabs>
|
||||
<Tabs>
|
||||
<TabItem value="v1">Tab 1</TabItem>
|
||||
<TabItem value="v2" default>
|
||||
Tab 2
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
<Tabs defaultValue="v1">
|
||||
<TabItem value="v1" label="V1">
|
||||
Tab 1
|
||||
</TabItem>
|
||||
<TabItem value="v2" label="V2">
|
||||
Tab 2
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
<Tabs
|
||||
defaultValue="v1"
|
||||
values={[
|
||||
{value: 'v1', label: 'V1'},
|
||||
{value: 'v2', label: 'V2'},
|
||||
]}>
|
||||
<TabItem value="v1">Tab 1</TabItem>
|
||||
<TabItem value="v2">Tab 2</TabItem>
|
||||
</Tabs>
|
||||
<Tabs
|
||||
defaultValue={null}
|
||||
values={[
|
||||
{value: 'v1', label: 'V1'},
|
||||
{value: 'v2', label: 'V2'},
|
||||
]}>
|
||||
<TabItem value="v1">Tab 1</TabItem>
|
||||
<TabItem value="v2">Tab 2</TabItem>
|
||||
</Tabs>
|
||||
<Tabs defaultValue={null}>
|
||||
<TabItem value="v1" label="V1">
|
||||
Tab 1
|
||||
</TabItem>
|
||||
<TabItem value="v2" label="V2">
|
||||
Tab 2
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
</UserPreferencesProvider>
|
||||
</ScrollControllerProvider>,
|
||||
);
|
||||
}).toMatchInlineSnapshot(`[Function]`); // This is just a check that the function returns. We don't care about the actual DOM.
|
||||
}).not.toThrow(); // TODO Better Jest infrastructure to mock the Layout
|
||||
});
|
||||
// https://github.com/facebook/docusaurus/issues/5729
|
||||
test('Should accept dynamic Tabs with number values', () => {
|
||||
expect(() => {
|
||||
const tabs = ['Apple', 'Banana', 'Carrot'];
|
||||
renderer.create(
|
||||
<ScrollControllerProvider>
|
||||
<UserPreferencesProvider>
|
||||
<Tabs
|
||||
values={tabs.map((t, idx) => ({label: t, value: idx}))}
|
||||
defaultValue={0}>
|
||||
{tabs.map((t, idx) => (
|
||||
<TabItem value={idx}>{t}</TabItem>
|
||||
))}
|
||||
</Tabs>
|
||||
</UserPreferencesProvider>
|
||||
</ScrollControllerProvider>,
|
||||
);
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -25,7 +25,7 @@ import styles from './styles.module.css';
|
|||
// A very rough duck type, but good enough to guard against mistakes while
|
||||
// allowing customization
|
||||
function isTabItem(comp: ReactElement): comp is ReactElement<TabItemProps> {
|
||||
return typeof comp.props.value === 'string';
|
||||
return typeof comp.props.value !== 'undefined';
|
||||
}
|
||||
|
||||
function TabsComponent(props: Props): JSX.Element {
|
||||
|
@ -51,10 +51,7 @@ function TabsComponent(props: Props): JSX.Element {
|
|||
);
|
||||
});
|
||||
const values =
|
||||
valuesProp ??
|
||||
children.map(({props: {value, label}}) => {
|
||||
return {value, label};
|
||||
});
|
||||
valuesProp ?? children.map(({props: {value, label}}) => ({value, label}));
|
||||
const dup = duplicates(values, (a, b) => a.value === b.value);
|
||||
if (dup.length > 0) {
|
||||
throw new Error(
|
||||
|
|
Loading…
Add table
Reference in a new issue