diff --git a/cypress/e2e/AnimationList/test-absolute-autoAdapt.cy.ts b/cypress/e2e/AnimationList/test-absolute-autoAdapt.cy.ts new file mode 100644 index 000000000..ad0757519 --- /dev/null +++ b/cypress/e2e/AnimationList/test-absolute-autoAdapt.cy.ts @@ -0,0 +1,59 @@ +it('下拉列表', () => { + cy.visit('/cn/components/Select?example=009-popupContainer-absolute-long') + + function getNearestPositionDom(target: HTMLElement): HTMLElement { + if (target) { + const { position } = getComputedStyle(target) + + if (position !== 'static') { + return target + } + + if (target.parentElement) { + return getNearestPositionDom(target.parentElement) + } + } + return document.body + } + + cy.get('#relative-app').as('App') + cy.get('#app-out-container').as('OutContainer') + cy.get('#app-root-container').as('Container') + + cy.viewport(1100, 500) + cy.scrollTo(0, 1000) + cy.get('#app-out-container').scrollTo(100, 150) + + cy.get('#app-root-container').as('Container') + + cy.get(`.select`).as('select') + cy.get(`@select`).click() + cy.get('@Container') + .find(`.so-select-options`) + .should('have.length', 1) + + cy.get(`.select`).then($el => { + const rect = $el[0].getBoundingClientRect() + cy.get('@Container') + .find(`.so-select-options`) + .then($co => { + const coRect = $co[0].getBoundingClientRect() + // 3 为固定间距 + expect(Math.abs(coRect.top - rect.top - rect.height)).to.eq(3) + }) + }) + + cy.get('.so-select-options').then($el => { + const rect = $el[0].getBoundingClientRect() + cy.get(`@select`).then($co => { + const coRect = $co[0].getBoundingClientRect() + expect(rect.width + coRect.left).to.be.greaterThan(1100) + }) + cy.get('@Container').then($container => { + const nearstPositionDom = getNearestPositionDom($container[0]) + const nearstPositionDomRect = nearstPositionDom.getBoundingClientRect() + const offset = 1100 - nearstPositionDomRect.left - nearstPositionDomRect.width + expect(getComputedStyle($el[0]).right).to.eq(`${offset * -1}px`) + }) + }) +}) diff --git a/cypress/e2e/AnimationList/test.absolute-relative.cy.ts b/cypress/e2e/AnimationList/test.absolute-relative.cy.ts new file mode 100644 index 000000000..69015cdaa --- /dev/null +++ b/cypress/e2e/AnimationList/test.absolute-relative.cy.ts @@ -0,0 +1,106 @@ +describe('Select[clickAway]', () => { + it('下拉列表', () => { + cy.visit('/cn/components/Select?example=008-popupContainer-absolute-relative') + + const components = [ + { + selector: 'select', + dropDown: 'so-select-options', + }, + { + selector: 'datepicker', + dropDown: 'so-datepicker-picker', + }, + { + selector: 'cascader', + dropDown: 'so-cascader-options', + }, + { + selector: 'treeselect', + dropDown: 'so-treeSelect-options', + }, + ] + + cy.get('#relative-app').as('App') + cy.get('#app-out-container').as('OutContainer') + cy.get('#app-root-container').as('Container') + + cy.get('#app-out-container').scrollTo(50, 50) + + components.forEach(async com => { + const { selector, dropDown } = com + + cy.get(`.${selector}`).as(selector) + cy.get(`@${selector}`).click() + cy.get('@Container') + .find(`.${dropDown}`) + .should('have.length', 1) + + cy.get(`.${selector}`).then($el => { + const rect = $el[0].getBoundingClientRect() + cy.get('@Container') + .find(`.${dropDown}`) + .then($co => { + const coRect = $co[0].getBoundingClientRect() + // 3 为固定间距 + expect(Math.abs(coRect.top - rect.top - rect.height)).to.eq(3) + }) + cy.get('@Container').click({ force: true }) + }) + }) + }) + + it('上拉列表', () => { + cy.visit('/cn/components/Select?example=008-popupContainer-absolute-relative') + + const components = [ + { + selector: 'select', + dropDown: 'so-select-options', + }, + { + selector: 'datepicker', + dropDown: 'so-datepicker-picker', + }, + { + selector: 'cascader', + dropDown: 'so-cascader-options', + }, + { + selector: 'treeselect', + dropDown: 'so-treeSelect-options', + }, + ] + + cy.get('#relative-app').as('App') + cy.get('#app-out-container').as('OutContainer') + cy.get('#app-root-container').as('Container') + + cy.get('#app-out-container').scrollTo(50, 50) + + cy.get('#apis').invoke('css', { display: 'none' }) + cy.get('#api-Select').invoke('css', { display: 'none' }) + cy.get('.doc-api-table').invoke('css', { display: 'none' }) + + components.forEach(async com => { + const { selector, dropDown } = com + + cy.get(`.${selector}`).as(selector) + cy.get(`@${selector}`).click() + cy.get('@Container') + .find(`.${dropDown}`) + .should('have.length', 1) + + cy.get(`.${selector}`).then($el => { + const rect = $el[0].getBoundingClientRect() + cy.get('@Container') + .find(`.${dropDown}`) + .then($co => { + const coRect = $co[0].getBoundingClientRect() + // 3 为固定间距 + expect(Math.abs(coRect.top - rect.top)).to.eq(coRect.height + 3) + }) + }) + }) + }) +}) diff --git a/cypress/e2e/AnimationList/test.absolute.cy.ts b/cypress/e2e/AnimationList/test.absolute.cy.ts new file mode 100644 index 000000000..c54d82076 --- /dev/null +++ b/cypress/e2e/AnimationList/test.absolute.cy.ts @@ -0,0 +1,105 @@ +describe('Select[clickAway]', () => { + it('下拉列表', () => { + cy.visit('/cn/components/Select?example=007-popupContainer-absolute') + + const components = [ + { + selector: 'select', + dropDown: 'so-select-options', + }, + { + selector: 'datepicker', + dropDown: 'so-datepicker-picker', + }, + { + selector: 'cascader', + dropDown: 'so-cascader-options', + }, + { + selector: 'treeselect', + dropDown: 'so-treeSelect-options', + }, + ] + + cy.get('#relative-app').as('App') + cy.get('#app-out-container').as('OutContainer') + cy.get('#app-root-container').as('Container') + + cy.get('#app-out-container').scrollTo(50, 50) + + components.forEach(async com => { + const { selector, dropDown } = com + + cy.get(`.${selector}`).as(selector) + cy.get(`@${selector}`).click() + cy.get('@Container') + .find(`.${dropDown}`) + .should('have.length', 1) + + cy.get(`.${selector}`).then($el => { + const rect = $el[0].getBoundingClientRect() + cy.get('@Container') + .find(`.${dropDown}`) + .then($co => { + const coRect = $co[0].getBoundingClientRect() + // 3 为固定间距 + expect(Math.abs(coRect.top - rect.top - rect.height)).to.eq(3) + }) + }) + }) + }) + + it('上拉列表', () => { + cy.visit('/cn/components/Select?example=007-popupContainer-absolute') + + const components = [ + { + selector: 'select', + dropDown: 'so-select-options', + }, + { + selector: 'datepicker', + dropDown: 'so-datepicker-picker', + }, + { + selector: 'cascader', + dropDown: 'so-cascader-options', + }, + { + selector: 'treeselect', + dropDown: 'so-treeSelect-options', + }, + ] + + cy.get('#relative-app').as('App') + cy.get('#app-out-container').as('OutContainer') + cy.get('#app-root-container').as('Container') + + cy.get('#app-out-container').scrollTo(50, 50) + + cy.get('#apis').invoke('css', { display: 'none' }) + cy.get('#api-Select').invoke('css', { display: 'none' }) + cy.get('.doc-api-table').invoke('css', { display: 'none' }) + + components.forEach(async com => { + const { selector, dropDown } = com + + cy.get(`.${selector}`).as(selector) + cy.get(`@${selector}`).click() + cy.get('@Container') + .find(`.${dropDown}`) + .should('have.length', 1) + + cy.get(`.${selector}`).then($el => { + const rect = $el[0].getBoundingClientRect() + cy.get('@Container') + .find(`.${dropDown}`) + .then($co => { + const coRect = $co[0].getBoundingClientRect() + // 3 为固定间距 + expect(Math.abs(coRect.top - rect.top)).to.eq(coRect.height + 3) + }) + }) + }) + }) +}) diff --git a/site/chunks/Components/Select.js b/site/chunks/Components/Select.js index 6835b187f..5e3c4e9a4 100644 --- a/site/chunks/Components/Select.js +++ b/site/chunks/Components/Select.js @@ -416,6 +416,45 @@ const examples = [ parseTsText: require('!raw-loader!ts-loader!doc/pages/components/Select/test-006-open.tsx'), }, + { + name: 'test-007-popupContainer-absolute', + isTs: true, + isTest: true, + title: locate( + '指定无定位属性容器后,下拉菜单是否正常定位 \n 检查容器位置是否在下拉菜单之下。该示例需要单独运行,否则 setConfig 会干扰其他示例', + ' \n ' + ), + component: require('doc/pages/components/Select/test-007-popupContainer-absolute.tsx').default, + rawText: require('!raw-loader!doc/pages/components/Select/test-007-popupContainer-absolute.tsx'), + parseTsText: require('!raw-loader!ts-loader!doc/pages/components/Select/test-007-popupContainer-absolute.tsx'), + + }, + { + name: 'test-008-popupContainer-absolute-relative', + isTs: true, + isTest: true, + title: locate( + '指定容器后,下拉菜单是否正常定位 \n 检查容器位置是否在下拉菜单之下。该示例需要单独运行,否则 setConfig 会干扰其他示例', + ' \n ' + ), + component: require('doc/pages/components/Select/test-008-popupContainer-absolute-relative.tsx').default, + rawText: require('!raw-loader!doc/pages/components/Select/test-008-popupContainer-absolute-relative.tsx'), + parseTsText: require('!raw-loader!ts-loader!doc/pages/components/Select/test-008-popupContainer-absolute-relative.tsx'), + + }, + { + name: 'test-009-popupContainer-absolute-long', + isTs: true, + isTest: true, + title: locate( + '指定无定位属性容器后,超长下拉菜单是否正常定位 \n ', + ' \n options auto adapt width' + ), + component: require('doc/pages/components/Select/test-009-popupContainer-absolute-long.tsx').default, + rawText: require('!raw-loader!doc/pages/components/Select/test-009-popupContainer-absolute-long.tsx'), + parseTsText: require('!raw-loader!ts-loader!doc/pages/components/Select/test-009-popupContainer-absolute-long.tsx'), + + }, ] const codes = undefined diff --git a/site/pages/components/Select/test-007-popupContainer-absolute.tsx b/site/pages/components/Select/test-007-popupContainer-absolute.tsx new file mode 100644 index 000000000..1b5f4edb1 --- /dev/null +++ b/site/pages/components/Select/test-007-popupContainer-absolute.tsx @@ -0,0 +1,138 @@ +/** + * cn - 指定无定位属性容器后,下拉菜单是否正常定位 + * -- 检查容器位置是否在下拉菜单之下。该示例需要单独运行,否则 setConfig 会干扰其他示例 + * en - + * -- + */ + +import React, { useEffect, useState } from 'react' +import { Select, setConfig, DatePicker, Cascader, TreeSelect } from 'shineout' + +type SelectItem = string +const data: SelectItem[] = ['red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'violet'] + +for (let i = 0; i < 50; i++) { + data.push(`color-${i}`) +} + +const cascaderData = [ + { + value: 'jiangsu', + children: [ + { + value: 'nanjing', + children: [ + { + value: 'jiangning', + }, + ], + }, + ], + }, + { + value: 'anhui', + children: [ + { + value: 'hefei', + children: [ + { + value: 'feidong', + }, + ], + }, + ], + }, +] + +const treeSelectData = [ + { + id: '1', + title: '1', + children: [ + { id: '1-1', title: '1-1', children: [{ id: '1-1-1', title: '1-1-1' }, { id: '1-1-2', title: '1-1-2' }] }, + { id: '1-2', title: '1-2' }, + ], + }, + { id: '2', title: '2', children: [{ id: '2-1', title: '2-1' }, { id: '2-2', title: '2-2' }] }, + { id: '3', title: '3', children: [{ id: '3-1', title: '3-1' }] }, +] + +const container: React.CSSProperties = { + padding: 10, + height: 100, + width: 300, + background: '#ebebeb', + overflow: 'auto', +} + +const style: React.CSSProperties = { + width: 200, + marginInlineEnd: 12, + marginBottom: 8, + marginLeft: 100, +} + +const App: React.FC = () => { + const [mount, setMount] = useState(false) + + useEffect(() => { + setConfig({ + popupContainer: document.getElementById('app-root-container') || document.body, + }) + + setMount(true) + }, []) + + return ( + <> +
+