diff --git a/jest.config.js b/jest.config.js index 75c2a280e..c914639be 100644 --- a/jest.config.js +++ b/jest.config.js @@ -25,6 +25,10 @@ module.exports = { }, ], }, + moduleNameMapper: { + '/\\.(css|less)$/': 'identity-obj-proxy', + '^@ant-design/web3$': '/packages/web3/src/index', + }, setupFiles: ['/tests/setup.js'], collectCoverageFrom: ['/packages/*/src/**/*.ts'], coveragePathIgnorePatterns: ['/node_modules/', '/(.*)mock(.*)/'], diff --git a/package.json b/package.json index f3cc6ca23..c1a20e305 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "release:beta": "changeset version --snapshot beta && changeset publish --tag beta", "ci": "npm run build && npm run lint && npm run test:ci", "test": "jest", + "test:update": "jest -u", "test:coverage": "jest --coverage", "test:watch": "jest --watch", "test:ci": "jest --coverage --maxWorkers=4 --forceExit", diff --git a/packages/web3/src/ConnectModal/__tests__/__snapshots__/basic.test.tsx.snap b/packages/web3/src/ConnectModal/__tests__/__snapshots__/basic.test.tsx.snap new file mode 100644 index 000000000..0aec298e0 --- /dev/null +++ b/packages/web3/src/ConnectModal/__tests__/__snapshots__/basic.test.tsx.snap @@ -0,0 +1,969 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ConnectModal with guide should render in dark mode 1`] = ` + +
+
+
+
+
+ +
+ +`; + +exports[`ConnectModal with guide should render in light mode 1`] = ` + +
+
+
+
+
+ +
+ +`; diff --git a/packages/web3/src/ConnectModal/__tests__/__snapshots__/simple.test.tsx.snap b/packages/web3/src/ConnectModal/__tests__/__snapshots__/simple.test.tsx.snap new file mode 100644 index 000000000..b44d19b9d --- /dev/null +++ b/packages/web3/src/ConnectModal/__tests__/__snapshots__/simple.test.tsx.snap @@ -0,0 +1,701 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ConnectModal without guide should render in dark mode 1`] = ` + +
+
+
+
+
+ +
+ +`; + +exports[`ConnectModal without guide should render in light mode 1`] = ` + +
+
+
+
+
+ +
+ +`; diff --git a/packages/web3/src/ConnectModal/__tests__/basic.test.tsx b/packages/web3/src/ConnectModal/__tests__/basic.test.tsx new file mode 100644 index 000000000..0a1fc0468 --- /dev/null +++ b/packages/web3/src/ConnectModal/__tests__/basic.test.tsx @@ -0,0 +1,52 @@ +import { ConnectModal } from "@ant-design/web3"; +import { groupOrder, guide, walletList } from "./mock"; +import { render } from "@testing-library/react"; + +describe("ConnectModal with guide", () => { + + function testWithTheme(theme: 'light' | 'dark') { + it(`should render in ${theme} mode`, () => { + const App = () => ( + + ); + const { baseElement } = render(); + + expect(baseElement).toMatchSnapshot(); + // should have ant-connect-modal class + expect(baseElement.querySelector('.ant-modal')?.className).toContain('ant-connect-modal'); + expect(baseElement.querySelector('.ant-modal')?.className).toContain(`ant-connect-modal-${theme}`); + + // should have simple class when without guide + expect(baseElement.querySelector('.ant-connect-modal-body')?.className).not.toContain('simple'); + + // should have title and footer + expect(baseElement.querySelector('.ant-connect-modal-title')?.textContent).toBe('ConnectModal'); + expect(baseElement.querySelector('.ant-connect-modal-footer')?.textContent).toBe('蚂蚁链提供技术支持'); + + // group order + expect(baseElement.querySelectorAll('.ant-connect-modal-group-title')[0].textContent).toBe('Popular'); + expect(baseElement.querySelectorAll('.ant-connect-modal-group-title')[1].textContent).toBe('Default'); + + // wallet list items + expect(baseElement.querySelectorAll('.ant-connect-modal-wallet-item').length).toBe(walletList.length); + + // should have guide panel + expect(baseElement.querySelector('.ant-connect-modal-guide-panel')).not.toBeNull(); + expect(baseElement.querySelector('.ant-connect-modal-guide-title')?.textContent).toBe(guide.title); + expect(baseElement.querySelectorAll('.ant-connect-modal-guide-item').length).toBe(guide.infos.length); + expect(baseElement.querySelector('.ant-connect-modal-more')?.getAttribute("href")).toBe(guide.moreLink); + + }); + } + + (['light', 'dark'] as const).forEach(testWithTheme); + +}); \ No newline at end of file diff --git a/packages/web3/src/ConnectModal/__tests__/mock/index.ts b/packages/web3/src/ConnectModal/__tests__/mock/index.ts new file mode 100644 index 000000000..fabb16339 --- /dev/null +++ b/packages/web3/src/ConnectModal/__tests__/mock/index.ts @@ -0,0 +1,152 @@ +import type { DefaultGuide, Wallet } from '@ant-design/web3'; + +export const walletList: Wallet[] = [ + { + icon: 'https://xsgames.co/randomusers/avatar.php?g=pixel&key=0', + name: '测试钱包', + remark: '备注', + app: { + link: 'https://test.com/xxx', + }, + extensions: [ + { + key: 'Chrome', + link: 'https://test.com/xxx', + browserIcon: + 'https://github.com/ant-design/ant-design/assets/10286961/0d4e4ac7-8f89-4147-a06a-de72c02e85cb', + browserName: 'Chrome', + description: 'Access your wallet right from your favorite web browser.', + }, + { + key: 'Firefox', + link: 'https://test.com/xxx', + browserIcon: + 'https://github.com/ant-design/ant-design/assets/10286961/a6559d9b-d20a-4ac7-a263-53c04b9038a4', + browserName: 'Firefox', + description: 'Access your wallet right from your favorite web browser.', + }, + ], + group: 'Popular', + }, + { + icon: 'https://xsgames.co/randomusers/avatar.php?g=pixel&key=1', + name: '测试钱包2', + remark: '备注2', + app: { + link: 'https://test.com/xxx', + }, + extensions: [ + { + key: 'Firefox', + link: 'https://test.com/xxx', + browserIcon: + 'https://github.com/ant-design/ant-design/assets/10286961/a6559d9b-d20a-4ac7-a263-53c04b9038a4', + browserName: 'Firefox', + description: 'Access your wallet right from your favorite web browser.', + }, + ], + }, + { + icon: 'https://xsgames.co/randomusers/avatar.php?g=pixel&key=3', + name: '测试钱包3', + remark: '备注3', + group: 'Popular', + app: { + link: 'https://test.com/xxx', + }, + }, + { + name: '测试钱包4', + remark: '备注4', + extensions: [ + { + key: 'Safari', + link: 'https://test.com/xxx', + browserIcon: + 'https://github.com/ant-design/ant-design/assets/10286961/9d56eba7-84d7-4360-b013-bf57d419b058', + browserName: 'Safari', + description: 'Access your wallet right from your favorite web browser.', + }, + ], + }, + { + name: '测试钱包5', + remark: '备注5', + app: { + link: 'https://test.com/xxx', + }, + }, + { + name: '测试钱包6', + remark: '备注6', + key: 6, + app: { + link: 'https://test.com/xxx', + }, + extensions: [ + { + key: 'Chrome', + link: 'https://test.com/xxx', + browserIcon: + 'https://github.com/ant-design/ant-design/assets/10286961/0d4e4ac7-8f89-4147-a06a-de72c02e85cb', + browserName: 'Chrome', + description: 'Access your wallet right from your favorite web browser.', + }, + ], + }, + { + name: '测试钱包6', + remark: '备注6', + key: 7, + app: { + link: 'https://test.com/xxx', + }, + extensions: [ + { + key: 'Chrome', + link: 'https://test.com/xxx', + browserIcon: + 'https://github.com/ant-design/ant-design/assets/10286961/0d4e4ac7-8f89-4147-a06a-de72c02e85cb', + browserName: 'Chrome', + description: 'Access your wallet right from your favorite web browser.', + }, + ], + }, +]; + +export const groupOrder = (a: string, b: string) => { + if (a === 'Popular') return -1; + if (b === 'Popular') return 1; + return a.localeCompare(b); +}; + +export const guide: DefaultGuide = { + title: 'What is a Wallet?', + infos: [ + { + title: 'A Home for your Digital Assets', + description: + 'Wallets are used to send, receive, store, and display digital assets like Ethereum and NFTs.', + icon: 'https://xsgames.co/randomusers/avatar.php?g=pixel&key=4', + }, + { + title: 'A New Way to Log In', + description: + 'Instead of creating new accounts and passwords on every website, just connect your wallet.', + icon: 'https://xsgames.co/randomusers/avatar.php?g=pixel&key=5', + }, + { + title: 'A New Way to Log In2', + description: + 'Instead of creating new accounts and passwords on every website, just connect your wallet.', + icon: 'https://xsgames.co/randomusers/avatar.php?g=pixel&key=5', + }, + { + title: 'A New Way to Log In3', + description: + 'Instead of creating new accounts and passwords on every website, just connect your wallet.', + icon: 'https://xsgames.co/randomusers/avatar.php?g=pixel&key=5', + }, + ], + moreLink: 'https://test.com/xxx', +}; diff --git a/packages/web3/src/ConnectModal/__tests__/simple.test.tsx b/packages/web3/src/ConnectModal/__tests__/simple.test.tsx new file mode 100644 index 000000000..01f031c58 --- /dev/null +++ b/packages/web3/src/ConnectModal/__tests__/simple.test.tsx @@ -0,0 +1,42 @@ +import { ConnectModal } from "@ant-design/web3"; +import { groupOrder, walletList } from "./mock"; +import { render } from "@testing-library/react"; + +describe("ConnectModal without guide", () => { + function testWithTheme(theme: 'light' | 'dark') { + it(`should render in ${theme} mode`, () => { + const App = () => ( + + ); + const { baseElement } = render(); + + expect(baseElement).toMatchSnapshot(); + // should have ant-connect-modal class + expect(baseElement.querySelector('.ant-modal')?.className).toContain('ant-connect-modal'); + expect(baseElement.querySelector('.ant-modal')?.className).toContain(`ant-connect-modal-${theme}`); + + // should have simple class when without guide + expect(baseElement.querySelector('.ant-connect-modal-body')?.className).toContain('simple'); + + // should have title and footer + expect(baseElement.querySelector('.ant-connect-modal-title')?.textContent).toBe('ConnectModal'); + expect(baseElement.querySelector('.ant-connect-modal-footer')?.textContent).toBe('蚂蚁链提供技术支持'); + + // group order + expect(baseElement.querySelectorAll('.ant-connect-modal-group-title')[0].textContent).toBe('Popular'); + expect(baseElement.querySelectorAll('.ant-connect-modal-group-title')[1].textContent).toBe('Default'); + + // wallet list items + expect(baseElement.querySelectorAll('.ant-connect-modal-wallet-item').length).toBe(walletList.length); + }); + } + + (['light', 'dark'] as const).forEach(testWithTheme); +}); \ No newline at end of file diff --git a/packages/web3/src/ConnectModal/components/WalletList.tsx b/packages/web3/src/ConnectModal/components/WalletList.tsx index 79da4be55..d727598d0 100644 --- a/packages/web3/src/ConnectModal/components/WalletList.tsx +++ b/packages/web3/src/ConnectModal/components/WalletList.tsx @@ -40,7 +40,7 @@ const WalletList: React.FC = (props) => { rowKey="key" renderItem={(item) => ( = (props) => { const { open, diff --git a/packages/web3/src/ConnectModal/style/index.tsx b/packages/web3/src/ConnectModal/style/index.tsx index e44c6b304..f18afe8e3 100644 --- a/packages/web3/src/ConnectModal/style/index.tsx +++ b/packages/web3/src/ConnectModal/style/index.tsx @@ -123,7 +123,7 @@ const getThemeStyle = ( paddingInline: 6, }, [`${componentCls}-group-content`]: { - [`${componentCls}-item`]: { + [`${componentCls}-wallet-item`]: { cursor: 'pointer', paddingInline: 6, borderRadius: 8, diff --git a/tests/setup.js b/tests/setup.js index af30c44a6..7b2f2f927 100644 --- a/tests/setup.js +++ b/tests/setup.js @@ -1,5 +1,39 @@ /* eslint-disable no-console */ const React = require('react'); +const util = require('util'); + +/* eslint-disable global-require */ +if (typeof window !== 'undefined') { + global.window.resizeTo = (width, height) => { + global.window.innerWidth = width || global.window.innerWidth; + global.window.innerHeight = height || global.window.innerHeight; + global.window.dispatchEvent(new Event('resize')); + }; + global.window.scrollTo = () => {}; + // ref: https://github.com/ant-design/ant-design/issues/18774 + if (!window.matchMedia) { + Object.defineProperty(global.window, 'matchMedia', { + writable: true, + configurable: true, + value: jest.fn((query) => ({ + matches: query.includes('max-width'), + addListener: jest.fn(), + removeListener: jest.fn(), + })), + }); + } + + // Fix css-animation or rc-motion deps on these + // https://github.com/react-component/motion/blob/9c04ef1a210a4f3246c9becba6e33ea945e00669/src/util/motion.ts#L27-L35 + // https://github.com/yiminghe/css-animation/blob/a5986d73fd7dfce75665337f39b91483d63a4c8c/src/Event.js#L44 + window.AnimationEvent = window.AnimationEvent || window.Event; + window.TransitionEvent = window.TransitionEvent || window.Event; + + // ref: https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom + // ref: https://github.com/jsdom/jsdom/issues/2524 + Object.defineProperty(window, 'TextEncoder', { writable: true, value: util.TextEncoder }); + Object.defineProperty(window, 'TextDecoder', { writable: true, value: util.TextDecoder }); +} // eslint-disable-next-line no-console console.log('Current React Version:', React.version);