chore: auto merge branchs (#35190)

chore: merge master to next
This commit is contained in:
github-actions[bot] 2022-04-23 09:34:47 +00:00 committed by GitHub
commit 1d6da1a5cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 441 additions and 90 deletions

View File

@ -1,6 +1,5 @@
# Upload 📷 UI snapshots to argos server, help visual regression testing.
name: UI Upload
name: 📷 UI Upload
on:
workflow_run:
@ -21,25 +20,8 @@ jobs:
if: >
github.event.workflow_run.conclusion == 'success'
steps:
- name: Download commit artifact
uses: dawidd6/action-download-artifact@v2
with:
workflow: ${{ github.event.workflow_run.workflow_id }}
name: commit
- name: Save commit id
id: commit
run: echo "::set-output name=id::$(<commit.txt)"
- name: Download branch artifact
uses: dawidd6/action-download-artifact@v2
with:
workflow: ${{ github.event.workflow_run.workflow_id }}
name: branch
- name: Save branch id
id: branch
run: echo "::set-output name=id::$(<branch.txt)"
- name: checkout
uses: actions/checkout@v3
- name: Download snapshots artifact
uses: dawidd6/action-download-artifact@v2
@ -47,8 +29,13 @@ jobs:
workflow: ${{ github.event.workflow_run.workflow_id }}
workflow_conclusion: success
name: snapshots
path: imageSnapshots
- name: Install
run: npm i fast-glob lodash argos-cli
- name: Upload argos-ci
id: deploy
run: |
npx argos-cli upload ./ --token ${{ secrets.ARGOS_TOKEN }} --branch ${{ steps.branch.outputs.id }} --commit ${{ steps.commit.outputs.id }}
run: npm run argos
env:
ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}

View File

