Skip to content

Commit

Permalink
Merge branch 'main' into refactor/LW-10281-dApp-connector-screens-act…
Browse files Browse the repository at this point in the history
…ivity-details
  • Loading branch information
tommayeliog committed May 7, 2024
2 parents 92d5fa4 + 0bb7467 commit 6755b9f
Show file tree
Hide file tree
Showing 104 changed files with 1,682 additions and 1,440 deletions.
8 changes: 5 additions & 3 deletions .github/workflows/e2e-tests-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ env:
NETWORK: ${{ github.event.inputs.network || 'preprod' }}
RUN: ${{ github.run_number }}
DISPLAY: ':99.0'
NODE_OPTIONS: --max-old-space-size=16384

jobs:
tests:
Expand Down Expand Up @@ -73,7 +74,7 @@ jobs:
eval "$runCommand";
- name: Create allure properties
if: always()
working-directory: ./packages/e2e-tests/reports/allure/results
working-directory: './packages/e2e-tests/reports/allure/results'
run: |
echo "
env=${NETWORK}
Expand All @@ -82,19 +83,20 @@ jobs:
platform=Linux
" > environment.properties
- name: Publish allure report to S3
uses: andrcuns/allure-publish-action@v1.0.1
uses: andrcuns/allure-publish-action@v2.6.0
if: always()
env:
GITHUB_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
AWS_ACCESS_KEY_ID: ${{ secrets.E2E_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.E2E_AWS_SECRET_ACCESS_KEY }}
with:
storageType: s3
resultsGlob: './packages/e2e-tests/reports/allure/results/*'
resultsGlob: './packages/e2e-tests/reports/allure/results'
bucket: lace-e2e-test-results
prefix: 'all/linux/${BROWSER}/${RUN}'
copyLatest: true
ignoreMissingResults: true
baseUrl: 'https://${{ secrets.E2E_REPORTS_USER }}:${{ secrets.E2E_REPORTS_PASSWORD }}@${{ secrets.E2E_REPORTS_URL }}'
- name: Publish artifacts (logs, reports, screenshots)
uses: actions/upload-artifact@v4
if: always()
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/e2e-tests-win.yml
Original file line number Diff line number Diff line change
Expand Up @@ -154,19 +154,20 @@ jobs:
name: test-artifacts
path: ./packages/e2e-tests
- name: Publish allure report to S3
uses: andrcuns/allure-publish-action@v1.0.1
uses: andrcuns/allure-publish-action@v2.6.0
if: always()
env:
GITHUB_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
AWS_ACCESS_KEY_ID: ${{ secrets.E2E_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.E2E_AWS_SECRET_ACCESS_KEY }}
with:
storageType: s3
resultsGlob: './packages/e2e-tests/reports/allure/results/*'
resultsGlob: './packages/e2e-tests/reports/allure/results'
bucket: lace-e2e-test-results
prefix: 'all/windows/${BROWSER}/${RUN}'
copyLatest: true
ignoreMissingResults: true
baseUrl: 'https://${{ secrets.E2E_REPORTS_USER }}:${{ secrets.E2E_REPORTS_PASSWORD }}@${{ secrets.E2E_REPORTS_URL }}'
- name: Add link to summary
if: always()
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/smoke-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:
platform=Linux
" > environment.properties
- name: Publish allure report to S3
uses: andrcuns/allure-publish-action@v2.4.0
uses: andrcuns/allure-publish-action@v2.6.0
if: always()
env:
GITHUB_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React, { useEffect, useState } from 'react';
import { DappInfo, VotingProcedures } from '@lace/core';
import { hasValidDrepRegistration, votingProceduresInspector } from './utils';
import { votingProceduresInspector } from './utils';
import { useCexplorerBaseUrl, useDisallowSignTx } from './hooks';
import { Wallet } from '@lace/cardano';

import { NonRegisteredUserModal } from './NonRegisteredUserModal/NonRegisteredUserModal';
import { useViewsFlowContext } from '@providers';
import { useWalletStore } from '@src/stores';
Expand All @@ -13,7 +14,7 @@ export const VotingProceduresContainer = (): React.ReactElement => {
signTxRequest: { request },
dappInfo
} = useViewsFlowContext();
const { walletState } = useWalletStore();
const { inMemoryWallet } = useWalletStore();
const [votingProcedures, setVotingProcedures] = useState<Wallet.Cardano.VotingProcedures>([]);
const [isNonRegisteredUserModalVisible, setIsNonRegisteredUserModalVisible] = useState<boolean>(false);
const [userAckNonRegisteredState, setUserAckNonRegisteredState] = useState<boolean>(false);
Expand All @@ -29,9 +30,15 @@ export const VotingProceduresContainer = (): React.ReactElement => {
}, [request]);

