mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-11 11:32:52 +08:00
enhance: keep show clearIcon when in mobile view (#53576)
* feat: The clearIcon of the Select component remain displayed when hover=none device * chore: tmp of mobile test * test: support mobile snapshot * test: adjust logic * chore: force trigger * chore: rm is mobile config * chore: update enable check * chore: clean up * chore: force trigger * chore: debug for query * chore: trigger info * test: force disable mobile style --------- Co-authored-by: 刘欢 <lh01217311@antgroup.com> Co-authored-by: 二货机器人 <smith3816@gmail.com>
This commit is contained in:
parent
c1154c08e9
commit
e28247bf0c
@ -1,5 +1,7 @@
|
|||||||
import { imageDemoTest } from '../../../tests/shared/imageTest';
|
import { imageDemoTest } from '../../../tests/shared/imageTest';
|
||||||
|
|
||||||
describe('Select image', () => {
|
describe('Select image', () => {
|
||||||
imageDemoTest('select');
|
imageDemoTest('select', {
|
||||||
|
mobile: ['basic.tsx'],
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -72,6 +72,14 @@ const getSearchInputWithoutBorderStyle: GenerateStyle<SelectToken, CSSObject> =
|
|||||||
const genBaseStyle: GenerateStyle<SelectToken> = (token) => {
|
const genBaseStyle: GenerateStyle<SelectToken> = (token) => {
|
||||||
const { antCls, componentCls, inputPaddingHorizontalBase, iconCls } = token;
|
const { antCls, componentCls, inputPaddingHorizontalBase, iconCls } = token;
|
||||||
|
|
||||||
|
const hoverShowClearStyle: CSSObject = {
|
||||||
|
[`${componentCls}-clear`]: {
|
||||||
|
opacity: 1,
|
||||||
|
background: token.colorBgBase,
|
||||||
|
borderRadius: '50%',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
[componentCls]: {
|
[componentCls]: {
|
||||||
...resetComponent(token),
|
...resetComponent(token),
|
||||||
@ -198,11 +206,8 @@ const genBaseStyle: GenerateStyle<SelectToken> = (token) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
[`&:hover ${componentCls}-clear`]: {
|
'@media(hover:none)': hoverShowClearStyle,
|
||||||
opacity: 1,
|
'&:hover': hoverShowClearStyle,
|
||||||
background: token.colorBgBase,
|
|
||||||
borderRadius: '50%',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// ========================= Feedback ==========================
|
// ========================= Feedback ==========================
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// jest-puppeteer.config.js
|
// jest-puppeteer.config.js
|
||||||
module.exports = {
|
module.exports = {
|
||||||
launch: {
|
launch: {
|
||||||
|
headless: 'new',
|
||||||
ignoreDefaultArgs: ['--disable-extensions'],
|
ignoreDefaultArgs: ['--disable-extensions'],
|
||||||
args: [
|
args: [
|
||||||
// Required for Docker version of Puppeteer
|
// Required for Docker version of Puppeteer
|
||||||
|
@ -289,7 +289,7 @@
|
|||||||
"prettier": "^3.4.1",
|
"prettier": "^3.4.1",
|
||||||
"pretty-format": "^29.7.0",
|
"pretty-format": "^29.7.0",
|
||||||
"prismjs": "^1.29.0",
|
"prismjs": "^1.29.0",
|
||||||
"puppeteer": "^24.0.0",
|
"puppeteer": "^24.7.1",
|
||||||
"rc-footer": "^0.6.8",
|
"rc-footer": "^0.6.8",
|
||||||
"rc-tween-one": "^3.0.6",
|
"rc-tween-one": "^3.0.6",
|
||||||
"rc-virtual-list": "^3.17.0",
|
"rc-virtual-list": "^3.17.0",
|
||||||
|
@ -8,8 +8,8 @@ import fse from 'fs-extra';
|
|||||||
import { globSync } from 'glob';
|
import { globSync } from 'glob';
|
||||||
import { JSDOM } from 'jsdom';
|
import { JSDOM } from 'jsdom';
|
||||||
import MockDate from 'mockdate';
|
import MockDate from 'mockdate';
|
||||||
|
import type { HTTPRequest, Viewport } from 'puppeteer';
|
||||||
import rcWarning from 'rc-util/lib/warning';
|
import rcWarning from 'rc-util/lib/warning';
|
||||||
import type { HTTPRequest } from 'puppeteer';
|
|
||||||
import ReactDOMServer from 'react-dom/server';
|
import ReactDOMServer from 'react-dom/server';
|
||||||
|
|
||||||
import { App, ConfigProvider, theme } from '../../components';
|
import { App, ConfigProvider, theme } from '../../components';
|
||||||
@ -32,6 +32,7 @@ interface ImageTestOptions {
|
|||||||
onlyViewport?: boolean;
|
onlyViewport?: boolean;
|
||||||
ssr?: boolean;
|
ssr?: boolean;
|
||||||
openTriggerClassName?: string;
|
openTriggerClassName?: string;
|
||||||
|
mobile?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line jest/no-export
|
// eslint-disable-next-line jest/no-export
|
||||||
@ -109,9 +110,14 @@ export default function imageTest(
|
|||||||
container = doc.querySelector<HTMLDivElement>('#root')!;
|
container = doc.querySelector<HTMLDivElement>('#root')!;
|
||||||
});
|
});
|
||||||
|
|
||||||
function test(name: string, suffix: string, themedComponent: React.ReactElement) {
|
function test(name: string, suffix: string, themedComponent: React.ReactElement, mobile = false) {
|
||||||
it(name, async () => {
|
it(name, async () => {
|
||||||
await page.setViewport({ width: 800, height: 600 });
|
const sharedViewportConfig: Partial<Viewport> = {
|
||||||
|
isMobile: mobile,
|
||||||
|
hasTouch: mobile,
|
||||||
|
};
|
||||||
|
|
||||||
|
await page.setViewport({ width: 800, height: 600, ...sharedViewportConfig });
|
||||||
|
|
||||||
const onRequestHandle = (request: HTTPRequest) => {
|
const onRequestHandle = (request: HTTPRequest) => {
|
||||||
if (['image'].includes(request.resourceType())) {
|
if (['image'].includes(request.resourceType())) {
|
||||||
@ -166,6 +172,11 @@ export default function imageTest(
|
|||||||
unmount();
|
unmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove mobile css for hardcode since CI will always think as mobile
|
||||||
|
if (!mobile) {
|
||||||
|
styleStr = styleStr.replace(/@media\(hover:\s*none\)/g, '@media(hover:not-valid)');
|
||||||
|
}
|
||||||
|
|
||||||
if (openTriggerClassName) {
|
if (openTriggerClassName) {
|
||||||
styleStr += `<style>
|
styleStr += `<style>
|
||||||
.${openTriggerClassName} {
|
.${openTriggerClassName} {
|
||||||
@ -211,7 +222,7 @@ export default function imageTest(
|
|||||||
Please consider using \`onlyViewport: ["filename.tsx"]\`, read more: https://github.com/ant-design/ant-design/pull/52053`,
|
Please consider using \`onlyViewport: ["filename.tsx"]\`, read more: https://github.com/ant-design/ant-design/pull/52053`,
|
||||||
);
|
);
|
||||||
|
|
||||||
await page.setViewport({ width: 800, height: bodyHeight });
|
await page.setViewport({ width: 800, height: bodyHeight, ...sharedViewportConfig });
|
||||||
}
|
}
|
||||||
|
|
||||||
const image = await page.screenshot({
|
const image = await page.screenshot({
|
||||||
@ -225,29 +236,35 @@ export default function imageTest(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.entries(themes).forEach(([key, algorithm]) => {
|
if (!options.mobile) {
|
||||||
const configTheme = {
|
Object.entries(themes).forEach(([key, algorithm]) => {
|
||||||
algorithm,
|
const configTheme = {
|
||||||
token: {
|
algorithm,
|
||||||
fontFamily: 'Arial',
|
token: {
|
||||||
},
|
fontFamily: 'Arial',
|
||||||
};
|
},
|
||||||
|
};
|
||||||
|
|
||||||
test(
|
test(
|
||||||
`component image screenshot should correct ${key}`,
|
`component image screenshot should correct ${key}`,
|
||||||
`.${key}`,
|
`.${key}`,
|
||||||
<div style={{ background: key === 'dark' ? '#000' : '', padding: `24px 12px` }} key={key}>
|
<div style={{ background: key === 'dark' ? '#000' : '', padding: `24px 12px` }} key={key}>
|
||||||
<ConfigProvider theme={configTheme}>{component}</ConfigProvider>
|
<ConfigProvider theme={configTheme}>{component}</ConfigProvider>
|
||||||
</div>,
|
</div>,
|
||||||
);
|
);
|
||||||
test(
|
test(
|
||||||
`[CSS Var] component image screenshot should correct ${key}`,
|
`[CSS Var] component image screenshot should correct ${key}`,
|
||||||
`.${key}.css-var`,
|
`.${key}.css-var`,
|
||||||
<div style={{ background: key === 'dark' ? '#000' : '', padding: `24px 12px` }} key={key}>
|
<div style={{ background: key === 'dark' ? '#000' : '', padding: `24px 12px` }} key={key}>
|
||||||
<ConfigProvider theme={{ ...configTheme, cssVar: true }}>{component}</ConfigProvider>
|
<ConfigProvider theme={{ ...configTheme, cssVar: true }}>{component}</ConfigProvider>
|
||||||
</div>,
|
</div>,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Mobile Snapshot
|
||||||
|
} else {
|
||||||
|
test(identifier, `.mobile`, component, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Options = {
|
type Options = {
|
||||||
@ -257,6 +274,7 @@ type Options = {
|
|||||||
ssr?: boolean;
|
ssr?: boolean;
|
||||||
/** Open Trigger to check the popup render */
|
/** Open Trigger to check the popup render */
|
||||||
openTriggerClassName?: string;
|
openTriggerClassName?: string;
|
||||||
|
mobile?: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line jest/no-export
|
// eslint-disable-next-line jest/no-export
|
||||||
@ -266,25 +284,49 @@ export function imageDemoTest(component: string, options: Options = {}) {
|
|||||||
(file) => !file.includes('_semantic'),
|
(file) => !file.includes('_semantic'),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const mobileDemos: [file: string, node: any][] = [];
|
||||||
|
|
||||||
|
const getTestOption = (file: string) => ({
|
||||||
|
onlyViewport:
|
||||||
|
options.onlyViewport === true ||
|
||||||
|
(Array.isArray(options.onlyViewport) && options.onlyViewport.some((c) => file.endsWith(c))),
|
||||||
|
ssr: options.ssr,
|
||||||
|
openTriggerClassName: options.openTriggerClassName,
|
||||||
|
});
|
||||||
|
|
||||||
files.forEach((file) => {
|
files.forEach((file) => {
|
||||||
if (Array.isArray(options.skip) && options.skip.some((c) => file.endsWith(c))) {
|
if (Array.isArray(options.skip) && options.skip.some((c) => file.endsWith(c))) {
|
||||||
describeMethod = describe.skip;
|
describeMethod = describe.skip;
|
||||||
} else {
|
} else {
|
||||||
describeMethod = describe;
|
describeMethod = describe;
|
||||||
}
|
}
|
||||||
|
|
||||||
describeMethod(`Test ${file} image`, () => {
|
describeMethod(`Test ${file} image`, () => {
|
||||||
let Demo = require(`../../${file}`).default;
|
let Demo = require(`../../${file}`).default;
|
||||||
if (typeof Demo === 'function') {
|
if (typeof Demo === 'function') {
|
||||||
Demo = <Demo />;
|
Demo = <Demo />;
|
||||||
}
|
}
|
||||||
imageTest(Demo, `${component}-${path.basename(file, '.tsx')}`, {
|
imageTest(Demo, `${component}-${path.basename(file, '.tsx')}`, getTestOption(file));
|
||||||
onlyViewport:
|
|
||||||
options.onlyViewport === true ||
|
// Check if need mobile test
|
||||||
(Array.isArray(options.onlyViewport) &&
|
if ((options.mobile || []).some((c) => file.endsWith(c))) {
|
||||||
options.onlyViewport.some((c) => file.endsWith(c))),
|
mobileDemos.push([file, Demo]);
|
||||||
ssr: options.ssr,
|
}
|
||||||
openTriggerClassName: options.openTriggerClassName,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (mobileDemos.length) {
|
||||||
|
describeMethod(`Test mobile image`, () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await jestPuppeteer.resetPage();
|
||||||
|
});
|
||||||
|
|
||||||
|
mobileDemos.forEach(([file, Demo]) => {
|
||||||
|
imageTest(Demo, `${component}-${path.basename(file, '.tsx')}`, {
|
||||||
|
...getTestOption(file),
|
||||||
|
mobile: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user