diff --git a/ui/package-lock.json b/ui/package-lock.json index 720803b5e4..b6885ee7fe 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -62,6 +62,7 @@ }, "devDependencies": { "@iconify/react": "^5.2.0", + "@playwright/test": "^1.53.1", "@types/bcryptjs": "^2.4.6", "@types/node": "20.5.7", "@types/react": "18.3.3", @@ -4716,6 +4717,22 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/@playwright/test": { + "version": "1.53.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.53.1.tgz", + "integrity": "sha512-Z4c23LHV0muZ8hfv4jw6HngPJkbbtZxTkxPNIg7cJcTc9C28N/p2q7g3JZS2SiKBBHJ3uM1dgDye66bB7LEk5w==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.53.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@radix-ui/number": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz", @@ -11373,6 +11390,20 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -14626,6 +14657,38 @@ "node": ">= 6" } }, + "node_modules/playwright": { + "version": "1.53.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.53.1.tgz", + "integrity": "sha512-LJ13YLr/ocweuwxyGf1XNFWIU4M2zUSo149Qbp+A4cpwDjsxRPj7k6H25LBrEHiEwxvRbD8HdwvQmRMSvquhYw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.53.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.53.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.53.1.tgz", + "integrity": "sha512-Z46Oq7tLAyT0lGoFx4DOuB1IA9D1TPj0QkYxpPVUnGDqHHvDpCftu1J2hM2PiWsNMoZh8+LQaarAWcDfPBc6zg==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", diff --git a/ui/package.json b/ui/package.json index 00793efbf0..b514ada9c3 100644 --- a/ui/package.json +++ b/ui/package.json @@ -54,6 +54,7 @@ }, "devDependencies": { "@iconify/react": "^5.2.0", + "@playwright/test": "^1.53.1", "@types/bcryptjs": "^2.4.6", "@types/node": "20.5.7", "@types/react": "18.3.3", @@ -96,10 +97,11 @@ "lint:fix": "eslint . --ext .ts,.tsx -c .eslintrc.cjs --fix", "format:check": "./node_modules/.bin/prettier --check ./app", "format:write": "./node_modules/.bin/prettier --config .prettierrc.json --write ./app", - "prepare": "husky" + "prepare": "husky", + "test:e2e": "playwright test" }, "overrides": { "@react-types/shared": "3.26.0" }, "version": "0.0.1" -} +} \ No newline at end of file diff --git a/ui/playwright.config.ts b/ui/playwright.config.ts new file mode 100644 index 0000000000..b987efb907 --- /dev/null +++ b/ui/playwright.config.ts @@ -0,0 +1,68 @@ +import { defineConfig, devices } from "@playwright/test"; + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: "./tests/e2e", + /* Run tests in files in parallel */ + fullyParallel: true, + 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://localhost:3000", + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: "on-first-retry", + // Capture screenshot on failure + screenshot: "only-on-failure", + // Record video for failed tests + video: "retain-on-failure", + }, + + /* 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 dev", + url: "http://localhost:3000", + reuseExistingServer: true, + timeout: 300 * 1000, // 5 minute + }, +}); diff --git a/ui/tests/e2e/auth/authentication.spec.ts b/ui/tests/e2e/auth/authentication.spec.ts new file mode 100644 index 0000000000..9dcb9854ad --- /dev/null +++ b/ui/tests/e2e/auth/authentication.spec.ts @@ -0,0 +1,15 @@ +import { test } from '@playwright/test'; + +// Test credentials from environment variables +const TEST_USER_EMAIL = process.env.TEST_USER_EMAIL || 'dev@prowler.com'; +const TEST_USER_PASSWORD = process.env.TEST_USER_PASSWORD || 'thisisapassword123'; + +test('should login successfully and redirect to home page', async ({ page }) => { + await page.goto('/login'); + const title = await page.title(); + + await page.fill('input[name="email"]', TEST_USER_EMAIL); + await page.fill('input[name="password"]', TEST_USER_PASSWORD); + await page.click('button[type="submit"]'); + await page.waitForURL('/'); +}); \ No newline at end of file