Skip to content

Commit

Permalink
feat: git clone & lfs (blib-la#67)
Browse files Browse the repository at this point in the history
## Motivation

* Integrated GitPortable for Windows
* Use clone or lfs to interact with git
* Extended the installer to handle any amount of archives that need to
be downloaded & extracted, so that git-portable doesn't need to be
bundled with the installer

## Info

* Some e2e tests are only working on localhost, that's why the TEST_ENV
`local` was added. Tests marked as "local" will be skipped in ci.

---------

Co-authored-by: Gregor Adams <1148334+pixelass@users.noreply.github.com>
  • Loading branch information
TimPietrusky and pixelass committed Mar 4, 2024
1 parent 61a3295 commit 2a5bbc9
Show file tree
Hide file tree
Showing 19 changed files with 718 additions and 395 deletions.
1 change: 0 additions & 1 deletion .gitignore
Expand Up @@ -15,7 +15,6 @@ build

# python
resources/python-embedded/
resources/git/
resources/python/caption/wd14/models/model.onnx
__pycache__
.pytest_cache
Expand Down
6 changes: 2 additions & 4 deletions jest.config.electron.ts
@@ -1,13 +1,11 @@
import { defaults } from "jest-config";

// Adjust the import path to your tsconfig.json file

const jestConfig = {
...defaults,
roots: ["<rootDir>/src/electron"],
testMatch: ["**/?(*.)test.ts"],
transform: {
"^.+\\.ts$": ["@swc/jest"],
"^.+\\.(ts|js)$": ["@swc/jest"],
},
moduleNameMapper: {
"@/(.*)": "<rootDir>/src/electron/future/$1",
Expand All @@ -22,7 +20,7 @@ const jestConfig = {
lines: 80,
},
},
transformIgnorePatterns: ["/node_modules/"],
transformIgnorePatterns: ["/node_modules/.+\\.(?!c?js|mjs$)[^.]+$"],
extensionsToTreatAsEsm: [".ts"],
setupFilesAfterEnv: ["<rootDir>/jest.setup.electron.ts"],
};
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

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

4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -21,8 +21,8 @@
"spj": "npx sort-package-json@latest",
"test:client": "jest --runInBand --config jest.config.client.ts --verbose",
"pretest:e2e": "nextron build --no-pack",
"test:e2e": "xvfb-run --auto-servernum --server-args=\"-screen 0 1280x960x24\" -- npx playwright test",
"test:e2e:local": "npx playwright test",
"test:e2e": "xvfb-run --auto-servernum --server-args=\"-screen 0 1280x960x24\" -- cross-env TEST_ENV=test npx playwright test",
"test:e2e:local": "cross-env TEST_ENV=local npx playwright test",
"test:electron": "jest --runInBand --config jest.config.electron.ts --verbose",
"test:shared": "jest --runInBand --config jest.config.shared.ts --verbose",
"toc": "npx markdown-toc README.md -i",
Expand Down
111 changes: 111 additions & 0 deletions playwright/git.test.ts
@@ -0,0 +1,111 @@
import process from "process";

import type { ElectronApplication, Page } from "@playwright/test";
import { test, expect } from "@playwright/test";
import { _electron as electron } from "playwright";

import { buildKey } from "#/build-key";
import { ID } from "#/enums";
import type { GitCloneCompleted } from "@/utils/git";

/**
* For these tests to work, you need "portable-git" inside of "Captain_Data"
*/

const isLocalEnvironment = process.env.TEST_ENV === "local";
let electronApp: ElectronApplication;
let page: Page;

test.beforeAll(async () => {
electronApp = await electron.launch({
args: ["."],
env: {
...process.env,
TEST_ENV: "test",
TEST_VERSION: "upToDate",
TEST_APP_STATUS: "DONE",
},
});
const isPackaged = await electronApp.evaluate(async ({ app }) => app.isPackaged);
expect(isPackaged).toBe(false);
});

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

(isLocalEnvironment ? test : test.skip)("clone a repository until is is completed", async () => {
page = await electronApp.firstWindow();

const clone = buildKey([ID.DOWNLOADS], { suffix: ":clone" });
const cloned = buildKey([ID.DOWNLOADS], { suffix: ":cloned" });

const result = await page.evaluate(
([clone, cloned]) =>
new Promise(resolve => {
window.ipc.send(clone, {
repository: "blib-la/captain-test-model",
destination: "stable-diffusion",
});

const unsubscribe = window.ipc.on(cloned, result => {
unsubscribe();
resolve(result);
});
}),
[clone, cloned]
);

await expect(result).toHaveProperty("path");
await expect((result as GitCloneCompleted).path).toContain("captain-test-model");
});

(isLocalEnvironment ? test : test.skip)("get the progress when cloning a repository", async () => {
page = await electronApp.firstWindow();

const clone = buildKey([ID.DOWNLOADS], { suffix: ":clone" });
const progress = buildKey([ID.DOWNLOADS], { suffix: ":progress" });

const result = await page.evaluate(
([channelKey, progress]) =>
new Promise(resolve => {
window.ipc.send(channelKey, {
repository: "blib-la/captain-test-model",
destination: "stable-diffusion",
});

const unsubscribe = window.ipc.on(progress, result => {
unsubscribe();
resolve(result);
});
}),
[clone, progress]
);

await expect(result).toHaveProperty("percent");
});

(isLocalEnvironment ? test : test.skip)("clone a repository that doesn't exist", async () => {
page = await electronApp.firstWindow();

const clone = buildKey([ID.DOWNLOADS], { suffix: ":clone" });
const error = buildKey([ID.DOWNLOADS], { suffix: ":error" });

const result = await page.evaluate(
([clone, error]) =>
new Promise(resolve => {
window.ipc.send(clone, {
repository: "blib-la/captain-test-model-that-doesnt-exist",
destination: "stable-diffusion",
});

const unsubscribe = window.ipc.on(error, result => {
unsubscribe();
resolve(result);
});
}),
[clone, error]
);

await expect(result).toContain("Repository not found");
});
81 changes: 81 additions & 0 deletions playwright/installer.test.ts
Expand Up @@ -2,13 +2,22 @@ import type { ElectronApplication, Page } from "@playwright/test";
import { test, expect } from "@playwright/test";
import { _electron as electron } from "playwright";

import { buildKey } from "#/build-key";
import { ID } from "#/enums";

const isLocalEnvironment = process.env.TEST_ENV === "local";
let electronApp: ElectronApplication;
let page: Page;

test.beforeAll(async () => {
// Use package.main
electronApp = await electron.launch({
args: ["."],
env: {
...process.env,
TEST_ENV: "test",
TEST_APP_STATUS: "IDLE",
},
});
const isPackaged = await electronApp.evaluate(async ({ app }) => app.isPackaged);

Expand All @@ -33,3 +42,75 @@ test("Allows switching the language", async () => {
await page.getByText("Deutsch").click();
await expect(page.getByText("Sprache")).toBeVisible();
});

test("Can open page 2 of the installer & download & unpack", async () => {
page = await electronApp.firstWindow();

const locale = "de";
const pathname = "installer/02";

await page.goto(`app://./${locale}/${pathname}`);
await expect(page.getByText("Installieren").first()).toBeVisible();
expect(page.url()).toContain("de/installer/02");

await page.getByTestId("installer-02-start").click();
});

(isLocalEnvironment ? test : test.skip)("Download and unpack archives", async () => {
page = await electronApp.firstWindow();

const start = buildKey([ID.INSTALL], { suffix: ":start" });
const completed = buildKey([ID.INSTALL], { suffix: ":completed" });

const result = await page.evaluate(
([start, completed]) =>
new Promise(resolve => {
window.ipc.send(start, [
{
url: "https://blibla-captain-assets.s3.eu-central-1.amazonaws.com/test.7z",
destination: "test",
},
]);

const unsubscribe = window.ipc.on(completed, result => {
unsubscribe();
resolve(result);
});
}),
[start, completed]
);

await expect(result).toBeTruthy();
});

// Doesn't work yet
test.skip("error when trying to download and unpack archives", async () => {
page = await electronApp.firstWindow();

const start = buildKey([ID.INSTALL], { suffix: ":start" });
const completed = buildKey([ID.INSTALL], { suffix: ":completed" });
const failed = buildKey([ID.INSTALL], { suffix: ":failed" });

const result = await page.evaluate(
([start, completed, failed]) =>
new Promise(resolve => {
window.ipc.send(start, {
url: "https://blibla-captain-assets.s3.eu-central-1.amazonaws.com/asdf",
destination: "testtest",
});

const unsubscribe2 = window.ipc.on(completed, result => {
unsubscribe2();
resolve(result);
});

const unsubscribe = window.ipc.on(failed, result => {
unsubscribe();
resolve(result);
});
}),
[start, completed, failed]
);

await expect(result).toHaveProperty("path");
});
Binary file added resources/git/win/portable-git.7z
Binary file not shown.
4 changes: 2 additions & 2 deletions scripts/archive.mjs
Expand Up @@ -7,8 +7,8 @@ import Seven from "node-7z";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const my7z = path.join(__dirname, "..", "resources", "7zip", "win", "7za.exe");

const sourceFolder = path.join(__dirname, "..", "resources", "python-embedded");
const outputArchive = path.join(__dirname, "..", "resources", "python-embedded.7z");
const sourceFolder = path.join(__dirname, "..", "resources", "git/win/PortableGit");
const outputArchive = path.join(__dirname, "..", "resources", "portable-git.7z");

const files = await fsp.readdir(sourceFolder);

Expand Down

0 comments on commit 2a5bbc9

Please sign in to comment.