@ -12,9 +12,6 @@ concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
@ -28,6 +25,10 @@ jobs:
path: package-temp-dir
key: lock-${{ github.sha }}
- uses: actions/setup-node@v3
with:
node-version: '16'
- name: create package-lock.json
run: npm i --package-lock-only --ignore-scripts
@ -57,33 +58,3 @@ jobs:
name: snapshots
path: imageSnapshots/
retention-days: 3
- name: Save commit
if: github.event_name == 'pull_request' && github.base_ref == 'master'
run: echo ${{ github.event.pull_request.head.sha }} > ./commit.txt
- name: Save commit
if: github.event_name == 'push'
run: echo ${{ github.sha }} > ./commit.txt
- name: Upload commit
if: ${{ always() }}
uses: actions/upload-artifact@v3
with:
name: commit
path: ./commit.txt
- name: Save branch
if: github.event_name == 'pull_request' && github.base_ref == 'master'
run: echo pull/${{ github.event.pull_request.number }}/merge > ./branch.txt
- name: Save branch
if: github.event_name == 'push'
run: echo ${GITHUB_REF##*/} > ./branch.txt
- name: Upload branch
if: ${{ always() }}
uses: actions/upload-artifact@v3
with:
name: branch
path: ./branch.txt

View File

@ -12,7 +12,7 @@ Uma solução empresarial de design e biblioteca UI para React.
[![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url]
[![david deps][david-image]][david-url] [![david devDeps][david-dev-image]][david-dev-url] [![Total alerts][lgtm-image]][lgtm-url] [![][bundlesize-js-image]][unpkg-js-url] [![][bundlesize-css-image]][unpkg-css-url]
[![Renovate status][renovate-image]][renovate-dashboard-url] [![Total alerts][lgtm-image]][lgtm-url] [![][bundlesize-js-image]][unpkg-js-url] [![][bundlesize-css-image]][unpkg-css-url]
[![Follow Twitter][twitter-image]][twitter-url] [![FOSSA Status][fossa-image]][fossa-url] [![Discussions][discussions-image]][discussions-url] [![][issues-helper-image]][issues-helper-url] [![Issues need help][help-wanted-image]][help-wanted-url]
@ -22,10 +22,6 @@ Uma solução empresarial de design e biblioteca UI para React.
[github-action-url]: https://github.com/ant-design/ant-design/actions?query=workflow%3A%22%E2%9C%85+test%22
[codecov-image]: https://img.shields.io/codecov/c/github/ant-design/ant-design/master.svg?style=flat-square
[codecov-url]: https://codecov.io/gh/ant-design/ant-design/branch/master
[david-image]: https://img.shields.io/david/ant-design/ant-design?style=flat-square
[david-dev-url]: https://david-dm.org/ant-design/ant-design?type=dev
[david-dev-image]: https://img.shields.io/david/dev/ant-design/ant-design?style=flat-square
[david-url]: https://david-dm.org/ant-design/ant-design
[download-image]: https://img.shields.io/npm/dm/antd.svg?style=flat-square
[download-url]: https://npmjs.org/package/antd
[lgtm-image]: https://flat.badgen.net/lgtm/alerts/g/ant-design/ant-design
@ -44,6 +40,8 @@ Uma solução empresarial de design e biblioteca UI para React.
[unpkg-css-url]: https://unpkg.com/browse/antd/dist/antd.min.css
[issues-helper-image]: https://img.shields.io/badge/using-issues--helper-orange?style=flat-square
[issues-helper-url]: https://github.com/actions-cool/issues-helper
[renovate-image]: https://img.shields.io/badge/renovate-enabled-brightgreen.svg?style=flat-square
[renovate-dashboard-url]: https://github.com/ant-design/ant-design/issues/32498
</div>

View File

@ -12,7 +12,7 @@
[![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url]
[![david deps][david-image]][david-url] [![david devDeps][david-dev-image]][david-dev-url] [![Total alerts][lgtm-image]][lgtm-url] [![][bundlesize-js-image]][unpkg-js-url] [![][bundlesize-css-image]][unpkg-css-url]
[![Renovate status][renovate-image]][renovate-dashboard-url] [![Total alerts][lgtm-image]][lgtm-url] [![][bundlesize-js-image]][unpkg-js-url] [![][bundlesize-css-image]][unpkg-css-url]
[![Follow Twitter][twitter-image]][twitter-url] [![FOSSA Status][fossa-image]][fossa-url] [![Discussions][discussions-image]][discussions-url] [![][issues-helper-image]][issues-helper-url] [![Issues need help][help-wanted-image]][help-wanted-url]
@ -22,10 +22,6 @@
[github-action-url]: https://github.com/ant-design/ant-design/actions?query=workflow%3A%22%E2%9C%85+test%22
[codecov-image]: https://img.shields.io/codecov/c/github/ant-design/ant-design/master.svg?style=flat-square
[codecov-url]: https://codecov.io/gh/ant-design/ant-design/branch/master
[david-image]: https://img.shields.io/david/ant-design/ant-design?style=flat-square
[david-dev-url]: https://david-dm.org/ant-design/ant-design?type=dev
[david-dev-image]: https://img.shields.io/david/dev/ant-design/ant-design?style=flat-square
[david-url]: https://david-dm.org/ant-design/ant-design
[download-image]: https://img.shields.io/npm/dm/antd.svg?style=flat-square
[download-url]: https://npmjs.org/package/antd
[lgtm-image]: https://flat.badgen.net/lgtm/alerts/g/ant-design/ant-design
@ -44,6 +40,8 @@
[unpkg-css-url]: https://unpkg.com/browse/antd/dist/antd.min.css
[issues-helper-image]: https://img.shields.io/badge/using-issues--helper-orange?style=flat-square
[issues-helper-url]: https://github.com/actions-cool/issues-helper
[renovate-image]: https://img.shields.io/badge/renovate-enabled-brightgreen.svg?style=flat-square
[renovate-dashboard-url]: https://github.com/ant-design/ant-design/issues/32498
</div>

View File

@ -12,7 +12,7 @@
[![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url]
[![david deps][david-image]][david-url] [![david devDeps][david-dev-image]][david-dev-url] [![Total alerts][lgtm-image]][lgtm-url] [![][bundlesize-js-image]][unpkg-js-url] [![][bundlesize-css-image]][unpkg-css-url]
[![Renovate status][renovate-image]][renovate-dashboard-url] [![Total alerts][lgtm-image]][lgtm-url] [![][bundlesize-js-image]][unpkg-js-url] [![][bundlesize-css-image]][unpkg-css-url]
[![Follow Twitter][twitter-image]][twitter-url] [![FOSSA Status][fossa-image]][fossa-url] [![Discussions][discussions-image]][discussions-url] [![][issues-helper-image]][issues-helper-url] [![Issues need help][help-wanted-image]][help-wanted-url]
@ -22,10 +22,6 @@
[github-action-url]: https://github.com/ant-design/ant-design/actions?query=workflow%3A%22%E2%9C%85+test%22
[codecov-image]: https://img.shields.io/codecov/c/github/ant-design/ant-design/master.svg?style=flat-square
[codecov-url]: https://codecov.io/gh/ant-design/ant-design/branch/master
[david-image]: https://img.shields.io/david/ant-design/ant-design?style=flat-square
[david-dev-url]: https://david-dm.org/ant-design/ant-design?type=dev
[david-dev-image]: https://img.shields.io/david/dev/ant-design/ant-design?style=flat-square
[david-url]: https://david-dm.org/ant-design/ant-design
[download-image]: https://img.shields.io/npm/dm/antd.svg?style=flat-square
[download-url]: https://npmjs.org/package/antd
[lgtm-image]: https://flat.badgen.net/lgtm/alerts/g/ant-design/ant-design
@ -44,6 +40,8 @@
[unpkg-css-url]: https://unpkg.com/browse/antd/dist/antd.min.css
[issues-helper-image]: https://img.shields.io/badge/using-issues--helper-orange?style=flat-square
[issues-helper-url]: https://github.com/actions-cool/issues-helper
[renovate-image]: https://img.shields.io/badge/renovate-enabled-brightgreen.svg?style=flat-square
[renovate-dashboard-url]: https://github.com/ant-design/ant-design/issues/32498
</div>

View File

@ -142,6 +142,10 @@ return <div>{contextHolder}</div>;
## FAQ
### Why content not update when Modal closed?
Modal will use memo to avoid content jumping when closed. Also, if you use Form in Modal, you can reset `initialValues` by calling `resetFields` in effect.
### Why I can not access context, redux, ConfigProvider `locale/prefixCls` in Modal.xxx?
antd will dynamic create React instance by `ReactDOM.render` when call Modal methods. Whose context is different with origin code located context.

View File

@ -145,6 +145,10 @@ return <div>{contextHolder}</div>;
## FAQ
### 为什么 Modal 关闭时,内容不会更新?
Modal 在关闭时会将内容进行 memo 从而避免关闭过程中的内容跳跃。也因此如果你在配合使用 Form 有关闭时重置 `initialValues` 的操作,请通过在 effect 中调用 `resetFields` 来重置。
### 为什么 Modal 方法不能获取 context、redux、的内容和 ConfigProvider `locale/prefixCls` 配置?
直接调用 Modal 方法antd 会通过 `ReactDOM.render` 动态创建新的 React 实体。其 context 与当前代码所在 context 并不相同,因而无法获取 context 信息。

View File

@ -178,6 +178,106 @@ exports[`renders ./components/segmented/demo/controlled.md extend context correc
</div>
`;
exports[`renders ./components/segmented/demo/controlled-two.md extend context correctly 1`] = `
Array [
<div
class="ant-segmented"
>
<label
class="ant-segmented-item ant-segmented-item-selected"
>
<input
checked=""
class="ant-segmented-item-input"
type="radio"
/>
<div
class="ant-segmented-item-label"
title="AND"
>
AND
</div>
</label>
<label
class="ant-segmented-item"
>
<input
class="ant-segmented-item-input"
type="radio"
/>
<div
class="ant-segmented-item-label"
title="OR"
>
OR
</div>
</label>
<label
class="ant-segmented-item"
>
<input
class="ant-segmented-item-input"
type="radio"
/>
<div
class="ant-segmented-item-label"
title="NOT"
>
NOT
</div>
</label>
</div>,
"  ",
<div
class="ant-segmented"
>
<label
class="ant-segmented-item ant-segmented-item-selected"
>
<input
checked=""
class="ant-segmented-item-input"
type="radio"
/>
<div
class="ant-segmented-item-label"
title="AND"
>
AND
</div>
</label>
<label
class="ant-segmented-item"
>
<input
class="ant-segmented-item-input"
type="radio"
/>
<div
class="ant-segmented-item-label"
title="OR"
>
OR
</div>
</label>
<label
class="ant-segmented-item"
>
<input
class="ant-segmented-item-input"
type="radio"
/>
<div
class="ant-segmented-item-label"
title="NOT"
>
NOT
</div>
</label>
</div>,
]
`;
exports[`renders ./components/segmented/demo/custom.md extend context correctly 1`] = `
Array [
<div

View File

@ -178,6 +178,106 @@ exports[`renders ./components/segmented/demo/controlled.md correctly 1`] = `
</div>
`;
exports[`renders ./components/segmented/demo/controlled-two.md correctly 1`] = `
Array [
<div
class="ant-segmented"
>
<label
class="ant-segmented-item ant-segmented-item-selected"
>
<input
checked=""
class="ant-segmented-item-input"
type="radio"
/>
<div
class="ant-segmented-item-label"
title="AND"
>
AND
</div>
</label>
<label
class="ant-segmented-item"
>
<input
class="ant-segmented-item-input"
type="radio"
/>
<div
class="ant-segmented-item-label"
title="OR"
>
OR
</div>
</label>
<label
class="ant-segmented-item"
>
<input
class="ant-segmented-item-input"
type="radio"
/>
<div
class="ant-segmented-item-label"
title="NOT"
>
NOT
</div>
</label>
</div>,
"  ",
<div
class="ant-segmented"
>
<label
class="ant-segmented-item ant-segmented-item-selected"
>
<input
checked=""
class="ant-segmented-item-input"
type="radio"
/>
<div
class="ant-segmented-item-label"
title="AND"
>
AND
</div>
</label>
<label
class="ant-segmented-item"
>
<input
class="ant-segmented-item-input"
type="radio"
/>
<div
class="ant-segmented-item-label"
title="OR"
>
OR
</div>
</label>
<label
class="ant-segmented-item"
>
<input
class="ant-segmented-item-input"
type="radio"
/>
<div
class="ant-segmented-item-label"
title="NOT"
>
NOT
</div>
</label>
</div>,
]
`;
exports[`renders ./components/segmented/demo/custom.md correctly 1`] = `
Array [
<div

View File

@ -99,7 +99,7 @@ describe('Segmented', () => {
.map(el => (el.getDOMNode() as HTMLInputElement).checked),
).toEqual([true, false, false]);
expect(
wrapper.find(`.${prefixCls}-item`).at(0).hasClass(`${prefixCls}-item-selected`),
wrapper.find(`label.${prefixCls}-item`).at(0).hasClass(`${prefixCls}-item-selected`),
).toBeTruthy();
wrapper.find(`.${prefixCls}-item-input`).at(2).simulate('change');
@ -164,7 +164,7 @@ describe('Segmented', () => {
);
expect(wrapper.render()).toMatchSnapshot();
expect(
wrapper.find(`.${prefixCls}-item`).at(1).hasClass(`${prefixCls}-item-disabled`),
wrapper.find(`label.${prefixCls}-item`).at(1).hasClass(`${prefixCls}-item-disabled`),
).toBeTruthy();
expect(wrapper.find(`.${prefixCls}-item-input`).at(1).prop('disabled')).toBeTruthy();
@ -304,7 +304,7 @@ describe('Segmented', () => {
.map(el => (el.getDOMNode() as HTMLInputElement).checked),
).toEqual([true, false, false]);
expect(
wrapper.find(`.${prefixCls}-item`).at(0).hasClass(`${prefixCls}-item-selected`),
wrapper.find(`label.${prefixCls}-item`).at(0).hasClass(`${prefixCls}-item-selected`),
).toBeTruthy();
wrapper.find(`.${prefixCls}-item-input`).at(2).simulate('change');

View File

@ -0,0 +1,41 @@
---
order: 99
title:
zh-CN: 受控同步模式
en-US: Controlled Synced mode
debug: true
---
## zh-CN
测试受控模式下两个 Segmented 同步 state。
## en-US
Tests two Segmented synchronized states in controlled mode.
```jsx
import { useState } from 'react';
import { Segmented } from 'antd';
const Demo = () => {
const [foo, setFoo] = useState('AND');
return (
<>
<Segmented
value={foo}
options={['AND', 'OR', 'NOT']}
onChange={e => setFoo(e.target.value)}
/>
&nbsp;&nbsp;
<Segmented
value={foo}
options={['AND', 'OR', 'NOT']}
onChange={e => setFoo(e.target.value)}
/>
</>
);
};
export default Demo;
```

View File

@ -114,3 +114,5 @@
will-change: transform, width;
}
}
@import './rtl';

View File

@ -0,0 +1,15 @@
@import '../../style/themes/index';
@import '../../style/mixins/index';
@segmented-prefix-cls: ~'@{ant-prefix}-segmented';
.@{segmented-prefix-cls} {
&&-rtl {
direction: rtl;
}
&&-rtl &-item-icon {
margin-right: 0;
margin-left: 6px;
}
}

View File

@ -9,7 +9,7 @@
// An override for the html selector for theme prefixes
@html-selector: html;
html {
@{html-selector} {
@base-primary: @blue-6;
// ========= Primary Color =========

View File

@ -2252,4 +2252,57 @@ describe('Table.filter', () => {
expect(wrapper.find('.ant-tree-checkbox-checked').length).toBe(1);
expect(wrapper.find('.ant-tree-checkbox-checked+span').text()).toBe('Girl');
});
it('filteredKeys should all be controlled or not controlled', () => {
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
errorSpy.mockReset();
const tableData = [
{
key: '1',
name: 'John Brown',
age: 32,
},
];
const columns = [
{
title: 'name',
dataIndex: 'name',
key: 'name',
filters: [],
},
{
title: 'age',
dataIndex: 'age',
key: 'age',
filters: [],
},
];
render(
createTable({
columns,
data: tableData,
}),
);
expect(errorSpy).not.toBeCalled();
errorSpy.mockReset();
columns[0].filteredValue = [];
render(
createTable({
columns,
data: tableData,
}),
);
expect(errorSpy).toBeCalledWith(
'Warning: [antd: Table] Columns should all contain `filteredValue` or not contain `filteredValue`.',
);
errorSpy.mockReset();
columns[1].filteredValue = [];
render(
createTable({
columns,
data: tableData,
}),
);
expect(errorSpy).not.toBeCalled();
});
});

View File

@ -211,24 +211,25 @@ function useFilter<RecordType>({
const mergedFilterStates = React.useMemo(() => {
const collectedStates = collectFilterStates(mergedColumns, false);
const filteredKeysIsNotControlled = collectedStates.every(
({ filteredKeys }) => filteredKeys === undefined,
);
let filteredKeysIsAllNotControlled = true;
let filteredKeysIsAllControlled = true;
collectedStates.forEach(({ filteredKeys }) => {
if (filteredKeys !== undefined) {
filteredKeysIsAllNotControlled = false;
} else {
filteredKeysIsAllControlled = false;
}
});
// Return if not controlled
if (filteredKeysIsNotControlled) {
if (filteredKeysIsAllNotControlled) {
return filterStates;
}
const filteredKeysIsAllControlled = collectedStates.every(
({ filteredKeys }) => filteredKeys !== undefined,
);
devWarning(
filteredKeysIsNotControlled || filteredKeysIsAllControlled,
filteredKeysIsAllControlled,
'Table',
'`FilteredKeys` should all be controlled or not controlled.',
'Columns should all contain `filteredValue` or not contain `filteredValue`.',
);
return collectedStates;

View File

@ -35,6 +35,20 @@ describe('Upload.typescript', () => {
expect(upload).toBeTruthy();
});
it('onChange fileList', () => {
type IFile = {
customFile: File;
};
const upload = (
<Upload<IFile> onChange={({ fileList }) => fileList.map(file => file.response?.customFile)}>
<span>click to upload</span>
</Upload>
);
expect(upload).toBeTruthy();
});
it('onChange in UploadProps', () => {
const uploadProps: UploadProps<File> = {
onChange: ({ file }) => file,

View File

@ -44,7 +44,7 @@ export interface InternalUploadFile<T = any> extends UploadFile<T> {
export interface UploadChangeParam<T = UploadFile> {
// https://github.com/ant-design/ant-design/issues/14420
file: T;
fileList: UploadFile[];
fileList: T[];
event?: { percent: number };
}

View File

@ -99,11 +99,11 @@
"tsc": "tsc --noEmit",
"site:test": "jest --config .jest.site.js --cache=false --force-exit",
"test-image": "npm run dist && docker-compose run tests",
"argos": "node ./scripts/argos-upload.js",
"version": "node ./scripts/generate-version",
"install-react-16": "npm i --no-save --legacy-peer-deps react@16 react-dom@16 enzyme-adapter-react-16",
"install-react-17": "npm i --no-save --legacy-peer-deps react@17 react-dom@17",
"install-react-18": "npm i --no-save --legacy-peer-deps react@18 react-dom@18 @testing-library/react@13",
"argos": "argos upload imageSnapshots"
"install-react-18": "npm i --no-save --legacy-peer-deps react@18 react-dom@18 @testing-library/react@13"
},
"browserslist": [
"> 0.5%",
@ -189,7 +189,6 @@
"@typescript-eslint/parser": "^5.0.0",
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.0",
"antd-img-crop": "^4.0.0",
"argos-cli": "^0.3.0",
"array-move": "^4.0.0",
"babel-plugin-add-react-displayname": "^0.0.5",
"bisheng": "^3.2.1",
@ -222,6 +221,7 @@
"eslint-plugin-react": "^7.28.0",
"eslint-plugin-react-hooks": "^4.1.2",
"eslint-plugin-unicorn": "^42.0.0",
"fast-glob": "^3.2.11",
"fetch-jsonp": "^1.1.3",
"fs-extra": "^10.0.0",
"full-icu": "^1.3.0",

65
scripts/argos-upload.js Normal file
View File

@ -0,0 +1,65 @@
// Thanks to material-ui ❤️
// Create chunks for Argos: https://github.com/mui/material-ui/pull/23518
// https://github.com/mui/material-ui/blob/af81aae3b292ed180e7652a665fad1be2b38a7b3/scripts/pushArgos.js
const util = require('util');
const glob = require('fast-glob');
const lodashChunk = require('lodash/chunk');
const childProcess = require('child_process');
const execFileNode = util.promisify(childProcess.execFile);
function execFile(command, args) {
return execFileNode(command, args, {
cwd: process.cwd(),
env: process.env,
encoding: 'utf-8',
});
}
const screenshotsBase = 'imageSnapshots';
const screenshotsTmp = `${screenshotsBase}/temp`;
const BATCH_SIZE = 200;
async function move2Temp(screenshot, target) {
await execFile('mkdir', ['-p', target]);
await execFile('mv', [screenshot, target]);
}
async function run() {
const screenshots = await glob(`${screenshotsBase}/**/*`);
const chunks = lodashChunk(screenshots, BATCH_SIZE);
await Promise.all(
chunks.map((chunk, chunkIndex) =>
Promise.all(
chunk.map(screenshot => move2Temp(screenshot, `${screenshotsTmp}/${chunkIndex}`)),
),
),
);
for (let i = 0; i < chunks.length; i += 1) {
// eslint-disable-next-line no-await-in-loop
const argosResults = await execFile('argos', [
'upload',
`${screenshotsTmp}/${i}`,
'--token',
process.env.ARGOS_TOKEN,
'--batchCount',
chunks.length,
'--branch',
process.env.GITHUB_REF_NAME,
'--commit',
process.env.GITHUB_SHA,
'--external-build-id',
process.env.GITHUB_SHA,
]);
// eslint-disable-next-line no-console -- pipe stdout
console.log(argosResults.stdout);
}
}
run().catch(error => {
// eslint-disable-next-line no-console
console.error(error);
process.exit(1);
});