useEffect(() => {
if (!walletState?.transactions.history || userAckNonRegisteredState) return;
setIsNonRegisteredUserModalVisible(!hasValidDrepRegistration(walletState.transactions.history));
}, [walletState?.transactions.history, userAckNonRegisteredState]);
if (userAckNonRegisteredState) return () => void 0;
const subscription = inMemoryWallet?.governance?.isRegisteredAsDRep$?.subscribe(
(hasValidDrepRegistration): void => {
setIsNonRegisteredUserModalVisible(!hasValidDrepRegistration);
}
);

return () => subscription?.unsubscribe();
}, [inMemoryWallet?.governance?.isRegisteredAsDRep$, userAckNonRegisteredState]);

const explorerBaseUrl = useCexplorerBaseUrl();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ const mockUseTranslation = jest.fn(() => ({ t }));
const mockVotingProcedures = jest.fn();
const mockNonRegisteredUserModal = jest.fn();
const mockUseDisallowSignTx = jest.fn();
const mockHasValidDrepRegistration = jest.fn();
const mockPreprodCexplorerBaseUrl = 'PREPROD_CEXPLORER_BASE_URL';
const mockCexplorerUrlPathsTx = 'CEXPLORER_URL_PATHS.TX';
import * as React from 'react';
Expand All @@ -21,6 +20,7 @@ import { buildMockTx } from '@src/utils/mocks/tx';
import { Wallet } from '@lace/cardano';
import { getWrapper } from '../testing.utils';
import { TransactionWitnessRequest } from '@cardano-sdk/web-extension';
import { of } from 'rxjs';

