tests(e2e): refactor register user to insert directly in db
This commit is contained in:
parent
6b6aba9545
commit
a31ecca41a
9 changed files with 62 additions and 125 deletions
15
.github/workflows/e2e.yml
vendored
15
.github/workflows/e2e.yml
vendored
|
@ -197,6 +197,21 @@ jobs:
|
|||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const comments = await github.rest.issues.listComments({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo
|
||||
});
|
||||
|
||||
const comment = comments.data.find(comment => comment.body.includes('Playwright report:'));
|
||||
|
||||
if (comment) {
|
||||
await github.rest.issues.deleteComment({
|
||||
comment_id: comment.id,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo
|
||||
});
|
||||
}
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import { test, expect } from '@playwright/test';
|
||||
import { registerUser } from './fixtures/fixtures';
|
||||
import { loginUser, createTestUser } from './fixtures/fixtures';
|
||||
import { testUser } from './helpers/constants';
|
||||
import { clearDatabase } from './helpers/db';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
test.beforeEach(async () => {
|
||||
await clearDatabase();
|
||||
await registerUser(page);
|
||||
});
|
||||
|
||||
test('user can login and is redirected to the dashboard', async ({ page }) => {
|
||||
await createTestUser();
|
||||
await page.goto('/login');
|
||||
|
||||
await page.getByPlaceholder('you@example.com').fill(testUser.email);
|
||||
|
@ -19,6 +19,7 @@ test('user can login and is redirected to the dashboard', async ({ page }) => {
|
|||
});
|
||||
|
||||
test('user can logout', async ({ page }) => {
|
||||
await loginUser(page);
|
||||
await page.getByTestId('logout-button').click();
|
||||
|
||||
await expect(page.getByText('Login to your account')).toBeVisible();
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
import { test, expect } from '@playwright/test';
|
||||
import { registerUser } from './fixtures/fixtures';
|
||||
import { loginUser } from './fixtures/fixtures';
|
||||
import { clearDatabase } from './helpers/db';
|
||||
|
||||
test.beforeEach(async ({ page, isMobile }) => {
|
||||
await clearDatabase();
|
||||
await registerUser(page);
|
||||
await loginUser(page);
|
||||
|
||||
// Go to hello world app
|
||||
if (isMobile) {
|
||||
await page.getByTestId('navbar-menu').click();
|
||||
// TODO: Fix mobile accessibility for the dropdown menu
|
||||
// await page.getByRole('button', { name: 'Menu' }).click();
|
||||
await page.goto('/app-store');
|
||||
} else {
|
||||
await page.getByRole('link', { name: 'App store' }).click();
|
||||
}
|
||||
await page.getByRole('link', { name: 'App store' }).click();
|
||||
|
||||
await page.getByPlaceholder('Search').fill('hello');
|
||||
await page.getByRole('link', { name: 'Hello World' }).click();
|
||||
});
|
||||
|
@ -27,7 +30,7 @@ test('user can install and uninstall app', async ({ page, context }) => {
|
|||
await expect(page.getByText('Running')).toBeVisible({ timeout: 60000 });
|
||||
await expect(page.getByText('App installed successfully')).toBeVisible();
|
||||
|
||||
const [newPage] = await Promise.all([context.waitForEvent('page'), page.getByRole('button', { name: 'Open' }).click()]);
|
||||
const [newPage] = await Promise.all([context.waitForEvent('page'), await page.getByTestId('app-details').getByRole('button', { name: 'Open' }).click()]);
|
||||
|
||||
await newPage.waitForLoadState();
|
||||
await expect(newPage.getByText('Hello World')).toBeVisible();
|
||||
|
|
|
@ -1,24 +1,25 @@
|
|||
import * as argon2 from 'argon2';
|
||||
import { expect, Page } from '@playwright/test';
|
||||
import { userTable } from '@/server/db/schema';
|
||||
import { db } from '../helpers/db';
|
||||
import { testUser } from '../helpers/constants';
|
||||
|
||||
export const registerUser = async (page: Page) => {
|
||||
await page.goto('/register');
|
||||
await page.getByPlaceholder('you@example.com').click();
|
||||
await page.getByPlaceholder('you@example.com').fill(testUser.email);
|
||||
|
||||
await page.getByPlaceholder('Enter your password', { exact: true }).fill(testUser.password);
|
||||
await page.getByPlaceholder('Confirm your password').fill(testUser.password);
|
||||
|
||||
await page.getByRole('button', { name: 'Register' }).click();
|
||||
await expect(page).toHaveTitle(/Dashboard/);
|
||||
export const createTestUser = async () => {
|
||||
// Create user in database
|
||||
const password = await argon2.hash(testUser.password);
|
||||
await db.insert(userTable).values({ password, username: testUser.email, operator: true });
|
||||
};
|
||||
|
||||
export const loginUser = async (page: Page) => {
|
||||
// Create user in database
|
||||
await createTestUser();
|
||||
|
||||
// Login flow
|
||||
await page.goto('/login');
|
||||
|
||||
await page.getByPlaceholder('you@example.com').fill(testUser.email);
|
||||
await page.getByPlaceholder('Your password').fill(testUser.password);
|
||||
await page.getByRole('button', { name: 'Login' }).click();
|
||||
|
||||
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeDefined();
|
||||
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
|
||||
};
|
||||
|
|
|
@ -1,19 +1,17 @@
|
|||
import pg from 'pg';
|
||||
import { Pool } from 'pg';
|
||||
import { drizzle } from 'drizzle-orm/node-postgres';
|
||||
import * as schema from '../../src/server/db/schema';
|
||||
|
||||
const connectionString = `postgresql://tipi:postgres@${process.env.SERVER_IP}:5432/tipi?connect_timeout=300`;
|
||||
|
||||
const pool = new Pool({
|
||||
connectionString,
|
||||
});
|
||||
|
||||
export const db = drizzle(pool, { schema });
|
||||
|
||||
export const clearDatabase = async () => {
|
||||
const pgClient = new pg.Client({
|
||||
user: 'tipi',
|
||||
host: process.env.SERVER_IP,
|
||||
database: 'tipi',
|
||||
password: 'postgres',
|
||||
port: 5432,
|
||||
});
|
||||
|
||||
await pgClient.connect();
|
||||
|
||||
// delete all data in table user
|
||||
await pgClient.query('DELETE FROM "user"');
|
||||
await pgClient.query('DELETE FROM "app"');
|
||||
|
||||
await pgClient.end();
|
||||
await db.delete(schema.userTable);
|
||||
await db.delete(schema.appTable);
|
||||
};
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
"start:dev-container": "./.devcontainer/filewatcher.sh && npm run start:dev",
|
||||
"start:rc": "docker-compose -f docker-compose.rc.yml --env-file .env up --build",
|
||||
"start:dev": "./scripts/start-dev.sh",
|
||||
"start:prod": "./scripts/start-prod.sh",
|
||||
"start:e2e": "./scripts/start-e2e.sh latest",
|
||||
"start:pg": "docker run --name test-db -p 5433:5432 -d --rm -e POSTGRES_PASSWORD=postgres postgres:14",
|
||||
"version": "echo $npm_package_version",
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
import { defineConfig, devices } from '@playwright/test';
|
||||
|
||||
/**
|
||||
* Read environment variables from file.
|
||||
* https://github.com/motdotla/dotenv
|
||||
*/
|
||||
// require('dotenv').config();
|
||||
|
||||
/**
|
||||
* See https://playwright.dev/docs/test-configuration.
|
||||
*/
|
||||
|
@ -42,15 +36,15 @@ export default defineConfig({
|
|||
use: { ...devices['Desktop Chrome'] },
|
||||
},
|
||||
|
||||
{
|
||||
name: 'firefox',
|
||||
use: { ...devices['Desktop Firefox'] },
|
||||
},
|
||||
// {
|
||||
// name: 'firefox',
|
||||
// use: { ...devices['Desktop Firefox'] },
|
||||
// },
|
||||
|
||||
{
|
||||
name: 'webkit',
|
||||
use: { ...devices['Desktop Safari'] },
|
||||
},
|
||||
// {
|
||||
// name: 'webkit',
|
||||
// use: { ...devices['Desktop Safari'] },
|
||||
// },
|
||||
|
||||
/* Test against mobile viewports. */
|
||||
{
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
if [[ "${TRACE-0}" == "1" ]]; then
|
||||
set -o xtrace
|
||||
fi
|
||||
|
||||
source "${BASH_SOURCE%/*}/common.sh"
|
||||
|
||||
clean_logs
|
||||
|
||||
### --------------------------------
|
||||
### General variables
|
||||
### --------------------------------
|
||||
ROOT_FOLDER="${PWD}"
|
||||
STATE_FOLDER="${ROOT_FOLDER}/state"
|
||||
|
||||
### --------------------------------
|
||||
### Apps repository configuration
|
||||
### --------------------------------
|
||||
apps_repository="https://github.com/meienberger/runtipi-appstore"
|
||||
|
||||
env_variables_json=$(cat <<EOF
|
||||
{
|
||||
"dns_ip": "9.9.9.9",
|
||||
"domain": "tipi.localhost",
|
||||
"root_folder": "${ROOT_FOLDER}",
|
||||
"nginx_port": 3000,
|
||||
"nginx_port_ssl": 443,
|
||||
"jwt_secret": "secret",
|
||||
"postgres_password": "postgres",
|
||||
"postgres_username": "tipi",
|
||||
"postgres_dbname": "tipi",
|
||||
"postgres_port": 5432,
|
||||
"postgres_host": "tipi-db",
|
||||
"redis_host": "tipi-redis",
|
||||
"tipi_version": "$(get_json_field "${ROOT_FOLDER}/package.json" version)",
|
||||
"internal_ip": "localhost",
|
||||
"demo_mode": false,
|
||||
"apps_repository": "${apps_repository}",
|
||||
"storage_path": "${ROOT_FOLDER}",
|
||||
"repo_id": "$("${ROOT_FOLDER}"/scripts/git.sh get_hash ${apps_repository})"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
### --------------------------------
|
||||
### Watcher and system-info
|
||||
### --------------------------------
|
||||
mkdir -p "${ROOT_FOLDER}/state"
|
||||
|
||||
if [[ ! -f "${ROOT_FOLDER}/state/events" ]]; then
|
||||
touch "${ROOT_FOLDER}/state/events"
|
||||
fi
|
||||
|
||||
if [[ ! -f "${ROOT_FOLDER}/state/system-info.json" ]]; then
|
||||
echo "{}" >"${ROOT_FOLDER}/state/system-info.json"
|
||||
fi
|
||||
|
||||
chmod -R a+rwx "${ROOT_FOLDER}/state/events"
|
||||
chmod -R a+rwx "${ROOT_FOLDER}/state/system-info.json"
|
||||
kill_watcher
|
||||
"${ROOT_FOLDER}/scripts/watcher.sh" &
|
||||
|
||||
### --------------------------------
|
||||
### env file generation
|
||||
### --------------------------------
|
||||
generate_env_file "${env_variables_json}"
|
||||
|
||||
### --------------------------------
|
||||
### Start the project
|
||||
### --------------------------------
|
||||
docker compose -f docker-compose.test.yml up --build
|
|
@ -30,7 +30,7 @@ export const Header: React.FC<IProps> = ({ isUpdateAvailable }) => {
|
|||
return (
|
||||
<header className="text-white navbar navbar-expand-md navbar-dark navbar-overlap d-print-none" data-bs-theme="dark">
|
||||
<div className="container-xl">
|
||||
<button data-testid="navbar-menu" aria-label="menu" className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar-menu">
|
||||
<button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar-menu">
|
||||
<span className="navbar-toggler-icon" />
|
||||
</button>
|
||||
<Link href="/" passHref>
|
||||
|
|
Loading…
Reference in a new issue