Skip to content

Commit

Permalink
chore: update stories for name component (#28049)
Browse files Browse the repository at this point in the history
## **Description**

Fix and expand the storybook stories for the `Name` component to include
a story for each display name fallback.

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/28049?quickstart=1)

## **Related issues**

## **Manual testing steps**

## **Screenshots/Recordings**

### **Before**

### **After**

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
  • Loading branch information
matthewwalsh0 authored Oct 24, 2024
1 parent 5983dc1 commit f1db383
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 119 deletions.
3 changes: 3 additions & 0 deletions .storybook/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ module.exports = {
config.resolve.alias['@ethereumjs/util'] = require.resolve(
'../ui/__mocks__/ethereumjs-util.js',
);
config.resolve.alias['./useNftCollectionsMetadata'] = require.resolve(
'../ui/__mocks__/useNftCollectionsMetadata.js',
);
config.resolve.fallback = {
child_process: false,
constants: false,
Expand Down
14 changes: 14 additions & 0 deletions ui/__mocks__/useNftCollectionsMetadata.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module.exports = {
useNftCollectionsMetadata: () => {
return {
'0x1': {
'0xc0ffee254729296a45a3885639ac7e10f9d54979': {
name: 'Everything I Own',
image:
'https://img.reservoir.tools/images/v2/mainnet/z9JRSpLYGu7%2BCZoKWtAuAN%2F%2FMfWcOGcwki5%2FxXYtCb4OfGsOPvxN1LZHZ5%2BcuQGwJciTvgr58ThRjooWLMWehc1nSTXtbfFJ1TNtL%2FeIjglkPKsEG%2Fbem0E%2B3yo7tAUqlZ1ou0SMzGOfq%2FG1BHwIpgHQ524PRAlaynVkDcp8y58kALOPTQSDN1tgaqkZD%2FZiNBEaYq6Bp9XH8Vm8tMXsaQ%3D%3D?width=250',
isSpam: false,
},
},
};
},
};
282 changes: 163 additions & 119 deletions ui/components/app/name/name.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,108 +3,75 @@ import React from 'react';
import { NameType } from '@metamask/name-controller';
import { Provider } from 'react-redux';
import configureStore from '../../../store/store';
import Name from './name';
import { mockNetworkState } from '../../../../test/stub/networks';
import Name, { NameProps } from './name';
import mockState from '../../../../test/data/mock-state.json';
import {
EXPERIENCES_TYPE,
FIRST_PARTY_CONTRACT_NAMES,
} from '../../../../shared/constants/first-party-contracts';
import { cloneDeep } from 'lodash';

const addressNoSavedNameMock = '0xc0ffee254729296a45a3885639ac7e10f9d54978';
const addressSavedNameMock = '0xc0ffee254729296a45a3885639ac7e10f9d54977';
const addressSavedTokenMock = '0x0a3bb08b3a15a19b4de82f8acfc862606fb69a2d';
const addressUnsavedTokenMock = '0x0a5e677a6a24b2f1a2bf4f3bffc443231d2fdec8';
const chainIdMock = '0x1';
const ADDRESS_MOCK = '0xc0ffee254729296a45a3885639ac7e10f9d54978';
const ADDRESS_NFT_MOCK = '0xc0ffee254729296a45a3885639ac7e10f9d54979';
const VARIATION_MOCK = '0x1';
const NAME_MOCK = 'Saved Name';

const storeMock = configureStore({
const ADDRESS_FIRST_PARTY_MOCK =
FIRST_PARTY_CONTRACT_NAMES[EXPERIENCES_TYPE.METAMASK_BRIDGE][
VARIATION_MOCK
].toLowerCase();

const PROPOSED_NAMES_MOCK = {
ens: {
proposedNames: ['test.eth'],
lastRequestTime: 123,
retryDelay: null,
},
etherscan: {
proposedNames: ['TestContract'],
lastRequestTime: 123,
retryDelay: null,
},
token: {
proposedNames: ['Test Token'],
lastRequestTime: 123,
retryDelay: null,
},
lens: {
proposedNames: ['test.lens'],
lastRequestTime: 123,
retryDelay: null,
},
};

const STATE_MOCK = {
...mockState,
metamask: {
...mockNetworkState({chainId: chainIdMock}),
...mockState.metamask,
useTokenDetection: true,
tokenList: {
'0x0a3bb08b3a15a19b4de82f8acfc862606fb69a2d': {
address: '0x0a3bb08b3a15a19b4de82f8acfc862606fb69a2d',
symbol: 'IUSD',
name: 'iZUMi Bond USD',
iconUrl:
'https://static.cx.metamask.io/api/v1/tokenIcons/1/0x0a3bb08b3a15a19b4de82f8acfc862606fb69a2d.png',
},
'0x0a5e677a6a24b2f1a2bf4f3bffc443231d2fdec8': {
address: '0x0a5e677a6a24b2f1a2bf4f3bffc443231d2fdec8',
symbol: 'USX',
name: 'dForce USD',
iconUrl:
'https://static.cx.metamask.io/api/v1/tokenIcons/1/0x0a5e677a6a24b2f1a2bf4f3bffc443231d2fdec8.png',
},
},
tokensChainsCache: {},
names: {
[NameType.ETHEREUM_ADDRESS]: {
[addressNoSavedNameMock]: {
[chainIdMock]: {
proposedNames: {
ens: {
proposedNames: ['test.eth'],
lastRequestTime: 123,
retryDelay: null,
},
etherscan: {
proposedNames: ['TestContract'],
lastRequestTime: 123,
retryDelay: null,
},
token: {
proposedNames: ['Test Token'],
lastRequestTime: 123,
retryDelay: null,
},
lens: {
proposedNames: ['test.lens'],
lastRequestTime: 123,
retryDelay: null,
},
},
[ADDRESS_MOCK]: {
[VARIATION_MOCK]: {
proposedNames: PROPOSED_NAMES_MOCK,
},
},
[addressSavedNameMock]: {
[chainIdMock]: {
proposedNames: {
ens: {
proposedNames: ['test.eth'],
lastRequestTime: 123,
retryDelay: null,
},
etherscan: {
proposedNames: ['TestContract'],
lastRequestTime: 123,
retryDelay: null,
},
token: {
proposedNames: ['Test Token'],
lastRequestTime: 123,
retryDelay: null,
},
lens: {
proposedNames: ['test.lens'],
lastRequestTime: 123,
retryDelay: null,
},
},
name: 'Test Token',
sourceId: 'token',
[ADDRESS_NFT_MOCK]: {
[VARIATION_MOCK]: {
proposedNames: PROPOSED_NAMES_MOCK,
},
},
[addressSavedTokenMock]: {
[chainIdMock]: {
proposedNames: {},
name: 'Saved Token Name',
sourceId: 'token',
[ADDRESS_FIRST_PARTY_MOCK]: {
[VARIATION_MOCK]: {
proposedNames: PROPOSED_NAMES_MOCK,
},
},
},
},
nameSources: {
ens: { label: 'Ethereum Name Service (ENS)' },
etherscan: { label: 'Etherscan (Verified Contract Name)' },
token: { label: 'Blockchain (Token Name)' },
lens: { label: 'Lens Protocol' },
},
nameSources: {},
},
});
};

/**
* Displays the saved name for a raw value such as an Ethereum address.<br/><br/>
Expand All @@ -125,6 +92,10 @@ export default {
description: `The type of value.<br/><br/>
Limited to the values in the \`NameType\` enum.`,
},
variation: {
control: 'text',
description: `The variation of the value.<br/><br/>For example, the chain ID if the type is Ethereum address.`,
},
disableEdit: {
control: 'boolean',
description: `Whether to prevent the modal from opening when the component is clicked.`,
Expand All @@ -134,68 +105,141 @@ export default {
},
},
args: {
value: addressNoSavedNameMock,
value: ADDRESS_MOCK,
type: NameType.ETHEREUM_ADDRESS,
variation: VARIATION_MOCK,
disableEdit: false,
},
decorators: [(story) => <Provider store={storeMock}>{story()}</Provider>],
render: ({ state, ...args }) => {
const finalState = cloneDeep(STATE_MOCK);
state?.(finalState);

return (
<Provider store={configureStore(finalState)}>
<Name {...(args as NameProps)} />
</Provider>
);
},
};

// eslint-disable-next-line jsdoc/require-param
/**
* No name has been saved for the value and type.
*/
export const DefaultStory = (args) => {
return <Name {...args} />;
export const NoSavedName = {
name: 'No Saved Name',
args: {
value: ADDRESS_MOCK,
type: NameType.ETHEREUM_ADDRESS,
variation: VARIATION_MOCK,
},
};

DefaultStory.storyName = 'No Saved Name';

/**
* A name was previously saved for this value and type.<br/><br/>
* The component will still display a modal when clicked to edit the name.
*/
export const SavedNameStory = () => {
return <Name value={addressSavedNameMock} type={NameType.ETHEREUM_ADDRESS} />;
export const SavedNameStory = {
name: 'Saved Name',
args: {
value: ADDRESS_MOCK,
type: NameType.ETHEREUM_ADDRESS,
variation: VARIATION_MOCK,
state: (state) => {
state.metamask.names[NameType.ETHEREUM_ADDRESS][ADDRESS_MOCK][
VARIATION_MOCK
].name = NAME_MOCK;
},
},
};

SavedNameStory.storyName = 'Saved Name';

/**
* No name was previously saved for this recognized token.<br/><br/>
* The component will still display a modal when clicked to edit the name.
*/
export const UnsavedTokenNameStory = () => {
return (
<Name value={addressUnsavedTokenMock} type={NameType.ETHEREUM_ADDRESS} />
);
export const DefaultTokenNameStory = {
name: 'Default ERC-20 Token Name',
args: {
value: ADDRESS_MOCK,
type: NameType.ETHEREUM_ADDRESS,
variation: VARIATION_MOCK,
state: (state) => {
state.metamask.tokensChainsCache = {
[VARIATION_MOCK]: {
data: {
[ADDRESS_MOCK]: {
address: ADDRESS_MOCK,
symbol: 'IUSD',
name: 'iZUMi Bond USD',
iconUrl:
'https://static.cx.metamask.io/api/v1/tokenIcons/1/0x0a3bb08b3a15a19b4de82f8acfc862606fb69a2d.png',
},
},
},
};
},
},
};

UnsavedTokenNameStory.storyName = 'Unsaved Token Name';
/**
* No name was previously saved for this watched NFT.<br/><br/>
* The component will still display a modal when clicked to edit the name.
*/
export const DefaultWatchedNFTNameStory = {
name: 'Default Watched NFT Name',
args: {
value: ADDRESS_MOCK,
type: NameType.ETHEREUM_ADDRESS,
variation: VARIATION_MOCK,
state: (state) => {
state.metamask.allNftContracts = {
'0x123': {
[VARIATION_MOCK]: [
{
address: ADDRESS_MOCK,
name: 'Everything I Own',
},
],
},
};
},
},
};

/**
* A name was previously saved for this recognized token.<br/><br/>
* No name was previously saved for this recognized NFT.<br/><br/>
* The component will still display a modal when clicked to edit the name.
*/
export const SavedTokenNameStory = () => {
return (
<Name value={addressSavedTokenMock} type={NameType.ETHEREUM_ADDRESS} />
);
export const DefaultNFTNameStory = {
name: 'Default NFT Name',
args: {
value: ADDRESS_NFT_MOCK,
type: NameType.ETHEREUM_ADDRESS,
variation: VARIATION_MOCK,
},
};

SavedTokenNameStory.storyName = 'Saved Token Name';
/**
* No name was previously saved for this first-party contract.<br/><br/>
* The component will still display a modal when clicked to edit the name.
*/
export const DefaultFirstPartyNameStory = {
name: 'Default First-Party Name',
args: {
value: ADDRESS_FIRST_PARTY_MOCK,
type: NameType.ETHEREUM_ADDRESS,
variation: VARIATION_MOCK,
},
};

/**
* Clicking the component will not display a modal to edit the name.
*/
export const EditDisabledStory = () => {
return (
<Name
value={addressSavedNameMock}
type={NameType.ETHEREUM_ADDRESS}
disableEdit
/>
);
export const EditDisabledStory = {
name: 'Edit Disabled',
args: {
value: ADDRESS_MOCK,
type: NameType.ETHEREUM_ADDRESS,
variation: VARIATION_MOCK,
disableEdit: true,
},
};

EditDisabledStory.storyName = 'Edit Disabled';

0 comments on commit f1db383

Please sign in to comment.