Add tests

This commit is contained in:
Arnaud 2024-10-10 19:14:27 +02:00
parent 72a753879c
commit 91d8669cdb
No known key found for this signature in database
GPG Key ID: 69D6CE281FCAE663
11 changed files with 376 additions and 6 deletions

4
.gitignore vendored
View File

@ -22,3 +22,7 @@ dist-ssr
*.njsproj
*.sln
*.sw?
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/

BIN
e2e/assets/chatgpt.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

BIN
e2e/assets/mountain.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@ -0,0 +1,57 @@
import test, { expect } from "@playwright/test";
import { APP_URL } from './constants';
test('creates an availability', async ({ page }) => {
await page.goto(APP_URL + '/dashboard');
await page.getByRole('link', { name: 'Sales' }).click();
await page.getByRole('button').first().click();
await page.getByLabel('Total size').click();
await page.getByLabel('Total size').fill('0.50');
await page.getByLabel('Duration').click();
await page.getByLabel('Duration').fill('30');
await page.getByLabel('Min price').click();
await page.getByLabel('Min price').fill('5');
await page.getByLabel('Max collateral').click();
await page.getByLabel('Max collateral').fill('30');
await page.getByLabel('Min price').fill('5');
await page.getByLabel('Nickname').click();
await page.getByLabel('Nickname').fill('test');
await page.getByRole('button', { name: 'Next' }).click();
await expect(page.getByText('Confirm your new sale')).toBeVisible();
await page.locator('small').filter({ hasText: /^512\.0 MB$/ }).click();
await page.getByRole('button', { name: 'Next' }).click();
await expect(page.getByText('Success', { exact: true })).toBeVisible();
await page.getByRole('button', { name: 'Finish' }).click();
await expect(page.getByText('512.0 MB allocated for the').first()).toBeVisible();
})
test('availability navigation buttons', async ({ page }) => {
await page.goto(APP_URL + '/dashboard/availabilities');
await page.getByRole('button').first().click();
await expect(page.locator('.stepper-number-done')).not.toBeVisible()
await expect(page.locator('.stepper-number-active')).toBeVisible()
await expect(page.locator('.stepper-buttons .button--primary')).not.toHaveAttribute("disabled");
await expect(page.locator('.stepper-buttons .button--outline')).not.toHaveAttribute("disabled");
await page.getByLabel('Total size').click();
await page.getByLabel('Total size').fill('19');
await expect(page.locator('.stepper-buttons .button--outline')).not.toHaveAttribute("disabled");
await expect(page.locator('.stepper-buttons .button--primary')).toHaveAttribute("disabled");
await page.getByLabel('Total size').click();
await page.getByLabel('Total size').fill('0.5');
await page.getByRole('button', { name: 'Next' }).click();
await expect(page.locator('.stepper-buttons .button--outline')).not.toHaveAttribute("disabled");
await expect(page.locator('.stepper-buttons .button--primary')).not.toHaveAttribute("disabled");
await expect(page.locator('.stepper-number-done')).toBeVisible()
await expect(page.locator('.stepper-number-active')).toBeVisible()
await page.getByRole('button', { name: 'Back' }).click();
await expect(page.locator('.stepper-number-done')).not.toBeVisible()
await expect(page.locator('.stepper-number-active')).toBeVisible()
await page.getByRole('button', { name: 'Next' }).click();
await page.getByRole('button', { name: 'Next' }).click();
await expect(page.locator('.stepper-number-done')).toHaveCount(2)
await expect(page.locator('.stepper-number-active')).toBeVisible()
await expect(page.locator('.stepper-buttons .button--outline')).toHaveAttribute("disabled");
await expect(page.locator('.stepper-buttons .button--primary')).not.toHaveAttribute("disabled");
await page.getByRole('button', { name: 'Finish' }).click();
await expect(page.locator('.modal--open')).not.toBeVisible();
})

1
e2e/constants.ts Normal file
View File

@ -0,0 +1 @@
export const APP_URL = "http://localhost:5173"

10
e2e/settings.spec.ts Normal file
View File