jest.mock('@src/stores', () => ({
...jest.requireActual<any>('@src/stores'),
Expand Down Expand Up @@ -66,11 +66,6 @@ jest.mock('react-i18next', () => {
};
});

jest.mock('../utils', () => ({
...jest.requireActual<any>('../utils'),
hasValidDrepRegistration: mockHasValidDrepRegistration
}));

jest.mock('../hooks', () => {
const original = jest.requireActual('../hooks');
return {
Expand Down Expand Up @@ -177,11 +172,12 @@ jest.mock('@providers', () => ({

describe('Testing VotingProceduresContainer component', () => {
beforeEach(() => {
mockHasValidDrepRegistration.mockReset();
mockHasValidDrepRegistration.mockReturnValue(true);
mockUseWalletStore.mockReset();
mockUseWalletStore.mockImplementation(() => ({
environmentName: 'Preprod'
environmentName: 'Preprod',
inMemoryWallet: {
governance: {}
}
}));
mockVotingProcedures.mockReset();
mockVotingProcedures.mockReturnValue(<span data-testid="VotingProcedures" />);
Expand Down Expand Up @@ -236,14 +232,12 @@ describe('Testing VotingProceduresContainer component', () => {
});

test('should handle NonRegisteredUserModal onConfirm', async () => {
mockHasValidDrepRegistration.mockReset();
mockHasValidDrepRegistration.mockReturnValue(false);
mockUseWalletStore.mockReset();
mockUseWalletStore.mockImplementation(() => ({
environmentName: 'Preprod',
walletState: {
transactions: {
history: []
inMemoryWallet: {
governance: {
isRegisteredAsDRep$: of(false)
}
}
}));
Expand Down Expand Up @@ -273,14 +267,12 @@ describe('Testing VotingProceduresContainer component', () => {
const disallowSignTxMock = jest.fn();
mockUseDisallowSignTx.mockReset();
mockUseDisallowSignTx.mockReturnValue(disallowSignTxMock);
mockHasValidDrepRegistration.mockReset();
mockHasValidDrepRegistration.mockReturnValue(false);
mockUseWalletStore.mockReset();
mockUseWalletStore.mockImplementation(() => ({
environmentName: 'Preprod',
walletState: {
transactions: {
history: []
inMemoryWallet: {
governance: {
isRegisteredAsDRep$: of(false)
}
}
}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ import {
votingProceduresInspector,
getTxType,
pubDRepKeyToHash,
depositPaidWithSymbol,
hasValidDrepRegistration
depositPaidWithSymbol
} from '../utils';

jest.mock('@cardano-sdk/core', () => ({
Expand Down Expand Up @@ -168,59 +167,4 @@ describe('Testing utils', () => {
'coinId Unknown not supported'
);
});

describe('hasValidDrepRegistration', () => {
test('should return false if there transactions', () => {
const transactions = [] as unknown as Wallet.Cardano.HydratedTx[];
expect(hasValidDrepRegistration(transactions)).toBe(false);
});

test('should return false if there is no certificates', () => {
const transactions = [{ body: {} }, { body: { certificates: [] } }] as unknown as Wallet.Cardano.HydratedTx[];
expect(hasValidDrepRegistration(transactions)).toBe(false);
});

test('should return true if first certificate has RegisterDelegateRepresentative __typename', () => {
const transactions = [
{
body: {
certificates: [
{ __typename: Wallet.Cardano.CertificateType.RegisterDelegateRepresentative },
{ __typename: Wallet.Cardano.CertificateType.UnregisterDelegateRepresentative }
]
}
},
{
body: {
certificates: [
{ __typename: Wallet.Cardano.CertificateType.UnregisterDelegateRepresentative },
{ __typename: Wallet.Cardano.CertificateType.RegisterDelegateRepresentative }
]
}
}
] as unknown as Wallet.Cardano.HydratedTx[];
expect(hasValidDrepRegistration(transactions)).toBe(true);
});
test('should return false if first certificate has UnregisterDelegateRepresentative __typename', () => {
const transactions = [
{
body: {
certificates: [
{ __typename: Wallet.Cardano.CertificateType.UnregisterDelegateRepresentative },
{ __typename: Wallet.Cardano.CertificateType.RegisterDelegateRepresentative }
]
}
},
{
body: {
certificates: [
{ __typename: Wallet.Cardano.CertificateType.RegisterDelegateRepresentative },
{ __typename: Wallet.Cardano.CertificateType.UnregisterDelegateRepresentative }
]
}
}
] as unknown as Wallet.Cardano.HydratedTx[];
expect(hasValidDrepRegistration(transactions)).toBe(false);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ import { NftDetail as NftDetailView } from '@lace/core';
import { Wallet } from '@lace/cardano';
import { useTranslation } from 'react-i18next';
import { SendFlowTriggerPoints, useOutputInitialState } from '@src/views/browser-view/features/send-transaction';
import { DEFAULT_WALLET_BALANCE, SEND_NFT_DEFAULT_AMOUNT } from '@src/utils/constants';
import { APP_MODE_POPUP, DEFAULT_WALLET_BALANCE, SEND_NFT_DEFAULT_AMOUNT } from '@src/utils/constants';
import { PostHogAction } from '@providers/AnalyticsProvider/analyticsTracker';
import { useAnalyticsContext } from '@providers';
import { buttonIds } from '@hooks/useEnterKeyPress';
import { withNftsFoldersContext } from '../context';

export const NftDetail = (): React.ReactElement => {
const { inMemoryWallet } = useWalletStore();
export const NftDetail = withNftsFoldersContext((): React.ReactElement => {
const {
inMemoryWallet,
walletUI: { appMode }
} = useWalletStore();
const { t } = useTranslation();
const analytics = useAnalyticsContext();

Expand All @@ -33,12 +37,6 @@ export const NftDetail = (): React.ReactElement => {

const amount = useMemo(() => Wallet.util.calculateAssetBalance(bigintBalance, assetInfo), [assetInfo, bigintBalance]);

const nftDetailTranslation = {
tokenInformation: t('core.nftDetail.tokenInformation'),
attributes: t('core.nftDetail.attributes'),
setAsAvatar: t('core.nftDetail.setAsAvatar')
};

const handleOpenSend = () => {
// eslint-disable-next-line camelcase
analytics.sendEventToPostHog(PostHogAction.SendClick, { trigger_point: SendFlowTriggerPoints.NFTS });
Expand All @@ -64,11 +62,11 @@ export const NftDetail = (): React.ReactElement => {
{assetInfo && (
<NftDetailView
{...nftDetailSelector(assetInfo)}
isPopup={appMode === APP_MODE_POPUP}
amount={amount}
translations={nftDetailTranslation}
title={<h2 className={styles.secondaryTitle}>{assetInfo.nftMetadata?.name ?? assetInfo.fingerprint}</h2>}
/>
)}
</Drawer>
);
};
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable unicorn/no-useless-undefined */
/* eslint-disable unicorn/no-useless-undefined, max-statements */
import { useAssetInfo, useRedirection } from '@hooks';
import { useWalletStore } from '@src/stores';
import { Button, useObservable } from '@lace/common';
Expand All @@ -8,7 +8,7 @@ import isNil from 'lodash/isNil';
import React, { useCallback, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import styles from './Nfts.module.scss';
import { NftFolderItemProps, NftItemProps, NftList, NftListProps, NftsItemsTypes } from '@lace/core';
import { ListEmptyState, NftFolderItemProps, NftItemProps, NftList, NftListProps, NftsItemsTypes } from '@lace/core';
import { ContentLayout } from '@src/components/Layout';
import { FundWalletBanner } from '@src/views/browser-view/components';
import { walletRoutePaths } from '@routes';
Expand All @@ -23,6 +23,11 @@ import { RenameFolderType } from '@views/browser/features/nfts';
import { NftFolderConfirmationModal } from '@views/browser/features/nfts/components/NftFolderConfirmationModal';
import RemoveFolderIcon from '@assets/icons/remove-folder.component.svg';
import { useAnalyticsContext, useCurrencyStore } from '@providers';
import { SearchBox } from '@lace/ui';
import { Skeleton } from 'antd';
import { useNftSearch } from '@hooks/useNftSearch';

const MIN_ASSET_COUNT_FOR_SEARCH = 10;

export const Nfts = withNftsFoldersContext((): React.ReactElement => {
const redirectToNftDetail = useRedirection<{ params: { id: string } }>(walletRoutePaths.nftDetail);
Expand All @@ -33,6 +38,7 @@ export const Nfts = withNftsFoldersContext((): React.ReactElement => {
const { walletInfo, inMemoryWallet } = useWalletStore();
const { t } = useTranslation();
const assetsInfo = useAssetInfo();
const { isSearching, handleSearch, filteredResults } = useNftSearch(assetsInfo);
const assetsBalance = useObservable(inMemoryWallet.balance.utxo.total$, DEFAULT_WALLET_BALANCE.utxo.total$);
const analytics = useAnalyticsContext();
const { fiatCurrency } = useCurrencyStore();
Expand All @@ -44,6 +50,10 @@ export const Nfts = withNftsFoldersContext((): React.ReactElement => {
utils: { deleteRecord }
} = useNftsFoldersContext();

const [searchValue, setSearchValue] = useState('');

const [hasRecordedAnalytics, setHasRecordedAnalytics] = useState(false);

const onSelectNft = useCallback(
(nft) => {
analytics.sendEventToPostHog(PostHogAction.NFTsImageClick);
Expand Down Expand Up @@ -121,6 +131,16 @@ export const Nfts = withNftsFoldersContext((): React.ReactElement => {
setSelectedFolderId(undefined);
}, []);

const handleNftSearch = (searchItems: NftItemProps[], value: string) => {
setSearchValue(value);
if (!hasRecordedAnalytics) {
analytics.sendEventToPostHog(PostHogAction.NFTsSearchType);
setHasRecordedAnalytics(true);
}

handleSearch(searchItems, value);
};

return (
<>
<ContentLayout
Expand Down Expand Up @@ -153,7 +173,24 @@ export const Nfts = withNftsFoldersContext((): React.ReactElement => {
<div className={styles.nfts}>
<div className={styles.content} data-testid="nft-list-container">
{items.length > 0 ? (
<NftList items={items} rows={2} />
<>
{items.length >= MIN_ASSET_COUNT_FOR_SEARCH && (
<SearchBox
placeholder={t('browserView.nfts.searchPlaceholder')}
onChange={(value) => handleNftSearch(nfts, value)}
data-testid="nft-search-input"
value={searchValue}
onClear={() => setSearchValue('')}
/>
)}
<Skeleton loading={isSearching}>
{searchValue !== '' && filteredResults.length > 0 && <NftList items={filteredResults} rows={2} />}
{searchValue !== '' && filteredResults.length === 0 && (
<ListEmptyState message={t('core.assetSelectorOverlay.noMatchingResult')} icon="sad-face" />
)}
{searchValue === '' && <NftList items={items} rows={2} />}
</Skeleton>
</>
) : (
<FundWalletBanner
title={t('browserView.nfts.fundWalletBanner.title')}
Expand Down

0 comments on commit 6755b9f

Please sign in to comment.