diff --git a/.github/workflows/test-apps.yml b/.github/workflows/test-apps.yml index 411b35c71..72063e184 100644 --- a/.github/workflows/test-apps.yml +++ b/.github/workflows/test-apps.yml @@ -45,4 +45,18 @@ jobs: # Return to the original directory using absolute path cd "../" fi - done \ No newline at end of file + done + + - name: E2E Test for apps + run: | + # Absolute path to the 'sdk-vite-integration' directory + sdk_vite_integration_directory="$(pwd)/apps/sdk-vite-integration" + + # LOG + echo "Running yarn in $sdk_vite_integration_directory" + + # Navigate to the directory using absolute path + cd "$sdk_vite_integration_directory" + + # Test + yarn test:e2e \ No newline at end of file diff --git a/apps/sdk-vite-integration/.gitignore b/apps/sdk-vite-integration/.gitignore index a547bf36d..93e4eac99 100644 --- a/apps/sdk-vite-integration/.gitignore +++ b/apps/sdk-vite-integration/.gitignore @@ -22,3 +22,6 @@ dist-ssr *.njsproj *.sln *.sw? + +# playwright +test-results/ diff --git a/apps/sdk-vite-integration/e2e/hash.spec.ts b/apps/sdk-vite-integration/e2e/hash.spec.ts new file mode 100644 index 000000000..42ee1e684 --- /dev/null +++ b/apps/sdk-vite-integration/e2e/hash.spec.ts @@ -0,0 +1,48 @@ +import { test, expect } from '@playwright/test'; +import { + Blake2b256, + Keccak256, + Sha256, + Txt +} from '@vechain/sdk-core/dist/index.mjs'; + +test('Hash example', async ({ page }) => { + await page.goto("/"); + + const hashLink = page.getByTestId('hash-link'); + + // Expect link to be visible + await expect(hashLink).toBeVisible(); + + // Click on link + await hashLink.click(); + + // Enter content to hash + const content = "SDK is awesome!"; + const hashInput = page.getByTestId('contentToHash'); + await hashInput.clear(); + await hashInput.fill(content); + + // Expect hash component to be visible with expected text + const blake2bHash = page.getByTestId('blake2b256HashLabel'); + const keccak256Hash = page.getByTestId('keccak256HashLabel'); + const sha256Hash = page.getByTestId('sha256HashLabel'); + await expect(blake2bHash).toBeVisible(); + await expect(keccak256Hash).toBeVisible(); + await expect(sha256Hash).toBeVisible(); + + // Assert hash value for blake2b256 + const expectedBlake2b256Hash = Blake2b256.of(Txt.of(content).bytes) + await expect(blake2bHash).toContainText('Blake2b256'); + await expect(blake2bHash).toContainText(expectedBlake2b256Hash.toString()); + + // Assert hash value for keccak256 + const expectedKeccak256Hash = Keccak256.of(Txt.of(content).bytes) + await expect(keccak256Hash).toContainText('Keccak256'); + await expect(keccak256Hash).toContainText(expectedKeccak256Hash.toString()); + + // Assert hash value for sha256 + const expectedSha256Hash = Sha256.of(Txt.of(content).bytes) + await expect(sha256Hash).toContainText('Sha256'); + await expect(sha256Hash).toContainText(expectedSha256Hash.toString()); +}); \ No newline at end of file diff --git a/apps/sdk-vite-integration/e2e/lastblock.spec.ts b/apps/sdk-vite-integration/e2e/lastblock.spec.ts new file mode 100644 index 000000000..360ede8cb --- /dev/null +++ b/apps/sdk-vite-integration/e2e/lastblock.spec.ts @@ -0,0 +1,24 @@ +import { test, expect } from '@playwright/test'; + +test('Latest block example', async ({ page }) => { + await page.goto("/"); + + const latestBlockLink = page.getByTestId('latest-block-link'); + + // Expect link to be visible + await expect(latestBlockLink).toBeVisible(); + + // Click on link + await latestBlockLink.click(); + + // Click get last block button + const getLastBlockButton = page.getByTestId('getlastblock'); + await expect(getLastBlockButton).toBeVisible(); + await getLastBlockButton.click(); + + // Assert last block details + const lastBlockDetails = page.getByTestId('last-block-details'); + await expect(lastBlockDetails).toBeVisible(); + await expect(lastBlockDetails).toContainText('number'); + await expect(lastBlockDetails).toContainText('id'); +}); \ No newline at end of file diff --git a/apps/sdk-vite-integration/e2e/logs.spec.ts b/apps/sdk-vite-integration/e2e/logs.spec.ts new file mode 100644 index 000000000..3a3a21d20 --- /dev/null +++ b/apps/sdk-vite-integration/e2e/logs.spec.ts @@ -0,0 +1,29 @@ +import { test, expect } from '@playwright/test'; + +test('Transfer logs example', async ({ page }) => { + await page.goto("/"); + + const logsLink = page.getByTestId('transfers-link'); + + // Expect link to be visible + await expect(logsLink).toBeVisible(); + + // Click on link + await logsLink.click(); + + // Enter details to get transfer logs + const addressInput = page.getByTestId('address'); + const fromBlockInput = page.getByTestId('fromblock'); + const toBlockInput = page.getByTestId('toblock'); + + await addressInput.clear(); + await addressInput.fill('0xc3bE339D3D20abc1B731B320959A96A08D479583'); + await fromBlockInput.clear(); + await fromBlockInput.fill('1'); + await toBlockInput.clear(); + await toBlockInput.fill('19251959'); + + // expect logs table to be populated + const tableRows = page.locator('css=[data-testid="logs-table"] tr'); + await expect(tableRows).toHaveCount(8); // 8 rows in the table, this is a retryable assertion +}); \ No newline at end of file diff --git a/apps/sdk-vite-integration/package.json b/apps/sdk-vite-integration/package.json index f3cf6e83c..1e31c23a6 100644 --- a/apps/sdk-vite-integration/package.json +++ b/apps/sdk-vite-integration/package.json @@ -8,8 +8,8 @@ "build": "tsc -b && vite build", "lint": "eslint .", "preview": "vite preview", - "test": "vitest --config vitest.node.config.js", - "test:jsdom": "vitest --config vitest.jsdom.config.js" + "test": "vitest", + "test:e2e": "playwright test" }, "dependencies": { "@vechain/sdk-core": "1.0.0-rc.4", @@ -20,19 +20,19 @@ }, "devDependencies": { "@eslint/js": "^9.13.0", + "@playwright/test": "^1.49.0", "@types/react": "^18.3.11", "@types/react-dom": "^18.3.1", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^2.1.5", + "@vitest/browser": "^2.1.6", "eslint": "^9.13.0", "eslint-plugin-react-hooks": "^5.0.0", "eslint-plugin-react-refresh": "^0.4.14", "globals": "^15.11.0", - "playwright": "^1.48.2", "typescript": "~5.6.2", "typescript-eslint": "^8.10.0", "vite": "^5.4.11", - "vitest": "^2.1.4", + "vitest": "^2.1.6", "vitest-browser-react": "^0.0.3" } } \ No newline at end of file diff --git a/apps/sdk-vite-integration/playwright.config.ts b/apps/sdk-vite-integration/playwright.config.ts new file mode 100644 index 000000000..a53a50ce2 --- /dev/null +++ b/apps/sdk-vite-integration/playwright.config.ts @@ -0,0 +1,44 @@ +// playwright.config.ts +import { defineConfig, devices } from '@playwright/test'; + +export default defineConfig({ + // Look for test files in the "tests" directory, relative to this configuration file. + testDir: 'e2e', + + // Run all tests in parallel. + fullyParallel: true, + + // Fail the build on CI if you accidentally left test.only in the source code. + forbidOnly: !!process.env.CI, + + // Retry on CI only. + retries: process.env.CI ? 2 : 0, + + // Opt out of parallel tests on CI. + workers: process.env.CI ? 1 : undefined, + + // Reporter to use, see https://playwright.dev/docs/test-reporters + reporter: 'html', + + use: { + // Base URL to use in actions like `await page.goto('/')`. + baseURL: 'http://localhost:5173', + + // Collect trace when retrying the failed test. + trace: 'on-first-retry', + }, + // Configure projects for major browsers. + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + ], + // Run your local dev server before starting the tests. + webServer: { + command: 'yarn dev', + url: 'http://localhost:5173', + timeout: 120 * 1000, + reuseExistingServer: !process.env.CI, + }, +}); \ No newline at end of file diff --git a/apps/sdk-vite-integration/src/App.tsx b/apps/sdk-vite-integration/src/App.tsx index f4ea4028a..f0f8e40f1 100644 --- a/apps/sdk-vite-integration/src/App.tsx +++ b/apps/sdk-vite-integration/src/App.tsx @@ -22,7 +22,7 @@ function App() {

