diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 9c71b23c..9218a3ac 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -8,13 +8,13 @@ jobs: strategy: fail-fast: false matrix: - shard: [1/6, 2/6, 3/6, 4/6, 5/6, 6/6] + tests-name: [TBDTC000001, TBDTC000003, TBDTC000005, TBDTC000008, TBDTC000010, TradeExample] defaults: run: working-directory: ./integration-test steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: 18 - name: Install Metamask 11.0.0 @@ -24,14 +24,15 @@ jobs: - name: Install Playwright Browsers run: npx playwright install --with-deps chromium - name: Run Playwright tests - run: npx playwright test --shard ${{ matrix.shard }} + run: npx playwright test tests/${{ matrix.tests-name}}.spec.ts env: BASE_URL: ${{ github.event.deployment_status.environment_url }} + TEST_NAME: ${{ matrix.tests-name}} - name: Upload blob report to GitHub Actions Artifacts if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: all-blob-reports + name: blob-report-${{ matrix.tests-name}} path: ./blob-report retention-days: 1 @@ -45,26 +46,27 @@ jobs: run: working-directory: ./integration-test steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: 18 - name: Install dependencies run: npm i - name: Download blob reports from GitHub Actions Artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: - name: all-blob-reports path: ./integration-test/all-blob-reports + pattern: blob-report-* + merge-multiple: true - name: Merge into HTML Report run: npx playwright merge-reports --reporter html ./all-blob-reports - name: Upload HTML report - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: Playwright-Report-${{ github.run_id}} + name: playwright-report-${{github.run_id}} path: ./playwright-report retention-days: 14 diff --git a/.gitignore b/.gitignore index 79d13019..b8b54196 100644 --- a/.gitignore +++ b/.gitignore @@ -98,7 +98,7 @@ package-lock.json # Playwright output /test-results/ -/playwright-report/ +/playwright-report* /playwright/.cache/ metamask-chrome-11.0.0 @@ -133,7 +133,3 @@ src/constants/walletconnect.js .DS_Store .vscode - -integration-test/metamask-chrome-11.0.0/ -playwright-report/ -test-results/ \ No newline at end of file diff --git a/integration-test/pages/LandingPage.ts b/integration-test/pages/LandingPage.ts index c17d2fa1..6670bc23 100644 --- a/integration-test/pages/LandingPage.ts +++ b/integration-test/pages/LandingPage.ts @@ -6,9 +6,8 @@ export class LandingPage { readonly getAnncmnt: Locator; constructor(page: Page) { - const okButton = {name: t('ANNOUNCEMENT_MODAL.OK_BUTTON')}; this.page = page; - this.getAnncmnt = page.getByRole('button', okButton); + this.getAnncmnt = page.locator('#AnnouncementModalOkButton'); } async goto() { diff --git a/integration-test/pages/LeaderboardPage.ts b/integration-test/pages/LeaderboardPage.ts index 4b9e3d9c..be82095c 100644 --- a/integration-test/pages/LeaderboardPage.ts +++ b/integration-test/pages/LeaderboardPage.ts @@ -6,9 +6,8 @@ export class LeaderboardPage { readonly getAnncmnt: Locator; constructor(page: Page) { - const okButton = {name: t('ANNOUNCEMENT_MODAL.OK_BUTTON')}; this.page = page; - this.getAnncmnt = page.getByRole('button', okButton); + this.getAnncmnt = page.locator('#AnnouncementModalOkButton'); } async goto() { diff --git a/integration-test/pages/MyAssetsPage.ts b/integration-test/pages/MyAssetsPage.ts index 7363c244..5b389c83 100644 --- a/integration-test/pages/MyAssetsPage.ts +++ b/integration-test/pages/MyAssetsPage.ts @@ -6,23 +6,18 @@ export class MyAssetsPage { readonly getAnncmnt: Locator; constructor(page: Page) { - const okButton = {name: t('ANNOUNCEMENT_MODAL.OK_BUTTON')}; this.page = page; - this.getAnncmnt = page.getByRole('button', okButton); + this.getAnncmnt = page.locator('#AnnouncementModalOkButton'); } // Info: (20231013 - Jacky) Use profile button to go to My Assets page async goto() { await this.page.goto('./'); - if (this.getAnncmnt) { + if ((await this.getAnncmnt.count()) > 0) { await this.getAnncmnt.click(); } - await this.page - .locator( - '#__next > div > div.w-full.text-center> nav > div > div > div> div.mr-5.inline-flex > div > button' - ) - .click(); - await this.page.locator('#userDropdown > ul > li:nth-child(1) > button > a').click(); + await this.page.locator('#UserAvatarButton').click(); + await this.page.locator('#UserMyAssets').click(); await expect.soft(this.page).toHaveTitle(/My Assets/); if (this.getAnncmnt) { await this.getAnncmnt.click(); @@ -31,48 +26,63 @@ export class MyAssetsPage { // Info: (20231013 - Jacky) Check balance higher than 20 async checkBalance() { - await this.page - .locator( - '#__next > div > div:nth-child(17) > main > div > div > div.pt-10 > div:nth-child(1) > div > div > div.flex.items-center.justify-center.space-x-2.text-center > button' - ) - .click(); + await this.page.locator('#ShowBalanceButton').click(); const assetsAvailable = await this.page .locator( - '#__next > div > div:nth-child(17) > main > div > div > div.pt-10 > div:nth-child(1) > div > div:nth-child(2) > div:nth-child(3) > div > span:nth-child(1)' + '#__next > div > div:nth-child(6) > main > div > div > div.pt-10 > div:nth-child(2) > div:nth-child(3) > span:nth-child(1)' ) .textContent(); - expect(Number((assetsAvailable as string).replace(',', '').trim())).toBeGreaterThan(20); + expect( + Number( + (assetsAvailable as string) + .substring(0, assetsAvailable.length - 4) + .replace(',', '') + .trim() + ) + ).toBeGreaterThan(20); } async checkTradeLog() { - const titleButton = {name: t('MY_ASSETS_PAGE.RECEIPT_SECTION_TRADING_TYPE_TITLE')}; - const depositButton = {name: t('MY_ASSETS_PAGE.RECEIPT_SECTION_TRADING_TYPE_DEPOSIT')}; - const openButton = {name: t('MY_ASSETS_PAGE.RECEIPT_SECTION_TRADING_TYPE_CFD_OPEN')}; - const updateButton = { - name: t('MY_ASSETS_PAGE.RECEIPT_SECTION_TRADING_TYPE_CFD_UPDATE'), - }; - const closeButton = {name: t('MY_ASSETS_PAGE.RECEIPT_SECTION_TRADING_TYPE_CFD_CLOSE')}; - await this.page.getByRole('button', titleButton).click(); await this.page .locator( - '#__next > div > div:nth-child(17) > main > div > div > div.pt-10 > div:nth-child(4) > div > div.flex.flex-col.items-center> div > div.relative.mt-2.hidden.w-160px> div > button:nth-child(2)' + '#__next > div > div:nth-child(6) > main > div > div > div.pt-10 > div.p-4 > div:nth-child(2) > div > div > div > div:nth-child(1) > div > div:nth-child(2) > div:nth-child(1) > button' + ) + .isVisible(); + + await this.page.locator('#TradingTypeMenuButton').click(); + await this.page.locator('#TypeDepositButton').click(); + await this.page + .locator( + '#__next > div > div:nth-child(6) > main > div > div > div.pt-10 > div.p-4 > div:nth-child(2) > div > div > div > div:nth-child(1)> div > div:nth-child(2) > div:nth-child(1) > button' ) .click(); - await expect.soft(this.page.getByRole('button', depositButton).last()).toBeVisible(); - await this.page.getByRole('button', depositButton).nth(2).click(); + await this.page.locator('#HistoryCloseButton').click(); + await expect + .soft( + this.page.locator( + '#__next > div > div:nth-child(6) > main > div > div > div.pt-10 > div.p-4 > div:nth-child(2) > div > div > div > div:nth-child(1) > div > div:nth-child(2) > div:nth-child(1) > button' + ) + ) + .toBeVisible(); + await this.page.locator('#TradingTypeMenuButton').click(); + await this.page.locator('#TypeOpenButton').click(); await this.page .locator( - '#__next > div > div:nth-child(17) > main > div > div > div.pt-10 > div:nth-child(4) > div > div.flex.flex-col.items-center> div > div.relative.mt-2.hidden.w-160px> div > button:nth-child(4)' + '#__next > div > div:nth-child(6) > main > div > div > div.pt-10 > div.p-4 > div:nth-child(2) > div > div > div > div:nth-child(1) > div > div:nth-child(2) > div:nth-child(1) > button' ) .click(); - await expect.soft(this.page.getByRole('button', openButton).last()).toBeVisible(); - await expect.soft(this.page.getByRole('button', updateButton).last()).toBeVisible(); - await this.page.getByRole('button', openButton).first().click(); + if (await this.page.locator('#UpdateFormCloseButton').isVisible()) { + await this.page.locator('#UpdateFormCloseButton').click(); + } else { + await this.page.locator('#HistoryModalCloseButton').click(); + } + await this.page.locator('#TradingTypeMenuButton').click(); + await this.page.locator('#TypeCloseButton').click(); await this.page .locator( - '#__next > div > div:nth-child(17) > main > div > div > div.pt-10 > div:nth-child(4) > div > div.flex.flex-col.items-center> div > div.relative.mt-2.hidden.w-160px> div > button:nth-child(5)' + '#__next > div > div:nth-child(6) > main > div > div > div.pt-10 > div.p-4 > div:nth-child(2) > div > div > div > div:nth-child(1) > div > div:nth-child(2) > div:nth-child(1) > button' ) .click(); - await expect.soft(this.page.getByRole('button', closeButton).last()).toBeVisible(); + await expect.soft(this.page.locator('#HistoryModalCloseButton')).toBeVisible(); } } diff --git a/integration-test/pages/TradePage.ts b/integration-test/pages/TradePage.ts index a92c460f..e63b9b23 100644 --- a/integration-test/pages/TradePage.ts +++ b/integration-test/pages/TradePage.ts @@ -7,11 +7,8 @@ export class TradePage { readonly context: BrowserContext; constructor(page: Page, context: BrowserContext) { - const ANNOUCEMENT_MODAL_OK_BUTTON = t('ANNOUNCEMENT_MODAL.OK_BUTTON'); this.page = page; - this.getAnncmnt = page.getByRole('button', { - name: ANNOUCEMENT_MODAL_OK_BUTTON, - }); + this.getAnncmnt = page.locator('#AnnouncementModalOkButton'); this.context = context; } @@ -45,9 +42,7 @@ export class TradePage { await newPage.goto('chrome-extension://' + extensionId + '/popup.html'); await newPage.getByTestId('signature-request-scroll-button').click(); await newPage.getByTestId('page-container-footer-next').click(); - await this.page - .locator('#__next > div > div:nth-child(11) > div > div > div.flex > button ') - .click(); + await this.page.locator('#UpdateFormCloseButton').click(); newPage.close(); } async openShortPosition(extensionId: string) { @@ -60,76 +55,55 @@ export class TradePage { await newPage.goto('chrome-extension://' + extensionId + '/popup.html'); await newPage.getByTestId('signature-request-scroll-button').click(); await newPage.getByTestId('page-container-footer-next').click(); - await this.page - .locator('#__next > div > div:nth-child(11) > div > div > div.flex > button > svg') - .click(); + await this.page.locator('#UpdateFormCloseButton').click(); newPage.close(); } // Info: (20231013 - Jacky) number="1" means the last position async updatePosition(extensionId: string, number = '1') { - const positionTab = {name: t('TRADE_PAGE.POSITION_TAB')}; - const updatePostion = {name: t('POSITION_MODAL.UPDATE_POSITION_TITLE')}; - const confirmButton = {name: t('POSITION_MODAL.CONFIRM_BUTTON')}; - await this.page.getByRole('button', positionTab).click(); + await this.page.waitForTimeout(10000); + await this.page.locator('#PositionTabButton').click(); await this.page .locator( - '#__next > div > main > div > div:nth-child(3) > div > div > div > div > div:nth-last-child(' + + '#__next > div > main > div > div:nth-child(2) > div:nth-child(2) > div > div > div > div > div:nth-last-child(' + number + ')' ) .click(); - await this.page - .locator( - '#__next > div > div:nth-child(11) > div > div > div.flex-col.items-center.text-xs > div.mt-3.flex-col.leading-relaxed.text-lightWhite > div.mb-2.h-50px > div.flex.items-center.justify-between > div:nth-child(3) > div > div' - ) - .click(); - await this.page - .locator( - '#__next > div > div:nth-child(11) > div > div > div.flex-col.items-center.text-xs > div.mt-3.flex-col.leading-relaxed.text-lightWhite > div.mb-5.h-70px > div:nth-child(3) > div > input' - ) - .check(); - if (this.page.locator('body > vercel-live-feedback')) { + const pagePromise = this.context.newPage(); + await this.page.locator('#UpdateFormTpToggle').click(); + await this.page.locator('#UpdateFormSlToggle').click(); + await this.page.locator('#UpdateFormGslCheckbox').check(); + if ((await this.page.locator('vercel-live-feedback').count()) > 0) { await this.page.$eval('vercel-live-feedback', el => el.remove()); } - await this.page.getByRole('button', updatePostion).click(); - await this.page.getByRole('button', confirmButton).click(); - const pagePromise = this.context.newPage(); + await this.page.locator('#UpdateFormButton').click(); + await this.page.locator('#UpdateSubmitButton').click(); const newPage = await pagePromise; await newPage.goto('chrome-extension://' + extensionId + '/popup.html'); await newPage.getByTestId('signature-request-scroll-button').click(); await newPage.getByTestId('page-container-footer-next').click(); - await this.page - .locator('#__next > div > div:nth-child(11) > div > div > div.flex > button > svg') - .click(); + await this.page.locator('#UpdateFormCloseButton').click(); newPage.close(); } // Info: (20231013 - Jacky) number="1" means the last position async closePosition(extensionId: string, number = '1') { - const POSITION_TAB = {name: t('TRADE_PAGE.POSITION_TAB')}; - const CLOSE_POSITION_TITLE = {name: t('POSITION_MODAL.CONFIRM_BUTTON')}; - await this.page.getByRole('button', POSITION_TAB).click(); + await this.page.locator('#PositionTabButton').click(); await this.page .locator( - '#__next > div > main > div > div.pointer-events-none.fixed.right-0.top-82px.z-10.flex.overflow-x-hidden.overflow-y-hidden.outline-none > div > div > div > div > div:nth-last-child(' + + '#__next > div > main > div > div:nth-child(2) > div:nth-child(2) > div > div > div > div > div:nth-last-child(' + number + - ') > div > div:nth-child(3) > div:nth-child(3)' + ') > div > div:nth-child(3) > div:nth-child(3) > div:nth-child(1)' ) .click(); - // if (this.page.locator('body > vercel-live-feedback')) { - // await this.page.$eval('vercel-live-feedback', el => el.remove()); - // } const pagePromise = this.context.newPage(); - await this.page.getByRole('button', CLOSE_POSITION_TITLE).click(); - // await this.page.waitForTimeout(2000); + await this.page.locator('#ClosePositionButton').click(); const newPage = await pagePromise; await newPage.goto('chrome-extension://' + extensionId + '/popup.html'); await newPage.getByTestId('signature-request-scroll-button').click(); await newPage.getByTestId('page-container-footer-next').click(); - await this.page - .locator('#__next > div > div:nth-child(11) > div > div > div.flex > button > svg') - .click(); + await this.page.locator('#HistoryModalCloseButton').click(); newPage.close(); } } diff --git a/integration-test/pages/WalletConnect.ts b/integration-test/pages/WalletConnect.ts index 6b4d2257..7d9e59cb 100644 --- a/integration-test/pages/WalletConnect.ts +++ b/integration-test/pages/WalletConnect.ts @@ -37,7 +37,7 @@ export class WalletConnect { '#app-content > div > div.mm-box.main-container-wrapper > div > div > div > ul > li:nth-child(3) > button' ) .click(); - await this.page.getByRole('button', {name: 'I agree'}).click(); + await this.page.getByTestId('metametrics-i-agree').click(); for (let i = 0; i < 12; i++) { await this.page.locator('#import-srp__srp-word-' + i).fill(metamask['srp-word'][i]); } @@ -45,25 +45,21 @@ export class WalletConnect { await this.page.getByTestId('create-password-new').fill(metamask['new-password']); await this.page.getByTestId('create-password-confirm').fill(metamask['new-password']); await this.page.getByTestId('create-password-terms').click(); - await this.page.getByRole('button', {name: 'Import My wallet'}).click(); - await this.page.getByRole('button', {name: 'Got it'}).click(); + await this.page.getByTestId('create-password-import').click(); + await this.page.getByTestId('onboarding-complete-done').click(); await this.page.getByTestId('pin-extension-next').click(); await this.page.getByTestId('pin-extension-done').click(); - await this.page.waitForTimeout(1500); await this.page.getByTestId('popover-close').click(); } async connectWallet() { - const okButton = {name: i18next.t('ANNOUNCEMENT_MODAL.OK_BUTTON')}; - const walletConnectButton = {name: i18next.t('NAV_BAR.WALLET_CONNECT')}; await this.page.goto('./'); - this.page.getByRole('button', okButton).click(); + await this.page.locator('#AnnouncementModalOkButton').click(); const pagePromise = this.context.newPage(); - await this.page.getByRole('button', walletConnectButton).click(); + await this.page.locator('#NavWalletButtonDesktop').click(); await this.page.waitForTimeout(2000); await this.page - .locator('div') - .filter({hasText: /^MetaMask$/}) - .nth(1) + .locator('#MetaMaskButton') + .click(); const newPage = await pagePromise; await newPage.goto('chrome-extension://' + this.extensionId + '/popup.html'); @@ -72,64 +68,41 @@ export class WalletConnect { await newPage.close(); } async sendRequest() { - const requestsButton = { - name: i18next.t('WALLET_PANEL.SEND_REQUESTS_BUTTON'), - }; - const doneButton = {name: i18next.t('WALLET_PANEL.DONE_BUTTON')}; const pagePromise = this.context.newPage(); - await this.page.getByRole('button', requestsButton).click(); + await this.page.locator('#SendRequestButton').click(); const newPage = await pagePromise; await newPage.goto('chrome-extension://' + this.extensionId + '/popup.html'); await newPage.getByTestId('signature-request-scroll-button').click(); await newPage.getByTestId('page-container-footer-next').click(); - await this.page.getByRole('button', doneButton).click(); + await this.page.locator('#HelloModalDone').click(); await newPage.close(); } async deposit() { - const maxButton = {name: i18next.t('D_W_MODAL.MAX')}; - const okButton = {name: i18next.t('ANNOUNCEMENT_MODAL.OK_BUTTON')}; - const viewOnButton = {name: i18next.t('POSITION_MODAL.VIEW_ON_BUTTON')}; + await this.page.locator('#TotalBalanceShowButton').click(); const navAvailable = await this.page .locator( - '#__next > div > div.w-full.text-center > nav > div > div > div.flex.items-center > div > div > div > div:nth-child(1) > div:nth-child(2)' + '#__next > div > div.fixed.inset-x-0.top-0.z-40.bg-black > nav > div > div > div.flex.items-center > div > div > div > div.flex.justify-between.w-full.space-x-3.flex-1 > div:nth-child(1) > p' ) .textContent(); const navAvailableNum = (navAvailable as string).substring( 0, (navAvailable as string).length - 4 ); - await this.page - .locator( - '#__next > div > div.w-full.text-center> nav > div > div > div> div.mr-5.inline-flex > div > button' - ) - .click(); - await this.page.locator('#userDropdown > ul > li:nth-child(2) > button').click(); - await this.page.getByRole('button', maxButton).click(); - await this.page - .locator( - '#depositModal > div.relative.flex-auto.pt-0 > div > div > div:nth-child(4) > div > button' - ) - .click(); - const hasDeposit = await this.page.getByRole('button', viewOnButton).isVisible(); - if (hasDeposit) { + await this.page.locator('#UserAvatarButton').click(); + await this.page.locator('#UserDeposit').click(); + await this.page.locator('#DepositMaxButton').click(); + await this.page.locator('#DepositButton').click(); + // Info: (20240226 - Jacky) wait for the depositModal element shows up + await this.page.waitForTimeout(3000); + if ((await this.page.locator('#SuccessfulModalCloseButton').count()) > 0) { this.page.reload(); - this.page.getByRole('button', okButton).click(); - // profile button - await this.page - .locator( - '#__next > div > div.w-full.text-center> nav > div > div > div> div.mr-5.inline-flex > div > button' - ) - .click(); - await this.page.locator('#userDropdown > ul > li:nth-child(1) > button > a').click(); - await this.page.getByRole('button', okButton).click(); - await this.page - .locator( - '#__next > div > div:nth-child(17) > main > div > div > div.pt-10 > div:nth-child(1) > div > div > div.flex.items-center.justify-center.space-x-2.text-center > button' - ) - .click(); + await this.page.locator('#AnnouncementModalOkButton').click(); + await this.page.locator('#UserAvatarButton').click(); + await this.page.locator('#UserMyAssets').click(); + await this.page.locator('#AnnouncementModalOkButton').click(); const assetsAvailable = await this.page .locator( - '#__next > div > div:nth-child(17) > main > div > div > div.pt-10 > div:nth-child(1) > div > div:nth-child(2) > div:nth-child(3) > div > span:nth-child(1)' + '#__next > div > div:nth-child(6) > main > div > div > div.pt-10 > div:nth-child(2) > div:nth-child(3) > span:nth-child(1)' ) .textContent(); let expectedNavAvailable = Number(assetsAvailable); diff --git a/integration-test/playwright.config.ts b/integration-test/playwright.config.ts index d7f94e1c..cf3bbd1d 100644 --- a/integration-test/playwright.config.ts +++ b/integration-test/playwright.config.ts @@ -15,15 +15,14 @@ export default defineConfig({ /* Retry on CI only */ retries: process.env.CI ? 1 : 0, /* Opt out of parallel tests on CI. */ - workers: process.env.CI ? 2 : undefined, + workers: process.env.CI ? 3 : undefined, // Limit the number of failures on CI to save resources - maxFailures: process.env.CI ? 30 : undefined, + maxFailures: process.env.CI ? 25 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: process.env.CI ? 'blob' : 'html', + reporter: process.env.CI ? [['blob', {fileName: `report-${process.env.TEST_NAME}.zip`}]] : 'html', /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { - /* Base URL to use in actions like `await page.goto('/')`. */ - // baseURL: 'http://127.0.0.1:3000', + timezoneId: 'Asia/Taipei', /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: 'on-first-retry', @@ -36,7 +35,7 @@ export default defineConfig({ use: { locale: 'en', ...devices['Desktop Chrome'], - baseURL: baseURL, + baseURL: baseURL + '/en/', }, }, { @@ -44,7 +43,7 @@ export default defineConfig({ use: { locale: 'tw', ...devices['Desktop Chrome'], - baseURL: baseURL + '/tw/', + baseURL: baseURL, }, }, { diff --git a/integration-test/tests/TBDTC000001.spec.ts b/integration-test/tests/TBDTC000001.spec.ts index 1d100b06..ab27fa57 100644 --- a/integration-test/tests/TBDTC000001.spec.ts +++ b/integration-test/tests/TBDTC000001.spec.ts @@ -23,23 +23,23 @@ test('1. 進入 TideBit-DeFi 首頁,確認網站為英文後,將錢包連接 await landingPage.clickAnncmnt(); const navAvailable = await page .locator( - '#__next > div > div.w-full.text-center > nav > div > div > div.flex.items-center > div > div > div > div:nth-child(1) > div:nth-child(2)' + '#__next > div > div.fixed.inset-x-0.top-0.z-40.bg-black > nav > div > div > div.flex.items-center > div > div > div > div.flex.justify-between.w-full.space-x-3.flex-1 > div:nth-child(1) > p' ) .textContent(); - const navAvailableNum = Number(navAvailable.substring(0, navAvailable.length - 4)); + const navAvailableNum = (navAvailable as string).substring( + 0, + (navAvailable as string).length - 4 + ); // Info: (20231013 - Jacky) make sure navAvailable is bigger than 100 - if (navAvailableNum < 100) { + if (Number(navAvailableNum) < 100) { walletConnect.deposit(); } }); -// Todo: (20231013 - Jacky) This test should be fixed after the favorite cookie test('2. 進入「交易」頁面,點擊左上方ETH後,點擊ETH上的星星移除我的最愛,點擊我的最愛查看後重新添加,再點擊BTC。', async ({ page, context, }) => { - const favoriteTabButton = {name: i18next.t('TRADE_PAGE.TICKER_SELECTOR_TAB_FAVORITE')}; - const allTabButton = {name: i18next.t('TRADE_PAGE.TICKER_SELECTOR_TAB_ALL')}; const walletConnect = new WalletConnect(page, context); await walletConnect.getMetamaskId(); await walletConnect.connectMetamask(); @@ -48,42 +48,25 @@ test('2. 進入「交易」頁面,點擊左上方ETH後,點擊ETH上的星 const tradePage = new TradePage(page, context); await tradePage.goto(); await tradePage.clickAnncmnt(); - await page.getByRole('button', {name: 'ETH'}).click(); - await page - .locator( - '#tickerSelectorModal > div:nth-child(2) > div:nth-child(2) > div > div > div > div > div:nth-child(3) > div > div > div:nth-child(3) > button' - ) - .click(); - await page.getByRole('button', favoriteTabButton).click(); - await expect - .soft( - page.locator( - '#tickerSelectorModal > div:nth-child(2) > div.flex.flex-auto.flex-col.items-center.pt-10 > div > div > div > div > div:nth-child(3) > div > div.flex.items-center > div.ml-3.items-center > p.text-lg.leading-6.text-lightWhite' - ) - ) - .toBeHidden(); - await page.getByRole('button', allTabButton).click(); - await page - .locator( - '#tickerSelectorModal > div:nth-child(2) > div:nth-child(2) > div > div > div > div > div:nth-child(3) > div > div > div:nth-child(3) > button' - ) - .click(); - await page - .locator( - '#tickerSelectorModal > div:nth-child(2) > div:nth-child(2) > div > div > div > div > div:nth-child(3)' - ) - .click(); + await page.locator('#TickerSelectorDesktop').click(); + await page.locator('#FavoriteTab').click(); + await page.locator('#StarETH').click(); + await page.locator('#AllTab').click(); + await page.locator('#FavoriteTab').click(); + await expect.soft(page.locator('#CryptoCardETH')).toBeHidden(); + await page.locator('#CryptoCardBTC').click(); await expect(page).toHaveURL(/.*btc-usdt/); }); test('3. 至ETH交易頁面,下滑點擊白皮書與官方網站。', async ({page, context}) => { - const whitePaper = {name: i18next.t('TRADE_PAGE.CRYPTO_SUMMARY_WHITE_PAPER')}; - const website = {name: i18next.t('TRADE_PAGE.CRYPTO_SUMMARY_WEBSITE')}; + // Bug: (20240227 - Jacky) This URL should be fixed after the hidden chart issue is fixed. const tradePage = new TradePage(page, context); - await tradePage.goto(); - await expect.soft(page.getByRole('link', whitePaper)).toHaveAttribute('href', /.*whitepaper/); + // await tradePage.goto(); + await page.goto('https://tidebit-defi.com/en/trade/cfd/eth-usdt'); + await tradePage.clickAnncmnt(); + await expect.soft(page.locator('#CryptoWhitePaperLink')).toHaveAttribute('href', /.*whitepaper/); await expect - .soft(page.getByRole('link', website)) + .soft(page.locator('#CryptoWebsiteLink')) .toHaveAttribute('href', /https:\/\/ethereum.org/); }); @@ -97,7 +80,7 @@ test('4. 點擊任一篇ETH新聞後,下滑至最下面點擊分享至FB', asy await expect.soft(page).toHaveURL(/.*\/news\/.*/); await tradePage.clickAnncmnt(); const pagePromise = context.waitForEvent('page'); - await page.getByRole('img', {name: 'FACEBOOK', exact: true}).click(); + await page.locator('#ShareNewsToFACEBOOK').click(); const newPage = await pagePromise; await expect.soft(newPage).toHaveTitle(/Facebook/); }); @@ -118,25 +101,37 @@ test('5. 回到「交易」頁面後,在「看漲」和「看跌」各開一 await tradePage.openLongPosition(walletConnect.extensionId); await tradePage.inputAmount(); await tradePage.openShortPosition(walletConnect.extensionId); - // Todo (20231013 - Jacky) This test should be finished after the efficiency improvement of CFD trade - // await page.getByRole('button', {name: i18next.t('TRADE_PAGE.POSITION_TAB') as string}).click(); - // await expect - // .soft( - // page.locator( - // '#__next > div > main > div > div.pointer-events-none.fixed.right-0.top-82px.z-10.flex.overflow-x-hidden.overflow-y-hidden.outline-none > div > div > div > div > div:nth-child(1) > div.relative.my-2.min-h-140px > div.mt-2.flex.justify-between > div.inline-flex.items-center.text-sm > div' - // ) - // ) - // .toContainText('Up'); - // await expect - // .soft( - // page.locator( - // '#__next > div > main > div > div.pointer-events-none.fixed.right-0.top-82px.z-10.flex.overflow-x-hidden.overflow-y-hidden.outline-none > div > div > div > div > div:nth-child(1) > div.relative.my-2.min-h-140px > div.mt-2.flex.justify-between > div.inline-flex.items-center.text-sm > div' - // ) - // ) - // .toContainText('Down'); + await page.locator('#PositionTabButton').click(); + await page + .locator( + '#__next > div > main > div > div:nth-child(2) > div:nth-child(2) > div > div > div > div > div:nth-last-child(1) ' + ) + .click(); + await page.locator('#UpdateFormCloseButton').click(); + const lastPositionMinuteText = await page + .locator( + '#__next > div > main > div > div:nth-child(2) > div:nth-child(2) > div > div > div > div > div:nth-last-child(2) > div:nth-child(1) > div:nth-child(2) > div:nth-child(2) > p:nth-child(2)' + ) + .textContent(); + const NextTolastPositionMinuteText = await page + .locator( + '#__next > div > main > div > div:nth-child(2) > div:nth-child(2) > div > div > div > div > div:nth-last-child(1) > div:nth-child(1) > div:nth-child(2) > div:nth-child(2) > p:nth-child(2)' + ) + .textContent(); + const lastPositionMinute = Number(lastPositionMinuteText.substring(3, 5)); + const NextTolastPositionMinute = Number(NextTolastPositionMinuteText.substring(3, 5)); + if (new Date().getUTCMinutes() > 0) { + expect(new Date().getUTCMinutes() - lastPositionMinute).toBeGreaterThanOrEqual(0); + expect(new Date().getUTCMinutes() - lastPositionMinute).toBeLessThanOrEqual(2); + expect(new Date().getUTCMinutes() - NextTolastPositionMinute).toBeGreaterThanOrEqual(0); + expect(new Date().getUTCMinutes() - NextTolastPositionMinute).toBeLessThanOrEqual(2); + } else { + expect(new Date().getUTCMinutes() - lastPositionMinute).toBeLessThanOrEqual(0); + expect(new Date().getUTCMinutes() - NextTolastPositionMinute).toBeLessThanOrEqual(0); + } }); -// Info (20231013 - Jacky) This test should pass after the efficiency improvement of CFD trade +// Info (20231013 - Jacky) This test still fails by invalid ethereum address for no reason test('6. 點擊其中一個持倉,設定止盈點與止損點後,點擊更新持倉。', async ({page, context}) => { const walletConnect = new WalletConnect(page, context); await walletConnect.getMetamaskId(); @@ -154,7 +149,6 @@ test('7. 點擊倒數計時的圈圈,將持倉關閉,並查看「歷史紀 page, context, }) => { - const HistoryTabButton = {name: i18next.t('TRADE_PAGE.POSITION_TAB_HISTORY')}; const walletConnect = new WalletConnect(page, context); await walletConnect.getMetamaskId(); await walletConnect.connectMetamask(); @@ -164,14 +158,13 @@ test('7. 點擊倒數計時的圈圈,將持倉關閉,並查看「歷史紀 await tradePage.goto(); await tradePage.clickAnncmnt(); await tradePage.closePosition(walletConnect.extensionId); - await tradePage.closePosition(walletConnect.extensionId); - await page.getByRole('button', HistoryTabButton).click(); - const minutetext = await page + await page.locator('#HistoryTabButton').click(); + const minuteText = await page .locator( - '#__next > div > main > div > div.pointer-events-none.fixed.right-0.top-82px.z-10.flex.overflow-x-hidden.overflow-y-hidden.outline-none > div > div > div > div > div:nth-child(1) > div.mt-3.text-xs > div > div.w-48px > div:nth-child(2)' + '#__next > div > main > div > div:nth-child(2) > div:nth-child(2) > div > div > div > div > div:nth-child(1) > div:nth-child(1) > div > div.w-48px > div:nth-child(2)' ) .textContent(); - const minute = Number(minutetext.substring(3)); + const minute = Number(minuteText.substring(3)); if (new Date().getUTCMinutes() > 0) { expect(new Date().getUTCMinutes() - minute).toBeGreaterThanOrEqual(0); expect(new Date().getUTCMinutes() - minute).toBeLessThanOrEqual(2); diff --git a/integration-test/tests/TBDTC000003.spec.ts b/integration-test/tests/TBDTC000003.spec.ts index ebc4c842..a8579de3 100644 --- a/integration-test/tests/TBDTC000003.spec.ts +++ b/integration-test/tests/TBDTC000003.spec.ts @@ -8,139 +8,90 @@ test.beforeEach(async ({page}) => { }); test('1. 進入 TideBit-DeFi 首頁,檢查登入狀態為未登入,切換語言為英文', async ({page}) => { - const walletConnectButton = {name: i18next.t('NAV_BAR.WALLET_CONNECT')}; - const walletConnect = i18next.t('NAV_BAR.WALLET_CONNECT'); const landingPage = new LandingPage(page); await landingPage.goto(); - await expect.soft(page.getByRole('button', walletConnectButton)).toHaveText(walletConnect); + await expect.soft(page.locator('#NavWalletButtonDesktop')).toBeVisible(); }); test('2. 點擊導覽列的上全部按鈕', async ({page}) => { - const tradeLink = {name: i18next.t('NAV_BAR.TRADE')}; - const leaderboardLink = {name: i18next.t('NAV_BAR.LEADERBOARD')}; - const supportLink = {name: i18next.t('NAV_BAR.SUPPORT')}; const landingPage = new LandingPage(page); landingPage.goto(); landingPage.clickAnncmnt(); - await page - // Info (20231013 - Jacky) This test could be failed if the site version is changed - .getByRole('link', {name: 'TideBit_logo beta v0.8.0'}) - .click(); + await page.locator('#NavLogoDesktop').click(); await expect.soft(page).toHaveTitle(/TideBit DeFi/); - await page.getByRole('link', tradeLink).first().click(); + await page.locator('#NavTradeDesktop').click(); await expect.soft(page).toHaveURL(/.*trade/); landingPage.clickAnncmnt(); - await page.getByRole('link', leaderboardLink).click(); + await page.locator('#NavLeaderboardDesktop').click(); + await expect.soft(page).toHaveURL(/.*leaderboard/); landingPage.clickAnncmnt(); - await page.getByRole('link', supportLink).click(); + await page.locator('#NavSupportDesktop').click(); landingPage.clickAnncmnt(); await page.locator('#globe').click(); - await page.getByRole('link', {name: '繁體中文'}).click(); - await expect.soft(page).toHaveURL(/.*tw/); + await page.locator('#ENButtonDesktop').click(); + await expect.soft(page).toHaveURL(/.*en/); await page.locator('#globe').click(); - await page.getByRole('link', {name: '简体中文'}).click(); + await page.locator('#CNButtonDesktop').click(); await expect.soft(page).toHaveURL(/.*cn/); await page.locator('#globe').click(); - await page.getByRole('link', {name: 'English'}).click(); + await page.locator('#TWButtonDesktop').click(); await expect.soft(page).toHaveTitle(/TideBit DeFi/); - await page.getByRole('button', {name: '2 notification icon'}).click(); - await page.locator('.translate-x-0 > div > div').first().click(); + await page.locator('#NavBellDesktop').click(); + await page.getByRole('heading', {name: 'Happy Birthday to TideBit'}).first().click(); await expect - .soft(page.getByRole('heading', {name: 'Happy Birthday to TideBit'})) + .soft(page.getByRole('heading', {name: 'Happy Birthday to TideBit'}).first()) .toHaveText('Happy Birthday to TideBit'); }); test('3. 點擊首圖上的開始和信箱聯絡按鈕、白皮書和 AI 報告按鈕下載', async ({page}) => { - const ctaButton = {name: i18next.t('HOME_PAGE.CTA_BUTTON')}; - const whitePaperButton = {name: i18next.t('HOME_PAGE.WHITEPAPER')}; const whitePaperLink = i18next.t('HOME_PAGE.WHITEPAPER_LINK'); - const downloadReportButton = {name: i18next.t('HOME_PAGE.DOWNLOAD_REPORT')}; - const comprehensiveIncomeStatementButton = { - name: i18next.t('HOME_PAGE.COMPREHENSIVE_INCOME_STATEMENT'), - }; - const balanceSheetButton = {name: i18next.t('HOME_PAGE.BALANCE_SHEET')}; - const cashFlowStatementButton = {name: i18next.t('HOME_PAGE.CASH_FLOW_STATEMENT')}; - const redFlagAnalysisButton = {name: i18next.t('HOME_PAGE.RED_FLAG_ANALYSIS')}; - const redFlagAnalysis = i18next.t('HOME_PAGE.RED_FLAG_ANALYSIS_LINK'); const landingPage = new LandingPage(page); landingPage.goto(); landingPage.clickAnncmnt(); await expect - .soft(page.getByRole('link', {name: 'contact@tidebit-defi.com'})) + .soft(page.locator('#ContactEmailButton')) .toHaveAttribute('href', 'mailto:contact@tidebit-defi.com'); - await page.getByRole('button', ctaButton).click(); + await page.locator('#StartTradingButton').click(); await expect.soft(page).toHaveURL(/.*trade/); landingPage.goto(); + await expect.soft(page.locator('#WhitepaperLink')).toHaveAttribute('href', whitePaperLink); + await expect.soft(page.locator('#DownloadReportButton')).toHaveAttribute('href', /.*balance/); await expect - .soft(page.getByRole('link', whitePaperButton)) - .toHaveAttribute('href', whitePaperLink); - await expect - .soft(page.getByRole('link', downloadReportButton)) - .toHaveAttribute('href', /.*balance/); - await expect - .soft(page.getByRole('link', comprehensiveIncomeStatementButton)) + .soft(page.locator('#IncomeStatementDownload')) .toHaveAttribute('href', /.*comprehensive-income/); + await expect.soft(page.locator('#BalanceSheetDownload')).toHaveAttribute('href', /.*balance/); await expect - .soft(page.getByRole('link', balanceSheetButton)) - .toHaveAttribute('href', /.*balance/); - await expect - .soft(page.getByRole('link', cashFlowStatementButton)) + .soft(page.locator('#CashFlowStatementDownload')) .toHaveAttribute('href', /.*cash-flow/); - await expect - .soft(page.getByRole('link', redFlagAnalysisButton)) - .toHaveAttribute('href', redFlagAnalysis); + await expect.soft(page.locator('#RedFlagAnalysisDownload')).toHaveAttribute('href', /.*baifa.io/); }); test('4. 確認按鈕連結跳轉網頁正確。', async ({page}) => { - const reserveRatioBlockCard = {name: i18next.t('HOME_PAGE.RESERVE_RATIO_BLOCK_CARD_2')}; - const iSunOne = {name: i18next.t('HOME_PAGE.ISUNONE_PROMOTION_DESCRIPTION')}; - const trade = {name: i18next.t('NAV_BAR.TRADE')}; - const tidebitUniversity = {name: i18next.t('NAV_BAR.TIDEBIT_UNIVERSITY')}; - const helpCenter = {name: i18next.t('NAV_BAR.HELP_CENTER')}; - const hiring = {name: i18next.t('FOOTER.HIRING')}; - const privacyPolicy = {name: i18next.t('FOOTER.PRIVACY_POLICY')}; const landingPage = new LandingPage(page); landingPage.goto(); landingPage.clickAnncmnt(); + await expect.soft(page.locator('#USDTReserveRatioLink')).toHaveAttribute('href', /.*baifa.io/); + await expect.soft(page.locator('#PoweredByLink')).toHaveAttribute('href', /.*baifa.io/); await expect - .soft(page.getByRole('link', reserveRatioBlockCard).nth(0)) - .toHaveAttribute('href', /.*baifa.io/); - await expect.soft(page.getByRole('link', {name: 'BAIFA'})).toHaveAttribute('href', /.*baifa.io/); - await expect - .soft(page.getByRole('link', {name: 'Ethereum ETH'})) + .soft(page.locator('#CryptoCategory > div > div:nth-child(2) > div > div:nth-child(1) > a')) .toHaveAttribute('href', /.*trade\/cfd\/eth-usdt/); await expect - .soft(page.getByRole('link', {name: 'Bitcoin BTC'})) + .soft(page.locator('#CryptoCategory > div > div:nth-child(2) > div > div:nth-child(2) > a')) .toHaveAttribute('href', /.*trade\/cfd\/btc-usdt/); - await expect - .soft(page.getByRole('link', iSunOne)) - .toHaveAttribute('href', /https:\/\/www.isun1.com*/); - await expect - .soft(page.getByRole('link', {name: 'app-store'})) - .toHaveAttribute('href', /.*coming-soon/); - await expect - .soft(page.getByRole('link', {name: 'google play'})) + await expect.soft(page.locator('#AppStoreLink')).toHaveAttribute('href', /.*coming-soon/); + await expect.soft(page.locator('#GooglePlayLink')).toHaveAttribute('href', /.*coming-soon/); + await expect.soft(page.locator('#FooterFacebookLink')).toHaveAttribute('href', /.*coming-soon/); + await expect.soft(page.locator('#FooterInstagramLink')).toHaveAttribute('href', /.*coming-soon/); + await expect.soft(page.locator('#FooterTwitterLink')).toHaveAttribute('href', /.*coming-soon/); + await expect.soft(page.locator('#FooterRedditLink')).toHaveAttribute('href', /.*coming-soon/); + await expect.soft(page.locator('#FooterTradeLink')).toHaveAttribute('href', /.*trade/); + await expect.soft(page.locator('#FooterUniversityLink')).toHaveAttribute('href', /.*coming-soon/); + await expect.soft(page.locator('#FooterHelpCenterLink')).toHaveAttribute('href', /.*coming-soon/); + await expect.soft(page.locator('#FooterHiringLink')).toHaveAttribute('href', /.*coming-soon/); + await expect + .soft(page.locator('#FooterServicePolicyLink')) .toHaveAttribute('href', /.*coming-soon/); await expect - .soft(page.getByRole('link', {name: 'Facebook'})) - .toHaveAttribute('href', /.*coming-soon/); - await expect - .soft(page.getByRole('link', {name: 'instagram'})) - .toHaveAttribute('href', /.*coming-soon/); - await expect - .soft(page.getByRole('link', {name: 'twitter'})) - .toHaveAttribute('href', /.*coming-soon/); - await expect - .soft(page.getByRole('link', {name: 'reddit'})) - .toHaveAttribute('href', /.*coming-soon/); - await expect - .soft(page.getByRole('contentinfo').getByRole('link', trade)) - .toHaveAttribute('href', /.*trade/); - await expect - .soft(page.getByRole('link', tidebitUniversity)) + .soft(page.locator('#FooterPrivacyPolicyLink')) .toHaveAttribute('href', /.*coming-soon/); - await expect.soft(page.getByRole('link', helpCenter)).toHaveAttribute('href', /.*coming-soon/); - await expect.soft(page.getByRole('link', hiring)).toHaveAttribute('href', /.*coming-soon/); - await expect.soft(page.getByRole('link', hiring)).toHaveAttribute('href', /.*coming-soon/); - await expect.soft(page.getByRole('link', privacyPolicy)).toHaveAttribute('href', /.*coming-soon/); }); diff --git a/integration-test/tests/TBDTC000005.spec.ts b/integration-test/tests/TBDTC000005.spec.ts index 584af704..fb11fafc 100644 --- a/integration-test/tests/TBDTC000005.spec.ts +++ b/integration-test/tests/TBDTC000005.spec.ts @@ -9,11 +9,10 @@ test.beforeEach(async ({page}) => { }); test('1. 進入 TideBit-DeFi 首頁,確定語言為英文,點擊錢包連接', async ({page}) => { - const walletConnectButton = {name: i18next.t('NAV_BAR.WALLET_CONNECT')}; const landingPage = new LandingPage(page); await landingPage.goto(); await landingPage.clickAnncmnt(); - await page.getByRole('button', walletConnectButton).click(); + await page.locator('#NavWalletButtonDesktop').click(); await expect(page.getByRole('img', {name: 'MetaMask'})).toHaveAttribute('alt', 'MetaMask'); }); @@ -21,8 +20,6 @@ test('2. 至metamask切換到ETH以外的鏈上後,發送確認身份與API授 page, context, }) => { - const walletConnectButton = {name: i18next.t('NAV_BAR.WALLET_CONNECT')}; - const sendRequestButton = {name: i18next.t('WALLET_PANEL.SEND_REQUESTS_BUTTON')}; const walletConnect = new WalletConnect(page, context); const errorMessage = i18next.t('WALLET_PANEL.DISABLE_SERVICE_TERM_ERROR_MESSAGE'); await walletConnect.getMetamaskId(); @@ -31,12 +28,17 @@ test('2. 至metamask切換到ETH以外的鏈上後,發送確認身份與API授 const landingPage = new LandingPage(page); await landingPage.goto(); await landingPage.clickAnncmnt(); - await page.getByRole('button', walletConnectButton).click(); + await page.locator('#NavWalletButtonDesktop').click(); await expect(page.getByRole('img', {name: 'MetaMask'})).toHaveAttribute('alt', 'MetaMask'); - await page.getByRole('img', {name: 'MetaMask'}).click(); + await page.locator('#MetaMaskButton').click(); const pagePromise1 = context.newPage(); const newPage1 = await pagePromise1; await newPage1.goto('chrome-extension://' + walletConnect.extensionId + '/home.html'); + // Info (20240229 - Jacky) This loop only needed in CI, not in local + await newPage1.getByTestId('network-display').isVisible(); + while ((await newPage1.getByTestId('popover-close').count()) > 0) { + await newPage1.getByTestId('popover-close').click(); + } await newPage1.getByTestId('network-display').click(); await newPage1 .locator( @@ -44,10 +46,10 @@ test('2. 至metamask切換到ETH以外的鏈上後,發送確認身份與API授 ) .click(); await newPage1.getByRole('button', {name: 'GOT IT'}).click(); - await page.getByRole('button', sendRequestButton).click(); + await page.locator('#SendRequestButton').click(); await expect( page.locator( - '#connectModal > div.flex.flex-auto.flex-col.items-center.py-5 > div > div > div.space-y-12.flex.flex-col.px-4.pt-16 > div:nth-child(2) > div.-mb-5.mt-7.w-271px.space-y-1.text-lightWhite > div.text-sm.text-lightRed3' + '#SignatureProcessModal > div.flex.flex-col.items-center.text-lg.leading-relaxed.text-lightWhite > div.space-y-12.flex.flex-col.pt-16.pb-4.items-start > div:nth-child(2) > div.space-y-1.text-lightWhite > div.text-sm.text-lightRed3' ) ).toContainText(errorMessage); }); diff --git a/integration-test/tests/TBDTC000008.spec.ts b/integration-test/tests/TBDTC000008.spec.ts index ef936f00..c7e44e3d 100644 --- a/integration-test/tests/TBDTC000008.spec.ts +++ b/integration-test/tests/TBDTC000008.spec.ts @@ -23,8 +23,6 @@ test('2. 點擊右上角profile的icon,再點擊我的資產,點擊總餘額 page, context, }) => { - const maxButton = {name: i18next.t('D_W_MODAL.MAX')}; - const max = i18next.t('D_W_MODAL.MAX'); const walletConnect = new WalletConnect(page, context); await walletConnect.getMetamaskId(); await walletConnect.connectMetamask(); @@ -32,26 +30,20 @@ test('2. 點擊右上角profile的icon,再點擊我的資產,點擊總餘額 await walletConnect.sendRequest(); const myAssetsPage = new MyAssetsPage(page); await myAssetsPage.goto(); - await myAssetsPage.checkBalance(); + await page.locator('#ShowBalanceButton').click(); const headerPNL = await page .locator( - '#__next > div > div:nth-child(17) > div.w-full.text-center > nav > div > div > div.flex.items-center > div > div > div > div:nth-child(3) > div.whitespace-nowrap.text-sm > span' + '#__next > div > div:nth-child(6) > div.fixed.inset-x-0.top-0.z-40.bg-black > nav > div > div > div.flex.items-center > div > div > div > div.flex.justify-between.w-full.space-x-3.flex-1 > div:nth-child(1) > p' ) .textContent(); const myAssetsPNL = await page .locator( - '#__next > div > div:nth-child(17) > main > div > div > div.pt-10 > div:nth-child(2) > section > div.mx-auto > div > div:nth-child(3) > div > h2' + '#__next > div > div:nth-child(6) > main > div > div > div.pt-10 > div:nth-child(2) > div:nth-child(3) > span:nth-child(1)' ) .textContent(); - await expect - .soft(myAssetsPNL.replace(',', '')) - .toContain(headerPNL.replace(',', '').replace(/ /g, '')); - await page - .locator( - '#__next > div > div:nth-child(17) > main > div > div > div.pt-10 > div:nth-child(1) > div > div:nth-child(3) > div:nth-child(1) > button' - ) - .click(); - await expect(page.getByRole('button', maxButton)).toContainText(max); + expect.soft(headerPNL as string).toContain(myAssetsPNL as string); + await page.locator('#MyAssetsDeposit').click(); + await expect(page.locator('#DepositMaxButton')).toBeVisible(); }); test('3. 若缺乏從入金 ➡️ 建倉 ➡️ 更新持倉 ➡️ 關倉 ➡️ 出金的完整交易紀錄,則先完成上述流程,否則跳到下一步。', async ({ @@ -78,22 +70,12 @@ test('4. 查看現有交易紀錄與日期區間', async ({page, context}) => { const myAssetsPage = new MyAssetsPage(page); await myAssetsPage.goto(); const todayDate = new Date().getUTCDate(); - await page.waitForTimeout(15000); - await expect - .soft( - page.locator( - '#__next > div > div:nth-child(17) > main > div > div > div.pt-10 > div:nth-child(4) > div > div:nth-child(2) > div > div > div > div:nth-child(1)' - ) + const logDate = await page + .locator( + '#__next > div > div:nth-child(6) > main > div > div > div.pt-10 > div.p-4 > div:nth-child(2) > div > div > div > div:nth-child(1) > div > div.w-70px > div > p' ) - .toContainText(String(todayDate)); - // Todo (20231013 - Jacky) This expect should be finished after existing a button show all logs. - // await expect - // .soft( - // page.locator( - // '#__next > div > div:nth-child(17) > main > div > div > div.pt-10 > div:nth-child(4) > div > div:nth-child(2) > div > div > div > div:nth-last-child(1)' - // ) - // ) - // .toContainText(String(todayDate - 7)); + .textContent(); + expect.soft(logDate).toContain(String(todayDate)); }); test('5. 設定日期區間篩選交易紀錄', async ({page, context}) => { @@ -105,36 +87,25 @@ test('5. 設定日期區間篩選交易紀錄', async ({page, context}) => { const myAssetsPage = new MyAssetsPage(page); await myAssetsPage.goto(); const todayDate = new Date().getUTCDate(); - await page - .locator( - '#__next > div > div:nth-child(17) > main > div > div > div.pt-10 > div:nth-child(4) > div > div.flex.flex-col.items-center > div > div.mt-2.hidden.items-center.space-x-2 > div:nth-child(1) > button' - ) - .click(); - await page - .locator( - '#__next > div > div:nth-child(17) > main > div > div > div.pt-10 > div:nth-child(4) > div > div.flex.flex-col.items-center> div > div.mt-2.hidden.items-center.space-x-2 > div.relative.flex.h-48px.flex-col.items-start.justify-center.transition-all.duration-200.ease-in-out.bg-darkGray8 > div > div:nth-child(3)' - ) - .getByText('01') - .click(); + await page.locator('#DateStartPicker').click(); + await page.locator('#DateStartPicker01').click(); const firstLogDate = await page .locator( - '#__next > div > div:nth-child(17) > main > div > div > div.pt-10 > div:nth-child(4) > div > div:nth-child(2) > div > div > div > div:nth-child(1)' + '#__next > div > div:nth-child(6) > main > div > div > div.pt-10 > div.p-4 > div:nth-child(2) > div > div > div > div:nth-last-child(1) > div > div.w-70px > div > p' ) .textContent(); - const lastLogdate = await page + const lastLogDate = await page .locator( - '#__next > div > div:nth-child(17) > main > div > div > div.pt-10 > div:nth-child(4) > div > div:nth-child(2) > div > div > div > div:nth-last-child(1)' + '#__next > div > div:nth-child(6) > main > div > div > div.pt-10 > div.p-4 > div:nth-child(2) > div > div > div > div:nth-child(1) > div > div.w-70px > div > p' ) .textContent(); - expect(Number(firstLogDate.substring(0, 2))).toBeGreaterThanOrEqual(Number(todayDate)); - expect(Number(lastLogdate.substring(0, 2))).toBeGreaterThanOrEqual(1); + expect(Number(lastLogDate)).toBeLessThanOrEqual(Number(todayDate)); + expect(Number(firstLogDate)).toBeGreaterThanOrEqual(1); }); test('6. 點選交易類型切換至入金並點選第一筆紀錄的入金按鈕,再關閉紀錄。', async ({ page, context, }) => { - const titleButton = {name: i18next.t('MY_ASSETS_PAGE.RECEIPT_SECTION_TRADING_TYPE_TITLE')}; - const depositButton = {name: i18next.t('MY_ASSETS_PAGE.RECEIPT_SECTION_TRADING_TYPE_DEPOSIT')}; const walletConnect = new WalletConnect(page, context); await walletConnect.getMetamaskId(); await walletConnect.connectMetamask(); @@ -142,21 +113,21 @@ test('6. 點選交易類型切換至入金並點選第一筆紀錄的入金按 await walletConnect.sendRequest(); const myAssetsPage = new MyAssetsPage(page); await myAssetsPage.goto(); - await page.getByRole('button', titleButton).click(); + await page.locator('#TradingTypeMenuButton').click(); + await page.locator('#TypeDepositButton').click(); await page .locator( - '#__next > div > div:nth-child(17) > main > div > div > div.pt-10 > div:nth-child(4) > div > div.flex.flex-col.items-center> div > div.relative.mt-2.hidden.w-160px> div > button:nth-child(2)' + '#__next > div > div:nth-child(6) > main > div > div > div.pt-10 > div.p-4 > div:nth-child(2) > div > div > div > div:nth-child(1) > div > div:nth-child(2) > div:nth-child(1) > button' ) .click(); - await page.getByRole('button', depositButton).nth(3).click(); - await expect(page.locator('#depositHistoryModal')).toBeVisible(); + await expect.soft(page.locator('#DWHistoryModal')).toBeVisible(); + await page.locator('#HistoryCloseButton').click(); }); test('7. 點選交易類型切換至關倉並點選第一筆紀錄的關倉按鈕後,點擊分享至FB,再關閉紀錄。', async ({ page, context, }) => { - const closeButton = {name: i18next.t('MY_ASSETS_PAGE.RECEIPT_SECTION_CLOSE_BUTTON')}; const walletConnect = new WalletConnect(page, context); await walletConnect.getMetamaskId(); await walletConnect.connectMetamask(); @@ -164,11 +135,19 @@ test('7. 點選交易類型切換至關倉並點選第一筆紀錄的關倉按 await walletConnect.sendRequest(); const myAssetsPage = new MyAssetsPage(page); await myAssetsPage.goto(); - await page.getByRole('button', closeButton).first().click(); - const pagePromise = context.waitForEvent('page'); - await page.getByRole('img', {name: 'FACEBOOK'}).first().click(); - const newPage = await pagePromise; - await newPage.waitForLoadState(); - await expect.soft(newPage).toHaveURL(/facebook.com/); - await expect.soft(newPage).toHaveTitle(/Facebook/); + await page.locator('#TradingTypeMenuButton').click(); + await page.locator('#TypeCloseButton').click(); + if ((await page.locator('vercel-live-feedback').count()) > 0) { + await page.$eval('vercel-live-feedback', el => el.remove()); + } + await page + .locator( + '#__next > div > div:nth-child(6) > main > div > div > div.pt-10 > div.p-4 > div:nth-child(2) > div > div > div > div:nth-child(1) > div > div:nth-child(2) > div:nth-child(1) > button' + ) + .click(); + await page.locator('#ShareHistoryToFACEBOOK').click(); + const flag = await page.waitForRequest( + /https:\/\/api.tidebit-defi.com\/api\/v1\/public\/shared\/cfd*/ + ); + await expect.soft(flag).toBeTruthy(); }); diff --git a/integration-test/tests/TBDTC000010.spec.ts b/integration-test/tests/TBDTC000010.spec.ts index f0a1780b..953e83a7 100644 --- a/integration-test/tests/TBDTC000010.spec.ts +++ b/integration-test/tests/TBDTC000010.spec.ts @@ -20,14 +20,13 @@ test('2. 點擊前三名查看用戶資料後關閉。', async ({page}) => { const leaderboardPage = new LeaderboardPage(page); await leaderboardPage.goto(); await leaderboardPage.clickAnncmnt(); - await page.locator('.mt-24 > .relative > div').first().click(); - await page.locator('#personalInfoModal > div > button > span > svg').click(); - await page.locator('.mt-20 > .relative > div').first().click(); - await page.locator('#personalInfoModal > div > button > span > svg').click(); - await page.locator('.mt-28 > .relative > div').first().click(); - await page.locator('#personalInfoModal > div > button > span > svg').click(); + await page.locator('#Ranking1').click(); + await page.locator('#AchievementModalCloseButton').click(); + await page.locator('#Ranking2').click(); + await page.locator('#AchievementModalCloseButton').click(); }); +// Info: (20240226 - Jacky) pass only on asia/taipei timezone will fail on UTC timezone test('3. 切換日、週、月排名,停留在日排名。', async ({page}) => { const leaderboardPage = new LeaderboardPage(page); await leaderboardPage.goto(); @@ -53,52 +52,25 @@ test('3. 切換日、週、月排名,停留在日排名。', async ({page}) => 'November', 'December', ]; - const dailyButton = {name: i18next.t('LEADERBOARD_PAGE.DAILY')}; - const weeklyButton = {name: i18next.t('LEADERBOARD_PAGE.WEEKLY')}; - const monthlyButton = {name: i18next.t('LEADERBOARD_PAGE.MONTHLY')}; + await expect.soft(await page.locator('#LiveRemainingTime')).toBeVisible(); + await page.locator('#DailyTab').click(); await expect - .soft( - await page.locator( - '#__next > div > div:nth-child(17) > main > div > div > div.min-h-screen > div > div.inline-block > span' - ) - ) - .toBeVisible(); - await page.getByRole('button', dailyButton).click(); - // cant locate the text - await expect - .soft( - await page.locator( - '#__next > div > div:nth-child(17) > main > div > div > div.min-h-screen > div > div.inline-block.text-base > span' - ) - ) + .soft(await page.locator('#DailyTimePeriod > span')) .toContainText(today.toISOString().slice(0, 10)); - await page.getByRole('button', weeklyButton).click(); + await page.locator('#WeeklyTab').click(); await expect - .soft( - await page.locator( - '#__next > div > div:nth-child(17) > main > div > div > div.min-h-screen > div > div.inline-block.text-base> span:nth-child(1)' - ) - ) + .soft(await page.locator('#WeeklyTimePeriod > span:nth-child(1)')) .toContainText(lastWeekStart.toISOString().slice(0, 10)); await expect - .soft( - await page.locator( - '#__next > div > div:nth-child(17) > main > div > div > div.min-h-screen > div > div.inline-block.text-base > span:nth-child(2)' - ) - ) + .soft(await page.locator('#WeeklyTimePeriod > span:nth-child(2)')) .toContainText(lastWeekEnd.toISOString().slice(0, 10)); - await page.getByRole('button', monthlyButton).click(); + await page.locator('#MonthlyTab').click(); await expect - .soft( - await page.locator( - '#__next > div > div:nth-child(17) > main > div > div > div.min-h-screen > div > div.inline-block.text-base > span' - ) - ) + .soft(await page.locator('#MonthlyTimePeriod > span')) .toContainText(monthNames[today.getUTCMonth() - 1] + ' ' + today.getFullYear()); }); test('4. 點擊此帳號的地址後點擊入金徽章並將徽章分享至FB。', async ({page, context}) => { - const dailyButton = {name: i18next.t('LEADERBOARD_PAGE.DAILY')}; const walletConnect = new WalletConnect(page, context); await walletConnect.getMetamaskId(); await walletConnect.connectMetamask(); @@ -107,21 +79,11 @@ test('4. 點擊此帳號的地址後點擊入金徽章並將徽章分享至FB。 const leaderboardPage = new LeaderboardPage(page); await leaderboardPage.goto(); await leaderboardPage.clickAnncmnt(); - await page.getByRole('button', dailyButton).click(); - await page - .locator( - '#__next > div > div:nth-child(17) > main > div > div > div.min-h-screen > div > div.pt-150px > div > div.my-10.w-screen> div.flex.w-full.flex-col.bg-darkGray7.pt-2 > div.sticky.bottom-0.z-30> div > div.flex.flex-1.items-center.space-x-2' - ) - .click(); - await page - .locator( - '#personalInfoModal > div:nth-child(2) > div:nth-child(3) > div:nth-child(2) > div:nth-child(6)' - ) - .click(); + await page.locator('#DailyTab').click(); + await page.locator('#UserPersonalRanking').click(); + await page.locator('#BadgeDeposit').click(); const pagePromise = context.waitForEvent('page'); - await page - .locator('#BadgeModal > div:nth-child(2) > div:nth-child(3) > div > button:nth-child(1) > svg') - .click(); + await page.locator('#ShareBadgeToFacebook').click(); const newPage = await pagePromise; await expect.soft(newPage).toHaveTitle(/Facebook/); }); diff --git a/integration-test/tests/TradeExample.spec.ts b/integration-test/tests/TradeExample.spec.ts index ef8d7bd6..fcf14fb6 100644 --- a/integration-test/tests/TradeExample.spec.ts +++ b/integration-test/tests/TradeExample.spec.ts @@ -25,6 +25,8 @@ test('Trade example', async ({page, context}) => { await tradePage.inputAmount(); // open long position await tradePage.openLongPosition(walletConnect.extensionId); + // update position default value is 1 means the last position + await tradePage.updatePosition(walletConnect.extensionId); //close position default value is 1 means the last position await tradePage.closePosition(walletConnect.extensionId); // go to BTC trade page @@ -34,6 +36,4 @@ test('Trade example', async ({page, context}) => { // open short position await tradePage.openShortPosition(walletConnect.extensionId); await tradePage.closePosition(walletConnect.extensionId); - // update position default value is 1 means the last position - await tradePage.updatePosition(walletConnect.extensionId); });