mirror of
https://github.com/StarFleetCPTN/GoMFT.git
synced 2026-09-08 15:41:20 +02:00
feat: Add UI testing setup and storage provider tests
- Introduced a new script for installing UI testing dependencies, including Node.js and Playwright browsers. - Added comprehensive tests for managing storage providers, covering creation, editing, deletion, and connection testing. - Implemented helper functions for user login and provider management in the test setup. - Enhanced test coverage for various storage provider types, including SFTP, FTP, SMB, S3, and cloud services.
This commit is contained in:
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script to install UI testing dependencies
|
||||
|
||||
echo "Installing Node.js dependencies for UI testing..."
|
||||
npm install
|
||||
|
||||
echo "Installing Playwright browsers..."
|
||||
npx playwright install
|
||||
|
||||
echo "UI testing setup complete!"
|
||||
echo ""
|
||||
echo "You can now run UI tests with the following commands:"
|
||||
echo " npm test - Run all tests"
|
||||
echo " npm run test:headed - Run tests with visible browsers"
|
||||
echo " npm run test:debug - Run tests in debug mode"
|
||||
echo " npm run test:ui - Run tests with Playwright UI"
|
||||
echo ""
|
||||
echo "For more information, see tests/README.md"
|
||||
@@ -0,0 +1,434 @@
|
||||
// @ts-check
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { login, createStorageProvider, cleanupCreatedProviders, testProviderConnection } from './test-setup.js';
|
||||
|
||||
/**
|
||||
* This test logs in to the application and tests storage providers
|
||||
*/
|
||||
test.describe('Storage Providers', () => {
|
||||
// Login before each test
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await login(
|
||||
page,
|
||||
process.env.TEST_USERNAME || 'admin@example.com',
|
||||
process.env.TEST_PASSWORD || 'admin'
|
||||
);
|
||||
});
|
||||
|
||||
// Clean up created providers after tests
|
||||
test.afterEach(async ({ page }) => {
|
||||
await cleanupCreatedProviders(page);
|
||||
});
|
||||
|
||||
// Test navigating to storage providers page
|
||||
test('can navigate to storage providers page', async ({ page }) => {
|
||||
// Navigate to storage providers page
|
||||
await page.goto('/storage-providers');
|
||||
|
||||
// Verify the page title
|
||||
await expect(page.locator('h1:has-text("Storage Providers")')).toBeVisible();
|
||||
});
|
||||
|
||||
// Test creating a new storage provider (SFTP)
|
||||
test('can create a new SFTP storage provider', async ({ page }) => {
|
||||
// Navigate to the storage providers page
|
||||
await page.goto('/storage-providers');
|
||||
|
||||
// Click on "New Provider" button
|
||||
await page.click('a:has-text("New Provider")');
|
||||
|
||||
// Verify we're on the provider creation form
|
||||
await expect(page.locator('h1:has-text("New Storage Provider")')).toBeVisible();
|
||||
|
||||
// Fill in the form for SFTP provider
|
||||
await page.fill('#name', 'Test SFTP Provider');
|
||||
await page.selectOption('#type', 'sftp');
|
||||
|
||||
// Wait for the SFTP fields to be visible
|
||||
await expect(page.locator('#sftp-ftp-fields')).toBeVisible();
|
||||
|
||||
// Fill the SFTP form fields
|
||||
await page.fill('#host', process.env.SFTP_HOST || 'sftp.example.com');
|
||||
await page.fill('#port', process.env.SFTP_PORT || '22');
|
||||
await page.fill('#username', process.env.SFTP_USERNAME || 'testuser');
|
||||
await page.fill('#password', process.env.SFTP_PASSWORD || 'testpassword');
|
||||
if (process.env.SFTP_KEY_FILE) {
|
||||
await page.fill('#keyFile', process.env.SFTP_KEY_FILE);
|
||||
}
|
||||
|
||||
// Save the provider
|
||||
await page.click('button:has-text("Save Provider")');
|
||||
|
||||
// Verify we're redirected back to the providers list
|
||||
await expect(page.locator('h1:has-text("Storage Providers")')).toBeVisible();
|
||||
|
||||
// Verify our new provider is in the list - using more specific selector
|
||||
await expect(page.locator('.text-blue-600.truncate:has-text("Test SFTP Provider")')).toBeVisible();
|
||||
|
||||
// Optionally test the connection if not using stubs
|
||||
if (process.env.TEST_USE_STUBBED_PROVIDERS !== 'true') {
|
||||
await testProviderConnection(page, 'Test SFTP Provider');
|
||||
}
|
||||
});
|
||||
|
||||
// Test creating a new FTP storage provider
|
||||
test('can create a new FTP storage provider', async ({ page }) => {
|
||||
// Create a provider using the helper function
|
||||
const providerName = await createStorageProvider(page, {
|
||||
name: 'Test FTP Provider',
|
||||
type: 'ftp',
|
||||
host: process.env.FTP_HOST || 'ftp.example.com',
|
||||
port: process.env.FTP_PORT || '21',
|
||||
username: process.env.FTP_USERNAME || 'ftpuser',
|
||||
password: process.env.FTP_PASSWORD || 'ftppassword'
|
||||
});
|
||||
|
||||
// Verify our new provider is in the list
|
||||
await expect(page.locator(`.text-blue-600.truncate:has-text("${providerName}")`)).toBeVisible();
|
||||
|
||||
// Optionally test the connection if not using stubs
|
||||
if (process.env.TEST_USE_STUBBED_PROVIDERS !== 'true') {
|
||||
await testProviderConnection(page, providerName);
|
||||
}
|
||||
});
|
||||
|
||||
// Test creating a new Hetzner storage provider
|
||||
test('can create a new Hetzner storage provider', async ({ page }) => {
|
||||
// Create a provider using the helper function
|
||||
const providerName = await createStorageProvider(page, {
|
||||
name: 'Test Hetzner Provider',
|
||||
type: 'hetzner',
|
||||
host: process.env.HETZNER_HOST || 'u123456.your-storagebox.de',
|
||||
port: process.env.HETZNER_PORT || '23',
|
||||
username: process.env.HETZNER_USERNAME || 'u123456',
|
||||
password: process.env.HETZNER_PASSWORD || 'hetznerpassword'
|
||||
});
|
||||
|
||||
// Verify our new provider is in the list
|
||||
await expect(page.locator(`.text-blue-600.truncate:has-text("${providerName}")`)).toBeVisible();
|
||||
|
||||
// Optionally test the connection if not using stubs
|
||||
if (process.env.TEST_USE_STUBBED_PROVIDERS !== 'true') {
|
||||
await testProviderConnection(page, providerName);
|
||||
}
|
||||
});
|
||||
|
||||
// Test creating a new SMB/CIFS storage provider
|
||||
test('can create a new SMB/CIFS storage provider', async ({ page }) => {
|
||||
// Create a provider using the helper function
|
||||
const providerName = await createStorageProvider(page, {
|
||||
name: 'Test SMB Provider',
|
||||
type: 'smb',
|
||||
host: process.env.SMB_HOST || 'fileserver.example.com',
|
||||
port: process.env.SMB_PORT || '445',
|
||||
username: process.env.SMB_USERNAME || 'smbuser',
|
||||
password: process.env.SMB_PASSWORD || 'smbpassword',
|
||||
share: process.env.SMB_SHARE || 'Shared',
|
||||
domain: process.env.SMB_DOMAIN || 'WORKGROUP'
|
||||
});
|
||||
|
||||
// Verify our new provider is in the list
|
||||
await expect(page.locator(`.text-blue-600.truncate:has-text("${providerName}")`)).toBeVisible();
|
||||
|
||||
// Optionally test the connection if not using stubs
|
||||
if (process.env.TEST_USE_STUBBED_PROVIDERS !== 'true') {
|
||||
await testProviderConnection(page, providerName);
|
||||
}
|
||||
});
|
||||
|
||||
// Test creating a new S3 storage provider
|
||||
test('can create a new S3 storage provider', async ({ page }) => {
|
||||
// Create a provider using the helper function
|
||||
const providerName = await createStorageProvider(page, {
|
||||
name: 'Test S3 Provider',
|
||||
type: 's3',
|
||||
endpoint: process.env.S3_ENDPOINT || 's3.amazonaws.com',
|
||||
region: process.env.S3_REGION || 'us-east-1',
|
||||
bucket: process.env.S3_BUCKET || 'test-bucket',
|
||||
accessKey: process.env.S3_ACCESS_KEY || 'AKIAIOSFODNN7EXAMPLE',
|
||||
secretKey: process.env.S3_SECRET_KEY || 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'
|
||||
});
|
||||
|
||||
// Verify our new provider is in the list
|
||||
await expect(page.locator(`.text-blue-600.truncate:has-text("${providerName}")`)).toBeVisible();
|
||||
|
||||
// Optionally test the connection if not using stubs
|
||||
if (process.env.TEST_USE_STUBBED_PROVIDERS !== 'true') {
|
||||
await testProviderConnection(page, providerName);
|
||||
}
|
||||
});
|
||||
|
||||
// Test creating a new Wasabi storage provider
|
||||
test('can create a new Wasabi storage provider', async ({ page }) => {
|
||||
// Create a provider using the helper function
|
||||
const providerName = await createStorageProvider(page, {
|
||||
name: 'Test Wasabi Provider',
|
||||
type: 'wasabi',
|
||||
endpoint: process.env.WASABI_ENDPOINT || 's3.wasabisys.com',
|
||||
region: process.env.WASABI_REGION || 'us-east-1',
|
||||
bucket: process.env.WASABI_BUCKET || 'wasabi-test-bucket',
|
||||
accessKey: process.env.WASABI_ACCESS_KEY || 'WASABIEXAMPLEKEY',
|
||||
secretKey: process.env.WASABI_SECRET_KEY || 'wasabiexamplesecretkey12345'
|
||||
});
|
||||
|
||||
// Verify our new provider is in the list
|
||||
await expect(page.locator(`.text-blue-600.truncate:has-text("${providerName}")`)).toBeVisible();
|
||||
|
||||
// Optionally test the connection if not using stubs
|
||||
if (process.env.TEST_USE_STUBBED_PROVIDERS !== 'true') {
|
||||
await testProviderConnection(page, providerName);
|
||||
}
|
||||
});
|
||||
|
||||
// Test creating a new MinIO storage provider
|
||||
test('can create a new MinIO storage provider', async ({ page }) => {
|
||||
// Create a provider using the helper function
|
||||
const providerName = await createStorageProvider(page, {
|
||||
name: 'Test MinIO Provider',
|
||||
type: 'minio',
|
||||
endpoint: process.env.MINIO_ENDPOINT || 'play.min.io',
|
||||
region: process.env.MINIO_REGION || 'us-east-1',
|
||||
bucket: process.env.MINIO_BUCKET || 'minio-test-bucket',
|
||||
accessKey: process.env.MINIO_ACCESS_KEY || 'Q3AM3UQ867SPQQA43P2F',
|
||||
secretKey: process.env.MINIO_SECRET_KEY || 'zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG'
|
||||
});
|
||||
|
||||
// Verify our new provider is in the list
|
||||
await expect(page.locator(`.text-blue-600.truncate:has-text("${providerName}")`)).toBeVisible();
|
||||
|
||||
// Optionally test the connection if not using stubs
|
||||
if (process.env.TEST_USE_STUBBED_PROVIDERS !== 'true') {
|
||||
await testProviderConnection(page, providerName);
|
||||
}
|
||||
});
|
||||
|
||||
// Test creating a new Backblaze B2 storage provider
|
||||
test('can create a new Backblaze B2 storage provider', async ({ page }) => {
|
||||
// Create a provider using the helper function
|
||||
const providerName = await createStorageProvider(page, {
|
||||
name: 'Test B2 Provider',
|
||||
type: 'b2',
|
||||
endpoint: process.env.B2_ENDPOINT || 's3.us-west-002.backblazeb2.com',
|
||||
region: process.env.B2_REGION || 'us-west-002',
|
||||
bucket: process.env.B2_BUCKET || 'b2-test-bucket',
|
||||
accessKey: process.env.B2_ACCESS_KEY || 'B2EXAMPLEKEYID',
|
||||
secretKey: process.env.B2_SECRET_KEY || 'b2examplesecretkeyvalueforbackblazeb2'
|
||||
});
|
||||
|
||||
// Verify our new provider is in the list
|
||||
await expect(page.locator(`.text-blue-600.truncate:has-text("${providerName}")`)).toBeVisible();
|
||||
|
||||
// Optionally test the connection if not using stubs
|
||||
if (process.env.TEST_USE_STUBBED_PROVIDERS !== 'true') {
|
||||
await testProviderConnection(page, providerName);
|
||||
}
|
||||
});
|
||||
|
||||
// Test creating a new WebDAV storage provider
|
||||
test('can create a new WebDAV storage provider', async ({ page }) => {
|
||||
// Create a provider using the helper function
|
||||
const providerName = await createStorageProvider(page, {
|
||||
name: 'Test WebDAV Provider',
|
||||
type: 'webdav',
|
||||
host: process.env.WEBDAV_HOST || 'webdav.example.com',
|
||||
port: process.env.WEBDAV_PORT || '443',
|
||||
username: process.env.WEBDAV_USERNAME || 'webdavuser',
|
||||
password: process.env.WEBDAV_PASSWORD || 'webdavpassword'
|
||||
});
|
||||
|
||||
// Verify our new provider is in the list
|
||||
await expect(page.locator(`.text-blue-600.truncate:has-text("${providerName}")`)).toBeVisible();
|
||||
|
||||
// Optionally test the connection if not using stubs
|
||||
if (process.env.TEST_USE_STUBBED_PROVIDERS !== 'true') {
|
||||
await testProviderConnection(page, providerName);
|
||||
}
|
||||
});
|
||||
|
||||
// Test creating a new Nextcloud storage provider
|
||||
test('can create a new Nextcloud storage provider', async ({ page }) => {
|
||||
// Create a provider using the helper function
|
||||
const providerName = await createStorageProvider(page, {
|
||||
name: 'Test Nextcloud Provider',
|
||||
type: 'nextcloud',
|
||||
host: process.env.NEXTCLOUD_HOST || 'nextcloud.example.com',
|
||||
port: process.env.NEXTCLOUD_PORT || '443',
|
||||
username: process.env.NEXTCLOUD_USERNAME || 'nextclouduser',
|
||||
password: process.env.NEXTCLOUD_PASSWORD || 'nextcloudpassword'
|
||||
});
|
||||
|
||||
// Verify our new provider is in the list
|
||||
await expect(page.locator(`.text-blue-600.truncate:has-text("${providerName}")`)).toBeVisible();
|
||||
|
||||
// Optionally test the connection if not using stubs
|
||||
if (process.env.TEST_USE_STUBBED_PROVIDERS !== 'true') {
|
||||
await testProviderConnection(page, providerName);
|
||||
}
|
||||
});
|
||||
|
||||
// Test creating a new Google Drive provider
|
||||
test('can create a new Google Drive provider', async ({ page }) => {
|
||||
// Create a provider using the helper function
|
||||
const providerName = await createStorageProvider(page, {
|
||||
name: 'Test Google Drive Provider',
|
||||
type: 'gdrive',
|
||||
clientID: process.env.GDRIVE_CLIENT_ID || '1234567890-abcdefghijklmnopqrstuvwxyz.apps.googleusercontent.com',
|
||||
clientSecret: process.env.GDRIVE_CLIENT_SECRET || 'GOCSPX-abcdefghijklmnopqrstuvwxyz',
|
||||
driveID: process.env.GDRIVE_DRIVE_ID,
|
||||
teamDrive: process.env.GDRIVE_TEAM_DRIVE
|
||||
});
|
||||
|
||||
// Verify our new provider is in the list
|
||||
await expect(page.locator(`.text-blue-600.truncate:has-text("${providerName}")`)).toBeVisible();
|
||||
|
||||
// Note: We don't test connection for cloud providers as they require OAuth authentication
|
||||
});
|
||||
|
||||
// Test creating a new Google Photos provider
|
||||
test('can create a new Google Photos provider', async ({ page }) => {
|
||||
// Create a provider using the helper function
|
||||
const providerName = await createStorageProvider(page, {
|
||||
name: 'Test Google Photos Provider',
|
||||
type: 'gphotos',
|
||||
clientID: process.env.GPHOTOS_CLIENT_ID || '1234567890-abcdefghijklmnopqrstuvwxyz.apps.googleusercontent.com',
|
||||
clientSecret: process.env.GPHOTOS_CLIENT_SECRET || 'GOCSPX-abcdefghijklmnopqrstuvwxyz'
|
||||
});
|
||||
|
||||
// Verify our new provider is in the list
|
||||
await expect(page.locator(`.text-blue-600.truncate:has-text("${providerName}")`)).toBeVisible();
|
||||
|
||||
// Note: We don't test connection for cloud providers as they require OAuth authentication
|
||||
});
|
||||
|
||||
// Test creating a new OneDrive provider
|
||||
test('can create a new OneDrive provider', async ({ page }) => {
|
||||
// Create a provider using the helper function
|
||||
const providerName = await createStorageProvider(page, {
|
||||
name: 'Test OneDrive Provider',
|
||||
type: 'onedrive',
|
||||
clientID: process.env.ONEDRIVE_CLIENT_ID || '12345678-1234-1234-1234-123456789012',
|
||||
clientSecret: process.env.ONEDRIVE_CLIENT_SECRET || 'abc~12345678901234567890abcdefghijklmn'
|
||||
});
|
||||
|
||||
// Verify our new provider is in the list
|
||||
await expect(page.locator(`.text-blue-600.truncate:has-text("${providerName}")`)).toBeVisible();
|
||||
|
||||
// Note: We don't test connection for cloud providers as they require OAuth authentication
|
||||
});
|
||||
|
||||
// Test creating a local file system provider
|
||||
test('can create a new local filesystem provider', async ({ page }) => {
|
||||
// Create a provider using the helper function
|
||||
const providerName = await createStorageProvider(page, {
|
||||
name: 'Test Local Provider',
|
||||
type: 'local',
|
||||
localPath: process.env.LOCAL_PATH || '/tmp/test-storage'
|
||||
});
|
||||
|
||||
// Verify our new provider is in the list
|
||||
await expect(page.locator(`.text-blue-600.truncate:has-text("${providerName}")`)).toBeVisible();
|
||||
|
||||
// Optionally test the connection if not using stubs
|
||||
if (process.env.TEST_USE_STUBBED_PROVIDERS !== 'true') {
|
||||
await testProviderConnection(page, providerName);
|
||||
}
|
||||
});
|
||||
|
||||
// Test editing a storage provider
|
||||
test('can edit an existing storage provider', async ({ page }) => {
|
||||
// Create a provider first
|
||||
const providerName = await createStorageProvider(page, {
|
||||
name: 'Provider To Edit',
|
||||
type: 'sftp',
|
||||
host: 'original.example.com',
|
||||
port: '22',
|
||||
username: 'original',
|
||||
password: 'password'
|
||||
});
|
||||
|
||||
// Find and click the edit button for this provider
|
||||
const providerRow = page.locator(`li:has(.text-blue-600.truncate:has-text("${providerName}"))`);
|
||||
await providerRow.locator('a:has-text("Edit")').click();
|
||||
|
||||
// Verify we're on the edit page
|
||||
await expect(page.locator('h1:has-text("Edit Storage Provider")')).toBeVisible();
|
||||
|
||||
// Change the name and host
|
||||
await page.fill('#name', 'Edited Provider');
|
||||
await page.fill('#host', 'edited.example.com');
|
||||
|
||||
// Save the changes
|
||||
await page.click('button:has-text("Save Provider")');
|
||||
|
||||
// Verify we're back at the list
|
||||
await expect(page.locator('h1:has-text("Storage Providers")')).toBeVisible();
|
||||
|
||||
// Verify the updated provider name is showing
|
||||
await expect(page.locator('.text-blue-600.truncate:has-text("Edited Provider")')).toBeVisible();
|
||||
await expect(page.locator('li:has(.text-blue-600.truncate:has-text("Edited Provider"))').locator('text=edited.example.com')).toBeVisible();
|
||||
});
|
||||
|
||||
// Test testing a storage provider connection
|
||||
test('can test a storage provider connection', async ({ page }) => {
|
||||
// Create a provider to test
|
||||
const providerName = await createStorageProvider(page, {
|
||||
name: 'Provider To Test Connection',
|
||||
type: 'local',
|
||||
localPath: '/tmp/test-connection'
|
||||
});
|
||||
|
||||
// Test the connection
|
||||
await testProviderConnection(page, providerName);
|
||||
|
||||
// Toast should be visible (we don't assert success because it depends on actual connection ability)
|
||||
await expect(page.locator('.toast')).toBeVisible();
|
||||
});
|
||||
|
||||
// Test duplicating a storage provider
|
||||
test('can duplicate a storage provider', async ({ page }) => {
|
||||
// Create a provider to duplicate
|
||||
const providerName = await createStorageProvider(page, {
|
||||
name: 'Provider To Duplicate',
|
||||
type: 'local',
|
||||
localPath: '/tmp/duplicate-test'
|
||||
});
|
||||
|
||||
// Navigate to storage providers
|
||||
await page.goto('/storage-providers');
|
||||
|
||||
// Find the provider to duplicate
|
||||
const providerRow = page.locator(`li:has(.text-blue-600.truncate:has-text("${providerName}"))`);
|
||||
|
||||
// Click the duplicate button
|
||||
await providerRow.locator('button:has-text("Duplicate")').click();
|
||||
|
||||
// There should now be a provider with the same name in the list more than once
|
||||
await expect(page.locator(`.text-blue-600.truncate:has-text("${providerName}")`).count()).toBeGreaterThan(1);
|
||||
});
|
||||
|
||||
// Test deleting a storage provider
|
||||
test('can delete a storage provider', async ({ page }) => {
|
||||
// Create a provider to delete
|
||||
const providerName = await createStorageProvider(page, {
|
||||
name: 'Provider To Delete',
|
||||
type: 'local',
|
||||
localPath: '/tmp/delete-me'
|
||||
});
|
||||
|
||||
// Navigate back to the providers list to refresh
|
||||
await page.goto('/storage-providers');
|
||||
|
||||
// Verify the provider was created
|
||||
await expect(page.locator(`.text-blue-600.truncate:has-text("${providerName}")`)).toBeVisible();
|
||||
|
||||
// Find and click the delete button for this provider
|
||||
const providerRow = page.locator(`li:has(.text-blue-600.truncate:has-text("${providerName}"))`);
|
||||
await providerRow.locator('button:has-text("Delete"):not([hx-delete])').click();
|
||||
|
||||
// A confirmation dialog should appear - confirm deletion
|
||||
await page.locator('button[hx-delete]:has-text("Delete"):visible').click();
|
||||
|
||||
// Verify the provider is no longer in the list
|
||||
await expect(page.locator(`.text-blue-600.truncate:has-text("${providerName}")`)).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,222 @@
|
||||
// @ts-check
|
||||
import { expect } from '@playwright/test';
|
||||
import dotenv from 'dotenv';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
// Load environment variables from .env.test if it exists
|
||||
const testEnvPath = path.join(process.cwd(), '.env.test');
|
||||
if (fs.existsSync(testEnvPath)) {
|
||||
dotenv.config({ path: testEnvPath });
|
||||
} else {
|
||||
// Fallback to regular .env
|
||||
dotenv.config();
|
||||
}
|
||||
|
||||
// Store providers created during the test so we can clean them up
|
||||
const createdProviders = new Set();
|
||||
|
||||
/**
|
||||
* Custom expect extension to wait for toast notifications
|
||||
*/
|
||||
expect.extend({
|
||||
async toShowToast(page, type, message) {
|
||||
const toastSelector = type ? `.toast-${type}` : '.toast';
|
||||
|
||||
try {
|
||||
await page.waitForSelector(toastSelector, { timeout: 5000 });
|
||||
|
||||
if (message) {
|
||||
const toastContent = await page.locator(toastSelector).textContent();
|
||||
return {
|
||||
pass: toastContent?.includes(message),
|
||||
message: () => `Expected toast to contain "${message}" but found "${toastContent}"`
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
pass: true,
|
||||
message: () => `Toast of type ${type || 'any'} was found`
|
||||
};
|
||||
} catch (e) {
|
||||
return {
|
||||
pass: false,
|
||||
message: () => `Toast of type ${type || 'any'} was not found: ${e.message}`
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Helper to log in a user
|
||||
* @param {import('@playwright/test').Page} page
|
||||
* @param {string} username
|
||||
* @param {string} password
|
||||
*/
|
||||
export async function login(page, username, password) {
|
||||
// Navigate to the login page
|
||||
await page.goto('/login');
|
||||
|
||||
// Check that we're on the login page
|
||||
await expect(page.locator('h2:has-text("Sign In")')).toBeVisible();
|
||||
|
||||
// Fill in login form
|
||||
await page.fill('#email', username);
|
||||
await page.fill('#password', password);
|
||||
|
||||
// Submit the form
|
||||
await page.click('button:has-text("Sign in")');
|
||||
|
||||
// Wait for navigation to complete (dashboard should load)
|
||||
await page.waitForURL('**/dashboard');
|
||||
|
||||
// Verify we're logged in by checking for user menu
|
||||
await expect(page.locator('#user-menu-button')).toBeVisible();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to create a storage provider for testing
|
||||
* @param {import('@playwright/test').Page} page
|
||||
* @param {Object} providerData
|
||||
* @returns {Promise<string>} The name of the created provider
|
||||
*/
|
||||
export async function createStorageProvider(page, providerData) {
|
||||
// Navigate to the storage providers page
|
||||
await page.goto('/storage-providers');
|
||||
|
||||
// Click on "New Provider" button
|
||||
await page.click('a:has-text("New Provider")');
|
||||
|
||||
// Fill in the common fields
|
||||
await page.fill('#name', providerData.name);
|
||||
await page.selectOption('#type', providerData.type);
|
||||
|
||||
// Fill in type-specific fields
|
||||
switch (providerData.type) {
|
||||
case 'sftp':
|
||||
case 'ftp':
|
||||
case 'hetzner':
|
||||
await page.fill('#host', providerData.host || 'test.example.com');
|
||||
if (providerData.port) await page.fill('#port', providerData.port);
|
||||
await page.fill('#username', providerData.username || 'testuser');
|
||||
await page.fill('#password', providerData.password || 'testpass');
|
||||
break;
|
||||
|
||||
case 'smb':
|
||||
await page.fill('#host', providerData.host || 'fileserver.example.com');
|
||||
if (providerData.port) await page.fill('#port', providerData.port);
|
||||
await page.fill('#username', providerData.username || 'smbuser');
|
||||
await page.fill('#password', providerData.password || 'smbpassword');
|
||||
await page.fill('#share', providerData.share || 'Shared');
|
||||
if (providerData.domain) await page.fill('#domain', providerData.domain);
|
||||
break;
|
||||
|
||||
case 's3':
|
||||
case 'wasabi':
|
||||
case 'minio':
|
||||
await page.fill('#endpoint', providerData.endpoint || 's3.example.com');
|
||||
await page.fill('#region', providerData.region || 'us-east-1');
|
||||
await page.fill('#bucket', providerData.bucket || 'test-bucket');
|
||||
await page.fill('#accessKey', providerData.accessKey || 'AKIATEST');
|
||||
await page.fill('#secretKey', providerData.secretKey || 'secretkey123');
|
||||
break;
|
||||
|
||||
case 'gdrive':
|
||||
case 'gphotos':
|
||||
case 'onedrive':
|
||||
await page.fill('#clientID', providerData.clientID || '123456789012-abcdef.apps.googleusercontent.com');
|
||||
await page.fill('#clientSecret', providerData.clientSecret || 'GOCSPX-abcdefghij');
|
||||
break;
|
||||
|
||||
case 'local':
|
||||
await page.fill('#localPath', providerData.localPath || '/tmp/test-path');
|
||||
break;
|
||||
}
|
||||
|
||||
// Save the provider
|
||||
await page.click('button:has-text("Save Provider")');
|
||||
|
||||
// Wait to be redirected back to the list
|
||||
await page.waitForURL('**/storage-providers*');
|
||||
|
||||
// Add to the list of created providers for cleanup
|
||||
createdProviders.add(providerData.name);
|
||||
|
||||
return providerData.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to delete a storage provider by name
|
||||
* @param {import('@playwright/test').Page} page
|
||||
* @param {string} providerName Name of the provider to delete
|
||||
*/
|
||||
export async function deleteStorageProvider(page, providerName) {
|
||||
// Navigate to the storage providers page
|
||||
await page.goto('/storage-providers');
|
||||
|
||||
// Look for the provider with the given name
|
||||
const providerRow = page.locator(`li:has(.text-blue-600.truncate:has-text("${providerName}"))`);
|
||||
|
||||
// Check if the provider exists
|
||||
if (await providerRow.count() === 0) {
|
||||
return; // Provider doesn't exist or was already deleted
|
||||
}
|
||||
|
||||
// Click the delete button - Using a more specific selector to get only the visible button with the trash icon
|
||||
await providerRow.locator('button:has-text("Delete"):not([hx-delete])').click();
|
||||
|
||||
// Confirm deletion in the dialog - use a more specific selector for the confirmation button
|
||||
await page.locator('button[hx-delete]:has-text("Delete"):visible').click();
|
||||
|
||||
// Wait for the toast notification
|
||||
try {
|
||||
await page.waitForSelector('.toast', { timeout: 5000 });
|
||||
} catch (e) {
|
||||
// Continue even if toast doesn't appear
|
||||
}
|
||||
|
||||
// Remove from the set of created providers
|
||||
createdProviders.delete(providerName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup all created providers
|
||||
* @param {import('@playwright/test').Page} page
|
||||
*/
|
||||
export async function cleanupCreatedProviders(page) {
|
||||
// Only attempt cleanup if there are providers to clean up
|
||||
if (createdProviders.size === 0) return;
|
||||
|
||||
// Navigate to the storage providers page
|
||||
await page.goto('/storage-providers');
|
||||
|
||||
// Delete each created provider
|
||||
for (const providerName of createdProviders) {
|
||||
await deleteStorageProvider(page, providerName);
|
||||
}
|
||||
|
||||
// Clear the set
|
||||
createdProviders.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to test a provider connection
|
||||
* @param {import('@playwright/test').Page} page
|
||||
* @param {string} providerName Name of the provider to test
|
||||
*/
|
||||
export async function testProviderConnection(page, providerName) {
|
||||
// Navigate to the storage providers page
|
||||
await page.goto('/storage-providers');
|
||||
|
||||
// Find the provider row
|
||||
const providerRow = page.locator(`li:has(.text-blue-600.truncate:has-text("${providerName}"))`);
|
||||
|
||||
// Click the test button
|
||||
await providerRow.locator('button:has-text("Test")').click();
|
||||
|
||||
// Wait for toast notification
|
||||
await page.waitForSelector('.toast', { timeout: 10000 });
|
||||
|
||||
// Return whether it was successful (toast-success) or not
|
||||
return await page.locator('.toast-success').count() > 0;
|
||||
}
|
||||
Reference in New Issue
Block a user