summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOskar <oskar@mullvad.net>2024-09-20 16:29:26 +0200
committerOskar <oskar@mullvad.net>2024-09-24 13:18:18 +0200
commit4bb25616f02af4e15b0140767c07b61e49e8aa83 (patch)
treeed5371911d23ba2bab8e701f351d822202d63d57
parent659aa11f05ae2b278eef6ab0ef5bc537e756109a (diff)
downloadmullvadvpn-4bb25616f02af4e15b0140767c07b61e49e8aa83.tar.xz
mullvadvpn-4bb25616f02af4e15b0140767c07b61e49e8aa83.zip
Fix linting errors
-rw-r--r--gui/scripts/extract-translations.js2
-rw-r--r--gui/scripts/verify-translations-format.ts20
-rw-r--r--gui/src/main/daemon-rpc.ts2
-rw-r--r--gui/src/main/index.ts5
-rw-r--r--gui/src/main/linux-desktop-entry.ts1
-rw-r--r--gui/src/main/linux-split-tunneling.ts4
-rw-r--r--gui/src/main/logging.ts2
-rw-r--r--gui/src/main/user-interface.ts2
-rw-r--r--gui/src/main/windows-split-tunneling.ts2
-rw-r--r--gui/src/renderer/app.tsx2
-rw-r--r--gui/src/renderer/components/ClipboardLabel.tsx2
-rw-r--r--gui/src/renderer/components/EditApiAccessMethod.tsx2
-rw-r--r--gui/src/renderer/components/ImageView.tsx1
-rw-r--r--gui/src/renderer/components/Login.tsx2
-rw-r--r--gui/src/renderer/components/NotificationBanner.tsx2
-rw-r--r--gui/src/renderer/components/ProblemReport.tsx6
-rw-r--r--gui/src/renderer/components/main-view/FeatureIndicators.tsx2
-rw-r--r--gui/src/renderer/lib/ip.ts18
-rw-r--r--gui/tasks/assets.js9
-rw-r--r--gui/tasks/distribution.js96
-rw-r--r--gui/tasks/scripts.js4
-rw-r--r--gui/test/e2e/installed/installed-utils.ts2
-rw-r--r--gui/test/e2e/installed/playwright.config.ts2
-rw-r--r--gui/test/e2e/installed/state-dependent/api-access-methods.spec.ts30
-rw-r--r--gui/test/e2e/installed/state-dependent/custom-bridge.spec.ts73
-rw-r--r--gui/test/e2e/installed/state-dependent/device-revoked.spec.ts8
-rw-r--r--gui/test/e2e/installed/state-dependent/disconnected.spec.ts2
-rw-r--r--gui/test/e2e/installed/state-dependent/location.spec.ts3
-rw-r--r--gui/test/e2e/installed/state-dependent/login.spec.ts72
-rw-r--r--gui/test/e2e/installed/state-dependent/macos-split-tunneling.spec.ts29
-rw-r--r--gui/test/e2e/installed/state-dependent/obfuscation.spec.ts36
-rw-r--r--gui/test/e2e/installed/state-dependent/settings-import.spec.ts64
-rw-r--r--gui/test/e2e/installed/state-dependent/too-many-devices.spec.ts19
-rw-r--r--gui/test/e2e/installed/state-dependent/tunnel-state.spec.ts16
-rw-r--r--gui/test/e2e/mocked/expired-account-error-view.spec.ts23
-rw-r--r--gui/test/e2e/mocked/feature-indicators.spec.ts39
-rw-r--r--gui/test/e2e/mocked/mocked-utils.ts4
-rw-r--r--gui/test/e2e/mocked/settings.spec.ts4
-rw-r--r--gui/test/e2e/mocked/tunnel-state.spec.ts15
-rw-r--r--gui/test/e2e/shared/tunnel-state.ts1
-rw-r--r--gui/test/e2e/utils.ts57
-rw-r--r--gui/test/unit/account-data-cache.spec.ts15
-rw-r--r--gui/test/unit/changelog.spec.ts3
-rw-r--r--gui/test/unit/date-helper.spec.ts88
-rw-r--r--gui/test/unit/history.spec.ts3
-rw-r--r--gui/test/unit/ip.spec.ts3
-rw-r--r--gui/test/unit/keyframe-animation.spec.ts3
-rw-r--r--gui/test/unit/list-diff.spec.ts3
-rw-r--r--gui/test/unit/logging.spec.ts7
-rw-r--r--gui/test/unit/notification-evaluation.spec.ts36
-rw-r--r--gui/test/unit/setup.ts2
-rw-r--r--gui/test/unit/tunnel-state.spec.ts4
52 files changed, 451 insertions, 401 deletions
diff --git a/gui/scripts/extract-translations.js b/gui/scripts/extract-translations.js
index 30e04e298a..e101ca03a5 100644
--- a/gui/scripts/extract-translations.js
+++ b/gui/scripts/extract-translations.js
@@ -1,4 +1,4 @@
-const { GettextExtractor, JsExtractors, HtmlExtractors } = require('gettext-extractor');
+const { GettextExtractor, JsExtractors } = require('gettext-extractor');
const path = require('path');
const extractor = new GettextExtractor();
diff --git a/gui/scripts/verify-translations-format.ts b/gui/scripts/verify-translations-format.ts
index e44997d579..eaba3ee7b7 100644
--- a/gui/scripts/verify-translations-format.ts
+++ b/gui/scripts/verify-translations-format.ts
@@ -62,14 +62,14 @@ function checkFormatSpecifiers(translation: GetTextTranslation): boolean {
.every((result) => result);
}
-function checkHtmlTagsImpl(value: string): { correct: boolean, amount: number } {
- const tagsRegexp = new RegExp("<.*?>", "g");
+function checkHtmlTagsImpl(value: string): { correct: boolean; amount: number } {
+ const tagsRegexp = new RegExp('<.*?>', 'g');
const tags = value.match(tagsRegexp) ?? [];
const tagTypes = tags.map((tag) => tag.slice(1, -1));
// Make sure tags match by pushing start-tags to a stack and matching closing tags with the last
// item.
- let tagStack: string[] = [];
+ const tagStack: string[] = [];
for (let tag of tagTypes) {
const selfClosing = tag.endsWith('/');
const endTag = tag.startsWith('/');
@@ -94,21 +94,23 @@ function checkHtmlTagsImpl(value: string): { correct: boolean, amount: number }
}
if (tagStack.length > 0) {
- console.error(`Missing closing-tags (${tagStack}) in "${value}"`);
- return { correct: false, amount: NaN };
+ console.error(`Missing closing-tags (${tagStack}) in "${value}"`);
+ return { correct: false, amount: NaN };
}
return { correct: true, amount: tags.length / 2 };
}
function checkHtmlTags(translation: GetTextTranslation): boolean {
- let { correct, amount: sourceAmount } = checkHtmlTagsImpl(translation.msgid);
+ const { correct, amount: sourceAmount } = checkHtmlTagsImpl(translation.msgid);
- let translationsCorrect = translation.msgstr.every((value) => {
- let { correct, amount } = checkHtmlTagsImpl(value);
+ const translationsCorrect = translation.msgstr.every((value) => {
+ const { correct, amount } = checkHtmlTagsImpl(value);
// The amount doesn't make sense if the string isn't correctly formatted.
if (correct && amount !== sourceAmount) {
- console.error(`Incorrect amount of tags in translation for "${translation.msgid}": "${value}"`);
+ console.error(
+ `Incorrect amount of tags in translation for "${translation.msgid}": "${value}"`,
+ );
}
return correct && amount === sourceAmount;
});
diff --git a/gui/src/main/daemon-rpc.ts b/gui/src/main/daemon-rpc.ts
index 31f6ddcfab..1c96be12bb 100644
--- a/gui/src/main/daemon-rpc.ts
+++ b/gui/src/main/daemon-rpc.ts
@@ -791,7 +791,6 @@ export class DaemonRpc {
}
private channelOptions(): grpc.ClientOptions {
- /* eslint-disable @typescript-eslint/naming-convention */
return {
'grpc.max_reconnect_backoff_ms': 3000,
'grpc.initial_reconnect_backoff_ms': 3000,
@@ -799,7 +798,6 @@ export class DaemonRpc {
'grpc.keepalive_timeout_ms': Math.pow(2, 30),
'grpc.client_idle_timeout_ms': Math.pow(2, 30),
};
- /* eslint-enable @typescript-eslint/naming-convention */
}
private connectivityChangeCallback(timeoutErr?: Error) {
diff --git a/gui/src/main/index.ts b/gui/src/main/index.ts
index c5144ee99e..be6c6609a0 100644
--- a/gui/src/main/index.ts
+++ b/gui/src/main/index.ts
@@ -70,6 +70,7 @@ import Version, { GUI_VERSION } from './version';
const execAsync = util.promisify(exec);
// Only import split tunneling library on correct OS.
+// eslint-disable-next-line @typescript-eslint/no-require-imports
const linuxSplitTunneling = process.platform === 'linux' && require('./linux-split-tunneling');
// This is used on Windows and macOS and will be undefined on Linux.
const splitTunneling: ISplitTunnelingAppListRetriever | undefined = importSplitTunneling();
@@ -1115,11 +1116,11 @@ class ApplicationMain
function importSplitTunneling() {
if (process.platform === 'win32') {
- // eslint-disable-next-line @typescript-eslint/no-var-requires
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
const { WindowsSplitTunnelingAppListRetriever } = require('./windows-split-tunneling');
return new WindowsSplitTunnelingAppListRetriever();
} else if (process.platform === 'darwin') {
- // eslint-disable-next-line @typescript-eslint/no-var-requires
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
const { MacOsSplitTunnelingAppListRetriever } = require('./macos-split-tunneling');
return new MacOsSplitTunnelingAppListRetriever();
}
diff --git a/gui/src/main/linux-desktop-entry.ts b/gui/src/main/linux-desktop-entry.ts
index d6c11c7943..7cc46862a5 100644
--- a/gui/src/main/linux-desktop-entry.ts
+++ b/gui/src/main/linux-desktop-entry.ts
@@ -265,7 +265,6 @@ function getGtkThemeDirectories(): Promise<DirectoryDescription[]> {
process.env.ORIGINAL_XDG_CURRENT_DESKTOP ?? process.env.XDG_CURRENT_DESKTOP ?? '';
child_process.exec(
'gsettings get org.gnome.desktop.interface icon-theme',
- // eslint-disable-next-line @typescript-eslint/naming-convention
{ env: { XDG_CURRENT_DESKTOP: xdgCurrentDesktop } },
(error, stdout) => {
if (error) {
diff --git a/gui/src/main/linux-split-tunneling.ts b/gui/src/main/linux-split-tunneling.ts
index 3ae1a15390..6d690aa453 100644
--- a/gui/src/main/linux-split-tunneling.ts
+++ b/gui/src/main/linux-split-tunneling.ts
@@ -113,7 +113,7 @@ export async function getApplications(locale: string): Promise<ILinuxSplitTunnel
for (const entryPath of desktopEntryPaths) {
try {
desktopEntries.push(await readDesktopEntry(entryPath, locale));
- } catch (e) {
+ } catch {
// no-op
}
}
@@ -141,7 +141,7 @@ async function replaceIconNameWithDataUrl(
}
return { ...app, icon: await getImageDataUrl(iconPath) };
- } catch (e) {
+ } catch {
return app;
}
}
diff --git a/gui/src/main/logging.ts b/gui/src/main/logging.ts
index f71e3a62f0..a1942d5007 100644
--- a/gui/src/main/logging.ts
+++ b/gui/src/main/logging.ts
@@ -113,7 +113,7 @@ function fileExists(filePath: string): boolean {
try {
fs.accessSync(filePath);
return true;
- } catch (e) {
+ } catch {
return false;
}
}
diff --git a/gui/src/main/user-interface.ts b/gui/src/main/user-interface.ts
index a0b4662c48..f7b81247ff 100644
--- a/gui/src/main/user-interface.ts
+++ b/gui/src/main/user-interface.ts
@@ -494,7 +494,7 @@ export default class UserInterface implements WindowControllerDelegate {
return;
}
- // eslint-disable-next-line @typescript-eslint/no-var-requires
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
const { NSEventMonitor, NSEventMask } = require('nseventmonitor');
const macEventMonitor = new NSEventMonitor();
const eventMask = NSEventMask.leftMouseDown | NSEventMask.rightMouseDown;
diff --git a/gui/src/main/windows-split-tunneling.ts b/gui/src/main/windows-split-tunneling.ts
index 5ba594f7cc..7ae73827d0 100644
--- a/gui/src/main/windows-split-tunneling.ts
+++ b/gui/src/main/windows-split-tunneling.ts
@@ -288,7 +288,7 @@ export class WindowsSplitTunnelingAppListRetriever implements ISplitTunnelingApp
let fileHandle: fs.promises.FileHandle;
try {
fileHandle = await fs.promises.open(path, fs.constants.O_RDONLY);
- } catch (e) {
+ } catch {
return false;
}
diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx
index a4d5fc2fad..c961d07258 100644
--- a/gui/src/renderer/app.tsx
+++ b/gui/src/renderer/app.tsx
@@ -400,7 +400,7 @@ export default class AppRenderer {
this.loginState = 'too many devices';
this.history.reset(RoutePath.tooManyDevices, { transition: transitions.push });
- } catch (e) {
+ } catch {
log.error('Failed to fetch device list');
actions.account.loginFailed('list-devices');
}
diff --git a/gui/src/renderer/components/ClipboardLabel.tsx b/gui/src/renderer/components/ClipboardLabel.tsx
index 582e03b02d..e9f760fd07 100644
--- a/gui/src/renderer/components/ClipboardLabel.tsx
+++ b/gui/src/renderer/components/ClipboardLabel.tsx
@@ -62,7 +62,7 @@ export default function ClipboardLabel(props: IProps) {
return (
<StyledLabelContainer>
<StyledLabel aria-hidden={obscured} {...otherProps}>
- {obscured ? '●●●● ●●●● ●●●● ●●●●' : displayValue ?? value}
+ {obscured ? '●●●● ●●●● ●●●● ●●●●' : (displayValue ?? value)}
</StyledLabel>
{obscureValue !== false && (
<StyledButton
diff --git a/gui/src/renderer/components/EditApiAccessMethod.tsx b/gui/src/renderer/components/EditApiAccessMethod.tsx
index 97996d7f42..a8602675a0 100644
--- a/gui/src/renderer/components/EditApiAccessMethod.tsx
+++ b/gui/src/renderer/components/EditApiAccessMethod.tsx
@@ -62,7 +62,7 @@ function AccessMethodForm() {
const onSave = useCallback(
async (newMethod: NamedCustomProxy) => {
- const enabled = id === undefined ? true : method?.enabled ?? true;
+ const enabled = id === undefined ? true : (method?.enabled ?? true);
updatedMethod.current = { ...newMethod, enabled };
if (
updatedMethod.current !== undefined &&
diff --git a/gui/src/renderer/components/ImageView.tsx b/gui/src/renderer/components/ImageView.tsx
index fa3855b21a..f40a93fbbc 100644
--- a/gui/src/renderer/components/ImageView.tsx
+++ b/gui/src/renderer/components/ImageView.tsx
@@ -46,7 +46,6 @@ export default function ImageView(props: IImageViewProps) {
? props.source
: `../../assets/images/${props.source}.svg`;
- // eslint-disable-next-line @typescript-eslint/naming-convention
const style = useMemo(() => ({ WebkitMaskImage: `url('${url}')` }), [url]);
if (props.tintColor) {
diff --git a/gui/src/renderer/components/Login.tsx b/gui/src/renderer/components/Login.tsx
index 32eb5bbe82..e5f981eafb 100644
--- a/gui/src/renderer/components/Login.tsx
+++ b/gui/src/renderer/components/Login.tsx
@@ -281,7 +281,7 @@ export default class Login extends React.Component<IProps, IState> {
await this.props.clearAccountHistory();
// TODO: Remove account from memory
- } catch (error) {
+ } catch {
// TODO: Show error
}
}
diff --git a/gui/src/renderer/components/NotificationBanner.tsx b/gui/src/renderer/components/NotificationBanner.tsx
index ad84ad3697..f79855f004 100644
--- a/gui/src/renderer/components/NotificationBanner.tsx
+++ b/gui/src/renderer/components/NotificationBanner.tsx
@@ -167,7 +167,7 @@ export function NotificationBanner(props: INotificationBannerProps) {
useEffect(() => {
const newHeight =
- props.children !== undefined ? contentRef.current?.getBoundingClientRect().height ?? 0 : 0;
+ props.children !== undefined ? (contentRef.current?.getBoundingClientRect().height ?? 0) : 0;
if (newHeight !== contentHeight) {
setContentHeight(newHeight);
setAlignBottom((alignBottom) => alignBottom || contentHeight === 0 || newHeight === 0);
diff --git a/gui/src/renderer/components/ProblemReport.tsx b/gui/src/renderer/components/ProblemReport.tsx
index 3a0a9bbd0e..fd481cde07 100644
--- a/gui/src/renderer/components/ProblemReport.tsx
+++ b/gui/src/renderer/components/ProblemReport.tsx
@@ -137,7 +137,7 @@ function Form() {
try {
const reportId = await collectLog();
await viewLog(reportId);
- } catch (error) {
+ } catch {
// TODO: handle error
} finally {
setDisableActions(false);
@@ -431,7 +431,7 @@ const ProblemReportContextProvider = ({ children }: { children: ReactNode }) =>
await sendProblemReport(email, message, reportId);
clearReportForm();
setSendState(SendState.success);
- } catch (error) {
+ } catch {
setSendState(SendState.failed);
}
}, [email, message]);
@@ -447,7 +447,7 @@ const ProblemReportContextProvider = ({ children }: { children: ReactNode }) =>
try {
setSendState(SendState.sending);
await sendReport();
- } catch (error) {
+ } catch {
// No-op
}
}
diff --git a/gui/src/renderer/components/main-view/FeatureIndicators.tsx b/gui/src/renderer/components/main-view/FeatureIndicators.tsx
index 1696a6fd20..a4bf8659c6 100644
--- a/gui/src/renderer/components/main-view/FeatureIndicators.tsx
+++ b/gui/src/renderer/components/main-view/FeatureIndicators.tsx
@@ -116,7 +116,7 @@ export default function FeatureIndicators(props: FeatureIndicatorsProps) {
tunnelState.state === 'connected' || tunnelState.state === 'connecting';
const featureIndicators = useRef(
- featureIndicatorsVisible ? tunnelState.featureIndicators ?? [] : [],
+ featureIndicatorsVisible ? (tunnelState.featureIndicators ?? []) : [],
);
if (featureIndicatorsVisible && tunnelState.featureIndicators) {
diff --git a/gui/src/renderer/lib/ip.ts b/gui/src/renderer/lib/ip.ts
index 94eb807d49..db458aa256 100644
--- a/gui/src/renderer/lib/ip.ts
+++ b/gui/src/renderer/lib/ip.ts
@@ -15,7 +15,7 @@ export abstract class IpAddress<G extends number[]> {
public static fromString(ip: string): IPv4Address | IPv6Address {
try {
return IPv4Address.fromString(ip);
- } catch (e) {
+ } catch {
return IPv6Address.fromString(ip);
}
}
@@ -80,7 +80,7 @@ export class IPv4Address extends IpAddress<IPv4Octets> {
try {
const octets = IPv4Address.octetsFromString(ip);
return new IPv4Address(octets);
- } catch (e) {
+ } catch {
throw new Error(`Invalid ip: ${ip}`);
}
}
@@ -94,7 +94,7 @@ export class IPv4Address extends IpAddress<IPv4Octets> {
return parsedOctets;
}
}
- } catch (e) {
+ } catch {
// no-op
}
@@ -105,7 +105,7 @@ export class IPv4Address extends IpAddress<IPv4Octets> {
try {
IPv4Address.fromString(ip);
return true;
- } catch (e) {
+ } catch {
return false;
}
}
@@ -135,7 +135,7 @@ export class IPv4Range extends IpRange<IPv4Octets> {
const prefixSize = parseInt(parts[1]);
return new IPv4Range(octets, prefixSize);
}
- } catch (e) {
+ } catch {
// no-op
}
@@ -167,7 +167,7 @@ export class IPv6Address extends IpAddress<IPv6Groups> {
try {
const groups = IPv6Address.groupsFromString(ip);
return new IPv6Address(groups);
- } catch (e) {
+ } catch {
throw new Error(`Invalid ip: ${ip}`);
}
}
@@ -200,7 +200,7 @@ export class IPv6Address extends IpAddress<IPv6Groups> {
}
}
}
- } catch (e) {
+ } catch {
// no-op
}
@@ -211,7 +211,7 @@ export class IPv6Address extends IpAddress<IPv6Groups> {
try {
IPv6Address.fromString(ip);
return true;
- } catch (e) {
+ } catch {
return false;
}
}
@@ -241,7 +241,7 @@ export class IPv6Range extends IpRange<IPv6Groups> {
const prefixSize = parseInt(parts[1], 10);
return new IPv6Range(groups, prefixSize);
}
- } catch (e) {
+ } catch {
// no-op
}
diff --git a/gui/tasks/assets.js b/gui/tasks/assets.js
index 56b0c7a8ad..8028124180 100644
--- a/gui/tasks/assets.js
+++ b/gui/tasks/assets.js
@@ -31,7 +31,14 @@ copyHtml.displayName = 'copy-html';
copyLocales.displayName = 'copy-locales';
copyGeoData.displayName = 'copy-geo-data';
-exports.copyAll = parallel(copyStaticAssets, copyConfig, copyCss, copyHtml, copyLocales, copyGeoData);
+exports.copyAll = parallel(
+ copyStaticAssets,
+ copyConfig,
+ copyCss,
+ copyHtml,
+ copyLocales,
+ copyGeoData,
+);
exports.copyStaticAssets = copyStaticAssets;
exports.copyCss = copyCss;
exports.copyHtml = copyHtml;
diff --git a/gui/tasks/distribution.js b/gui/tasks/distribution.js
index a7f7c29d6d..0e80c3c73f 100644
--- a/gui/tasks/distribution.js
+++ b/gui/tasks/distribution.js
@@ -42,7 +42,7 @@ const config = {
name: 'mullvad-vpn',
// We have to stick to semver on Windows for now due to:
// https://github.com/electron-userland/electron-builder/issues/7173
- version: productVersion(process.platform === 'win32' ? ['semver'] : [])
+ version: productVersion(process.platform === 'win32' ? ['semver'] : []),
},
files: [
@@ -139,23 +139,44 @@ const config = {
publisherName: 'Mullvad VPN AB',
extraResources: [
{ from: distAssets(path.join(getWindowsDistSubdir(), 'mullvad.exe')), to: '.' },
- { from: distAssets(path.join(getWindowsDistSubdir(), 'mullvad-problem-report.exe')), to: '.' },
+ {
+ from: distAssets(path.join(getWindowsDistSubdir(), 'mullvad-problem-report.exe')),
+ to: '.',
+ },
{ from: distAssets(path.join(getWindowsDistSubdir(), 'mullvad-daemon.exe')), to: '.' },
{ from: distAssets(path.join(getWindowsDistSubdir(), 'talpid_openvpn_plugin.dll')), to: '.' },
{
- from: root(path.join('windows', 'winfw', 'bin', getWindowsTargetArch() + '-${env.CPP_BUILD_MODE}', 'winfw.dll')),
+ from: root(
+ path.join(
+ 'windows',
+ 'winfw',
+ 'bin',
+ getWindowsTargetArch() + '-${env.CPP_BUILD_MODE}',
+ 'winfw.dll',
+ ),
+ ),
to: '.',
},
// TODO: OpenVPN does not have an ARM64 build yet.
{ from: distAssets('binaries/x86_64-pc-windows-msvc/openvpn.exe'), to: '.' },
- { from: distAssets(path.join('binaries', getWindowsTargetSubdir(), 'apisocks5.exe')), to: '.' },
- { from: distAssets(path.join('binaries', getWindowsTargetSubdir(), 'wintun/wintun.dll')), to: '.' },
{
- from: distAssets(path.join('binaries', getWindowsTargetSubdir(), 'split-tunnel/mullvad-split-tunnel.sys')),
- to: '.'
+ from: distAssets(path.join('binaries', getWindowsTargetSubdir(), 'apisocks5.exe')),
+ to: '.',
+ },
+ {
+ from: distAssets(path.join('binaries', getWindowsTargetSubdir(), 'wintun/wintun.dll')),
+ to: '.',
+ },
+ {
+ from: distAssets(
+ path.join('binaries', getWindowsTargetSubdir(), 'split-tunnel/mullvad-split-tunnel.sys'),
+ ),
+ to: '.',
},
{
- from: distAssets(path.join('binaries', getWindowsTargetSubdir(), 'wireguard-nt/mullvad-wireguard.dll')),
+ from: distAssets(
+ path.join('binaries', getWindowsTargetSubdir(), 'wireguard-nt/mullvad-wireguard.dll'),
+ ),
to: '.',
},
{ from: distAssets('maybenot_machines'), to: '.' },
@@ -180,7 +201,10 @@ const config = {
extraResources: [
{ from: distAssets(path.join(getLinuxTargetSubdir(), 'mullvad-problem-report')), to: '.' },
{ from: distAssets(path.join(getLinuxTargetSubdir(), 'mullvad-setup')), to: '.' },
- { from: distAssets(path.join(getLinuxTargetSubdir(), 'libtalpid_openvpn_plugin.so')), to: '.' },
+ {
+ from: distAssets(path.join(getLinuxTargetSubdir(), 'libtalpid_openvpn_plugin.so')),
+ to: '.',
+ },
{ from: distAssets(path.join('linux', 'apparmor_mullvad')), to: '.' },
{ from: distAssets(path.join('binaries', '${env.TARGET_TRIPLE}', 'openvpn')), to: '.' },
{ from: distAssets(path.join('binaries', '${env.TARGET_TRIPLE}', 'apisocks5')), to: '.' },
@@ -197,8 +221,10 @@ const config = {
distAssets('linux/before-install.sh'),
'--before-remove',
distAssets('linux/before-remove.sh'),
- distAssets('linux/mullvad-daemon.service') +'=/usr/lib/systemd/system/mullvad-daemon.service',
- distAssets('linux/mullvad-early-boot-blocking.service') +'=/usr/lib/systemd/system/mullvad-early-boot-blocking.service',
+ distAssets('linux/mullvad-daemon.service') +
+ '=/usr/lib/systemd/system/mullvad-daemon.service',
+ distAssets('linux/mullvad-early-boot-blocking.service') +
+ '=/usr/lib/systemd/system/mullvad-early-boot-blocking.service',
distAssets(path.join(getLinuxTargetSubdir(), 'mullvad')) + '=/usr/bin/',
distAssets(path.join(getLinuxTargetSubdir(), 'mullvad-daemon')) + '=/usr/bin/',
distAssets(path.join(getLinuxTargetSubdir(), 'mullvad-exclude')) + '=/usr/bin/',
@@ -228,8 +254,10 @@ const config = {
distAssets('linux/before-remove.sh'),
'--rpm-posttrans',
distAssets('linux/post-transaction.sh'),
- distAssets('linux/mullvad-daemon.service') +'=/usr/lib/systemd/system/mullvad-daemon.service',
- distAssets('linux/mullvad-early-boot-blocking.service') +'=/usr/lib/systemd/system/mullvad-early-boot-blocking.service',
+ distAssets('linux/mullvad-daemon.service') +
+ '=/usr/lib/systemd/system/mullvad-daemon.service',
+ distAssets('linux/mullvad-early-boot-blocking.service') +
+ '=/usr/lib/systemd/system/mullvad-early-boot-blocking.service',
distAssets(path.join(getLinuxTargetSubdir(), 'mullvad')) + '=/usr/bin/',
distAssets(path.join(getLinuxTargetSubdir(), 'mullvad-daemon')) + '=/usr/bin/',
distAssets(path.join(getLinuxTargetSubdir(), 'mullvad-exclude')) + '=/usr/bin/',
@@ -265,7 +293,7 @@ function packWin() {
process.env.SETUP_SUBDIR = 'aarch64-pc-windows-msvc';
break;
default:
- throw new Error(`Invalid or unknown target (only one may be specified)`);
+ throw new Error('Invalid or unknown target (only one may be specified)');
}
return true;
},
@@ -279,9 +307,12 @@ function packWin() {
for (const artifactPath of buildResult.artifactPaths) {
const artifactDir = path.dirname(artifactPath);
const artifactSemverFilename = path.basename(artifactPath);
- const artifactDesiredFilename = artifactSemverFilename.replace(productSemverVersion, productTargetVersion);
+ const artifactDesiredFilename = artifactSemverFilename.replace(
+ productSemverVersion,
+ productTargetVersion,
+ );
const targetArtifactPath = path.join(artifactDir, artifactDesiredFilename);
- console.log("Moving", artifactSemverFilename, "=>", artifactDesiredFilename);
+ console.log('Moving', artifactSemverFilename, '=>', artifactDesiredFilename);
fs.renameSync(artifactPath, targetArtifactPath);
}
},
@@ -310,9 +341,8 @@ function packMac() {
break;
}
- process.env.BINARIES_PATH = hostTargetTriple !== process.env.TARGET_TRIPLE
- ? process.env.TARGET_TRIPLE
- : '';
+ process.env.BINARIES_PATH =
+ hostTargetTriple !== process.env.TARGET_TRIPLE ? process.env.TARGET_TRIPLE : '';
return true;
},
@@ -322,8 +352,12 @@ function packMac() {
// if they're present for both targets. So make sure we remove libraries for other archs.
// Remove the workaround once the issue has been fixed:
// https://github.com/electron/universal/issues/41#issuecomment-1496288834
- await fs.promises.rm('node_modules/nseventmonitor/lib/binding/Release', { recursive: true });
- } catch {}
+ await fs.promises.rm('node_modules/nseventmonitor/lib/binding/Release', {
+ recursive: true,
+ });
+ } catch {
+ // noop
+ }
config.beforePack?.(context);
},
afterPack: (context) => {
@@ -336,13 +370,15 @@ function packMac() {
return Promise.resolve();
},
- afterAllArtifactBuild: async (buildResult) => {
+ afterAllArtifactBuild: async (_buildResult) => {
// Remove the folder that contains the unpacked app. Electron builder cleans up some of
// these directories and it's changed between versions without a mention in the changelog.
for (const dir of appOutDirs) {
try {
await fs.promises.rm(dir, { recursive: true });
- } catch {}
+ } catch {
+ // noop
+ }
}
},
afterSign: (context) => {
@@ -359,7 +395,7 @@ function packLinux() {
}
if (targets && targets === 'aarch64-unknown-linux-gnu') {
- config.rpm.fpm.unshift('--architecture', 'aarch64')
+ config.rpm.fpm.unshift('--architecture', 'aarch64');
}
return builder.build({
@@ -422,7 +458,7 @@ function getWindowsTargetArch() {
if (targets === 'aarch64-pc-windows-msvc') {
return 'arm64';
}
- throw new Error(`Invalid or unknown target (only one may be specified)`);
+ throw new Error('Invalid or unknown target (only one may be specified)');
}
// Use host architecture (we assume this is x64 since building on Arm64 isn't supported).
return 'x64';
@@ -433,7 +469,7 @@ function getWindowsTargetSubdir() {
if (targets === 'aarch64-pc-windows-msvc') {
return targets;
}
- throw new Error(`Invalid or unknown target (only one may be specified)`);
+ throw new Error('Invalid or unknown target (only one may be specified)');
}
// Use host architecture (we assume this is x64 since building on Arm64 isn't supported).
return 'x86_64-pc-windows-msvc';
@@ -444,7 +480,7 @@ function getLinuxTargetArch() {
if (targets === 'aarch64-unknown-linux-gnu') {
return 'arm64';
}
- throw new Error(`Invalid or unknown target (only one may be specified)`);
+ throw new Error('Invalid or unknown target (only one may be specified)');
}
// Use host architecture.
return undefined;
@@ -455,7 +491,7 @@ function getLinuxTargetSubdir() {
if (targets === 'aarch64-unknown-linux-gnu') {
return targets;
}
- throw new Error(`Invalid or unknown target (only one may be specified)`);
+ throw new Error('Invalid or unknown target (only one may be specified)');
}
return '';
}
@@ -489,8 +525,8 @@ function getLinuxVersion() {
// Returns the product version. The `args` argument is optional. Set it to `'semver'`
// to get the version in semver format.
-function productVersion(extra_args) {
- const args = ['run', '-q', '--bin', 'mullvad-version', ...extra_args];
+function productVersion(extraArgs) {
+ const args = ['run', '-q', '--bin', 'mullvad-version', ...extraArgs];
return execFileSync('cargo', args, { encoding: 'utf-8' }).trim();
}
diff --git a/gui/tasks/scripts.js b/gui/tasks/scripts.js
index 36b9def82d..20acc69c35 100644
--- a/gui/tasks/scripts.js
+++ b/gui/tasks/scripts.js
@@ -37,7 +37,9 @@ function makeWatchCompiler(onFirstSuccess, onSuccess) {
) {
lastBundle = bundle;
lastPreloadBundle = preloadBundle;
- !wasFirstBuild && onSuccess();
+ if (!wasFirstBuild) {
+ onSuccess();
+ }
}
}),
);
diff --git a/gui/test/e2e/installed/installed-utils.ts b/gui/test/e2e/installed/installed-utils.ts
index 1a8cd4258e..9e4dd6c79c 100644
--- a/gui/test/e2e/installed/installed-utils.ts
+++ b/gui/test/e2e/installed/installed-utils.ts
@@ -2,7 +2,7 @@ import { startApp } from '../utils';
export const startInstalledApp = async (): ReturnType<typeof startApp> => {
return startApp({ executablePath: getAppInstallPath() });
-}
+};
function getAppInstallPath(): string {
switch (process.platform) {
diff --git a/gui/test/e2e/installed/playwright.config.ts b/gui/test/e2e/installed/playwright.config.ts
index 9c1fa7fb87..9487e06905 100644
--- a/gui/test/e2e/installed/playwright.config.ts
+++ b/gui/test/e2e/installed/playwright.config.ts
@@ -1,4 +1,4 @@
-import { defineConfig } from "@playwright/test";
+import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: process.cwd(),
diff --git a/gui/test/e2e/installed/state-dependent/api-access-methods.spec.ts b/gui/test/e2e/installed/state-dependent/api-access-methods.spec.ts
index 0d6e8a0672..d17611261b 100644
--- a/gui/test/e2e/installed/state-dependent/api-access-methods.spec.ts
+++ b/gui/test/e2e/installed/state-dependent/api-access-methods.spec.ts
@@ -1,9 +1,9 @@
import { expect, test } from '@playwright/test';
import { Page } from 'playwright';
-import { startInstalledApp } from '../installed-utils';
-import { TestUtils } from '../../utils';
import { RoutePath } from '../../../../src/renderer/lib/routes';
+import { TestUtils } from '../../utils';
+import { startInstalledApp } from '../installed-utils';
// This test expects the daemon to be logged in and only have "Direct" and "Mullvad Bridges"
// access methods.
@@ -31,10 +31,10 @@ test.afterAll(async () => {
});
async function navigateToAccessMethods() {
- await util.waitForNavigation(async () => await page.click('button[aria-label="Settings"]'));
- await util.waitForNavigation(async () => await page.getByText('API access').click());
+ await util.waitForNavigation(() => page.click('button[aria-label="Settings"]'));
+ await util.waitForNavigation(() => page.getByText('API access').click());
- const title = page.locator('h1')
+ const title = page.locator('h1');
await expect(title).toHaveText('API access');
}
@@ -52,9 +52,9 @@ test('App should display access methods', async () => {
});
test('App should add invalid access method', async () => {
- await util.waitForNavigation(async () => await page.locator('button:has-text("Add")').click());
+ await util.waitForNavigation(() => page.locator('button:has-text("Add")').click());
- const title = page.locator('h1')
+ const title = page.locator('h1');
await expect(title).toHaveText('Add method');
const inputs = page.locator('input');
@@ -71,13 +71,13 @@ test('App should add invalid access method', async () => {
await inputs.nth(2).fill(process.env.SHADOWSOCKS_SERVER_PORT!);
await expect(addButton).toBeEnabled();
- await addButton.click()
+ await addButton.click();
await expect(page.getByText('Testing method...')).toBeVisible();
await expect(page.getByText('API unreachable, add anyway?')).toBeVisible();
expect(
- await util.waitForNavigation(async () => await page.locator('button:has-text("Save")').click())
+ await util.waitForNavigation(() => page.locator('button:has-text("Save")').click()),
).toEqual(RoutePath.apiAccessMethods);
const accessMethods = page.getByTestId('access-method');
@@ -107,7 +107,7 @@ test('App should edit access method', async () => {
await customMethod.locator('button').last().click();
await util.waitForNavigation(() => customMethod.getByText('Edit').click());
- const title = page.locator('h1')
+ const title = page.locator('h1');
await expect(title).toHaveText('Edit method');
const inputs = page.locator('input');
@@ -125,11 +125,13 @@ test('App should edit access method', async () => {
await inputs.nth(3).fill(process.env.SHADOWSOCKS_SERVER_PASSWORD!);
await page.getByTestId('ciphers').click();
- await page.getByRole('option', { name: process.env.SHADOWSOCKS_SERVER_CIPHER!, exact: true }).click();
+ await page
+ .getByRole('option', { name: process.env.SHADOWSOCKS_SERVER_CIPHER!, exact: true })
+ .click();
- expect(
- await util.waitForNavigation(async () => await saveButton.click())
- ).toEqual(RoutePath.apiAccessMethods);
+ expect(await util.waitForNavigation(() => saveButton.click())).toEqual(
+ RoutePath.apiAccessMethods,
+ );
const accessMethods = page.getByTestId('access-method');
await expect(accessMethods).toHaveCount(3);
diff --git a/gui/test/e2e/installed/state-dependent/custom-bridge.spec.ts b/gui/test/e2e/installed/state-dependent/custom-bridge.spec.ts
index 5efd110213..34efb60f26 100644
--- a/gui/test/e2e/installed/state-dependent/custom-bridge.spec.ts
+++ b/gui/test/e2e/installed/state-dependent/custom-bridge.spec.ts
@@ -1,10 +1,10 @@
import { expect, test } from '@playwright/test';
import { Page } from 'playwright';
-import { startInstalledApp } from '../installed-utils';
-import { TestUtils } from '../../utils';
import { colors } from '../../../../src/config.json';
import { RoutePath } from '../../../../src/renderer/lib/routes';
+import { TestUtils } from '../../utils';
+import { startInstalledApp } from '../installed-utils';
// This test expects the daemon to be logged in and not have a custom bridge configured.
// Env parameters:
@@ -25,37 +25,35 @@ test.afterAll(async () => {
});
test('App should enable bridge mode', async () => {
- await util.waitForNavigation(async () => await page.click('button[aria-label="Settings"]'));
- expect(
- await util.waitForNavigation(async () => await page.getByText('VPN settings').click()),
- ).toBe(RoutePath.vpnSettings);
+ await util.waitForNavigation(() => page.click('button[aria-label="Settings"]'));
+ expect(await util.waitForNavigation(() => page.getByText('VPN settings').click())).toBe(
+ RoutePath.vpnSettings,
+ );
await page.getByRole('option', { name: 'OpenVPN' }).click();
- expect(
- await util.waitForNavigation(async () => await page.getByText('OpenVPN settings').click()),
- ).toBe(RoutePath.openVpnSettings);
+ expect(await util.waitForNavigation(() => page.getByText('OpenVPN settings').click())).toBe(
+ RoutePath.openVpnSettings,
+ );
await page.getByTestId('bridge-mode-on').click();
await expect(page.getByText('Enable bridge mode?')).toBeVisible();
- page.getByTestId('enable-confirm').click();
+ await page.getByTestId('enable-confirm').click();
- await util.waitForNavigation(async () => await page.click('button[aria-label="Back"]'));
- await util.waitForNavigation(async () => await page.click('button[aria-label="Back"]'));
- expect(
- await util.waitForNavigation(async () => await page.click('button[aria-label="Close"]')),
- ).toBe(RoutePath.main);
+ await util.waitForNavigation(() => page.click('button[aria-label="Back"]'));
+ await util.waitForNavigation(() => page.click('button[aria-label="Back"]'));
+ expect(await util.waitForNavigation(() => page.click('button[aria-label="Close"]'))).toBe(
+ RoutePath.main,
+ );
});
test('App display disabled custom bridge', async () => {
expect(
- await util.waitForNavigation(
- async () => await page.click('button[aria-label^="Select location"]'),
- ),
+ await util.waitForNavigation(() => page.click('button[aria-label^="Select location"]')),
).toBe(RoutePath.selectLocation);
- const title = page.locator('h1')
+ const title = page.locator('h1');
await expect(title).toHaveText('Select location');
await page.getByText(/^Entry$/).click();
@@ -66,12 +64,10 @@ test('App display disabled custom bridge', async () => {
test('App should add new custom bridge', async () => {
expect(
- await util.waitForNavigation(
- async () => await page.click('button[aria-label="Add new custom bridge"]'),
- ),
+ await util.waitForNavigation(() => page.click('button[aria-label="Add new custom bridge"]')),
).toBe(RoutePath.editCustomBridge);
- const title = page.locator('h1')
+ const title = page.locator('h1');
await expect(title).toHaveText('Add custom bridge');
const inputs = page.locator('input');
@@ -88,11 +84,11 @@ test('App should add new custom bridge', async () => {
await inputs.nth(2).fill(process.env.SHADOWSOCKS_SERVER_PASSWORD!);
await page.getByTestId('ciphers').click();
- await page.getByRole('option', { name: process.env.SHADOWSOCKS_SERVER_CIPHER!, exact: true }).click();
+ await page
+ .getByRole('option', { name: process.env.SHADOWSOCKS_SERVER_CIPHER!, exact: true })
+ .click();
- expect(
- await util.waitForNavigation(async () => await addButton.click())
- ).toEqual(RoutePath.selectLocation);
+ expect(await util.waitForNavigation(() => addButton.click())).toEqual(RoutePath.selectLocation);
const customBridgeButton = page.getByText('Custom bridge');
await expect(customBridgeButton).toBeEnabled();
@@ -109,11 +105,9 @@ test('App should select custom bridge', async () => {
await page.getByText(/^Entry$/).click();
await expect(customBridgeButton).not.toHaveCSS('background-color', colors.green);
-
await customBridgeButton.click();
await page.getByText(/^Entry$/).click();
await expect(customBridgeButton).toHaveCSS('background-color', colors.green);
-
});
test('App should edit custom bridge', async () => {
@@ -122,12 +116,10 @@ test('App should edit custom bridge', async () => {
await page.getByText(/^Entry$/).click();
expect(
- await util.waitForNavigation(
- async () => await page.click('button[aria-label="Edit custom bridge"]'),
- ),
+ await util.waitForNavigation(() => page.click('button[aria-label="Edit custom bridge"]')),
).toBe(RoutePath.editCustomBridge);
- const title = page.locator('h1')
+ const title = page.locator('h1');
await expect(title).toHaveText('Edit custom bridge');
const inputs = page.locator('input');
@@ -138,10 +130,7 @@ test('App should edit custom bridge', async () => {
await inputs.nth(1).fill(process.env.SHADOWSOCKS_SERVER_PORT!);
await expect(saveButton).toBeEnabled();
-
- expect(
- await util.waitForNavigation(async () => await saveButton.click())
- ).toEqual(RoutePath.selectLocation);
+ expect(await util.waitForNavigation(() => saveButton.click())).toEqual(RoutePath.selectLocation);
const customBridgeButton = page.locator('button:has-text("Custom bridge")');
await expect(customBridgeButton).toBeEnabled();
@@ -150,9 +139,7 @@ test('App should edit custom bridge', async () => {
test('App should delete custom bridge', async () => {
expect(
- await util.waitForNavigation(
- async () => await page.click('button[aria-label="Edit custom bridge"]'),
- ),
+ await util.waitForNavigation(() => page.click('button[aria-label="Edit custom bridge"]')),
).toBe(RoutePath.editCustomBridge);
const deleteButton = page.locator('button:has-text("Delete")');
@@ -163,9 +150,9 @@ test('App should delete custom bridge', async () => {
await expect(page.getByText('Delete custom bridge?')).toBeVisible();
const confirmButton = page.getByTestId('delete-confirm');
- expect(
- await util.waitForNavigation(async () => await confirmButton.click())
- ).toEqual(RoutePath.selectLocation);
+ expect(await util.waitForNavigation(() => confirmButton.click())).toEqual(
+ RoutePath.selectLocation,
+ );
const customBridgeButton = page.locator('button:has-text("Custom bridge")');
await expect(customBridgeButton).toBeDisabled();
diff --git a/gui/test/e2e/installed/state-dependent/device-revoked.spec.ts b/gui/test/e2e/installed/state-dependent/device-revoked.spec.ts
index 22aa30b3d5..2b9f8d0c58 100644
--- a/gui/test/e2e/installed/state-dependent/device-revoked.spec.ts
+++ b/gui/test/e2e/installed/state-dependent/device-revoked.spec.ts
@@ -1,8 +1,8 @@
import { expect, test } from '@playwright/test';
import { Page } from 'playwright';
+
import { RoutePath } from '../../../../src/renderer/lib/routes';
import { TestUtils } from '../../utils';
-
import { startInstalledApp } from '../installed-utils';
// This test expects the daemon to be logged in to a revoked device.
@@ -23,7 +23,7 @@ test('App should fail to login', async () => {
await expect(page.getByTestId('title')).toHaveText('Device is inactive');
- expect(await util.waitForNavigation(() => {
- page.getByText('Go to login').click();
- })).toEqual(RoutePath.login);
+ expect(await util.waitForNavigation(() => page.getByText('Go to login').click())).toEqual(
+ RoutePath.login,
+ );
});
diff --git a/gui/test/e2e/installed/state-dependent/disconnected.spec.ts b/gui/test/e2e/installed/state-dependent/disconnected.spec.ts
index 360a88338d..253545dad7 100644
--- a/gui/test/e2e/installed/state-dependent/disconnected.spec.ts
+++ b/gui/test/e2e/installed/state-dependent/disconnected.spec.ts
@@ -1,7 +1,7 @@
import { test } from '@playwright/test';
import { Page } from 'playwright';
-import { expectDisconnected } from '../../shared/tunnel-state';
+import { expectDisconnected } from '../../shared/tunnel-state';
import { startInstalledApp } from '../installed-utils';
// This test expects the daemon to be logged into an account that has time left and to be
diff --git a/gui/test/e2e/installed/state-dependent/location.spec.ts b/gui/test/e2e/installed/state-dependent/location.spec.ts
index 229adb9acc..f0bd2e11f7 100644
--- a/gui/test/e2e/installed/state-dependent/location.spec.ts
+++ b/gui/test/e2e/installed/state-dependent/location.spec.ts
@@ -20,7 +20,6 @@ test('App should have a country', async () => {
await expect(countryLabel).not.toBeEmpty();
const cityLabel = page.getByTestId('city');
- const noCityLabel = await cityLabel.count() === 0;
+ const noCityLabel = (await cityLabel.count()) === 0;
expect(noCityLabel).toBeTruthy();
});
-
diff --git a/gui/test/e2e/installed/state-dependent/login.spec.ts b/gui/test/e2e/installed/state-dependent/login.spec.ts
index ba72a5b466..ad49c88edd 100644
--- a/gui/test/e2e/installed/state-dependent/login.spec.ts
+++ b/gui/test/e2e/installed/state-dependent/login.spec.ts
@@ -1,11 +1,11 @@
-import { exec, execSync } from 'child_process';
import { expect, test } from '@playwright/test';
+import { exec, execSync } from 'child_process';
import { Locator, Page } from 'playwright';
+
import { RoutePath } from '../../../../src/renderer/lib/routes';
+import { expectDisconnected } from '../../shared/tunnel-state';
import { TestUtils } from '../../utils';
-
import { startInstalledApp } from '../installed-utils';
-import { expectDisconnected } from '../../shared/tunnel-state';
// This test expects the daemon to be logged out.
// Env parameters:
@@ -27,7 +27,7 @@ test.afterAll(async () => {
test('App should fail to login', async () => {
expect(await util.currentRoute()).toEqual(RoutePath.login);
- const title = page.locator('h1')
+ const title = page.locator('h1');
const subtitle = page.getByTestId('subtitle');
const loginInput = getInput(page);
@@ -46,15 +46,17 @@ test('App should fail to login', async () => {
test('App should create account', async () => {
expect(await util.currentRoute()).toEqual(RoutePath.login);
- const title = page.locator('h1')
+ const title = page.locator('h1');
const subtitle = page.getByTestId('subtitle');
- expect(await util.waitForNavigation(async () => {
- await page.getByText('Create account').click();
+ expect(
+ await util.waitForNavigation(async () => {
+ await page.getByText('Create account').click();
- await expect(title).toHaveText('Account created');
- await expect(subtitle).toHaveText('Logged in');
- })).toEqual(RoutePath.expired);
+ await expect(title).toHaveText('Account created');
+ await expect(subtitle).toHaveText('Logged in');
+ }),
+ ).toEqual(RoutePath.expired);
const outOfTimeTitle = page.getByTestId('title');
await expect(outOfTimeTitle).toHaveText('Congrats!');
@@ -65,15 +67,17 @@ test('App should create account', async () => {
});
test('App should become logged out', async () => {
- expect(await util.waitForNavigation(() => {
- exec('mullvad account logout');
- })).toEqual(RoutePath.login);
+ expect(
+ await util.waitForNavigation(() => {
+ exec('mullvad account logout');
+ }),
+ ).toEqual(RoutePath.login);
});
test('App should log in', async () => {
expect(await util.currentRoute()).toEqual(RoutePath.login);
- const title = page.locator('h1')
+ const title = page.locator('h1');
const subtitle = page.getByTestId('subtitle');
const loginInput = getInput(page);
@@ -82,25 +86,31 @@ test('App should log in', async () => {
await loginInput.fill(process.env.ACCOUNT_NUMBER!);
- expect(await util.waitForNavigation(async () => {
- await loginInput.press('Enter');
+ expect(
+ await util.waitForNavigation(async () => {
+ await loginInput.press('Enter');
- await expect(title).toHaveText('Logged in');
- await expect(subtitle).toHaveText('Valid account number');
- })).toEqual(RoutePath.main);
+ await expect(title).toHaveText('Logged in');
+ await expect(subtitle).toHaveText('Valid account number');
+ }),
+ ).toEqual(RoutePath.main);
await expectDisconnected(page);
});
test('App should log out', async () => {
- expect(await util.waitForNavigation(() => {
- void page.getByTestId('account-button').click();
- })).toEqual(RoutePath.account);
+ expect(
+ await util.waitForNavigation(() => {
+ void page.getByTestId('account-button').click();
+ }),
+ ).toEqual(RoutePath.account);
- expect(await util.waitForNavigation(() => {
- void page.getByText('Log out').click();
- })).toEqual(RoutePath.login);
+ expect(
+ await util.waitForNavigation(() => {
+ void page.getByText('Log out').click();
+ }),
+ ).toEqual(RoutePath.login);
- const title = page.locator('h1')
+ const title = page.locator('h1');
const subtitle = page.getByTestId('subtitle');
await expect(title).toHaveText('Login');
await expect(subtitle).toHaveText('Enter your account number');
@@ -109,7 +119,7 @@ test('App should log out', async () => {
test('App should log in to expired account', async () => {
expect(await util.currentRoute()).toEqual(RoutePath.login);
- const title = page.locator('h1')
+ const title = page.locator('h1');
const subtitle = page.getByTestId('subtitle');
const loginInput = getInput(page);
@@ -118,9 +128,11 @@ test('App should log in to expired account', async () => {
await loginInput.fill(accountNumber);
- expect(await util.waitForNavigation(async () => {
- await loginInput.press('Enter');
- })).toEqual(RoutePath.expired);
+ expect(
+ await util.waitForNavigation(async () => {
+ await loginInput.press('Enter');
+ }),
+ ).toEqual(RoutePath.expired);
const outOfTimeTitle = page.getByTestId('title');
await expect(outOfTimeTitle).toHaveText('Out of time');
diff --git a/gui/test/e2e/installed/state-dependent/macos-split-tunneling.spec.ts b/gui/test/e2e/installed/state-dependent/macos-split-tunneling.spec.ts
index 0f1680bf44..6d49173bcd 100644
--- a/gui/test/e2e/installed/state-dependent/macos-split-tunneling.spec.ts
+++ b/gui/test/e2e/installed/state-dependent/macos-split-tunneling.spec.ts
@@ -1,10 +1,10 @@
-import { Locator, expect, test } from '@playwright/test';
-import { Page } from 'playwright';
+import { expect, Locator, test } from '@playwright/test';
import { execSync } from 'child_process';
+import { Page } from 'playwright';
-import { startInstalledApp } from '../installed-utils';
-import { TestUtils } from '../../utils';
import { RoutePath } from '../../../../src/renderer/lib/routes';
+import { TestUtils } from '../../utils';
+import { startInstalledApp } from '../installed-utils';
// macOS only. This test expects the daemon to be logged in and for split tunneling to be off and
// have no split applications.
@@ -21,13 +21,13 @@ test.afterAll(async () => {
});
async function navigateToSplitTunneling() {
- await util.waitForNavigation(async () => await page.click('button[aria-label="Settings"]'));
+ await util.waitForNavigation(() => page.click('button[aria-label="Settings"]'));
- expect(
- await util.waitForNavigation(async () => await page.getByText('Split tunneling').click())
- ).toEqual(RoutePath.splitTunneling);
+ expect(await util.waitForNavigation(() => page.getByText('Split tunneling').click())).toEqual(
+ RoutePath.splitTunneling,
+ );
- const title = page.locator('h1')
+ const title = page.locator('h1');
await expect(title).toHaveText('Split tunneling');
}
@@ -46,7 +46,7 @@ test('App should enable split tunneling', async () => {
const launchPadApp = page.getByText('launchpad');
await expect(launchPadApp).not.toBeVisible();
- toggle.click();
+ await toggle.click();
await expect(toggle).toBeChecked();
await expect(splitList).not.toBeVisible();
await expect(nonSplitList).toBeVisible();
@@ -133,7 +133,7 @@ test('App should disable split tunneling', async () => {
const launchPadApp = page.getByText('launchpad');
await expect(launchPadApp).toBeVisible();
- toggle.click();
+ await toggle.click();
await expect(toggle).not.toBeChecked();
});
@@ -148,7 +148,7 @@ async function numberOfApplicationsInList(listTestid: string) {
return 0;
}
- return await list.locator('button').count();
+ return list.locator('button').count();
}
function getDaemonSplitTunnelingApplications() {
@@ -157,6 +157,7 @@ function getDaemonSplitTunnelingApplications() {
}
function isSplitInDaemon(app: string): boolean {
- return !!getDaemonSplitTunnelingApplications()
- .find((splitApp) => splitApp.toLowerCase().includes(app));
+ return !!getDaemonSplitTunnelingApplications().find((splitApp) =>
+ splitApp.toLowerCase().includes(app),
+ );
}
diff --git a/gui/test/e2e/installed/state-dependent/obfuscation.spec.ts b/gui/test/e2e/installed/state-dependent/obfuscation.spec.ts
index af72ded6d5..b9518f8717 100644
--- a/gui/test/e2e/installed/state-dependent/obfuscation.spec.ts
+++ b/gui/test/e2e/installed/state-dependent/obfuscation.spec.ts
@@ -2,10 +2,10 @@ import { expect, test } from '@playwright/test';
import { execSync } from 'child_process';
import { Page } from 'playwright';
-import { startInstalledApp } from '../installed-utils';
-import { TestUtils } from '../../utils';
import { colors } from '../../../../src/config.json';
import { RoutePath } from '../../../../src/renderer/lib/routes';
+import { TestUtils } from '../../utils';
+import { startInstalledApp } from '../installed-utils';
const SHADOWSOCKS_PORT = 65_000;
const UDPOVERTCP_PORT = '80';
@@ -25,14 +25,14 @@ test.afterAll(async () => {
});
test('App should have automatic obfuscation', async () => {
- await util.waitForNavigation(async () => await page.click('button[aria-label="Settings"]'));
- expect(
- await util.waitForNavigation(async () => await page.getByText('VPN settings').click()),
- ).toBe(RoutePath.vpnSettings);
+ await util.waitForNavigation(() => page.click('button[aria-label="Settings"]'));
+ expect(await util.waitForNavigation(() => page.getByText('VPN settings').click())).toBe(
+ RoutePath.vpnSettings,
+ );
- expect(
- await util.waitForNavigation(async () => await page.getByText('WireGuard settings').click()),
- ).toBe(RoutePath.wireguardSettings);
+ expect(await util.waitForNavigation(() => page.getByText('WireGuard settings').click())).toBe(
+ RoutePath.wireguardSettings,
+ );
const automatic = page.getByTestId('automatic-obfuscation');
await expect(automatic).toHaveCSS('background-color', colors.green);
@@ -45,9 +45,7 @@ test('App should have automatic obfuscation', async () => {
test('App should set obfuscation to shadowsocks with custom port', async () => {
expect(
- await util.waitForNavigation(
- async () => await page.click('button[aria-label="Shadowsocks settings"]'),
- ),
+ await util.waitForNavigation(() => page.click('button[aria-label="Shadowsocks settings"]')),
).toBe(RoutePath.shadowsocks);
const automatic = page.locator('button', { hasText: 'Automatic' });
@@ -61,7 +59,7 @@ test('App should set obfuscation to shadowsocks with custom port', async () => {
const customItem = page.locator('div[role="option"]', { hasText: 'Custom' });
await expect(customItem).toHaveCSS('background-color', colors.green);
- await util.waitForNavigation(async () => await page.click('button[aria-label="Back"]'));
+ await util.waitForNavigation(() => page.click('button[aria-label="Back"]'));
const shadowsocksItem = page.locator('button', { hasText: 'Shadowsocks' });
await shadowsocksItem.click();
@@ -74,22 +72,18 @@ test('App should set obfuscation to shadowsocks with custom port', async () => {
test('App should still have shadowsocks custom port', async () => {
expect(
- await util.waitForNavigation(
- async () => await page.click('button[aria-label="Shadowsocks settings"]'),
- ),
+ await util.waitForNavigation(() => page.click('button[aria-label="Shadowsocks settings"]')),
).toBe(RoutePath.shadowsocks);
const customItem = page.locator('div[role="option"]', { hasText: 'Custom' });
await expect(customItem).toHaveCSS('background-color', colors.green);
- await util.waitForNavigation(async () => await page.click('button[aria-label="Back"]'));
+ await util.waitForNavigation(() => page.click('button[aria-label="Back"]'));
});
test('App should set obfuscation to UDP-over-TCP with port', async () => {
expect(
- await util.waitForNavigation(
- async () => await page.click('button[aria-label="UDP-over-TCP settings"]'),
- ),
+ await util.waitForNavigation(() => page.click('button[aria-label="UDP-over-TCP settings"]')),
).toBe(RoutePath.udpOverTcp);
const automatic = page.locator('button', { hasText: 'Automatic' });
@@ -100,7 +94,7 @@ test('App should set obfuscation to UDP-over-TCP with port', async () => {
await expect(portButton).toHaveCSS('background-color', colors.green);
- await util.waitForNavigation(async () => await page.click('button[aria-label="Back"]'));
+ await util.waitForNavigation(() => page.click('button[aria-label="Back"]'));
const udpOverTcpItem = page.locator('button', { hasText: 'UDP-over-TCP' });
await udpOverTcpItem.click();
diff --git a/gui/test/e2e/installed/state-dependent/settings-import.spec.ts b/gui/test/e2e/installed/state-dependent/settings-import.spec.ts
index 6b37b36244..d9a8859f76 100644
--- a/gui/test/e2e/installed/state-dependent/settings-import.spec.ts
+++ b/gui/test/e2e/installed/state-dependent/settings-import.spec.ts
@@ -1,9 +1,9 @@
import { expect, test } from '@playwright/test';
import { Page } from 'playwright';
-import { startInstalledApp } from '../installed-utils';
-import { TestUtils } from '../../utils';
import { RoutePath } from '../../../../src/renderer/lib/routes';
+import { TestUtils } from '../../utils';
+import { startInstalledApp } from '../installed-utils';
const INVALID_JSON = 'invalid json';
const VALID_JSON = `
@@ -31,14 +31,14 @@ test.afterAll(async () => {
});
async function navigateToSettingsImport() {
- await util.waitForNavigation(async () => await page.click('button[aria-label="Settings"]'));
- await util.waitForNavigation(async () => await page.getByText('VPN settings').click());
+ await util.waitForNavigation(() => page.click('button[aria-label="Settings"]'));
+ await util.waitForNavigation(() => page.getByText('VPN settings').click());
- expect(
- await util.waitForNavigation(async () => await page.getByText('Server IP override').click())
- ).toEqual(RoutePath.settingsImport);
+ expect(await util.waitForNavigation(() => page.getByText('Server IP override').click())).toEqual(
+ RoutePath.settingsImport,
+ );
- const title = page.locator('h1')
+ const title = page.locator('h1');
await expect(title).toHaveText('Server IP override');
}
@@ -49,14 +49,14 @@ test('App should display no overrides', async () => {
});
test('App should fail to import text', async () => {
- expect(
- await util.waitForNavigation(async () => await page.getByText('Import via text').click())
- ).toEqual(RoutePath.settingsTextImport);
+ expect(await util.waitForNavigation(() => page.getByText('Import via text').click())).toEqual(
+ RoutePath.settingsTextImport,
+ );
await page.locator('textarea').fill(INVALID_JSON);
- expect(
- await util.waitForNavigation(async () => await page.click('button[aria-label="Save"]'))
- ).toEqual(RoutePath.settingsImport);
+ expect(await util.waitForNavigation(() => page.click('button[aria-label="Save"]'))).toEqual(
+ RoutePath.settingsImport,
+ );
await expect(page.getByTestId('status-title')).toHaveText('NO OVERRIDES IMPORTED');
await expect(page.getByTestId('status-subtitle')).toBeVisible();
@@ -65,16 +65,16 @@ test('App should fail to import text', async () => {
});
test('App should succeed to import text', async () => {
- expect(
- await util.waitForNavigation(async () => await page.getByText('Import via text').click())
- ).toEqual(RoutePath.settingsTextImport);
+ expect(await util.waitForNavigation(() => page.getByText('Import via text').click())).toEqual(
+ RoutePath.settingsTextImport,
+ );
const textarea = page.locator('textarea');
await expect(textarea).toHaveValue(INVALID_JSON);
await textarea.fill(VALID_JSON);
- expect(
- await util.waitForNavigation(async () => await page.click('button[aria-label="Save"]'))
- ).toEqual(RoutePath.settingsImport);
+ expect(await util.waitForNavigation(() => page.click('button[aria-label="Save"]'))).toEqual(
+ RoutePath.settingsImport,
+ );
await expect(page.getByTestId('status-title')).toHaveText('IMPORT SUCCESSFUL');
await expect(page.getByTestId('status-subtitle')).toBeVisible();
@@ -83,24 +83,24 @@ test('App should succeed to import text', async () => {
await expect(page.getByTestId('status-title')).toHaveText('OVERRIDES ACTIVE');
- expect(
- await util.waitForNavigation(async () => await page.getByText('Import via text').click())
- ).toEqual(RoutePath.settingsTextImport);
+ expect(await util.waitForNavigation(() => page.getByText('Import via text').click())).toEqual(
+ RoutePath.settingsTextImport,
+ );
await expect(textarea).toHaveValue('');
- expect(
- await util.waitForNavigation(async () => await page.click('button[aria-label="Close"]'))
- ).toEqual(RoutePath.settingsImport);
+ expect(await util.waitForNavigation(() => page.click('button[aria-label="Close"]'))).toEqual(
+ RoutePath.settingsImport,
+ );
});
test('App should show active overrides', async () => {
- expect(
- await util.waitForNavigation(async () => await page.click('button[aria-label="Back"]'))
- ).toEqual(RoutePath.vpnSettings);
- expect(
- await util.waitForNavigation(async () => await page.getByText('Server IP override').click())
- ).toEqual(RoutePath.settingsImport);
+ expect(await util.waitForNavigation(() => page.click('button[aria-label="Back"]'))).toEqual(
+ RoutePath.vpnSettings,
+ );
+ expect(await util.waitForNavigation(() => page.getByText('Server IP override').click())).toEqual(
+ RoutePath.settingsImport,
+ );
await expect(page.getByTestId('status-title')).toHaveText('OVERRIDES ACTIVE');
await expect(page.getByText('Clear all overrides')).toBeEnabled();
diff --git a/gui/test/e2e/installed/state-dependent/too-many-devices.spec.ts b/gui/test/e2e/installed/state-dependent/too-many-devices.spec.ts
index 9b6dbdbe3d..8ff8675b67 100644
--- a/gui/test/e2e/installed/state-dependent/too-many-devices.spec.ts
+++ b/gui/test/e2e/installed/state-dependent/too-many-devices.spec.ts
@@ -1,8 +1,8 @@
import { expect, test } from '@playwright/test';
import { Locator, Page } from 'playwright';
+
import { RoutePath } from '../../../../src/renderer/lib/routes';
import { TestUtils } from '../../utils';
-
import { startInstalledApp } from '../installed-utils';
// This test expects the daemon to be logged out and the provided account to have five registered
@@ -25,25 +25,26 @@ test('App should show too many devices', async () => {
expect(await util.currentRoute()).toEqual(RoutePath.login);
const loginInput = getInput(page);
- await loginInput.type(process.env.ACCOUNT_NUMBER!);
+ await loginInput.fill(process.env.ACCOUNT_NUMBER!);
- expect(await util.waitForNavigation(() => {
- loginInput.press('Enter');
- })).toEqual(RoutePath.tooManyDevices);
+ expect(await util.waitForNavigation(() => loginInput.press('Enter'))).toEqual(
+ RoutePath.tooManyDevices,
+ );
const loginButton = page.getByText('Continue with login');
await expect(page.getByTestId('title')).toHaveText('Too many devices');
await expect(loginButton).toBeDisabled();
- await page.getByLabel(/^Remove device named/).first().click();
+ await page
+ .getByLabel(/^Remove device named/)
+ .first()
+ .click();
await page.getByText('Yes, log out device').click();
await expect(loginButton).toBeEnabled();
// Trigger transition: too-many-devices -> login -> main
- expect(await util.waitForNavigation(() => {
- loginButton.click();
- })).toEqual(RoutePath.login);
+ expect(await util.waitForNavigation(() => loginButton.click())).toEqual(RoutePath.login);
// Note: `util.waitForNavigation` won't return the navigation event when
// transitioning from login -> main, so we need to observe the state of the
diff --git a/gui/test/e2e/installed/state-dependent/tunnel-state.spec.ts b/gui/test/e2e/installed/state-dependent/tunnel-state.spec.ts
index 53332ee6ab..15ce240e57 100644
--- a/gui/test/e2e/installed/state-dependent/tunnel-state.spec.ts
+++ b/gui/test/e2e/installed/state-dependent/tunnel-state.spec.ts
@@ -1,15 +1,11 @@
-import { exec as execAsync } from 'child_process';
-import { promisify } from 'util';
import { expect, test } from '@playwright/test';
+import { exec as execAsync } from 'child_process';
import { Page } from 'playwright';
-import {
- expectConnected,
- expectDisconnected,
- expectError,
-} from '../../shared/tunnel-state';
+import { promisify } from 'util';
-import { startInstalledApp } from '../installed-utils';
+import { expectConnected, expectDisconnected, expectError } from '../../shared/tunnel-state';
import { escapeRegExp } from '../../utils';
+import { startInstalledApp } from '../installed-utils';
const exec = promisify(execAsync);
@@ -164,7 +160,9 @@ test('App should show multihop', async () => {
await exec('mullvad relay set tunnel wireguard --use-multihop=on');
await expectConnected(page);
const relay = page.getByTestId('hostname-line');
- await expect(relay).toHaveText(new RegExp('^' + escapeRegExp(`${process.env.HOSTNAME} via`), 'i'));
+ await expect(relay).toHaveText(
+ new RegExp('^' + escapeRegExp(`${process.env.HOSTNAME} via`), 'i'),
+ );
await exec('mullvad relay set tunnel wireguard --use-multihop=off');
await page.getByText('Disconnect').click();
});
diff --git a/gui/test/e2e/mocked/expired-account-error-view.spec.ts b/gui/test/e2e/mocked/expired-account-error-view.spec.ts
index 5c906a134b..e63e62f51f 100644
--- a/gui/test/e2e/mocked/expired-account-error-view.spec.ts
+++ b/gui/test/e2e/mocked/expired-account-error-view.spec.ts
@@ -1,10 +1,11 @@
-import { Page } from 'playwright';
-import { MockedTestUtils, startMockedApp } from './mocked-utils';
import { expect, test } from '@playwright/test';
-import { IAccountData } from '../../../src/shared/daemon-rpc-types';
-import { getBackgroundColor } from '../utils';
+import { Page } from 'playwright';
+
import { colors } from '../../../src/config.json';
import { RoutePath } from '../../../src/renderer/lib/routes';
+import { IAccountData } from '../../../src/shared/daemon-rpc-types';
+import { getBackgroundColor } from '../utils';
+import { MockedTestUtils, startMockedApp } from './mocked-utils';
let page: Page;
let util: MockedTestUtils;
@@ -37,10 +38,12 @@ test('App should show out of time view after running out of time', async () => {
const expiryDate = new Date();
expiryDate.setSeconds(expiryDate.getSeconds() + 2);
- expect(await util.waitForNavigation(async () => {
- await util.sendMockIpcResponse<IAccountData>({
- channel: 'account-',
- response: { expiry: expiryDate.toISOString() },
- });
- })).toEqual(RoutePath.expired);
+ expect(
+ await util.waitForNavigation(async () => {
+ await util.sendMockIpcResponse<IAccountData>({
+ channel: 'account-',
+ response: { expiry: expiryDate.toISOString() },
+ });
+ }),
+ ).toEqual(RoutePath.expired);
});
diff --git a/gui/test/e2e/mocked/feature-indicators.spec.ts b/gui/test/e2e/mocked/feature-indicators.spec.ts
index 1ba216bd52..6e0e034c35 100644
--- a/gui/test/e2e/mocked/feature-indicators.spec.ts
+++ b/gui/test/e2e/mocked/feature-indicators.spec.ts
@@ -1,9 +1,14 @@
import { expect, test } from '@playwright/test';
import { Page } from 'playwright';
-import { MockedTestUtils, startMockedApp } from './mocked-utils';
-import { FeatureIndicator, ILocation, ITunnelEndpoint, TunnelState } from '../../../src/shared/daemon-rpc-types';
+import {
+ FeatureIndicator,
+ ILocation,
+ ITunnelEndpoint,
+ TunnelState,
+} from '../../../src/shared/daemon-rpc-types';
import { expectConnected } from '../shared/tunnel-state';
+import { MockedTestUtils, startMockedApp } from './mocked-utils';
const endpoint: ITunnelEndpoint = {
address: 'wg10:80',
@@ -91,23 +96,23 @@ test('App should show feature indicators', async () => {
await expect(ellipsis).toBeVisible();
await expectConnected(page);
- await expectFeatureIndicators(page, ["DAITA", "Quantum resistance"], false);
- await expectHiddenFeatureIndicator(page, "Mssfix");
+ await expectFeatureIndicators(page, ['DAITA', 'Quantum resistance'], false);
+ await expectHiddenFeatureIndicator(page, 'Mssfix');
await page.getByTestId('connection-panel-chevron').click();
await expect(ellipsis).not.toBeVisible();
await expectFeatureIndicators(page, [
- "DAITA",
- "Quantum resistance",
- "Mssfix",
- "MTU",
- "Obfuscation",
- "Local network sharing",
- "Lockdown mode",
- "Multihop",
- "Custom DNS",
- "Server IP override",
+ 'DAITA',
+ 'Quantum resistance',
+ 'Mssfix',
+ 'MTU',
+ 'Obfuscation',
+ 'Local network sharing',
+ 'Lockdown mode',
+ 'Multihop',
+ 'Custom DNS',
+ 'Server IP override',
]);
});
@@ -123,11 +128,7 @@ async function expectHiddenFeatureIndicator(page: Page, hiddenIndicator: string)
await expect(indicator).not.toBeVisible();
}
-async function expectFeatureIndicators(
- page: Page,
- expectedIndicators: Array<string>,
- only = true,
-) {
+async function expectFeatureIndicators(page: Page, expectedIndicators: Array<string>, only = true) {
const indicators = page.getByTestId('feature-indicator');
if (only) {
await expect(indicators).toHaveCount(expectedIndicators.length);
diff --git a/gui/test/e2e/mocked/mocked-utils.ts b/gui/test/e2e/mocked/mocked-utils.ts
index 1840ebbbb0..57998fae68 100644
--- a/gui/test/e2e/mocked/mocked-utils.ts
+++ b/gui/test/e2e/mocked/mocked-utils.ts
@@ -3,7 +3,7 @@ import { ElectronApplication } from 'playwright';
import { startApp, TestUtils } from '../utils';
interface StartMockedAppResponse extends Awaited<ReturnType<typeof startApp>> {
- util: MockedTestUtils,
+ util: MockedTestUtils;
}
export interface MockedTestUtils extends TestUtils {
@@ -22,7 +22,7 @@ export const startMockedApp = async (): Promise<StartMockedAppResponse> => {
...startAppResult.util,
mockIpcHandle,
sendMockIpcResponse,
- }
+ },
};
};
diff --git a/gui/test/e2e/mocked/settings.spec.ts b/gui/test/e2e/mocked/settings.spec.ts
index c6022678f5..52dbc72402 100644
--- a/gui/test/e2e/mocked/settings.spec.ts
+++ b/gui/test/e2e/mocked/settings.spec.ts
@@ -1,8 +1,8 @@
import { expect, test } from '@playwright/test';
import { Page } from 'playwright';
-import { MockedTestUtils, startMockedApp } from './mocked-utils';
import { IAccountData } from '../../../src/shared/daemon-rpc-types';
+import { MockedTestUtils, startMockedApp } from './mocked-utils';
let page: Page;
let util: MockedTestUtils;
@@ -21,7 +21,7 @@ test('Account button should be displayed correctly', async () => {
});
test('Headerbar account info should be displayed correctly', async () => {
- let expiryText = page.getByText(/^Time left:/);
+ const expiryText = page.getByText(/^Time left:/);
await expect(expiryText).toContainText(/Time left: 29 days/i);
/**
diff --git a/gui/test/e2e/mocked/tunnel-state.spec.ts b/gui/test/e2e/mocked/tunnel-state.spec.ts
index 3e20dab6ec..6ecf707ba6 100644
--- a/gui/test/e2e/mocked/tunnel-state.spec.ts
+++ b/gui/test/e2e/mocked/tunnel-state.spec.ts
@@ -1,9 +1,20 @@
import { test } from '@playwright/test';
import { Page } from 'playwright';
+import {
+ ErrorStateCause,
+ ILocation,
+ ITunnelEndpoint,
+ TunnelState,
+} from '../../../src/shared/daemon-rpc-types';
+import {
+ expectConnected,
+ expectConnecting,
+ expectDisconnected,
+ expectDisconnecting,
+ expectError,
+} from '../shared/tunnel-state';
import { MockedTestUtils, startMockedApp } from './mocked-utils';
-import { ErrorStateCause, ILocation, ITunnelEndpoint, TunnelState } from '../../../src/shared/daemon-rpc-types';
-import { expectConnected, expectConnecting, expectDisconnected, expectDisconnecting, expectError } from '../shared/tunnel-state';
const mockLocation: ILocation = {
country: 'Sweden',
diff --git a/gui/test/e2e/shared/tunnel-state.ts b/gui/test/e2e/shared/tunnel-state.ts
index 4d75f79d01..6a5fbfaf09 100644
--- a/gui/test/e2e/shared/tunnel-state.ts
+++ b/gui/test/e2e/shared/tunnel-state.ts
@@ -1,5 +1,6 @@
import { expect } from '@playwright/test';
import { Page } from 'playwright';
+
import { colors } from '../../../src/config.json';
import { anyOf } from '../utils';
diff --git a/gui/test/e2e/utils.ts b/gui/test/e2e/utils.ts
index 082ccfcf3f..2fb33319f2 100644
--- a/gui/test/e2e/utils.ts
+++ b/gui/test/e2e/utils.ts
@@ -1,4 +1,4 @@
-import { Locator, Page, _electron as electron, ElectronApplication } from 'playwright';
+import { _electron as electron, ElectronApplication, Locator, Page } from 'playwright';
export interface StartAppResponse {
app: ElectronApplication;
@@ -8,7 +8,7 @@ export interface StartAppResponse {
export interface TestUtils {
currentRoute: () => Promise<string>;
- waitForNavigation: (initiateNavigation?: () => Promise<void> | void) => Promise<string>;
+ waitForNavigation: (initiateNavigation?: () => Promise<void> | void) => Promise<string>;
waitForNoTransition: () => Promise<void>;
}
@@ -38,34 +38,28 @@ export const startApp = async (options: LaunchOptions): Promise<StartAppResponse
return { app, page, util };
};
-export const launch = async (options: LaunchOptions): Promise<ElectronApplication> => {
+export const launch = (options: LaunchOptions): Promise<ElectronApplication> => {
process.env.CI = 'e2e';
- return await electron.launch(options);
-}
+ return electron.launch(options);
+};
const currentRouteFactory = (app: ElectronApplication) => {
- return async () => {
- return await app.evaluate<string>(({ webContents }) => {
- return webContents.getAllWebContents()
- // Select window that isn't devtools
- .find((webContents) => webContents.getURL().startsWith('file://'))!
- .executeJavaScript('window.e2e.location');
- });
- };
-}
+ return () =>
+ app.evaluate<string>(({ webContents }) =>
+ webContents
+ .getAllWebContents()
+ // Select window that isn't devtools
+ .find((webContents) => webContents.getURL().startsWith('file://'))!
+ .executeJavaScript('window.e2e.location'),
+ );
+};
-const waitForNavigationFactory = (
- app: ElectronApplication,
- page: Page,
-) => {
+const waitForNavigationFactory = (app: ElectronApplication, page: Page) => {
// Wait for navigation animation to finish. A function can be provided that initiates the
// navigation, e.g. clicks a button.
return async (initiateNavigation?: () => Promise<void> | void) => {
// Wait for route to change after optionally initiating the navigation.
- const [route] = await Promise.all([
- waitForNextRoute(app),
- initiateNavigation?.(),
- ]);
+ const [route] = await Promise.all([waitForNextRoute(app), initiateNavigation?.()]);
// Wait for view corresponding to new route to appear
await page.getByTestId(route).isVisible();
@@ -77,7 +71,7 @@ const waitForNavigationFactory = (
const waitForNoTransition = async (page: Page) => {
// Wait until there's only one transitionContents
- let transitionContentsCount;
+ let transitionContentsCount;
do {
if (transitionContentsCount !== undefined) {
await new Promise((resolve) => setTimeout(resolve, 5));
@@ -93,14 +87,15 @@ const waitForNoTransition = async (page: Page) => {
};
// Returns the route when it changes
-const waitForNextRoute = async (app: ElectronApplication): Promise<string> => {
- return await app.evaluate(({ ipcMain }) => {
- return new Promise((resolve) => {
- ipcMain.once('navigation-setHistory', (_event, history: History) => {
+const waitForNextRoute = (app: ElectronApplication): Promise<string> => {
+ return app.evaluate(
+ ({ ipcMain }) =>
+ new Promise((resolve) => {
+ ipcMain.once('navigation-setHistory', (_event, history: History) => {
resolve(history.entries[history.index].pathname);
- });
- });
- });
+ });
+ }),
+ );
};
const getStyleProperty = (locator: Locator, property: string) => {
@@ -125,5 +120,5 @@ export function anyOf(...values: string[]): RegExp {
}
export function escapeRegExp(regexp: string): string {
- return regexp.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
+ return regexp.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
diff --git a/gui/test/unit/account-data-cache.spec.ts b/gui/test/unit/account-data-cache.spec.ts
index f3d6df3142..cf1c4299d8 100644
--- a/gui/test/unit/account-data-cache.spec.ts
+++ b/gui/test/unit/account-data-cache.spec.ts
@@ -1,7 +1,8 @@
+import { expect, spy } from 'chai';
+import sinon from 'sinon';
+
import AccountDataCache, { AccountFetchError } from '../../src/main/account-data-cache';
import { AccountDataResponse, IAccountData } from '../../src/shared/daemon-rpc-types';
-import sinon from 'sinon';
-import { expect, spy } from 'chai';
describe('IAccountData cache', () => {
const dummyAccountToken = '9876543210';
@@ -44,7 +45,7 @@ describe('IAccountData cache', () => {
const watcher = new Promise<void>((resolve, reject) => {
cache.fetch(dummyAccountToken, {
- onFinish: (_reason?: any) => resolve(),
+ onFinish: () => resolve(),
onError: (_error: AccountFetchError) => reject(),
});
});
@@ -254,9 +255,7 @@ describe('IAccountData cache', () => {
await new Promise((resolve) => setTimeout(resolve));
cache.fetch(dummyAccountToken, {
- onFinish: async () => {
- resolve();
- },
+ onFinish: () => resolve(),
onError: (_error: AccountFetchError) => reject(),
});
},
@@ -298,9 +297,7 @@ describe('IAccountData cache', () => {
await new Promise((resolve) => setTimeout(resolve));
cache.fetch(dummyAccountToken, {
- onFinish: async () => {
- resolve();
- },
+ onFinish: () => resolve(),
onError: (_error: AccountFetchError) => reject(),
});
},
diff --git a/gui/test/unit/changelog.spec.ts b/gui/test/unit/changelog.spec.ts
index 249c26e1db..774dca956b 100644
--- a/gui/test/unit/changelog.spec.ts
+++ b/gui/test/unit/changelog.spec.ts
@@ -1,5 +1,6 @@
import { expect } from 'chai';
-import { after, it, describe } from 'mocha';
+import { after, describe, it } from 'mocha';
+
import { parseChangelog } from '../../src/main/changelog';
// It should be handled the same no matter if the platforms are split with a space or not.
diff --git a/gui/test/unit/date-helper.spec.ts b/gui/test/unit/date-helper.spec.ts
index 74500ff960..82c4faeac7 100644
--- a/gui/test/unit/date-helper.spec.ts
+++ b/gui/test/unit/date-helper.spec.ts
@@ -1,5 +1,6 @@
import { expect } from 'chai';
-import { it, describe } from 'mocha';
+import { describe, it } from 'mocha';
+
import * as date from '../../src/shared/date-helper';
describe('Date helper', () => {
@@ -100,76 +101,61 @@ describe('Date helper', () => {
});
it('should format positive difference as string', () => {
- const diff1 = date.formatRelativeDate(
- '2021-01-01 13:37:10',
- '2021-01-01 13:37:20',
- { displayMonths: true },
- );
+ const diff1 = date.formatRelativeDate('2021-01-01 13:37:10', '2021-01-01 13:37:20', {
+ displayMonths: true,
+ });
expect(diff1).to.equal('less than a day');
- const diff2 = date.formatRelativeDate(
- '2021-01-01 13:37:10',
- '2021-01-02 13:37:20',
- { displayMonths: true },
- );
+ const diff2 = date.formatRelativeDate('2021-01-01 13:37:10', '2021-01-02 13:37:20', {
+ displayMonths: true,
+ });
expect(diff2).to.equal('1 day');
- const diff3 = date.formatRelativeDate(
- '2021-01-01 13:37:10',
- '2021-02-25 13:37:20',
- { displayMonths: true },
- );
+ const diff3 = date.formatRelativeDate('2021-01-01 13:37:10', '2021-02-25 13:37:20', {
+ displayMonths: true,
+ });
expect(diff3).to.equal('55 days');
- const diff4 = date.formatRelativeDate(
- '2021-01-01 13:37:10',
- '2021-04-25 13:37:20',
- { displayMonths: true },
- );
+ const diff4 = date.formatRelativeDate('2021-01-01 13:37:10', '2021-04-25 13:37:20', {
+ displayMonths: true,
+ });
expect(diff4).to.equal('3 months');
- const diff5 = date.formatRelativeDate(
- '2021-01-01 13:37:10',
- '2031-04-25 13:37:20',
- { displayMonths: true },
- );
+ const diff5 = date.formatRelativeDate('2021-01-01 13:37:10', '2031-04-25 13:37:20', {
+ displayMonths: true,
+ });
expect(diff5).to.equal('10 years');
});
it('should format positive difference as string suffixed with "left"', () => {
- const diff1 = date.formatRelativeDate(
- '2021-01-01 13:37:10',
- '2021-01-01 13:37:20',
- { suffix: true, displayMonths: true },
- );
+ const diff1 = date.formatRelativeDate('2021-01-01 13:37:10', '2021-01-01 13:37:20', {
+ suffix: true,
+ displayMonths: true,
+ });
expect(diff1).to.equal('less than a day left');
- const diff2 = date.formatRelativeDate(
- '2021-01-01 13:37:10',
- '2021-01-02 13:37:20',
- { suffix: true, displayMonths: true },
- );
+ const diff2 = date.formatRelativeDate('2021-01-01 13:37:10', '2021-01-02 13:37:20', {
+ suffix: true,
+ displayMonths: true,
+ });
expect(diff2).to.equal('1 day left');
- const diff3 = date.formatRelativeDate(
- '2021-01-01 13:37:10',
- '2021-02-25 13:37:20',
- { suffix: true, displayMonths: true },
- );
+ const diff3 = date.formatRelativeDate('2021-01-01 13:37:10', '2021-02-25 13:37:20', {
+ suffix: true,
+ displayMonths: true,
+ });
expect(diff3).to.equal('55 days left');
- const diff4 = date.formatRelativeDate(
- '2021-01-01 13:37:10',
- '2021-04-25 13:37:20',
- { suffix: true, displayMonths: true },
- );
+ const diff4 = date.formatRelativeDate('2021-01-01 13:37:10', '2021-04-25 13:37:20', {
+ suffix: true,
+ displayMonths: true,
+ });
expect(diff4).to.equal('3 months left');
- const diff5 = date.formatRelativeDate(
- '2021-01-01 13:37:10',
- '2031-04-25 13:37:20',
- { suffix: true, displayMonths: true },
- );
+ const diff5 = date.formatRelativeDate('2021-01-01 13:37:10', '2031-04-25 13:37:20', {
+ suffix: true,
+ displayMonths: true,
+ });
expect(diff5).to.equal('10 years left');
});
diff --git a/gui/test/unit/history.spec.ts b/gui/test/unit/history.spec.ts
index 03eabd80cc..739c65c5ca 100644
--- a/gui/test/unit/history.spec.ts
+++ b/gui/test/unit/history.spec.ts
@@ -1,5 +1,6 @@
import { expect, spy } from 'chai';
-import { it, describe, beforeEach } from 'mocha';
+import { beforeEach, describe, it } from 'mocha';
+
import History from '../../src/renderer/lib/history';
import { RoutePath } from '../../src/renderer/lib/routes';
diff --git a/gui/test/unit/ip.spec.ts b/gui/test/unit/ip.spec.ts
index 10b93bc890..5f6a265d25 100644
--- a/gui/test/unit/ip.spec.ts
+++ b/gui/test/unit/ip.spec.ts
@@ -1,5 +1,6 @@
import { expect } from 'chai';
-import { it, describe } from 'mocha';
+import { describe, it } from 'mocha';
+
import * as ip from '../../src/renderer/lib/ip';
const validIpv4Addresses = [
diff --git a/gui/test/unit/keyframe-animation.spec.ts b/gui/test/unit/keyframe-animation.spec.ts
index 59b5c2d6f7..0ba302e65c 100644
--- a/gui/test/unit/keyframe-animation.spec.ts
+++ b/gui/test/unit/keyframe-animation.spec.ts
@@ -1,5 +1,6 @@
import { expect } from 'chai';
-import { it, describe } from 'mocha';
+import { describe, it } from 'mocha';
+
import KeyframeAnimation from '../../src/main/keyframe-animation';
describe('lib/keyframe-animation', function () {
diff --git a/gui/test/unit/list-diff.spec.ts b/gui/test/unit/list-diff.spec.ts
index 9357579072..e64d79b193 100644
--- a/gui/test/unit/list-diff.spec.ts
+++ b/gui/test/unit/list-diff.spec.ts
@@ -1,5 +1,6 @@
import { expect } from 'chai';
-import { it, describe } from 'mocha';
+import { describe, it } from 'mocha';
+
import { calculateItemList, RowDisplayData } from '../../src/renderer/components/List';
const prevItems: Array<RowDisplayData<undefined>> = [
diff --git a/gui/test/unit/logging.spec.ts b/gui/test/unit/logging.spec.ts
index d107a23d3b..393b631ba5 100644
--- a/gui/test/unit/logging.spec.ts
+++ b/gui/test/unit/logging.spec.ts
@@ -1,10 +1,11 @@
import { expect, spy } from 'chai';
import fs from 'fs';
-import sinon from 'sinon';
-import { it, describe, before, beforeEach, after } from 'mocha';
+import { after, before, beforeEach, describe, it } from 'mocha';
import path from 'path';
-import { Logger } from '../../src/shared/logging';
+import sinon from 'sinon';
+
import { backupLogFile, rotateOrDeleteFile } from '../../src/main/logging';
+import { Logger } from '../../src/shared/logging';
import { LogLevel } from '../../src/shared/logging-types';
const aPath = path.normalize('log-directory/a.log');
diff --git a/gui/test/unit/notification-evaluation.spec.ts b/gui/test/unit/notification-evaluation.spec.ts
index 27de83cf29..723307b3d7 100644
--- a/gui/test/unit/notification-evaluation.spec.ts
+++ b/gui/test/unit/notification-evaluation.spec.ts
@@ -1,21 +1,25 @@
import { expect } from 'chai';
-import { it, describe } from 'mocha';
+import { describe, it } from 'mocha';
import sinon from 'sinon';
-import {
- UnsupportedVersionNotificationProvider,
- UpdateAvailableNotificationProvider,
-} from '../../src/shared/notifications/notification';
import NotificationController from '../../src/main/notification-controller';
import { TunnelState } from '../../src/shared/daemon-rpc-types';
import { ErrorStateCause } from '../../src/shared/daemon-rpc-types';
import { FirewallPolicyErrorType } from '../../src/shared/daemon-rpc-types';
+import {
+ UnsupportedVersionNotificationProvider,
+ UpdateAvailableNotificationProvider,
+} from '../../src/shared/notifications/notification';
function createController() {
return new NotificationController({
- openApp: () => { /* no-op */ },
+ openApp: () => {
+ /* no-op */
+ },
openLink: (_url: string, _withAuth?: boolean) => Promise.resolve(),
- showNotificationIcon: (_value: boolean) => { /* no-op */ },
+ showNotificationIcon: (_value: boolean) => {
+ /* no-op */
+ },
});
}
@@ -26,10 +30,18 @@ describe('System notifications', () => {
sandbox = sinon.createSandbox();
// @ts-ignore
sandbox.stub(NotificationController.prototype, 'createElectronNotification').returns({
- show: () => { /* no-op */ },
- close: () => { /* no-op */ },
- on: () => { /* no-op */ },
- removeAllListeners: () => { /* no-op */ },
+ show: () => {
+ /* no-op */
+ },
+ close: () => {
+ /* no-op */
+ },
+ on: () => {
+ /* no-op */
+ },
+ removeAllListeners: () => {
+ /* no-op */
+ },
});
});
@@ -133,7 +145,7 @@ describe('System notifications', () => {
cause: ErrorStateCause.isOffline,
blockingError: {
type: FirewallPolicyErrorType.generic,
- }
+ },
},
};
const result6 = controller.notifyTunnelState(nonBlockingErrorState, false, false, false, false);
diff --git a/gui/test/unit/setup.ts b/gui/test/unit/setup.ts
index 65644e28d9..a565ec50ca 100644
--- a/gui/test/unit/setup.ts
+++ b/gui/test/unit/setup.ts
@@ -1,6 +1,6 @@
import chai from 'chai';
-import spies from 'chai-spies';
import chaiAsPromised from 'chai-as-promised';
+import spies from 'chai-spies';
chai.use(spies);
chai.use(chaiAsPromised);
diff --git a/gui/test/unit/tunnel-state.spec.ts b/gui/test/unit/tunnel-state.spec.ts
index d4629ebc64..a6013523b8 100644
--- a/gui/test/unit/tunnel-state.spec.ts
+++ b/gui/test/unit/tunnel-state.spec.ts
@@ -1,6 +1,7 @@
import { expect, spy } from 'chai';
-import { it, describe } from 'mocha';
+import { describe, it } from 'mocha';
import sinon from 'sinon';
+
import TunnelStateHandler from '../../src/main/tunnel-state';
import { TunnelState } from '../../src/shared/daemon-rpc-types';
@@ -106,4 +107,3 @@ describe('Tunnel state', () => {
clock.restore();
});
});
-