mirror of
https://github.com/ant-design/ant-design.git
synced 2024-12-18 11:18:14 +08:00
commit
1aa5bc1d68
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"installCommand": "npm-install",
|
||||||
"sandboxes": ["antd-reproduction-template-forked-jyh2k9"],
|
"sandboxes": ["antd-reproduction-template-forked-jyh2k9"],
|
||||||
"node": "18"
|
"node": "18"
|
||||||
}
|
}
|
||||||
|
@ -54,15 +54,18 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
actions: read # for dawidd6/action-download-artifact to query and download artifacts
|
actions: read # for dawidd6/action-download-artifact to query and download artifacts
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: upstream-workflow-summary
|
needs: [upstream-workflow-summary]
|
||||||
steps:
|
steps:
|
||||||
|
- name: checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
# We need get persist key first
|
# We need get persist key first
|
||||||
- name: Download Visual Regression Ref
|
- name: Download Visual Regression Ref
|
||||||
uses: dawidd6/action-download-artifact@v2
|
uses: dawidd6/action-download-artifact@v2
|
||||||
with:
|
with:
|
||||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||||
run_id: ${{ github.event.workflow_run.id }}
|
run_id: ${{ github.event.workflow_run.id }}
|
||||||
name: visual-regression-persist-ref
|
name: visual-regression-master-ref
|
||||||
|
|
||||||
# Save visual-regression ref to output
|
# Save visual-regression ref to output
|
||||||
- name: Extra Visual Regression Ref
|
- name: Extra Visual Regression Ref
|
||||||
@ -78,36 +81,20 @@ jobs:
|
|||||||
name: image-snapshots
|
name: image-snapshots
|
||||||
path: ./
|
path: ./
|
||||||
|
|
||||||
- name: Persist to Snapshot Repo
|
- name: Persist Image Snapshot to OSS
|
||||||
if: github.ref_name == 'master'
|
if: github.ref_name == 'master'
|
||||||
id: persist
|
id: persist
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.ANTD_IMAGE_SNAP_REPO_TOKEN }}
|
ALI_OSS_AK_ID: ${{ secrets.ALI_OSS_AK_ID }}
|
||||||
# should push to snapshot repo firstly
|
ALI_OSS_AK_SECRET: ${{ secrets.ALI_OSS_AK_SECRET }}
|
||||||
# push the single folder to the repo
|
ALI_OSS_BUCKET: ${{ secrets.ALI_OSS_BUCKET }}
|
||||||
run: |
|
run: |
|
||||||
git clone https://$GITHUB_TOKEN@github.com/ant-design/antd-image-snapshots.git
|
rm package.json
|
||||||
|
npm i ali-oss --no-save
|
||||||
|
|
||||||
echo "✅ Clone Finished"
|
echo "🤖 Uploading"
|
||||||
|
node scripts/visual-regression-upload.js ./imageSnapshots.tar.gz --ref=${{ github.sha }}
|
||||||
|
node scripts/visual-regression-upload.js ./visual-regression-ref.txt --ref=${{ github.ref_name }}
|
||||||
|
|
||||||
rm antd-image-snapshots/*.txt
|
echo "✅ Uploaded"
|
||||||
mv visual-regression-ref.txt antd-image-snapshots/
|
|
||||||
|
|
||||||
rm -rf antd-image-snapshots/imageSnapshots/*
|
|
||||||
tar -xzvf imageSnapshots.tar.gz -C antd-image-snapshots/imageSnapshots
|
|
||||||
|
|
||||||
echo "✅ Changes Finished"
|
|
||||||
|
|
||||||
cd antd-image-snapshots
|
|
||||||
|
|
||||||
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
||||||
git config --local user.name "github-actions[bot]"
|
|
||||||
|
|
||||||
git commit -a -m 'feat: update snapshot from ${{steps.visuall-regression.outputs.id}}'
|
|
||||||
|
|
||||||
echo "✅ Commit Finished"
|
|
||||||
|
|
||||||
git push --prune https://vaugsX:$GITHUB_TOKEN@github.com/ant-design/antd-image-snapshots.git +refs/remotes/origin/*:refs/heads/*
|
|
||||||
|
|
||||||
echo "✅ Push Finished"
|
|
||||||
|
@ -90,5 +90,5 @@ jobs:
|
|||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: visual-regression-persist-ref
|
name: visual-regression-master-ref
|
||||||
path: ./visual-regression-ref.txt
|
path: ./visual-regression-ref.txt
|
||||||
|
@ -88,13 +88,13 @@ const InternalForm: React.ForwardRefRenderFunction<FormInstance, FormProps> = (p
|
|||||||
return requiredMark;
|
return requiredMark;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contextForm && contextForm.requiredMark !== undefined) {
|
|
||||||
return contextForm.requiredMark;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hideRequiredMark) {
|
if (hideRequiredMark) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (contextForm && contextForm.requiredMark !== undefined) {
|
||||||
|
return contextForm.requiredMark;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}, [hideRequiredMark, requiredMark, contextForm]);
|
}, [hideRequiredMark, requiredMark, contextForm]);
|
||||||
|
@ -1089,16 +1089,44 @@ describe('Form', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('legacy hideRequiredMark', () => {
|
describe('legacy hideRequiredMark', () => {
|
||||||
const { container } = render(
|
it('should work', () => {
|
||||||
<Form hideRequiredMark role="form">
|
const { container } = render(
|
||||||
<Form.Item name="light" label="light" required>
|
<Form hideRequiredMark role="form">
|
||||||
<Input />
|
<Form.Item name="light" label="light" required>
|
||||||
</Form.Item>
|
<Input />
|
||||||
</Form>,
|
</Form.Item>
|
||||||
);
|
</Form>,
|
||||||
|
);
|
||||||
|
|
||||||
expect(container.querySelector('form')!).toHaveClass('ant-form-hide-required-mark');
|
expect(container.querySelector('form')!).toHaveClass('ant-form-hide-required-mark');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('priority should be higher than CP', () => {
|
||||||
|
const { container, rerender } = render(
|
||||||
|
<ConfigProvider form={{ requiredMark: true }}>
|
||||||
|
<Form hideRequiredMark role="form">
|
||||||
|
<Form.Item name="light" label="light" required>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</ConfigProvider>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(container.querySelector('form')!).toHaveClass('ant-form-hide-required-mark');
|
||||||
|
|
||||||
|
rerender(
|
||||||
|
<ConfigProvider form={{ requiredMark: undefined }}>
|
||||||
|
<Form hideRequiredMark role="form">
|
||||||
|
<Form.Item name="light" label="light" required>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</ConfigProvider>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(container.querySelector('form')!).toHaveClass('ant-form-hide-required-mark');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('form should support disabled', () => {
|
it('form should support disabled', () => {
|
||||||
|
@ -75,7 +75,6 @@ const genSpinStyle: GenerateStyle<SpinToken> = (token: SpinToken): CSSObject =>
|
|||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
pointerEvents: 'none',
|
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
visibility: 'hidden',
|
visibility: 'hidden',
|
||||||
transition: `all ${token.motionDurationMid}`,
|
transition: `all ${token.motionDurationMid}`,
|
||||||
|
@ -202,6 +202,10 @@ const InternalTable = <RecordType extends AnyObject = AnyObject>(
|
|||||||
const prefixCls = getPrefixCls('table', customizePrefixCls);
|
const prefixCls = getPrefixCls('table', customizePrefixCls);
|
||||||
const dropdownPrefixCls = getPrefixCls('dropdown', customizeDropdownPrefixCls);
|
const dropdownPrefixCls = getPrefixCls('dropdown', customizeDropdownPrefixCls);
|
||||||
|
|
||||||
|
const [, token] = useToken();
|
||||||
|
const rootCls = useCSSVarCls(prefixCls);
|
||||||
|
const [wrapCSSVar, hashId] = useStyle(prefixCls, rootCls);
|
||||||
|
|
||||||
const mergedExpandable: ExpandableConfig<RecordType> = {
|
const mergedExpandable: ExpandableConfig<RecordType> = {
|
||||||
childrenColumnName: legacyChildrenColumnName,
|
childrenColumnName: legacyChildrenColumnName,
|
||||||
expandIconColumnIndex,
|
expandIconColumnIndex,
|
||||||
@ -349,6 +353,7 @@ const InternalTable = <RecordType extends AnyObject = AnyObject>(
|
|||||||
mergedColumns,
|
mergedColumns,
|
||||||
onFilterChange,
|
onFilterChange,
|
||||||
getPopupContainer: getPopupContainer || getContextPopupContainer,
|
getPopupContainer: getPopupContainer || getContextPopupContainer,
|
||||||
|
rootClassName: classNames(rootClassName, rootCls),
|
||||||
});
|
});
|
||||||
const mergedData = getFilterData(sortedData, filterStates);
|
const mergedData = getFilterData(sortedData, filterStates);
|
||||||
|
|
||||||
@ -538,10 +543,6 @@ const InternalTable = <RecordType extends AnyObject = AnyObject>(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const [, token] = useToken();
|
|
||||||
const rootCls = useCSSVarCls(prefixCls);
|
|
||||||
const [wrapCSSVar, hashId] = useStyle(prefixCls, rootCls);
|
|
||||||
|
|
||||||
const wrapperClassNames = classNames(
|
const wrapperClassNames = classNames(
|
||||||
rootCls,
|
rootCls,
|
||||||
`${prefixCls}-wrapper`,
|
`${prefixCls}-wrapper`,
|
||||||
|
@ -133,6 +133,7 @@ export interface FilterDropdownProps<RecordType> {
|
|||||||
locale: TableLocale;
|
locale: TableLocale;
|
||||||
getPopupContainer?: GetPopupContainer;
|
getPopupContainer?: GetPopupContainer;
|
||||||
filterResetToDefaultFilteredValue?: boolean;
|
filterResetToDefaultFilteredValue?: boolean;
|
||||||
|
rootClassName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function wrapStringListType(keys?: FilterKey) {
|
function wrapStringListType(keys?: FilterKey) {
|
||||||
@ -154,6 +155,7 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
|
|||||||
locale,
|
locale,
|
||||||
children,
|
children,
|
||||||
getPopupContainer,
|
getPopupContainer,
|
||||||
|
rootClassName,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -524,6 +526,7 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
|
|||||||
onOpenChange={onVisibleChange}
|
onOpenChange={onVisibleChange}
|
||||||
getPopupContainer={getPopupContainer}
|
getPopupContainer={getPopupContainer}
|
||||||
placement={direction === 'rtl' ? 'bottomLeft' : 'bottomRight'}
|
placement={direction === 'rtl' ? 'bottomLeft' : 'bottomRight'}
|
||||||
|
rootClassName={rootClassName}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
role="button"
|
role="button"
|
||||||
|
@ -76,6 +76,7 @@ function injectFilter<RecordType>(
|
|||||||
triggerFilter: (filterState: FilterState<RecordType>) => void,
|
triggerFilter: (filterState: FilterState<RecordType>) => void,
|
||||||
getPopupContainer?: GetPopupContainer,
|
getPopupContainer?: GetPopupContainer,
|
||||||
pos?: string,
|
pos?: string,
|
||||||
|
rootClassName?: string,
|
||||||
): ColumnsType<RecordType> {
|
): ColumnsType<RecordType> {
|
||||||
return columns.map((column, index) => {
|
return columns.map((column, index) => {
|
||||||
const columnPos = getColumnPos(index, pos);
|
const columnPos = getColumnPos(index, pos);
|
||||||
@ -103,6 +104,7 @@ function injectFilter<RecordType>(
|
|||||||
triggerFilter={triggerFilter}
|
triggerFilter={triggerFilter}
|
||||||
locale={locale}
|
locale={locale}
|
||||||
getPopupContainer={getPopupContainer}
|
getPopupContainer={getPopupContainer}
|
||||||
|
rootClassName={rootClassName}
|
||||||
>
|
>
|
||||||
{renderColumnTitle(column.title, renderProps)}
|
{renderColumnTitle(column.title, renderProps)}
|
||||||
</FilterDropdown>
|
</FilterDropdown>
|
||||||
@ -122,6 +124,7 @@ function injectFilter<RecordType>(
|
|||||||
triggerFilter,
|
triggerFilter,
|
||||||
getPopupContainer,
|
getPopupContainer,
|
||||||
columnPos,
|
columnPos,
|
||||||
|
rootClassName,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -184,6 +187,7 @@ interface FilterConfig<RecordType> {
|
|||||||
filterStates: FilterState<RecordType>[],
|
filterStates: FilterState<RecordType>[],
|
||||||
) => void;
|
) => void;
|
||||||
getPopupContainer?: GetPopupContainer;
|
getPopupContainer?: GetPopupContainer;
|
||||||
|
rootClassName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getMergedColumns = <RecordType extends unknown>(
|
const getMergedColumns = <RecordType extends unknown>(
|
||||||
@ -203,6 +207,7 @@ function useFilter<RecordType>({
|
|||||||
onFilterChange,
|
onFilterChange,
|
||||||
getPopupContainer,
|
getPopupContainer,
|
||||||
locale: tableLocale,
|
locale: tableLocale,
|
||||||
|
rootClassName,
|
||||||
}: FilterConfig<RecordType>): [
|
}: FilterConfig<RecordType>): [
|
||||||
TransformColumns<RecordType>,
|
TransformColumns<RecordType>,
|
||||||
FilterState<RecordType>[],
|
FilterState<RecordType>[],
|
||||||
@ -282,6 +287,8 @@ function useFilter<RecordType>({
|
|||||||
tableLocale,
|
tableLocale,
|
||||||
triggerFilter,
|
triggerFilter,
|
||||||
getPopupContainer,
|
getPopupContainer,
|
||||||
|
undefined,
|
||||||
|
rootClassName,
|
||||||
);
|
);
|
||||||
|
|
||||||
return [transformColumns, mergedFilterStates, filters];
|
return [transformColumns, mergedFilterStates, filters];
|
||||||
|
@ -5,7 +5,7 @@ order: 5
|
|||||||
title: Internationalization
|
title: Internationalization
|
||||||
---
|
---
|
||||||
|
|
||||||
The default language of `antd@2.x` is currently English. If you wish to use other languages, follow the instructions below.
|
The default language of `antd` is currently English. If you wish to use other languages, follow the instructions below.
|
||||||
|
|
||||||
## ConfigProvider
|
## ConfigProvider
|
||||||
|
|
||||||
|
@ -98,7 +98,8 @@
|
|||||||
"test:update": "jest --config .jest.js --no-cache -u",
|
"test:update": "jest --config .jest.js --no-cache -u",
|
||||||
"token-meta": "tsx scripts/generate-token-meta.ts",
|
"token-meta": "tsx scripts/generate-token-meta.ts",
|
||||||
"tsc": "tsc --noEmit",
|
"tsc": "tsc --noEmit",
|
||||||
"version": "tsx scripts/generate-version.ts"
|
"version": "tsx scripts/generate-version.ts",
|
||||||
|
"npm-install": "npm install"
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"*.{ts,tsx,js,jsx}": "biome format --write",
|
"*.{ts,tsx,js,jsx}": "biome format --write",
|
||||||
@ -183,6 +184,7 @@
|
|||||||
"@testing-library/jest-dom": "^6.1.4",
|
"@testing-library/jest-dom": "^6.1.4",
|
||||||
"@testing-library/react": "^14.1.2",
|
"@testing-library/react": "^14.1.2",
|
||||||
"@testing-library/user-event": "^14.5.1",
|
"@testing-library/user-event": "^14.5.1",
|
||||||
|
"@types/ali-oss": "^6.16.11",
|
||||||
"@types/fs-extra": "^11.0.4",
|
"@types/fs-extra": "^11.0.4",
|
||||||
"@types/gtag.js": "^0.0.18",
|
"@types/gtag.js": "^0.0.18",
|
||||||
"@types/http-server": "^0.12.4",
|
"@types/http-server": "^0.12.4",
|
||||||
@ -209,6 +211,7 @@
|
|||||||
"@types/warning": "^3.0.3",
|
"@types/warning": "^3.0.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
||||||
"@typescript-eslint/parser": "^6.12.0",
|
"@typescript-eslint/parser": "^6.12.0",
|
||||||
|
"ali-oss": "^6.18.1",
|
||||||
"antd-img-crop": "^4.17.0",
|
"antd-img-crop": "^4.17.0",
|
||||||
"antd-style": "^3.5.2",
|
"antd-style": "^3.5.2",
|
||||||
"antd-token-previewer": "^2.0.5",
|
"antd-token-previewer": "^2.0.5",
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
| expected | actual | diff |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| ![master image name](test/fixtures/4a.png) | ![pr image name](test/fixtures/4b.png) | ![diff](test/fixtures/4diff.png) |
|
|
||||||
| ![master image name](test/fixtures/3a.png) | ![pr image name](test/fixtures/3b.png) | ![diff](test/fixtures/3diff.png) |
|
|
||||||
| ![master image name](test/fixtures/6a.png) | ![pr image name](test/fixtures/6b.png) | ![diff](test/fixtures/6diff.png) |
|
|
121
scripts/visual-regression-upload.js
Normal file
121
scripts/visual-regression-upload.js
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/* eslint-disable no-restricted-syntax, no-console */
|
||||||
|
// Attention: use all node builtin modules except `ali-oss`
|
||||||
|
// Must keep our ak/sk safe
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
|
const OSS = require('ali-oss');
|
||||||
|
const path = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
|
const { assert } = require('console');
|
||||||
|
|
||||||
|
// node scripts/visual-regression-upload.js ./visualRegressionReport.tar.gz --ref=pr-id
|
||||||
|
// node scripts/visual-regression-upload.js ./imageSnapshots.tar.gz --ref=master-commitId
|
||||||
|
|
||||||
|
const args = process.argv.slice(2);
|
||||||
|
if (args.length < 2) {
|
||||||
|
console.error('Usage: node scripts/visual-regression-upload.js <tarFilePath> --ref=<refValue>');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the tar file path and ref value from the cli arguments
|
||||||
|
* @param {string[]} cliArgs
|
||||||
|
*/
|
||||||
|
function parseArgs(cliArgs) {
|
||||||
|
const filepath = cliArgs[0];
|
||||||
|
let refValue = '';
|
||||||
|
|
||||||
|
for (let i = 1; i < cliArgs.length; i++) {
|
||||||
|
if (cliArgs[i].startsWith('--ref=')) {
|
||||||
|
refValue = cliArgs[i].substring(6);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [filepath, refValue];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function walkDir(dirPath) {
|
||||||
|
const fileList = [];
|
||||||
|
|
||||||
|
const files = await fs.promises.readdir(dirPath);
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
const filePath = path.join(dirPath, file);
|
||||||
|
const fileStat = fs.statSync(filePath);
|
||||||
|
|
||||||
|
if (fileStat.isDirectory()) {
|
||||||
|
// Recursively call this func for subdirs
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
fileList.push(...(await walkDir(filePath)));
|
||||||
|
} else {
|
||||||
|
fileList.push(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import('ali-oss')} client
|
||||||
|
* @param {*} filePath
|
||||||
|
* @param {*} refValue
|
||||||
|
*/
|
||||||
|
async function uploadFile(client, filePath, refValue) {
|
||||||
|
const headers = {
|
||||||
|
// https://help.aliyun.com/zh/oss/user-guide/object-acl
|
||||||
|
'x-oss-object-acl': 'public-read',
|
||||||
|
// https://help.aliyun.com/zh/oss/developer-reference/prevent-objects-from-being-overwritten-by-objects-that-have-the-same-names-3
|
||||||
|
'x-oss-forbid-overwrite': 'false',
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log('Uploading file: %s', filePath);
|
||||||
|
try {
|
||||||
|
const targetFilePath = path.relative(process.cwd(), filePath);
|
||||||
|
const r1 = await client.put(`${refValue}/${targetFilePath}`, filePath, { headers });
|
||||||
|
console.log('Uploading file successfully: %s', r1.name);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Uploading file failed: %s', err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function boot() {
|
||||||
|
const [filepath, refValue] = parseArgs(args);
|
||||||
|
assert(filepath, 'filepath is required');
|
||||||
|
assert(refValue, 'refValue is required');
|
||||||
|
|
||||||
|
const fileOrFolderName = filepath;
|
||||||
|
// check if exists
|
||||||
|
const filePath = path.resolve(process.cwd(), fileOrFolderName);
|
||||||
|
|
||||||
|
if (!fs.existsSync(filePath)) {
|
||||||
|
console.error('File not exists: %s', filePath);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = new OSS({
|
||||||
|
endpoint: 'oss-cn-shanghai.aliyuncs.com',
|
||||||
|
accessKeyId: process.env.ALI_OSS_AK_ID,
|
||||||
|
accessKeySecret: process.env.ALI_OSS_AK_SECRET,
|
||||||
|
bucket: process.env.ALI_OSS_BUCKET,
|
||||||
|
});
|
||||||
|
|
||||||
|
// if is a file then upload it directly
|
||||||
|
const stat = fs.statSync(filePath);
|
||||||
|
if (stat.isFile()) {
|
||||||
|
await uploadFile(client, filePath, refValue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stat.isDirectory()) {
|
||||||
|
const fileList = await walkDir(filePath);
|
||||||
|
for (const file of fileList) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await uploadFile(client, file, refValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boot();
|
@ -3,6 +3,7 @@ import React from 'react';
|
|||||||
// eslint-disable-next-line import/no-unresolved
|
// eslint-disable-next-line import/no-unresolved
|
||||||
import { createCache, extractStyle, StyleProvider } from '@ant-design/cssinjs';
|
import { createCache, extractStyle, StyleProvider } from '@ant-design/cssinjs';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
import path from 'path';
|
||||||
import { globSync } from 'glob';
|
import { globSync } from 'glob';
|
||||||
import { configureToMatchImageSnapshot } from 'jest-image-snapshot';
|
import { configureToMatchImageSnapshot } from 'jest-image-snapshot';
|
||||||
import MockDate from 'mockdate';
|
import MockDate from 'mockdate';
|
||||||
@ -29,7 +30,11 @@ interface ImageTestOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line jest/no-export
|
// eslint-disable-next-line jest/no-export
|
||||||
export default function imageTest(component: React.ReactElement, options: ImageTestOptions) {
|
export default function imageTest(
|
||||||
|
component: React.ReactElement,
|
||||||
|
identifier: string,
|
||||||
|
options: ImageTestOptions,
|
||||||
|
) {
|
||||||
function test(name: string, themedComponent: React.ReactElement) {
|
function test(name: string, themedComponent: React.ReactElement) {
|
||||||
it(name, async () => {
|
it(name, async () => {
|
||||||
await jestPuppeteer.resetPage();
|
await jestPuppeteer.resetPage();
|
||||||
@ -80,7 +85,9 @@ export default function imageTest(component: React.ReactElement, options: ImageT
|
|||||||
fullPage: !options.onlyViewport,
|
fullPage: !options.onlyViewport,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(image).toMatchImageSnapshot();
|
expect(image).toMatchImageSnapshot({
|
||||||
|
customSnapshotIdentifier: `${identifier}-${name.replace(/\s/g, '-')}`,
|
||||||
|
});
|
||||||
|
|
||||||
MockDate.reset();
|
MockDate.reset();
|
||||||
page.off('request', onRequestHandle);
|
page.off('request', onRequestHandle);
|
||||||
@ -96,7 +103,7 @@ export default function imageTest(component: React.ReactElement, options: ImageT
|
|||||||
</div>,
|
</div>,
|
||||||
);
|
);
|
||||||
test(
|
test(
|
||||||
`[CSS Var] component image screenshot should correct ${key}`,
|
`component image screenshot should correct ${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}>
|
||||||
<div>CSS Var</div>
|
<div>CSS Var</div>
|
||||||
<ConfigProvider theme={{ algorithm, cssVar: true }}>{component}</ConfigProvider>
|
<ConfigProvider theme={{ algorithm, cssVar: true }}>{component}</ConfigProvider>
|
||||||
@ -115,7 +122,7 @@ export default function imageTest(component: React.ReactElement, options: ImageT
|
|||||||
</>,
|
</>,
|
||||||
);
|
);
|
||||||
test(
|
test(
|
||||||
`[CSS Var] component image screenshot should correct`,
|
`component image screenshot should correct.css-var`,
|
||||||
<>
|
<>
|
||||||
<div>CSS Var</div>
|
<div>CSS Var</div>
|
||||||
{Object.entries(themes).map(([key, algorithm]) => (
|
{Object.entries(themes).map(([key, algorithm]) => (
|
||||||
@ -151,7 +158,7 @@ export function imageDemoTest(component: string, options: Options = {}) {
|
|||||||
if (typeof Demo === 'function') {
|
if (typeof Demo === 'function') {
|
||||||
Demo = <Demo />;
|
Demo = <Demo />;
|
||||||
}
|
}
|
||||||
imageTest(Demo, {
|
imageTest(Demo, `${component}-${path.basename(file, '.tsx')}`, {
|
||||||
onlyViewport:
|
onlyViewport:
|
||||||
options.onlyViewport === true ||
|
options.onlyViewport === true ||
|
||||||
(Array.isArray(options.onlyViewport) &&
|
(Array.isArray(options.onlyViewport) &&
|
||||||
|
Loading…
Reference in New Issue
Block a user