@ -0,0 +1,10 @@
import test, { expect } from "@playwright/test";
import { APP_URL } from './constants';
test('update the log level', async ({ page }) => {
await page.goto(APP_URL + '/dashboard');
await page.getByRole('link', { name: 'Settings' }).click();
await page.getByLabel('Log level').selectOption('TRACE');
await page.getByRole('main').locator('div').filter({ hasText: 'Log' }).getByRole('button').click();
await expect(page.locator('span').filter({ hasText: 'success ! The log level has' }).locator('b')).toBeVisible();
})

View File

@ -0,0 +1,66 @@
import test, { expect } from "@playwright/test";
import path, { dirname } from "path";
import { fileURLToPath } from "url";
import { APP_URL } from './constants';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
test('creates a storage request', async ({ page }) => {
await page.goto(APP_URL + '/dashboard');
await page.getByRole('link', { name: 'Purchases' }).click();
await page.getByRole('button', { name: 'Storage Request' }).click();
await page.locator('div').getByTestId("upload").setInputFiles([
path.join(__dirname, "assets", 'chatgpt.jpg'),
]);
await expect(page.locator('#cid')).toHaveValue("zDvZRwzkvwapyNeL4mzw5gBsZvyn7x8F8Y9n4RYSC7ETBssDYpGe")
await expect(page.getByText('Success, the CID has been')).toBeVisible();
await page.getByRole('button', { name: 'Next' }).click();
await page.getByRole('button', { name: 'Next' }).click();
await expect(page.getByText('Your request is being processed.')).toBeVisible();
await page.getByRole('button', { name: 'Finish' }).click();
await expect(page.getByText('No data.')).not.toBeVisible();
await page.getByRole('cell', { name: 'pending' }).getByRole('paragraph').click();
})
test('select a uploaded cid when creating a storage request', async ({ page }) => {
await page.goto(APP_URL + '/dashboard');
await page.locator('div').getByTestId("upload").setInputFiles([
path.join(__dirname, "assets", 'chatgpt.jpg'),
]);
await page.getByRole('link', { name: 'Purchases' }).click();
await page.getByRole('button', { name: 'Storage Request' }).click();
await page.getByPlaceholder('Select or type your CID').click();
await page.getByText('N/A0').click();
await expect(page.getByText('button[disabled]')).not.toBeVisible();
})
test('storage request navigation buttons', async ({ page }) => {
await page.goto(APP_URL + '/dashboard/purchases');
await page.getByRole('button', { name: 'Storage Request' }).click();
await expect(page.locator('.stepper-number-done')).not.toBeVisible()
await expect(page.locator('.stepper-number-active')).toBeVisible()
await expect(page.locator('.stepper-buttons .button--primary')).toHaveAttribute("disabled");
await expect(page.locator('.stepper-buttons .button--outline')).not.toHaveAttribute("disabled");
await page.locator('div').getByTestId("upload").setInputFiles([
path.join(__dirname, "assets", 'chatgpt.jpg'),
]);
await expect(page.locator('.stepper-buttons .button--outline')).not.toHaveAttribute("disabled");
await expect(page.locator('.stepper-buttons .button--primary')).not.toHaveAttribute("disabled");
await page.getByRole('button', { name: 'Next' }).click();
await expect(page.locator('.stepper-buttons .button--outline')).not.toHaveAttribute("disabled");
await expect(page.locator('.stepper-buttons .button--primary')).not.toHaveAttribute("disabled");
await expect(page.locator('.stepper-number-done')).toBeVisible()
await expect(page.locator('.stepper-number-active')).toBeVisible()
await page.getByRole('button', { name: 'Back' }).click();
await expect(page.locator('.stepper-number-done')).not.toBeVisible()
await expect(page.locator('.stepper-number-active')).toBeVisible()
await page.getByRole('button', { name: 'Next' }).click();
await page.getByRole('button', { name: 'Next' }).click();
await expect(page.locator('.stepper-number-done')).toHaveCount(2)
await expect(page.locator('.stepper-number-active')).toBeVisible()
await expect(page.locator('.stepper-buttons .button--outline')).toHaveAttribute("disabled");
await expect(page.locator('.stepper-buttons .button--primary')).not.toHaveAttribute("disabled");
await page.getByRole('button', { name: 'Finish' }).click();
await expect(page.locator('.modal--open')).not.toBeVisible();
})

74
e2e/upload.spec.ts Normal file
View File

