tests: Start writing tests, Splash and some of the lib/ functions (#280)

This commit is contained in:
Tyler Wilding 2023-07-21 22:07:23 -06:00 committed by GitHub
parent ab4b38c792
commit 620c41ceb4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 6655 additions and 4976 deletions

33
.github/workflows/test.yaml vendored Normal file
View file

@ -0,0 +1,33 @@
name: 🧪 Tests
on:
push:
branches:
- main
tags:
- v*
pull_request:
branches:
- main
jobs:
frontend:
name: Frontend
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 18
cache: yarn
- name: Install NPM Dependencies
run: yarn install --frozen-lockfile
- name: Run Tests
run: yarn test
# TODO - capture and report on coverage

1
.gitignore vendored
View file

@ -41,3 +41,4 @@ TODO.md
vite.config.ts.timestamp*
.yarn/
.yarnrc.yml
coverage/

View file

@ -5,6 +5,8 @@
"type": "module",
"scripts": {
"dev": "vite",
"test": "vitest",
"coverage": "vitest run --coverage",
"build": "vite build",
"preview": "vite preview",
"tauri": "tauri",
@ -25,6 +27,8 @@
"@sveltejs/vite-plugin-svelte": "^2.4.2",
"@tauri-apps/cli": "^1.4.0",
"@tauri-apps/tauricon": "github:tauri-apps/tauricon",
"@testing-library/svelte": "^4.0.3",
"@vitest/coverage-v8": "^0.33.0",
"@tsconfig/svelte": "^5.0.0",
"ansi-to-span": "^0.0.1",
"autoprefixer": "^10.4.14",
@ -33,6 +37,7 @@
"execa": "^7.1.1",
"flowbite": "^1.6.5",
"flowbite-svelte": "^0.39.2",
"jsdom": "^22.1.0",
"postcss": "^8.4.26",
"postcss-load-config": "^4.0.1",
"prettier": "^2.8.8",
@ -42,6 +47,7 @@
"svelte-preprocess": "^5.0.3",
"tailwindcss": "^3.3.3",
"typescript": "^5.1.3",
"vitest": "^0.33.0",
"vite": "^4.4.4"
},
"dependencies": {

View file

@ -18,7 +18,7 @@
extractNewTexturePack,
listExtractedTexturePackInfo,
} from "$lib/rpc/features";
import { filePrompt } from "$lib/utils/file";
import { filePrompt } from "$lib/utils/file-dialogs";
import Icon from "@iconify/svelte";
import { convertFileSrc } from "@tauri-apps/api/tauri";
import {

View file

@ -11,7 +11,7 @@
runCompiler,
runDecompiler,
} from "$lib/rpc/binaries";
import { folderPrompt, isoPrompt } from "$lib/utils/file";
import { folderPrompt, isoPrompt } from "$lib/utils/file-dialogs";
import {
finalizeInstallation,
isAVXRequirementMet,

View file

@ -1,4 +1,4 @@
import { saveFilePrompt } from "$lib/utils/file";
import { saveFilePrompt } from "$lib/utils/file-dialogs";
import { invoke_rpc } from "./rpc";
export async function generateSupportPackage(): Promise<void> {

View file

@ -0,0 +1,14 @@
import { describe, expect, it } from "vitest";
import { isInDebugMode } from "./common";
describe("isInDebugMode", () => {
it("should return true when in debug mode", async () => {
process.env["NODE_ENV"] = "development";
expect(isInDebugMode()).toBeTruthy();
});
it("should return true when in debug mode", async () => {
process.env["NODE_ENV"] = "not-development";
expect(isInDebugMode()).toBeFalsy();
});
});

View file

@ -0,0 +1,284 @@
import { afterEach, describe, expect, it, vi, type Mock } from "vitest";
import { arch, platform } from "@tauri-apps/api/os";
import { listOfficialReleases } from "./github";
vi.mock("@tauri-apps/api/os");
global.fetch = vi.fn();
function createFetchResponse(data: any) {
return { json: () => new Promise((resolve) => resolve(data)) };
}
function createFakeGithubReleaseAsset(assetName) {
return {
url: "https://api.github.com/repos/open-goal/jak-project/releases/assets/115111791",
id: 115111791,
node_id: "RA_kwDOEUK6OM4G3Hdv",
name: assetName,
label: "",
uploader: {
login: "github-actions[bot]",
id: 41898282,
node_id: "MDM6Qm90NDE4OTgyODI=",
avatar_url: "https://avatars.githubusercontent.com/in/15368?v=4",
gravatar_id: "",
url: "https://api.github.com/users/github-actions%5Bbot%5D",
html_url: "https://github.com/apps/github-actions",
followers_url:
"https://api.github.com/users/github-actions%5Bbot%5D/followers",
following_url:
"https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}",
gists_url:
"https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}",
starred_url:
"https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}",
subscriptions_url:
"https://api.github.com/users/github-actions%5Bbot%5D/subscriptions",
organizations_url:
"https://api.github.com/users/github-actions%5Bbot%5D/orgs",
repos_url: "https://api.github.com/users/github-actions%5Bbot%5D/repos",
events_url:
"https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}",
received_events_url:
"https://api.github.com/users/github-actions%5Bbot%5D/received_events",
type: "Bot",
site_admin: false,
},
content_type: "application/x-gtar",
state: "uploaded",
size: 21698082,
download_count: 399,
created_at: "2023-07-01T06:38:26Z",
updated_at: "2023-07-01T06:38:28Z",
browser_download_url: `https://github.com/open-goal/jak-project/releases/download/v0.1.38/${assetName}`,
};
}
function createFakeGithubRelease(assetNames: string[]) {
const assets = [];
for (const assetName of assetNames) {
assets.push(createFakeGithubReleaseAsset(assetName));
}
return {
url: "https://api.github.com/repos/open-goal/jak-project/releases/110648537",
assets_url:
"https://api.github.com/repos/open-goal/jak-project/releases/110648537/assets",
upload_url:
"https://uploads.github.com/repos/open-goal/jak-project/releases/110648537/assets{?name,label}",
html_url: "https://github.com/open-goal/jak-project/releases/tag/v0.1.38",
id: 110648537,
author: {
login: "OpenGOALBot",
id: 99294829,
node_id: "U_kgDOBesebQ",
avatar_url: "https://avatars.githubusercontent.com/u/99294829?v=4",
gravatar_id: "",
url: "https://api.github.com/users/OpenGOALBot",
html_url: "https://github.com/OpenGOALBot",
followers_url: "https://api.github.com/users/OpenGOALBot/followers",
following_url:
"https://api.github.com/users/OpenGOALBot/following{/other_user}",
gists_url: "https://api.github.com/users/OpenGOALBot/gists{/gist_id}",
starred_url:
"https://api.github.com/users/OpenGOALBot/starred{/owner}{/repo}",
subscriptions_url:
"https://api.github.com/users/OpenGOALBot/subscriptions",
organizations_url: "https://api.github.com/users/OpenGOALBot/orgs",
repos_url: "https://api.github.com/users/OpenGOALBot/repos",
events_url: "https://api.github.com/users/OpenGOALBot/events{/privacy}",
received_events_url:
"https://api.github.com/users/OpenGOALBot/received_events",
type: "User",
site_admin: false,
},
node_id: "RE_kwDOEUK6OM4GmFzZ",
tag_name: "v0.1.38",
target_commitish: "master",
name: "v0.1.38",
draft: false,
prerelease: false,
created_at: "2023-07-01T06:09:09Z",
published_at: "2023-07-01T06:38:29Z",
assets: assets,
tarball_url:
"https://api.github.com/repos/open-goal/jak-project/tarball/v0.1.38",
zipball_url:
"https://api.github.com/repos/open-goal/jak-project/zipball/v0.1.38",
body: "## What's Changed\n* ci: ensure linux runners have the proper OpenGL headers by @xTVaser in https://github.com/open-goal/jak-project/pull/2790\n\n\n**Full Changelog**: https://github.com/open-goal/jak-project/compare/v0.1.37...v0.1.38",
reactions: {
url: "https://api.github.com/repos/open-goal/jak-project/releases/110648537/reactions",
total_count: 4,
"+1": 0,
"-1": 0,
laugh: 0,
hooray: 3,
confused: 0,
heart: 0,
rocket: 0,
eyes: 1,
},
mentions_count: 1,
};
}
describe("listOfficialReleases", () => {
afterEach(() => {
vi.clearAllMocks();
vi.resetAllMocks();
});
it("should retrieve intel macOS releases properly", async () => {
vi.mocked(platform).mockResolvedValue("darwin");
vi.mocked(arch).mockResolvedValue("x86_64");
(fetch as Mock).mockResolvedValue(
createFetchResponse([
createFakeGithubRelease([
"opengoal-macos-intel-v0.0.1.tar.gz",
"opengoal-windows-v0.0.1.zip",
"opengoal-linux-v0.0.1.tar.gz",
]),
])
);
const releases = await listOfficialReleases();
expect(releases.length).toBe(1);
expect(
releases[0].downloadUrl.endsWith("opengoal-macos-intel-v0.0.1.tar.gz")
).toBeTruthy();
});
it("should not retrieve macOS ARM releases", async () => {
vi.mocked(platform).mockResolvedValue("darwin");
vi.mocked(arch).mockResolvedValue("arm");
(fetch as Mock).mockResolvedValue(
createFetchResponse([
createFakeGithubRelease([
"opengoal-macos-intel-v0.0.1.tar.gz",
"opengoal-windows-v0.0.1.zip",
"opengoal-linux-v0.0.1.tar.gz",
]),
])
);
const releases = await listOfficialReleases();
expect(releases.length).toBe(1);
expect(releases[0].downloadUrl).toBeUndefined();
});
it("should retrieve windows releases properly", async () => {
vi.mocked(platform).mockResolvedValue("win32");
vi.mocked(arch).mockResolvedValue("x86_64");
(fetch as Mock).mockResolvedValue(
createFetchResponse([
createFakeGithubRelease([
"opengoal-macos-intel-v0.0.1.tar.gz",
"opengoal-windows-v0.0.1.zip",
"opengoal-linux-v0.0.1.tar.gz",
]),
])
);
const releases = await listOfficialReleases();
expect(releases.length).toBe(1);
expect(
releases[0].downloadUrl.endsWith("opengoal-windows-v0.0.1.zip")
).toBeTruthy();
});
it("should retrieve linux releases properly", async () => {
vi.mocked(platform).mockResolvedValue("linux");
vi.mocked(arch).mockResolvedValue("x86_64");
(fetch as Mock).mockResolvedValue(
createFetchResponse([
createFakeGithubRelease([
"opengoal-macos-intel-v0.0.1.tar.gz",
"opengoal-windows-v0.0.1.zip",
"opengoal-linux-v0.0.1.tar.gz",
]),
])
);
const releases = await listOfficialReleases();
expect(releases.length).toBe(1);
expect(
releases[0].downloadUrl.endsWith("opengoal-linux-v0.0.1.tar.gz")
).toBeTruthy();
});
});
describe("getLatestOfficialRelease", () => {
afterEach(() => {
vi.clearAllMocks();
vi.resetAllMocks();
});
it("should retrieve intel macOS releases properly", async () => {
vi.mocked(platform).mockResolvedValue("darwin");
vi.mocked(arch).mockResolvedValue("x86_64");
(fetch as Mock).mockResolvedValue(
createFetchResponse([
createFakeGithubRelease([
"opengoal-macos-intel-v0.0.1.tar.gz",
"opengoal-windows-v0.0.1.zip",
"opengoal-linux-v0.0.1.tar.gz",
]),
])
);
const releases = await listOfficialReleases();
expect(releases.length).toBe(1);
expect(
releases[0].downloadUrl.endsWith("opengoal-macos-intel-v0.0.1.tar.gz")
).toBeTruthy();
});
it("should not retrieve macOS ARM releases", async () => {
vi.mocked(platform).mockResolvedValue("darwin");
vi.mocked(arch).mockResolvedValue("arm");
(fetch as Mock).mockResolvedValue(
createFetchResponse([
createFakeGithubRelease([
"opengoal-macos-intel-v0.0.1.tar.gz",
"opengoal-windows-v0.0.1.zip",
"opengoal-linux-v0.0.1.tar.gz",
]),
])
);
const releases = await listOfficialReleases();
expect(releases.length).toBe(1);
expect(releases[0].downloadUrl).toBeUndefined();
});
it("should retrieve windows releases properly", async () => {
vi.mocked(platform).mockResolvedValue("win32");
vi.mocked(arch).mockResolvedValue("x86_64");
(fetch as Mock).mockResolvedValue(
createFetchResponse([
createFakeGithubRelease([
"opengoal-macos-intel-v0.0.1.tar.gz",
"opengoal-windows-v0.0.1.zip",
"opengoal-linux-v0.0.1.tar.gz",
]),
])
);
const releases = await listOfficialReleases();
expect(releases.length).toBe(1);
expect(
releases[0].downloadUrl.endsWith("opengoal-windows-v0.0.1.zip")
).toBeTruthy();
});
it("should retrieve linux releases properly", async () => {
vi.mocked(platform).mockResolvedValue("linux");
vi.mocked(arch).mockResolvedValue("x86_64");
(fetch as Mock).mockResolvedValue(
createFetchResponse([
createFakeGithubRelease([
"opengoal-macos-intel-v0.0.1.tar.gz",
"opengoal-windows-v0.0.1.zip",
"opengoal-linux-v0.0.1.tar.gz",
]),
])
);
const releases = await listOfficialReleases();
expect(releases.length).toBe(1);
expect(
releases[0].downloadUrl.endsWith("opengoal-linux-v0.0.1.tar.gz")
).toBeTruthy();
});
});

View file

@ -10,30 +10,54 @@ export interface ReleaseInfo {
pendingAction: boolean;
}
function isIntelMacOsRelease(
platform: string,
architecture: string,
assetName: string
): boolean {
return (
platform === "darwin" &&
architecture === "x86_64" &&
assetName.startsWith("opengoal-macos-intel-v")
);
}
// TODO - go back and fix old asset names so windows/linux can be simplified
function isWindowsRelease(
platform: string,
architecture: string,
assetName: string
): boolean {
return (
platform === "win32" &&
(assetName.startsWith("opengoal-windows-v") ||
(assetName.startsWith("opengoal-v") && assetName.includes("windows")))
);
}
function isLinuxRelease(
platform: string,
architecture: string,
assetName: string
): boolean {
return (
platform === "linux" &&
(assetName.startsWith("opengoal-linux-v") ||
(assetName.startsWith("opengoal-v") && assetName.includes("linux")))
);
}
async function getDownloadLinkForCurrentPlatform(
release
release: any
): Promise<string | undefined> {
const platformName = await platform();
const archName = await arch();
for (const asset of release.assets) {
if (
platformName === "darwin" &&
archName === "x86_64" &&
asset.name.startsWith("opengoal-macos-intel-v")
// macOS doesn't have the old naming scheme
) {
if (isIntelMacOsRelease(platformName, archName, asset.name)) {
return asset.browser_download_url;
} else if (
platformName === "win32" &&
(asset.name.startsWith("opengoal-windows-v") ||
(asset.name.startsWith("opengoal-v") && asset.name.includes("windows")))
) {
} else if (isWindowsRelease(platformName, archName, asset.name)) {
return asset.browser_download_url;
} else if (
platformName === "linux" &&
(asset.name.startsWith("opengoal-linux-v") ||
(asset.name.startsWith("opengoal-v") && asset.name.includes("linux")))
) {
} else if (isLinuxRelease(platformName, archName, asset.name)) {
return asset.browser_download_url;
}
}
@ -44,7 +68,6 @@ export async function listOfficialReleases(): Promise<ReleaseInfo[]> {
let releases = [];
// TODO - handle rate limiting
// TODO - long term - handle pagination (more than 100 releases)
// TODO - even longer term - extract this out into an API we control (avoid github rate limiting) -- will be needed for unofficial releases as well anyway
const resp = await fetch(
"https://api.github.com/repos/open-goal/jak-project/releases?per_page=100"
);
@ -68,7 +91,6 @@ export async function listOfficialReleases(): Promise<ReleaseInfo[]> {
export async function getLatestOfficialRelease(): Promise<ReleaseInfo> {
// TODO - handle rate limiting
// TODO - even longer term - extract this out into an API we control (avoid github rate limiting) -- will be needed for unofficial releases as well anyway
const resp = await fetch(
"https://api.github.com/repos/open-goal/jak-project/releases/latest"
);

View file

@ -4,7 +4,7 @@
setInstallationDirectory,
} from "$lib/rpc/config";
import { VersionStore } from "$lib/stores/VersionStore";
import { folderPrompt } from "$lib/utils/file";
import { folderPrompt } from "$lib/utils/file-dialogs";
import { Label, Input } from "flowbite-svelte";
import { onMount } from "svelte";
import { _ } from "svelte-i18n";

View file

@ -2,7 +2,7 @@
import { openMainWindow } from "$lib/rpc/window";
import { onMount } from "svelte";
import logo from "$assets/images/icon.webp";
import { folderPrompt } from "$lib/utils/file";
import { folderPrompt } from "$lib/utils/file-dialogs";
import {
deleteOldDataDirectory,
getInstallationDirectory,
@ -12,10 +12,10 @@
setLocale,
} from "$lib/rpc/config";
import { AVAILABLE_LOCALES } from "$lib/i18n/i18n";
import { _ } from "svelte-i18n";
import { locale as svelteLocale, _ } from "svelte-i18n";
let currentProgress = 10;
let currentStatusText = $_("splash_step_readingSettings");
let currentStatusText = "Loading Locales...";
let selectLocale = false;
let installationDirSet = true;
@ -26,6 +26,7 @@
onMount(async () => {
// First, see if the user has selected a locale
await checkLocale();
currentStatusText = $_("splash_step_readingSettings");
});
// TODO - cleanup this code and make it easier to add steps like with
@ -36,6 +37,7 @@
if (locale === null) {
// Prompt the user to select a locale
selectLocale = true;
svelteLocale.set("en-US");
} else {
// Set locale and continue
setLocale(locale);
@ -74,25 +76,35 @@
currentStatusText = $_("splash_step_errorOpening");
}
}
async function handleLocaleChange(evt: Event) {
const selectElement = evt.target as HTMLSelectElement;
setLocale(selectElement.value);
selectLocale = false;
await checkDirectories();
}
</script>
<div class="content" data-tauri-drag-region>
<div class="splash-logo no-pointer-events">
<img src={logo} aria-label="" draggable="false" />
<img
src={logo}
data-testId="splash-logo"
alt="OpenGOAL logo"
aria-label="OpenGOAL logo"
draggable="false"
/>
</div>
<div class="splash-contents no-pointer-events">
{#if selectLocale}
<span class="mb-1">{$_("splash_selectLocale")}</span>
<div class="splash-select">
<select
name="cars"
id="cars"
data-testId="locale-select"
name="locales"
id="locales"
class="pointer-events emoji-font"
on:change={async (evt) => {
setLocale(evt.target.value);
selectLocale = false;
await checkDirectories();
}}
on:change={handleLocaleChange}
>
<option disabled selected value hidden />
{#each AVAILABLE_LOCALES as locale}
@ -107,6 +119,7 @@
<br />
<span>
<button
data-testId="delete-old-data-dir-button"
class="splash-button pointer-events"
on:click={() => {
oldDataDirToClean = false;
@ -114,6 +127,7 @@
}}>{$_("splash_button_deleteOldInstallDir_yes")}</button
>
<button
data-testId="dont-delete-old-data-dir-button"
class="splash-button pointer-events"
on:click={() => {
oldDataDirToClean = false;
@ -128,6 +142,7 @@
{/if}
<br />
<button
data-testId="pick-install-folder-button"
class="splash-button pointer-events"
on:click={async () => {
// This is part of what allows for the user to install the games and such wherever they want

198
src/splash/splash.test.ts Normal file
View file

@ -0,0 +1,198 @@
import {
render,
waitFor,
screen,
cleanup,
fireEvent,
} from "@testing-library/svelte";
import Splash from "./Splash.svelte";
import { afterEach, describe, expect, it, vi } from "vitest";
import { mockIPC } from "@tauri-apps/api/mocks";
import { folderPrompt } from "$lib/utils/file-dialogs";
vi.mock("$lib/utils/file-dialogs");
describe("Splash.svelte", () => {
// TODO: @testing-library/svelte claims to add this automatically but it doesn't work without explicit afterEach
afterEach(() => {
cleanup();
vi.clearAllMocks();
vi.resetAllMocks();
});
it("should render the splash", async () => {
render(Splash, {});
const logo = screen.getByTestId("splash-logo");
expect(logo).toBeTruthy();
});
it("should display the locale dropdown", async () => {
// TODO - generalize into function
mockIPC((cmd, args) => {
if (cmd === "get_locale") {
return null;
} else {
console.log(`Unhandled Tauri IPC: ${cmd}`);
}
});
render(Splash, {});
const localeSelect = await screen.findByTestId("locale-select");
expect(localeSelect).toBeTruthy();
});
it("should set the locale when selected", async () => {
// TODO - generalize into function
mockIPC((cmd, args) => {
if (cmd === "get_locale") {
return null;
}
if (cmd === "set_locale") {
return;
} else {
console.log(`Unhandled Tauri IPC: ${cmd}`);
}
});
render(Splash, {});
const localeSelect = (await screen.findByTestId(
"locale-select"
)) as HTMLSelectElement;
expect(localeSelect).toBeTruthy();
fireEvent.change(localeSelect, { target: { value: "en-US" } });
expect(localeSelect.value).toBe("en-US");
});
it("should prompt user to delete old data directory - delete it", async () => {
// TODO - generalize into function
// return an object that tracks mock calls / args
let oldDataDirDeleted = false;
mockIPC((cmd, args) => {
if (cmd === "get_locale") {
return "en-US";
} else if (cmd === "get_install_directory") {
return null;
} else if (cmd === "has_old_data_directory") {
return true;
} else if (cmd === "delete_old_data_directory") {
oldDataDirDeleted = true;
} else {
console.log(`Unhandled Tauri IPC: ${cmd}`);
}
});
render(Splash, {});
const deleteOldDataDirButton = await screen.findByTestId(
"delete-old-data-dir-button"
);
expect(deleteOldDataDirButton).toBeTruthy();
// delete the dir, it'll go away
fireEvent.click(deleteOldDataDirButton);
expect(oldDataDirDeleted).toBeTruthy();
const pickInstallFolderButton = await screen.findByTestId(
"pick-install-folder-button"
);
expect(pickInstallFolderButton).toBeTruthy();
});
it("should prompt user to select installation directory - cancelled dialog", async () => {
// TODO - generalize into function
// return an object that tracks mock calls / args
mockIPC((cmd, args) => {
if (cmd === "get_locale") {
return "en-US";
} else if (cmd === "get_install_directory") {
return null;
} else if (cmd === "has_old_data_directory") {
return false;
} else {
console.log(`Unhandled Tauri IPC: ${cmd}`);
}
});
vi.mocked(folderPrompt).mockResolvedValue(undefined);
render(Splash, {});
let pickInstallFolderButton = await screen.findByTestId(
"pick-install-folder-button"
);
expect(pickInstallFolderButton).toBeTruthy();
fireEvent.click(pickInstallFolderButton);
// It's still there since the user didn't pick a folder
pickInstallFolderButton = await screen.findByTestId(
"pick-install-folder-button"
);
expect(pickInstallFolderButton).toBeTruthy();
});
it("should prompt user to select installation directory - successful dialog", async () => {
// TODO - generalize into function
// return an object that tracks mock calls / args
let setInstallDirectorySet = false;
let mainWindowOpened = false;
mockIPC((cmd, args) => {
if (cmd === "get_locale") {
return "en-US";
} else if (cmd === "get_install_directory") {
return null;
} else if (cmd === "has_old_data_directory") {
return false;
} else if (cmd === "set_install_directory") {
setInstallDirectorySet = true;
return null;
} else if (cmd === "open_main_window") {
mainWindowOpened = true;
return;
} else {
console.log(`Unhandled Tauri IPC: ${cmd}`);
}
});
vi.mocked(folderPrompt).mockResolvedValue("/wow/good/job/nice/folder");
render(Splash, {});
let pickInstallFolderButton = await screen.findByTestId(
"pick-install-folder-button"
);
expect(pickInstallFolderButton).toBeTruthy();
fireEvent.click(pickInstallFolderButton);
await waitFor(() => {
expect(setInstallDirectorySet).toBeTruthy();
});
await waitFor(
() => {
expect(mainWindowOpened).toBeTruthy();
},
{ timeout: 5000 }
);
});
it("should prompt user to select installation directory - bad directory choosen", async () => {
// TODO - generalize into function
// return an object that tracks mock calls / args
let mainWindowOpened = false;
mockIPC((cmd, args) => {
if (cmd === "get_locale") {
return "en-US";
} else if (cmd === "get_install_directory") {
return null;
} else if (cmd === "has_old_data_directory") {
return false;
} else if (cmd === "set_install_directory") {
return "wow that was a terrible directory";
} else if (cmd === "open_main_window") {
mainWindowOpened = true;
return;
} else {
console.log(`Unhandled Tauri IPC: ${cmd}`);
}
});
vi.mocked(folderPrompt).mockResolvedValue("/wow/good/job/nice/folder");
render(Splash, {});
let pickInstallFolderButton = await screen.findByTestId(
"pick-install-folder-button"
);
expect(pickInstallFolderButton).toBeTruthy();
fireEvent.click(pickInstallFolderButton);
await waitFor(() => {
screen.findByText("wow that was a terrible directory");
});
pickInstallFolderButton = await screen.findByTestId(
"pick-install-folder-button"
);
expect(pickInstallFolderButton).toBeTruthy();
});
});

5
src/tests/setup.ts Normal file
View file

@ -0,0 +1,5 @@
import { vi, beforeAll } from "vitest";
beforeAll(() => {
window.__TAURI_IPC__ = vi.fn();
});

View file

@ -24,7 +24,8 @@
* Typecheck JS in `.svelte` and `.js` files by default.
* Disable this if you'd like to use dynamic types.
*/
"checkJs": true
"checkJs": true,
"types": ["vitest/types"]
},
/**
* Use global.d.ts instead of compilerOptions.types

View file

@ -7,7 +7,7 @@ export default defineConfig({
server: {
port: 3000, // The port the server will listen on.
},
plugins: [svelte()],
plugins: [svelte({ hot: !process.env.VITEST })],
resolve: {
alias: {
$lib: fileURLToPath(new URL("./src/lib", import.meta.url)),

20
vitest.config.ts Normal file
View file

@ -0,0 +1,20 @@
import { defineConfig } from "vitest/config";
import { svelte } from "@sveltejs/vite-plugin-svelte";
import { fileURLToPath, URL } from "url";
export default defineConfig({
plugins: [svelte({ hot: !process.env.VITEST })],
resolve: {
alias: {
$lib: fileURLToPath(new URL("./src/lib", import.meta.url)),
$assets: fileURLToPath(new URL("./src/assets", import.meta.url)),
},
},
test: {
alias: [{ find: /^svelte$/, replacement: "svelte/internal" }],
include: ["./src/**/*.test.ts"],
globals: true,
environment: "jsdom",
setupFiles: ["./src/tests/setup.ts"],
},
});

10960
yarn.lock

File diff suppressed because it is too large Load diff