@vechain/sdk-core integration example:{' '} - @@ -31,7 +31,7 @@ function App() {

@vechain/sdk-network integration example:{' '} - @@ -40,7 +40,7 @@ function App() {

@vechain/sdk-network integration example:{' '} - diff --git a/apps/sdk-vite-integration/src/components/GetLastBlock.tsx b/apps/sdk-vite-integration/src/components/GetLastBlock.tsx index 7a7f240ec..be95c7a8a 100644 --- a/apps/sdk-vite-integration/src/components/GetLastBlock.tsx +++ b/apps/sdk-vite-integration/src/components/GetLastBlock.tsx @@ -22,13 +22,13 @@ const GetLastBlock = () => { return (

- {block && (

Last Block Details:

-
{JSON.stringify(block, null, 2)}
+
{JSON.stringify(block, null, 2)}
)}
diff --git a/apps/sdk-vite-integration/src/components/TransferLogs.tsx b/apps/sdk-vite-integration/src/components/TransferLogs.tsx index ad5a2fdee..a841fc406 100644 --- a/apps/sdk-vite-integration/src/components/TransferLogs.tsx +++ b/apps/sdk-vite-integration/src/components/TransferLogs.tsx @@ -1,7 +1,6 @@ import { useEffect, useState } from "react"; import { Address, FixedPointNumber, Units } from '@vechain/sdk-core'; import { - CompressedBlockDetail, FilterTransferLogsOptions } from '@vechain/sdk-network'; import { Link } from 'react-router-dom'; @@ -31,15 +30,16 @@ const TransferLogs = () => { '0xc3bE339D3D20abc1B731B320959A96A08D479583' ); + const [fromBlock, setFromBlock] = useState(1); + const [toBlock, setToBlock] = useState(19251959); + // /** // * Function to get the history for the provided address // * @param address The address to get the history for // */ async function getHistoryFor(address: string): Promise { try { - // Get the latest block - const bestBlock = await thorClient.blocks.getBestBlockCompressed(); - + // Filter options for the transfer logs const filterOptions: FilterTransferLogsOptions = { criteriaSet: [ @@ -49,8 +49,8 @@ const TransferLogs = () => { order: 'desc', // Order logs by descending timestamp range: { unit: 'block', - from: 0, - to: (bestBlock as CompressedBlockDetail).number + from: fromBlock, + to: toBlock } }; @@ -76,31 +76,77 @@ const TransferLogs = () => { // Update the history when the address changes useEffect(() => { - if (Address.isValid(address)) { + if (Address.isValid(address) && fromBlock) { void getHistoryFor(address); } - }, [address]); + }, [address, fromBlock, toBlock]); return (

- Insert an address to get the transfer history + Insert an address, fromBlock and ToBlock number to get the transfer logs

- { - setAddress(e.target.value); - }} - value={address} - className="block mx-auto w-full sm:max-w-md border-2 border-dark focus:border-purple-500 bg-transparent py-2 px-4 text-lg text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6 outline-none rounded-md" - placeholder="0xc3bE339D3D20abc1B731B320959A96A08D479583" - /> +
+ + { + setAddress(e.target.value); + }} + value={address} + className="block mx-auto w-full sm:max-w-md border-2 border-dark focus:border-purple-500 bg-transparent py-2 px-4 text-lg text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6 outline-none rounded-md" + placeholder="0xc3bE339D3D20abc1B731B320959A96A08D479583" + /> +
+
+ + { + setFromBlock(parseInt(e.target.value)); + }} + value={fromBlock} + className="block mx-auto w-full sm:max-w-md border-2 border-dark focus:border-purple-500 bg-transparent py-2 px-4 text-lg text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6 outline-none rounded-md" + placeholder="1" + /> +
+
+ + { + setToBlock(parseInt(e.target.value)); + }} + value={toBlock} + className="block mx-auto w-full sm:max-w-md border-2 border-dark focus:border-purple-500 bg-transparent py-2 px-4 text-lg text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6 outline-none rounded-md" + placeholder="19251959" + /> +
- +
diff --git a/apps/sdk-vite-integration/tsconfig.tsbuildinfo b/apps/sdk-vite-integration/tsconfig.tsbuildinfo index 3bb44fd7e..c6b6ab158 100644 --- a/apps/sdk-vite-integration/tsconfig.tsbuildinfo +++ b/apps/sdk-vite-integration/tsconfig.tsbuildinfo @@ -1 +1 @@ -{"root":["./vite.config.ts","./vitest.jsdom.config.ts","./vitest.node.config.ts","./src/app.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/components/getlastblock.tsx","./src/components/hash.tsx","./src/components/transferlogs.tsx","./src/const/const.tsx","./src/const/index.tsx","./src/types/index.tsx","./src/types/types.d.tsx","./tests/hash.spec.tsx"],"version":"5.6.3"} \ No newline at end of file +{"root":["./playwright.config.ts","./vite.config.ts","./vitest.workspace.ts","./e2e/hash.spec.ts","./e2e/lastblock.spec.ts","./e2e/logs.spec.ts","./src/app.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/components/getlastblock.tsx","./src/components/hash.tsx","./src/components/transferlogs.tsx","./src/const/const.tsx","./src/const/index.tsx","./src/types/index.tsx","./src/types/types.d.tsx","./tests/hash.spec.tsx"],"errors":true,"version":"5.6.3"} \ No newline at end of file diff --git a/apps/sdk-vite-integration/vite.config.ts b/apps/sdk-vite-integration/vite.config.ts index 8b0f57b91..a231402ed 100644 --- a/apps/sdk-vite-integration/vite.config.ts +++ b/apps/sdk-vite-integration/vite.config.ts @@ -3,5 +3,5 @@ import react from '@vitejs/plugin-react' // https://vite.dev/config/ export default defineConfig({ - plugins: [react()], + plugins: [react()] }) diff --git a/apps/sdk-vite-integration/vitest.jsdom.config.ts b/apps/sdk-vite-integration/vitest.jsdom.config.ts deleted file mode 100644 index 9ce2b10bd..000000000 --- a/apps/sdk-vite-integration/vitest.jsdom.config.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { defineConfig, ViteUserConfig } from 'vitest/config' -import react from '@vitejs/plugin-react' - -export default defineConfig({ - plugins: [react()] as ViteUserConfig["plugins"], - test: { - environment: 'jsdom', - browser: { - enabled: true, - name: 'chromium', - provider: 'playwright', - }, - }, -}) \ No newline at end of file diff --git a/apps/sdk-vite-integration/vitest.node.config.ts b/apps/sdk-vite-integration/vitest.node.config.ts deleted file mode 100644 index 52794398b..000000000 --- a/apps/sdk-vite-integration/vitest.node.config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { defineConfig, ViteUserConfig } from 'vitest/config' -import react from '@vitejs/plugin-react' - -export default defineConfig({ - plugins: [react()] as ViteUserConfig["plugins"], - test: { - browser: { - enabled: true, - name: 'chromium', - provider: 'playwright', - }, - }, -}) \ No newline at end of file diff --git a/apps/sdk-vite-integration/vitest.workspace.ts b/apps/sdk-vite-integration/vitest.workspace.ts new file mode 100644 index 000000000..89cb10c9e --- /dev/null +++ b/apps/sdk-vite-integration/vitest.workspace.ts @@ -0,0 +1,34 @@ +import { defineWorkspace, ViteUserConfig } from 'vitest/config'; +import react from '@vitejs/plugin-react' + +export default defineWorkspace([ + 'packages/*', + { + plugins: [react()] as ViteUserConfig["plugins"], + test: { + browser: { + enabled: true, + name: 'chromium', + provider: 'playwright' + }, + name: 'node-env', + environment: 'node', + include: ['tests/*.spec.tsx'], + exclude: ['e2e/*.spec.ts'], + }, + }, + { + plugins: [react()] as ViteUserConfig["plugins"], + test: { + browser: { + enabled: true, + name: 'chromium', + provider: 'playwright', + }, + name: 'jsdom-env', + environment: 'jsdom', + include: ['tests/*.spec.tsx'], + exclude: ['e2e/*.spec.ts'], + }, + } +]) \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 0c901fc3f..a49ad8070 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3732,6 +3732,13 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== +"@playwright/test@^1.49.0": + version "1.49.0" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.49.0.tgz#74227385b58317ee076b86b56d0e1e1b25cff01e" + integrity sha512-DMulbwQURa8rNIQrf94+jPJQ4FmOVdpE5ZppRNvWVjvhC+6sOeo28r8MgIpQRYouXRtt/FCCXU7zn20jnHR4Qw== + dependencies: + playwright "1.49.0" + "@polka/url@^1.0.0-next.24": version "1.0.0-next.28" resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.28.tgz#d45e01c4a56f143ee69c54dd6b12eade9e270a73" @@ -11885,17 +11892,17 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -playwright-core@1.48.2: - version "1.48.2" - resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.48.2.tgz#cd76ed8af61690edef5c05c64721c26a8db2f3d7" - integrity sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA== +playwright-core@1.49.0: + version "1.49.0" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.49.0.tgz#8e69ffed3f41855b854982f3632f2922c890afcb" + integrity sha512-R+3KKTQF3npy5GTiKH/T+kdhoJfJojjHESR1YEWhYuEKRVfVaxH3+4+GvXE5xyCngCxhxnykk0Vlah9v8fs3jA== -playwright@^1.48.2: - version "1.48.2" - resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.48.2.tgz#fca45ae8abdc34835c715718072aaff7e305167e" - integrity sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ== +playwright@1.49.0: + version "1.49.0" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.49.0.tgz#df6b9e05423377a99658202844a294a8afb95d0a" + integrity sha512-eKpmys0UFDnfNb3vfsf8Vx2LEOtflgRebl0Im2eQQnYMA4Aqd+Zw8bEOB+7ZKvN76901mRnqdsiOGKxzVTbi7A== dependencies: - playwright-core "1.48.2" + playwright-core "1.49.0" optionalDependencies: fsevents "2.3.2"
Time