diff --git a/.travis.yml b/.travis.yml index b50415fb..4a96ada2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,35 +1,18 @@ language: node_js -sudo: false - -notifications: - email: - - yiminghe@gmail.com - - hust2012jiangkai@gmail.com - node_js: -- 10 + - 10 -before_install: -- | - if ! git diff --name-only $TRAVIS_COMMIT_RANGE | grep -qvE '(\.md$)|(^(docs|examples))/' - then - echo "Only docs were updated, stopping build process." - exit - fi - phantomjs --version script: -- | + - | if [ "$TEST_TYPE" = test ]; then - npm test + npm test -- --coverage && \ + bash <(curl -s https://codecov.io/bash) else npm run $TEST_TYPE fi env: matrix: - - TEST_TYPE=lint - - TEST_TYPE=test - - TEST_TYPE=coverage - global: - - secure: S1VwbaPzLnSH/IUT/wlJulxAX5VHRIDmSt53h/ycHcZsszUpWcLCJRQAe0fTVB2dAx5MdBbSZ+o+tr3tRwVB5TRAYm0oTCsYAkOZaWOB28RuUQtdGt3wf9xxTG1UiPiaLLUW3waX9zAaf3yqKBcJGf1op0RD8dksxbCFw/7xVbU= - - secure: EBEDg8k///IlEsnx0AE8X3mbFl0QE5+xGKbG4AxXlGZda12uTIPUSMKJzdZQ2hVbZXduTzf1cQl9rcu9nGoSnkL/DWnIax9cvHi+1orx5+YPlxPHNWAwWByTnHosBn2MJhfy1s5paJfHC9cUzmmEL6x4fYthWxjsPUo+irEZH6E= + - TEST_TYPE=lint + - TEST_TYPE=test + - TEST_TYPE=compile \ No newline at end of file diff --git a/assets/index.less b/assets/index.less index 5ea98649..3392a6b5 100644 --- a/assets/index.less +++ b/assets/index.less @@ -95,33 +95,32 @@ font-size: 20px; background: rgba(255, 255, 255, 0.5); margin: 0; - padding: 8px 16px; + display: flex; outline: none; cursor: pointer; position: relative; font-weight: lighter; + align-items: center; - &-with-remove { - padding-right: 32px; + &-btn, + &-remove { + border: 0; + background: transparent; } - &-remove { - position: absolute; - right: 16px; - top: 50%; - transform: translateY(-50%); + &-btn { + font-weight: inherit; + line-height: 32px; + } + &-remove { &:hover { color: red; } } - &:focus { - background: rgba(0, 0, 255, 0.1); - } - &-active { - padding-left: 30px; + // padding-left: 30px; font-weight: bolder; } } diff --git a/examples/mix.tsx b/examples/mix.tsx index f7fb4882..36d7cce5 100644 --- a/examples/mix.tsx +++ b/examples/mix.tsx @@ -20,12 +20,12 @@ export default () => { const [position, setPosition] = React.useState('top'); const [gutter, setGutter] = React.useState(false); const [fixHeight, setFixHeight] = React.useState(true); - const [rtl, setRTL] = React.useState(true); + const [rtl, setRTL] = React.useState(false); const [editable, setEditable] = React.useState(true); const [destroyInactiveTabPane, setDestroyInactiveTabPane] = React.useState(false); const [destroy, setDestroy] = React.useState(false); const [animated, setAnimated] = React.useState(true); - const [tabPanes, setTabPanes] = React.useState(getTabPanes(50)); + const [tabPanes, setTabPanes] = React.useState(getTabPanes(10)); const editableConfig = editable ? { diff --git a/src/TabNavList/TabNode.tsx b/src/TabNavList/TabNode.tsx index be593725..99f8c513 100644 --- a/src/TabNavList/TabNode.tsx +++ b/src/TabNavList/TabNode.tsx @@ -11,7 +11,7 @@ export interface TabNodeProps { rtl: boolean; closable?: boolean; editable?: EditableConfig; - onClick?: React.MouseEventHandler; + onClick?: (e: React.MouseEvent | React.KeyboardEvent) => void; onResize?: (width: number, height: number, left: number, top: number) => void; tabBarGutter?: number; tabPosition: TabPosition; @@ -39,7 +39,7 @@ function TabNode( onRemove, onFocus, }: TabNodeProps, - ref: React.Ref, + ref: React.Ref, ) { const tabPrefix = `${prefixCls}-tab`; @@ -54,6 +54,12 @@ function TabNode( const removable = editable && closable !== false && !disabled; + function onInternalClick(e: React.MouseEvent | React.KeyboardEvent) { + if (disabled) return; + + onClick(e); + } + function onRemoveTab(event: React.MouseEvent | React.KeyboardEvent) { event.preventDefault(); event.stopPropagation(); @@ -64,45 +70,57 @@ function TabNode( } let node: React.ReactElement = ( - )} - + ); if (renderWrapper) { diff --git a/src/TabNavList/index.tsx b/src/TabNavList/index.tsx index 054e0d37..418c5ceb 100644 --- a/src/TabNavList/index.tsx +++ b/src/TabNavList/index.tsx @@ -66,7 +66,7 @@ function TabNavList(props: TabNavListProps, ref: React.Ref) { const tabListRef = useRef(); const operationsRef = useRef(); const innerAddButtonRef = useRef(); - const [getBtnRef, removeBtnRef] = useRefs(); + const [getBtnRef, removeBtnRef] = useRefs(); const tabPositionTopOrBottom = tabPosition === 'top' || tabPosition === 'bottom'; diff --git a/tests/__snapshots__/index.test.tsx.snap b/tests/__snapshots__/index.test.tsx.snap index 5c33729d..04a04e42 100644 --- a/tests/__snapshots__/index.test.tsx.snap +++ b/tests/__snapshots__/index.test.tsx.snap @@ -15,39 +15,48 @@ exports[`Tabs.Basic Normal 1`] = ` class="rc-tabs-nav-list" style="transform: translate(0px, 0px);" > - - - + +
@@ -126,17 +135,20 @@ exports[`Tabs.Basic Skip invalidate children 1`] = ` class="rc-tabs-nav-list" style="transform: translate(0px, 0px);" > - + +
diff --git a/tests/index.test.tsx b/tests/index.test.tsx index 7ee48b5d..5df2632c 100644 --- a/tests/index.test.tsx +++ b/tests/index.test.tsx @@ -50,14 +50,47 @@ describe('Tabs.Basic', () => { mount(getTabs({ children: null })); }); - it('onChange and onTabClick should work', () => { - const onChange = jest.fn(); - const onTabClick = jest.fn(); - const wrapper = mount(getTabs({ onChange, onTabClick })); - const targetTab = wrapper.find('.rc-tabs-tab').at(2); - targetTab.simulate('click'); - expect(onTabClick).toHaveBeenCalledWith('cute', expect.anything()); - expect(onChange).toHaveBeenCalledWith('cute'); + describe('onChange and onTabClick should work', () => { + const list: { name: string; trigger: (wrapper: ReactWrapper) => void }[] = [ + { + name: 'outer div', + trigger: wrapper => + wrapper + .find('.rc-tabs-tab') + .at(2) + .simulate('click'), + }, + { + name: 'inner button', + trigger: wrapper => + wrapper + .find('.rc-tabs-tab .rc-tabs-tab-btn') + .at(2) + .simulate('click'), + }, + { + name: 'inner button key down', + trigger: wrapper => + wrapper + .find('.rc-tabs-tab .rc-tabs-tab-btn') + .at(2) + .simulate('keydown', { + which: KeyCode.SPACE, + }), + }, + ]; + + list.forEach(({ name, trigger }) => { + it(name, () => { + const onChange = jest.fn(); + const onTabClick = jest.fn(); + const wrapper = mount(getTabs({ onChange, onTabClick })); + + trigger(wrapper); + expect(onTabClick).toHaveBeenCalledWith('cute', expect.anything()); + expect(onChange).toHaveBeenCalledWith('cute'); + }); + }); }); it('active first tab when children is changed', () => { @@ -177,14 +210,6 @@ describe('Tabs.Basic', () => { node.simulate('click'); }, }, - { - name: 'key', - trigger: node => { - node.simulate('keydown', { - which: KeyCode.SPACE, - }); - }, - }, ]; list.forEach(({ name, trigger }) => { @@ -195,6 +220,9 @@ describe('Tabs.Basic', () => { const first = wrapper.find('.rc-tabs-tab-remove').first(); trigger(first); + // Should be button to enable press SPACE key to trigger + expect(first.instance() instanceof HTMLButtonElement).toBeTruthy(); + expect(onEdit).toHaveBeenCalledWith('remove', { key: 'light', event: expect.anything(), diff --git a/tests/mobile.test.tsx b/tests/mobile.test.tsx index 85136eff..4fbe21c2 100644 --- a/tests/mobile.test.tsx +++ b/tests/mobile.test.tsx @@ -70,6 +70,9 @@ describe('Tabs.Mobile', () => { domSpy = spyElementPrototypes(HTMLDivElement, { offsetWidth: { get() { + if (this.className.includes('rc-tabs-tab')) { + return 20; + } if (this.className.includes('rc-tabs-nav-list')) { return tabCount * 20; } diff --git a/tests/overflow.test.tsx b/tests/overflow.test.tsx index 751245a4..fd94bc7e 100644 --- a/tests/overflow.test.tsx +++ b/tests/overflow.test.tsx @@ -14,7 +14,6 @@ import { TabPane } from '../src'; describe('Tabs.Overflow', () => { let domSpy: ReturnType; - let buttonSpy: ReturnType; let holder: HTMLDivElement; const hackOffsetInfo: { list?: number } = {}; @@ -32,12 +31,13 @@ describe('Tabs.Overflow', () => { return 20 * index; } - buttonSpy = spyElementPrototypes(HTMLButtonElement, { + domSpy = spyElementPrototypes(HTMLElement, { + scrollIntoView: () => {}, offsetWidth: { - get: () => 20, + get: getOffsetSizeFunc(hackOffsetInfo), }, offsetHeight: { - get: () => 20, + get: getOffsetSizeFunc(hackOffsetInfo), }, offsetLeft: { get: btnOffsetPosition, @@ -46,20 +46,9 @@ describe('Tabs.Overflow', () => { get: btnOffsetPosition, }, }); - - domSpy = spyElementPrototypes(HTMLElement, { - scrollIntoView: () => {}, - offsetWidth: { - get: getOffsetSizeFunc(hackOffsetInfo), - }, - offsetHeight: { - get: getOffsetSizeFunc(hackOffsetInfo), - }, - }); }); afterAll(() => { - buttonSpy.mockRestore(); domSpy.mockRestore(); document.body.removeChild(holder); }); diff --git a/tests/rtl.test.tsx b/tests/rtl.test.tsx index 118f5011..614400ba 100644 --- a/tests/rtl.test.tsx +++ b/tests/rtl.test.tsx @@ -7,15 +7,22 @@ import { getOffsetSizeFunc, getTabs, triggerResize, getTransformX } from './comm describe('Tabs.RTL', () => { let domSpy: ReturnType; - let buttonSpy: ReturnType; let holder: HTMLDivElement; beforeAll(() => { holder = document.createElement('div'); document.body.appendChild(holder); - buttonSpy = spyElementPrototypes(HTMLButtonElement, { + + domSpy = spyElementPrototypes(HTMLElement, { + scrollIntoView: () => {}, offsetWidth: { - get: () => 20, + get: getOffsetSizeFunc(), + }, + offsetHeight: { + get: getOffsetSizeFunc(), + }, + scrollWidth: { + get: () => 5 * 20, }, offsetLeft: { get() { @@ -29,23 +36,9 @@ describe('Tabs.RTL', () => { }, }, }); - - domSpy = spyElementPrototypes(HTMLElement, { - scrollIntoView: () => {}, - offsetWidth: { - get: getOffsetSizeFunc(), - }, - offsetHeight: { - get: getOffsetSizeFunc(), - }, - scrollWidth: { - get: () => 5 * 20, - }, - }); }); afterAll(() => { - buttonSpy.mockRestore(); domSpy.mockRestore(); document.body.removeChild(holder); });