Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/sync/table/test/synctable.0.test.ts
Views: 687
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import { SyncTable } from "../synctable";6import { once } from "@cocalc/util/async-utils";7import { ClientTest } from "./client-test";89describe("tests public API of a system_notifications SyncTable", () => {10let synctable: SyncTable;11const notifications = [12{13id: "123e4567-e89b-12d3-a456-426655440000",14time: new Date(),15text: "This is a message.",16priority: "low",17},18{19id: "123e4567-e89b-12d3-a456-426655440001",20time: new Date(),21text: "This is a second message.",22priority: "high",23},24];25const client = new ClientTest(notifications);26const query = {27system_notifications: [28{ id: null, time: null, text: null, priority: null },29],30};3132test("create the synctable", async () => {33// last 0 is to disable change throttling, which messes up jest.34synctable = new SyncTable(query, [], client, 0);35expect(synctable.get_state()).toBe("disconnected");36await once(synctable, "connected");37});3839test("get query the synctable", () => {40const x = synctable.get();41if (x == null) {42throw Error("must be defined since synctable is connected");43}44expect(x.toJS()).toEqual({45[notifications[0].id]: notifications[0],46[notifications[1].id]: notifications[1],47});48});4950test("get_one query the synctable", () => {51const x = synctable.get_one();52if (x == null) {53throw Error("must be defined since synctable is connected");54}55expect(x.toJS()).toEqual(notifications[0]);56});5758test("get_one query for one primary key", () => {59const x = synctable.get_one(notifications[0].id);60if (x == null) {61throw Error("must be defined since synctable is connected");62}63expect(x.toJS()).toEqual(notifications[0]);64expect(x).toBe(synctable.get(notifications[0].id));65});6667test("get_one query for other primary key", () => {68const x = synctable.get_one(notifications[1].id);69if (x == null) {70throw Error("must be defined since synctable is connected");71}72expect(x.toJS()).toEqual(notifications[1]);73// also the get is the same when there is an arg.74expect(x).toBe(synctable.get(notifications[1].id));75});7677test("get_one query for other primary key", () => {78const x = synctable.get_one("foo");79expect(x).toBe(undefined);80// also the get is the same when there is an arg.81expect(x).toBe(synctable.get("foo"));82});8384test("does not have uncommitted changes", () => {85expect(synctable.has_uncommitted_changes()).toBe(false);86});8788test("making change to invalid field raises error", () => {89expect(() => synctable.set({ foobar: "medium" })).toThrow(90"Cannot coerce: no field 'foobar' in table 'system_notifications'"91);92});9394test("making change to field not in query (even though it is valid) raises error", () => {95expect(() => synctable.set({ done: true })).toThrow("coerce");96});9798test("make change; then has uncommitted changes", () => {99expect(client.set_queries.length).toBe(0);100synctable.set({ id: notifications[1].id, priority: "medium" });101// Set does not cause a database write (via save).102expect(client.set_queries.length).toBe(0);103expect(synctable.has_uncommitted_changes()).toBe(true);104});105106test("save change; then does not have uncommitted changes", async () => {107await synctable.save();108// Set causes a database write:109expect(client.set_queries.length).toBe(1);110expect(synctable.has_uncommitted_changes()).toBe(false);111});112113test("waiting for a condition to be satisfied", async () => {114function satisfy_condition() {115synctable.set({ id: notifications[1].id, priority: "high" });116synctable.save();117}118119function until(s) {120const priority = s.get(notifications[1].id).get("priority");121return priority === "high";122}123124const p = synctable.wait(until);125satisfy_condition();126await p;127});128129// @ts-ignore130test("a change event", (done) => {131synctable.once("change", (keys) => {132expect(keys).toEqual(["123e4567-e89b-12d3-a456-426655440001"]);133done();134});135synctable.set({ id: notifications[1].id, priority: "medium" });136synctable.save();137});138139test("closing the synctable", async () => {140const n = client.set_queries.length;141expect(synctable.get_state()).toBe("connected");142synctable.set({ id: notifications[1].id, priority: "low" });143expect(synctable.has_uncommitted_changes()).toBe(true);144synctable.close();145await once(synctable, "closed");146expect(client.set_queries.length).toBe(n + 1); // final save happened147});148149test("closed synctable -- has the right state", () => {150expect(synctable.get_state()).toBe("closed");151});152153test("closed synctable -- most public API functions throw an error", async () => {154expect(() => synctable.set({ priority: "medium" })).toThrow(155"can't set until table is initialized"156);157expect(() => synctable.get()).toThrow("closed");158expect(() => synctable.get_one()).toThrow("table not yet initialized");159expect(synctable.has_uncommitted_changes()).toBe(false); // does not throw160await synctable.close();161try {162await synctable.wait(() => true);163} catch (err) {164expect(err.toString()).toContain("closed");165}166try {167await synctable.save();168} catch (err) {169expect(err.toString()).toContain("closed");170}171});172173// some errors...174175test("try create synctable with an invalid query and get exception", () => {176const invalid_query = {177// invalid since missing id primary key.178system_notifications: [{ time: null, text: null, priority: null }],179};180expect(() => new SyncTable(invalid_query, [], client, 0)).toThrow(181"primary key"182);183});184185test("try create synctable with another invalid query and get exception", () => {186const invalid_query = {187// invalid since extra foo key.188system_notifications: [189{ id: null, foo: null, time: null, text: null, priority: null },190],191};192expect(() => new SyncTable(invalid_query, [], client, 0)).toThrow(193"field in the schema"194);195});196});197198199