Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add settings e2e test #6776

Merged
merged 5 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions gui/test/e2e/installed/state-dependent/settings.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { expect, Page, test } from '@playwright/test';
import { execSync } from 'child_process';
import os from 'os';
import path from 'path';

import { fileExists, TestUtils } from '../../utils';
import { startInstalledApp } from '../installed-utils';

function getAutoStartPath() {
return path.join(os.homedir(), '.config', 'autostart', 'mullvad-vpn.desktop');
}

function autoStartPathExists() {
return fileExists(getAutoStartPath());
}

let page: Page;
let util: TestUtils;

test.beforeAll(async () => {
({ page, util } = await startInstalledApp());
});

test.afterAll(async () => {
await page.close();
});

test.describe('VPN Settings', () => {
test('Auto-connect setting', async () => {
// Navigate to the VPN settings view
await util.waitForNavigation(() => page.click('button[aria-label="Settings"]'));
await util.waitForNavigation(() => page.click('text=VPN settings'));

// Find the auto-connect toggle
const autoConnectToggle = page.getByText('Auto-connect').locator('..').getByRole('checkbox');

// Check initial state
const initialCliState = execSync('mullvad auto-connect get').toString().trim();
expect(initialCliState).toMatch(/off$/);
await expect(autoConnectToggle).toHaveAttribute('aria-checked', 'false');

// Toggle auto-connect
await autoConnectToggle.click();

// Verify the setting was applied correctly
await expect(autoConnectToggle).toHaveAttribute('aria-checked', 'true');
const newCliState = execSync('mullvad auto-connect get').toString().trim();
expect(newCliState).toMatch(/off$/);
});

test('Launch on startup setting', async () => {
// Find the launch on start-up toggle
const launchOnStartupToggle = page
.getByText('Launch app on start-up')
.locator('..')
.getByRole('checkbox');

// Check initial state
const initialCliState = execSync('mullvad auto-connect get').toString().trim();
expect(initialCliState).toMatch(/off$/);
await expect(launchOnStartupToggle).toHaveAttribute('aria-checked', 'false');
if (process.platform === 'linux') {
expect(autoStartPathExists()).toBeFalsy();
}

// Toggle launch on start-up
await launchOnStartupToggle.click();

// Verify the setting was applied correctly
await expect(launchOnStartupToggle).toHaveAttribute('aria-checked', 'true');
if (process.platform === 'linux') {
expect(autoStartPathExists()).toBeTruthy();
}
const newCliState = execSync('mullvad auto-connect get').toString().trim();
expect(newCliState).toMatch(/on$/);

await launchOnStartupToggle.click();

// Toggle auto-connect back off
// NOTE: This must be done to clean up the auto-start file
// TODO: Reset GUI settings between all tests
const autoConnectToggle = page.getByText('Auto-connect').locator('..').getByRole('checkbox');
await autoConnectToggle.click();
});

test('LAN settings', async () => {
// Find the LAN toggle
const lanToggle = page.getByText('Local network sharing').locator('..').getByRole('checkbox');

// Check initial state
const initialCliState = execSync('mullvad lan get').toString().trim();
expect(initialCliState).toMatch(/block$/);
await expect(lanToggle).toHaveAttribute('aria-checked', 'false');

// Toggle LAN setting
await lanToggle.click();

// Verify the setting was applied correctly
await expect(lanToggle).toHaveAttribute('aria-checked', 'true');
const newState = execSync('mullvad lan get').toString().trim();
expect(newState).toMatch(/allow$/);
});
});
10 changes: 10 additions & 0 deletions gui/test/e2e/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import fs from 'fs';
import { _electron as electron, ElectronApplication, Locator, Page } from 'playwright';

export interface StartAppResponse {
Expand Down Expand Up @@ -122,3 +123,12 @@ export function anyOf(...values: string[]): RegExp {
export function escapeRegExp(regexp: string): string {
return regexp.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}

export function fileExists(filePath: string): boolean {
try {
fs.accessSync(filePath);
return true;
} catch {
return false;
}
}
1 change: 1 addition & 0 deletions test/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions test/scripts/ssh-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ for file in test-runner connection-checker $APP_PACKAGE $PREVIOUS_APP $UI_RUNNER
cp -f "$SCRIPT_DIR/$file" "$RUNNER_DIR"
done

# Unprivileged users need execute rights for connection checker
chmod 551 "${RUNNER_DIR}/connection-checker"
# Unprivileged users need execute rights for some executables
chmod 775 "${RUNNER_DIR}/connection-checker"
chmod 775 "${RUNNER_DIR}/$UI_RUNNER"

chown -R root "$RUNNER_DIR/"

Expand Down
8 changes: 8 additions & 0 deletions test/test-manager/src/tests/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,3 +284,11 @@ pub async fn test_obfuscation_settings_ui(_: TestContext, rpc: ServiceClient) ->
assert!(ui_result.success());
Ok(())
}

/// Test settings in the GUI
#[test_function]
pub async fn test_settings_ui(_: TestContext, rpc: ServiceClient) -> Result<(), Error> {
let ui_result = run_test(&rpc, &["settings.spec"]).await?;
assert!(ui_result.success());
Ok(())
}
1 change: 1 addition & 0 deletions test/test-runner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ rust-version.workspace = true
workspace = true

[dependencies]
dirs = "5.0.1"
futures = { workspace = true }
tarpc = { workspace = true }
tokio = { workspace = true }
Expand Down
18 changes: 15 additions & 3 deletions test/test-runner/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,24 @@ impl Service for TestServer {
log::debug!("Exec {} (args: {args:?})", path);

let mut cmd = Command::new(&path);
cmd.stdout(Stdio::piped());
cmd.stderr(Stdio::piped());
cmd.stdin(Stdio::piped());
cmd.args(args);

// Make sure that PATH is updated
// TODO: We currently do not need this on non-Windows
#[cfg(target_os = "windows")]
cmd.env("PATH", sys::get_system_path_var()?);
{
// Make sure that PATH is updated
cmd.env("PATH", sys::get_system_path_var()?);
if let Some(home_dir) = dirs::home_dir() {
cmd.env("USERPROFILE", home_dir);
}
}

#[cfg(unix)]
if let Some(home_dir) = dirs::home_dir() {
cmd.env("HOME", home_dir);
}

cmd.envs(env);

Expand Down
Loading