@ -0,0 +1,74 @@
import { test, expect } from '@playwright/test';
import { Buffer } from 'buffer';
import { readFileSync } from 'fs';
import path, { dirname } from 'path';
import { fileURLToPath } from 'url';
import { APP_URL } from './constants';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
test('upload one file', async ({ page }) => {
await page.goto(APP_URL + '/dashboard');
await page.getByText('browse').click();
await page.locator('div').getByTestId("upload").setInputFiles([
path.join(__dirname, "assets", 'chatgpt.jpg'),
]);
await expect(page.getByText('File uploaded successfully')).toBeVisible();
});
test('multiple files upload', async ({ page }) => {
await page.goto(APP_URL + '/dashboard');
await page.getByText('browse').click();
await page.locator('div').getByTestId("upload").setInputFiles([
path.join(__dirname, "assets", 'chatgpt.jpg'),
path.join(__dirname, "assets", 'mountain.jpeg'),
]);
await expect(page.getByText('File uploaded successfully').first()).toBeVisible();
await expect(page.getByText('File uploaded successfully').nth(1)).toBeVisible();
await page.locator('.uploadFile-infoRight > .buttonIcon').first().click();
await page.locator('.uploadFile-infoRight > .buttonIcon').click();
await expect(page.getByText('File uploaded successfully').first()).not.toBeVisible();
await expect(page.getByText('File uploaded successfully').nth(1)).not.toBeVisible();
});
test('drag and drop file', async ({ page }) => {
await page.goto(APP_URL + '/dashboard');
const buffer = readFileSync(path.join(__dirname, "assets", 'chatgpt.jpg'));
// Create the DataTransfer and File
const dataTransfer = await page.evaluateHandle((data) => {
const dt = new DataTransfer();
// Convert the buffer to a hex array
const file = new File([data.toString('hex')], 'chat.jpg', { type: 'image/jpg' });
dt.items.add(file);
return dt;
}, buffer);
await page.dispatchEvent('input[type="file"]', 'drop', { dataTransfer });
await expect(page.getByText('File uploaded successfully').first()).toBeVisible();
});
test('stop an upload display a message', async ({ page }) => {
await page.goto(APP_URL + '/dashboard');
await page.getByText('browse').click();
const buffer = Buffer.alloc(10_000_000);
await page.locator('div').getByTestId("upload").setInputFiles({
buffer,
name: "test.txt",
mimeType: 'text/plain'
});
await page.locator('.uploadFile-infoRight > .buttonIcon--small').click();
await expect(page.getByText('The upload has been cancelled')).toBeVisible();
});

84
package-lock.json generated
View File

