Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ plugins {
alias(libs.plugins.detekt)
alias(libs.plugins.kotlinx.kover)
alias(libs.plugins.npm.publish) apply false
id("org.jetbrains.gradle.plugin.idea-ext") version "1.1.9" apply false
}

group = "org.modelix"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,17 @@ fun runWithNettyServer(
nettyServer.stop()
}
}

fun runTestApplication(block: suspend ApplicationTestBuilder.() -> Unit) {
val previousDevMode = System.getProperty("io.ktor.development")
System.setProperty("io.ktor.development", "false")
try {
io.ktor.server.testing.testApplication(block)
} finally {
if (previousDevMode == null) {
System.clearProperty("io.ktor.development")
} else {
System.setProperty("io.ktor.development", previousDevMode)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import io.ktor.client.statement.HttpResponse
import io.ktor.client.statement.bodyAsText
import io.ktor.http.HttpStatusCode
import io.ktor.server.testing.ApplicationTestBuilder
import io.ktor.server.testing.testApplication
import io.mockk.clearAllMocks
import io.mockk.coEvery
import io.mockk.every
Expand All @@ -42,6 +41,7 @@ import org.modelix.model.persistent.CPNode
import org.modelix.model.persistent.CPNodeRef
import org.modelix.model.server.handlers.RepositoriesManager
import org.modelix.model.server.installDefaultServerPlugins
import org.modelix.model.server.runTestApplication
import kotlin.test.BeforeTest
import kotlin.test.Test

Expand Down Expand Up @@ -308,7 +308,7 @@ class DiffViewTest {
val v1 = createCLVersion { it }
val v2 = createCLVersion(v1) { it }

private fun runDiffViewTest(block: suspend ApplicationTestBuilder.() -> Unit) = testApplication {
private fun runDiffViewTest(block: suspend ApplicationTestBuilder.() -> Unit) = runTestApplication {
application {
installDefaultServerPlugins()
DiffView(repositoriesManager).init(this)
Expand Down
1 change: 1 addition & 0 deletions vue-model-api/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { useModelsFromJson } from "./useModelsFromJson";
export { useModelClient } from "./useModelClient";
export { useReplicatedModels } from "./useReplicatedModels";
export { useReplicatedModel } from "./useReplicatedModel";
export { useReadonlyVersion } from "./useReadonlyVersion";
165 changes: 29 additions & 136 deletions vue-model-api/src/useReplicatedModel.test.ts
Original file line number Diff line number Diff line change
@@ -1,67 +1,56 @@
import { org } from "@modelix/model-client";
import type { INodeJS } from "@modelix/ts-model-api";
import { toRoleJS } from "@modelix/ts-model-api";
import { watchEffect, type Ref, ref } from "vue";
import { watchEffect } from "vue";
import { useModelClient } from "./useModelClient";
import { useReplicatedModel } from "./useReplicatedModel";
import { useReplicatedModel } from "./useReplicatedModels";
import IdSchemeJS = org.modelix.model.client2.IdSchemeJS;

type BranchJS = org.modelix.model.client2.MutableModelTreeJs;
type ReplicatedModelJS = org.modelix.model.client2.ReplicatedModelJS;
type ClientJS = org.modelix.model.client2.ClientJS;
type ReplicatedModelJS = org.modelix.model.client2.ReplicatedModelJS;

const { loadModelsFromJson } = org.modelix.model.client2;

class SuccessfulBranchJS {
public rootNode: INodeJS;

constructor(branchId: string) {
const root = {
root: {},
};

this.rootNode = loadModelsFromJson([JSON.stringify(root)]);
this.rootNode.setPropertyValue(toRoleJS("branchId"), branchId);
}

addListener = jest.fn();
}

class SuccessfulReplicatedModelJS {
private branch: BranchJS;
constructor(branchId: string) {
this.branch = new SuccessfulBranchJS(branchId) as unknown as BranchJS;
}

getBranch() {
return this.branch;
}
dispose = jest.fn();
}
import ReplicatedModelParameters = org.modelix.model.client2.ReplicatedModelParameters;

test("test branch connects", (done) => {
test("test wrapper backwards compatibility", (done) => {
class SuccessfulClientJS {
startReplicatedModel(
_repositoryId: string,
branchId: string,
startReplicatedModels(
parameters: ReplicatedModelParameters[],
): Promise<ReplicatedModelJS> {
return Promise.resolve(
new SuccessfulReplicatedModelJS(
branchId,
) as unknown as ReplicatedModelJS,
);
// Mock implementation that returns a dummy object with a branch
const branchId = parameters[0].branchId;
const rootNode = loadModelsFromJson([JSON.stringify({ root: {} })]);
rootNode.setPropertyValue(toRoleJS("branchId"), branchId);

const branch = {
rootNode,
getRootNodes: () => [rootNode],
addListener: jest.fn(),
removeListener: jest.fn(),
resolveNode: jest.fn(),
};

const replicatedModel = {
getBranch: () => branch,
dispose: jest.fn(),
getCurrentVersionInformation: jest.fn(),
} as unknown as ReplicatedModelJS;

return Promise.resolve(replicatedModel);
}
}

const { client } = useModelClient("anURL", () =>
Promise.resolve(new SuccessfulClientJS() as unknown as ClientJS),
);

const { rootNode, replicatedModel } = useReplicatedModel(
client,
"aRepository",
"aBranch",
IdSchemeJS.MODELIX,
);

watchEffect(() => {
if (rootNode.value !== null && replicatedModel.value !== null) {
expect(rootNode.value.getPropertyValue(toRoleJS("branchId"))).toBe(
Expand All @@ -71,99 +60,3 @@ test("test branch connects", (done) => {
}
});
});

test("test branch connection error is exposed", (done) => {
class FailingClientJS {
startReplicatedModel(
_repositoryId: string,
_branchId: string,
): Promise<BranchJS> {
return Promise.reject("Could not connect branch.");
}
}

const { client } = useModelClient("anURL", () =>
Promise.resolve(new FailingClientJS() as unknown as ClientJS),
);

const { error } = useReplicatedModel(
client,
"aRepository",
"aBranch",
IdSchemeJS.MODELIX,
);

watchEffect(() => {
if (error.value !== null) {
expect(error.value).toBe("Could not connect branch.");
done();
}
});
});

describe("does not start model", () => {
const startReplicatedModel = jest.fn((repositoryId, branchId) =>
Promise.resolve(
new SuccessfulReplicatedModelJS(branchId) as unknown as ReplicatedModelJS,
),
);

let client: Ref<ClientJS | null>;
class MockClientJS {
startReplicatedModel(
_repositoryId: string,
_branchId: string,
): Promise<ReplicatedModelJS> {
return startReplicatedModel(_repositoryId, _branchId);
}
}

beforeEach(() => {
jest.clearAllMocks();
client = useModelClient("anURL", () =>
Promise.resolve(new MockClientJS() as unknown as ClientJS),
).client;
});

test("if client is undefined", () => {
useReplicatedModel(undefined, "aRepository", "aBranch", IdSchemeJS.MODELIX);
expect(startReplicatedModel).not.toHaveBeenCalled();
});

test("if repositoryId is undefined", () => {
useReplicatedModel(client, undefined, "aBranch", IdSchemeJS.MODELIX);
expect(startReplicatedModel).not.toHaveBeenCalled();
});

test("if branchId is undefined", () => {
useReplicatedModel(client, "aRepository", undefined, IdSchemeJS.MODELIX);
expect(startReplicatedModel).not.toHaveBeenCalled();
});

test("if idScheme is undefined", () => {
useReplicatedModel(client, "aRepository", "aBranch", undefined);
expect(startReplicatedModel).not.toHaveBeenCalled();
});

test("if repositoryId switches to another value", async () => {
const repositoryId = ref<string | undefined>("aRepository");
useReplicatedModel(client, repositoryId, "aBranch", IdSchemeJS.MODELIX);
expect(startReplicatedModel).toHaveBeenCalled();

startReplicatedModel.mockClear();
repositoryId.value = "aNewValue";
await new Promise(process.nextTick);
expect(startReplicatedModel).toHaveBeenCalled();
});

test("if repositoryId switches to undefined", async () => {
const repositoryId = ref<string | undefined>("aRepository");
useReplicatedModel(client, repositoryId, "aBranch", IdSchemeJS.MODELIX);
expect(startReplicatedModel).toHaveBeenCalled();

startReplicatedModel.mockClear();
repositoryId.value = undefined;
await new Promise(process.nextTick);
expect(startReplicatedModel).not.toHaveBeenCalled();
});
});
Loading
Loading