diff --git a/.github/workflows/laravel.yml b/.github/workflows/laravel.yml index 158cd6e..92ebf23 100644 --- a/.github/workflows/laravel.yml +++ b/.github/workflows/laravel.yml @@ -22,6 +22,9 @@ jobs: run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist - name: Install and build Js Dependencies run: npm ci && npm run build + + - name: Install Playwright Browsers + run: npx playwright install --with-deps - name: Generate key run: php artisan key:generate - name: Directory Permissions @@ -35,3 +38,6 @@ jobs: DB_CONNECTION: sqlite DB_DATABASE: database/database.sqlite run: php artisan test + + - name: Run Playwright tests + run: npx playwright test diff --git a/.gitignore b/.gitignore index d46f4d3..24a8e8b 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,8 @@ yarn-error.log /public/**/ /resources/views/custom /Portal +node_modules/ +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/e2e/example.spec.cjs b/e2e/example.spec.cjs new file mode 100644 index 0000000..1b2aabb --- /dev/null +++ b/e2e/example.spec.cjs @@ -0,0 +1,12 @@ +// @ts-check +const { test, expect } = require('@playwright/test'); + +test('Has Login', async ({ page }) => { + await page.goto('./'); + + //Click Sign In button + await page.getByRole('button', { name: 'Sign In' }).click(); + + // Expects page to have a heading with the name of Installation. + await expect(page.getByRole('group', { name: 'Portal Login' })).toBeVisible(); +}); diff --git a/package-lock.json b/package-lock.json index 40bbb35..196aec7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,7 +4,6 @@ "requires": true, "packages": { "": { - "name": "Symbiota-Laravel", "dependencies": { "@fortawesome/fontawesome-free": "^6.5.2", "@fortawesome/fontawesome-svg-core": "^6.5.2", @@ -13,6 +12,8 @@ "htmx.org": "^1.9.12" }, "devDependencies": { + "@playwright/test": "^1.47.2", + "@types/node": "^22.7.1", "autoprefixer": "^10.4.19", "axios": "^1.1.2", "laravel-vite-plugin": "^0.8.0", @@ -570,6 +571,32 @@ "node": ">=14" } }, + "node_modules/@playwright/test": { + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.2.tgz", + "integrity": "sha512-jTXRsoSPONAs8Za9QEQdyjFn+0ZQFjCiIztAIF6bi1HqhBzG9Ma7g1WotyiGqFSBRZjIEqMdT8RUlbk1QVhzCQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.47.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@types/node": { + "version": "22.7.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.1.tgz", + "integrity": "sha512-adOMRLVmleuWs/5V/w5/l7o0chDK/az+5ncCsIapTKogsu/3MVWvSgP58qVTXi5IwpfGt8pMobNq9rOWtJyu5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, "node_modules/@vue/reactivity": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.5.tgz", @@ -1539,6 +1566,53 @@ "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==", + "dev": true, + "license": "Apache-2.0", + "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==", + "dev": true, + "license": "Apache-2.0", + "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==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/postcss": { "version": "8.4.38", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", @@ -2087,6 +2161,13 @@ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "dev": true }, + "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, + "license": "MIT" + }, "node_modules/update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", @@ -2590,6 +2671,24 @@ "dev": true, "optional": true }, + "@playwright/test": { + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.2.tgz", + "integrity": "sha512-jTXRsoSPONAs8Za9QEQdyjFn+0ZQFjCiIztAIF6bi1HqhBzG9Ma7g1WotyiGqFSBRZjIEqMdT8RUlbk1QVhzCQ==", + "dev": true, + "requires": { + "playwright": "1.47.2" + } + }, + "@types/node": { + "version": "22.7.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.1.tgz", + "integrity": "sha512-adOMRLVmleuWs/5V/w5/l7o0chDK/az+5ncCsIapTKogsu/3MVWvSgP58qVTXi5IwpfGt8pMobNq9rOWtJyu5Q==", + "dev": true, + "requires": { + "undici-types": "~6.19.2" + } + }, "@vue/reactivity": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.5.tgz", @@ -3255,6 +3354,31 @@ "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "dev": true }, + "playwright": { + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.2.tgz", + "integrity": "sha512-nx1cLMmQWqmA3UsnjaaokyoUpdVaaDhJhMoxX2qj3McpjnsqFHs516QAKYhqHAgOP+oCFTEOCOAaD1RgD/RQfA==", + "dev": true, + "requires": { + "fsevents": "2.3.2", + "playwright-core": "1.47.2" + }, + "dependencies": { + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + } + } + }, + "playwright-core": { + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.2.tgz", + "integrity": "sha512-3JvMfF+9LJfe16l7AbSmU555PaTl2tPyQsVInqm3id16pdDfvZ8TTZ/pyzmkbDrZTQefyzU7AIHlZqQnxpqHVQ==", + "dev": true + }, "postcss": { "version": "8.4.38", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", @@ -3595,6 +3719,12 @@ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "dev": true }, + "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 + }, "update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", diff --git a/package.json b/package.json index 85d554d..c54b976 100644 --- a/package.json +++ b/package.json @@ -1,24 +1,26 @@ { - "private": true, - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build" - }, - "devDependencies": { - "autoprefixer": "^10.4.19", - "axios": "^1.1.2", - "laravel-vite-plugin": "^0.8.0", - "postcss": "^8.4.38", - "postcss-nesting": "^12.1.1", - "tailwindcss": "^3.4.1", - "vite": "^4.0.0" - }, - "dependencies": { - "@fortawesome/fontawesome-free": "^6.5.2", - "@fortawesome/fontawesome-svg-core": "^6.5.2", - "alpinejs": "^3.13.8", - "color": "^4.2.3", - "htmx.org": "^1.9.12" - } + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build" + }, + "devDependencies": { + "@playwright/test": "^1.47.2", + "@types/node": "^22.7.1", + "autoprefixer": "^10.4.19", + "axios": "^1.1.2", + "laravel-vite-plugin": "^0.8.0", + "postcss": "^8.4.38", + "postcss-nesting": "^12.1.1", + "tailwindcss": "^3.4.1", + "vite": "^4.0.0" + }, + "dependencies": { + "@fortawesome/fontawesome-free": "^6.5.2", + "@fortawesome/fontawesome-svg-core": "^6.5.2", + "alpinejs": "^3.13.8", + "color": "^4.2.3", + "htmx.org": "^1.9.12" + } } diff --git a/playwright.config.cjs b/playwright.config.cjs new file mode 100644 index 0000000..c8c48d7 --- /dev/null +++ b/playwright.config.cjs @@ -0,0 +1,83 @@ +// @ts-check +const { defineConfig, devices } = require('@playwright/test'); +process.loadEnvFile(); + +const APP_URL =!process.env.CI? process.env.APP_URL : 'http://127.0.0.1:8000' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config({ path: path.resolve(__dirname, '.env') }); + +/** + * @see https://playwright.dev/docs/test-configuration + */ +module.exports = 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: APP_URL, + + /* 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: 'php artisan serve', + //url: !process.env.CI ? process.env.APP_URL : 'http://127.0.0.1:8000', + url: APP_URL, + reuseExistingServer: !process.env.CI, + }, +}); +