diff --git a/.gitignore b/.gitignore index 2c8a56a..02bb8b8 100644 --- a/.gitignore +++ b/.gitignore @@ -41,4 +41,8 @@ next-env.d.ts #build /pack subman.tar.gz - +node_modules/ +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/Jenkinsfile b/Jenkinsfile index f975188..d41ef1e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -11,6 +11,7 @@ agent any sh 'echo "DATABASE_URL=${DATABASE_URL}" | cat >> .env' sh 'npm install' sh 'npm run build' + sh 'rm -r pack' } } stage('deploy'){ diff --git a/package-lock.json b/package-lock.json index 8245c11..0c1ab1e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,6 +33,7 @@ "lucide-react": "^0.394.0", "next": "^14.2.13", "next-themes": "^0.3.0", + "playwright": "^1.47.2", "react": "^18", "react-day-picker": "^8.10.1", "react-dom": "^18", @@ -44,6 +45,7 @@ "zod": "^3.23.8" }, "devDependencies": { + "@playwright/test": "^1.47.2", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", @@ -408,6 +410,21 @@ "node": ">= 8" } }, + "node_modules/@playwright/test": { + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.2.tgz", + "integrity": "sha512-jTXRsoSPONAs8Za9QEQdyjFn+0ZQFjCiIztAIF6bi1HqhBzG9Ma7g1WotyiGqFSBRZjIEqMdT8RUlbk1QVhzCQ==", + "devOptional": true, + "dependencies": { + "playwright": "1.47.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@prisma/client": { "version": "5.16.0", "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.16.0.tgz", @@ -7490,6 +7507,47 @@ "node": ">= 6" } }, + "node_modules/playwright": { + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.2.tgz", + "integrity": "sha512-nx1cLMmQWqmA3UsnjaaokyoUpdVaaDhJhMoxX2qj3McpjnsqFHs516QAKYhqHAgOP+oCFTEOCOAaD1RgD/RQfA==", + "dependencies": { + "playwright-core": "1.47.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.2.tgz", + "integrity": "sha512-3JvMfF+9LJfe16l7AbSmU555PaTl2tPyQsVInqm3id16pdDfvZ8TTZ/pyzmkbDrZTQefyzU7AIHlZqQnxpqHVQ==", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/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, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "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/package.json b/package.json index 1b1990a..80b4793 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "lucide-react": "^0.394.0", "next": "^14.2.13", "next-themes": "^0.3.0", + "playwright": "^1.47.2", "react": "^18", "react-day-picker": "^8.10.1", "react-dom": "^18", @@ -47,6 +48,7 @@ "zod": "^3.23.8" }, "devDependencies": { + "@playwright/test": "^1.47.2", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", diff --git a/package.sh b/package.sh index a0c0e30..324e452 100755 --- a/package.sh +++ b/package.sh @@ -10,6 +10,4 @@ cd pack npx prisma db push cd .. - tar -cf subman.tar.gz pack -rm -r pack diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..c7a3478 --- /dev/null +++ b/playwright.config.ts @@ -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: './tests', + /* 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: 'node pack/server.js', + url: 'http://127.0.0.1:3000', + reuseExistingServer: !process.env.CI, + }, +}); diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 7432818..0f1a323 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -42,12 +42,12 @@ export default function RootLayout({ -
+
{children}
- + diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index a175dee..159ec2a 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -36,8 +36,7 @@ export default function LoginForm() { toast({ title: "login successful!" }) setSubmitted(true) await revalidate(redirect) - //BUG:the first time user logs in, page refreshes instead of redirecting - router.push(redirect) + window.location.href = redirect } else { toast({ title: "login failed!" }) } diff --git a/tests/login.spec.ts b/tests/login.spec.ts new file mode 100644 index 0000000..d05efbb --- /dev/null +++ b/tests/login.spec.ts @@ -0,0 +1,31 @@ +import { test, expect } from '@playwright/test' + +test('should redirect to login page if not logged in', async ({ page }) => { + await page.goto('/') + await page.click('text=Stories') + await expect(page).toHaveURL('/login?from=%2Fstory') + await page.click('text=Publications') + await expect(page).toHaveURL('/login?from=%2Fpublication') + await page.click('text=Submissions') + await expect(page).toHaveURL('/login?from=%2Fsubmission') +}) + +test('positive login', async ({ page }) => { + await page.goto('/login') + await page.getByRole('textbox', { name: 'email' }).fill('demo@demo.demo') + await page.getByRole('textbox', { name: 'password' }).fill('password') + await page.getByRole('button', { name: 'submit' }).click() + + await page.waitForURL('**/submission', { timeout: 5000 }) + await expect(page).toHaveURL('/submission'); + +}) + +test('negative login', async ({ page }) => { + + await page.goto('/login') + await page.getByRole('textbox', { name: 'email' }).fill('demo@demo.negative') + await page.getByRole('textbox', { name: 'password' }).fill('negative') + await page.getByRole('button', { name: 'submit' }).click() + await expect(page.getByText("login failed!")).toBeTruthy() +})