@ -9,7 +9,7 @@
"version": "0.0.3",
"license": "MIT",
"dependencies": {
"@codex-storage/marketplace-ui-components": "^0.0.17",
"@codex-storage/marketplace-ui-components": "^0.0.18",
"@codex-storage/sdk-js": "^0.0.7",
"@sentry/browser": "^8.32.0",
"@sentry/react": "^8.31.0",
@ -23,8 +23,10 @@
"react-dom": "^18.3.1"
},
"devDependencies": {
"@playwright/test": "^1.48.0",
"@tanstack/router-devtools": "^1.58.7",
"@tanstack/router-plugin": "^1.58.4",
"@types/node": "^22.7.5",
"@types/react": "^18.3.8",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^8.7.0",
@ -351,9 +353,9 @@
"dev": true
},
"node_modules/@codex-storage/marketplace-ui-components": {
"version": "0.0.17",
"resolved": "https://registry.npmjs.org/@codex-storage/marketplace-ui-components/-/marketplace-ui-components-0.0.17.tgz",
"integrity": "sha512-76NHMwL0Ggf8e3I11opvrnJqJ5kKc0sb1uEdsPLTYv+4xS2TCkhQwk+4E8Okw5bUeR1HQwVqj01hpQ1lR1fAVQ==",
"version": "0.0.18",
"resolved": "https://registry.npmjs.org/@codex-storage/marketplace-ui-components/-/marketplace-ui-components-0.0.18.tgz",
"integrity": "sha512-sK7YdlURXqE/GmoFDWJA4X18EdafFgCsJkEsdMyktn05qxCFtN7EGMWZHJrJ1FjlBFNZP5NIMljFrGKfY+xmVg==",
"dependencies": {
"lucide-react": "^0.441.0"
},
@ -601,6 +603,21 @@
"node": ">= 8"
}
},
"node_modules/@playwright/test": {
"version": "1.48.0",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.0.tgz",
"integrity": "sha512-W5lhqPUVPqhtc/ySvZI5Q8X2ztBOUgZ8LbAFy0JQgrXZs2xaILrUcNO3rQjwbLPfGK13+rZsDa1FpG+tqYkT5w==",
"dev": true,
"dependencies": {
"playwright": "1.48.0"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz",
@ -1630,6 +1647,15 @@
"dev": true,
"license": "MIT"
},
"node_modules/@types/node": {
"version": "22.7.5",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz",
"integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==",
"dev": true,
"dependencies": {
"undici-types": "~6.19.2"
}
},
"node_modules/@types/prop-types": {
"version": "15.7.12",
"dev": true,
@ -2609,6 +2635,20 @@
"dev": true,
"license": "ISC"
},
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"dev": true,
@ -3106,6 +3146,36 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/playwright": {
"version": "1.48.0",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.0.tgz",
"integrity": "sha512-qPqFaMEHuY/ug8o0uteYJSRfMGFikhUysk8ZvAtfKmUK3kc/6oNl/y3EczF8OFGYIi/Ex2HspMfzYArk6+XQSA==",
"dev": true,
"dependencies": {
"playwright-core": "1.48.0"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"fsevents": "2.3.2"
}
},
"node_modules/playwright-core": {
"version": "1.48.0",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.0.tgz",
"integrity": "sha512-RBvzjM9rdpP7UUFrQzRwR8L/xR4HyC1QXMzGYTbf1vjw25/ya9NRAVnXi/0fvFopjebvyPzsmoK58xxeEOaVvA==",
"dev": true,
"bin": {
"playwright-core": "cli.js"
},
"engines": {
"node": ">=18"
}
},
"node_modules/postcss": {
"version": "8.4.45",
"dev": true,
@ -3892,6 +3962,12 @@
"node": ">=14.17"
}
},
"node_modules/undici-types": {
"version": "6.19.8",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
"dev": true
},
"node_modules/unplugin": {
"version": "1.14.1",
"dev": true,

View File

@ -13,7 +13,8 @@
"build": "tsc -b && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview",
"format": "prettier --write ./src"
"format": "prettier --write ./src",
"test": "npx playwright test"
},
"keywords": [
"Codex",
@ -23,7 +24,7 @@
"React"
],
"dependencies": {
"@codex-storage/marketplace-ui-components": "^0.0.17",
"@codex-storage/marketplace-ui-components": "^0.0.18",
"@codex-storage/sdk-js": "^0.0.7",
"@sentry/browser": "^8.32.0",
"@sentry/react": "^8.31.0",
@ -37,8 +38,10 @@
"react-dom": "^18.3.1"
},
"devDependencies": {
"@playwright/test": "^1.48.0",
"@tanstack/router-devtools": "^1.58.7",
"@tanstack/router-plugin": "^1.58.4",
"@types/node": "^22.7.5",
"@types/react": "^18.3.8",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^8.7.0",

79
playwright.config.ts Normal file
View File

@ -0,0 +1,79 @@
import { defineConfig, devices } from '@playwright/test';
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// import dotenv from 'dotenv';
// import path from 'path';
// dotenv.config({ path: path.resolve(__dirname, '.env') });
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './e2e',
/* Run tests in files 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',
/* 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',
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},
/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
// {
// name: 'firefox',
// use: { ...devices['Desktop Firefox'] },
// },
// {
// name: 'webkit',
// use: { ...devices['Desktop Safari'] },
// },
/* Test against mobile viewports. */
// {
// name: 'Mobile Chrome',
// use: { ...devices['Pixel 5'] },
// },
// {
// name: 'Mobile Safari',
// use: { ...devices['iPhone 12'] },
// },
/* Test against branded browsers. */
// {
// name: 'Microsoft Edge',
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
// },
// {
// name: 'Google Chrome',
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
// },
],
/* Run your local dev server before starting the tests */
// webServer: {
// command: 'npm run start',
// url: 'http://127.0.0.1:3000',
// reuseExistingServer: !process.env.CI,
// },
});