@daml/react
Version:
React framework to interact with a Daml ledger
828 lines • 40.8 kB
JavaScript
;
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
// NOTE(MH): Unfortunately the `act` function triggers this warning by looking
// like a promise without being one.
/* eslint-disable @typescript-eslint/no-floating-promises */
var react_1 = __importStar(require("react"));
var react_hooks_1 = require("@testing-library/react-hooks");
var index_1 = __importStar(require("./index"));
var events_1 = require("events");
var mockConstructor = jest.fn();
var mockQuery = jest.fn();
var mockFetch = jest.fn();
var mockFetchByKey = jest.fn();
var mockStreamQueries = jest.fn();
var mockStreamFetchByKeys = jest.fn();
var mockFunctions = [
mockConstructor,
mockQuery,
mockFetch,
mockFetchByKey,
mockStreamQueries,
mockStreamFetchByKeys,
];
jest.mock("@daml/ledger", function () {
return /** @class */ (function () {
function class_1() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
mockConstructor.apply(void 0, args);
}
class_1.prototype.query = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return mockQuery.apply(void 0, args);
};
class_1.prototype.fetch = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return mockFetch.apply(void 0, args);
};
class_1.prototype.fetchByKey = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return mockFetchByKey.apply(void 0, args);
};
class_1.prototype.streamQueries = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return mockStreamQueries.apply(void 0, args);
};
class_1.prototype.streamFetchByKeys = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return mockStreamFetchByKeys.apply(void 0, args);
};
return class_1;
}());
});
/**
* Returns a mock stream object using an `EventEmitter` to implement on, off functions.
*/
var mockStream = function () {
var emitter = new events_1.EventEmitter();
var stream = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
on: function (type, listener) {
return void emitter.on(type, listener);
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
off: function (type, listener) {
return void emitter.on(type, listener);
},
close: function () {
emitter.removeAllListeners();
console.log("mock stream closed");
},
};
return [stream, emitter];
};
var TOKEN = "test_token";
var PARTY = "test_party";
var USER = { userId: "test_user" };
function renderDamlHook(callback) {
var wrapper = function (_a) {
var children = _a.children;
return react_1.default.createElement(index_1.default, { token: TOKEN, party: PARTY, user: USER, reconnectThreshold: 1337 }, children);
};
return (0, react_hooks_1.renderHook)(callback, { wrapper: wrapper });
}
/**
* Dummy template, needs at least the templateId field for debug messages emitted by
* `useStreamQuery`.
*/
var Foo = { templateId: "FooTemplateId" };
beforeEach(function () {
mockFunctions.forEach(function (mock) { return mock.mockClear(); });
});
test("DamlLedger", function () {
renderDamlHook(function () {
return;
});
expect(mockConstructor).toHaveBeenCalledTimes(1);
expect(mockConstructor).toHaveBeenLastCalledWith({
token: TOKEN,
httpBaseUrl: undefined,
wsBaseUrl: undefined,
reconnectThreshold: 1337,
});
});
test("useParty", function () {
var result = renderDamlHook(function () { return (0, index_1.useParty)(); }).result;
expect(result.current).toBe(PARTY);
});
test("useUser", function () {
var result = renderDamlHook(function () { return (0, index_1.useUser)(); }).result;
expect(result.current).toBe(USER);
});
describe("useQuery", function () {
test("one shot without query", function () { return __awaiter(void 0, void 0, void 0, function () {
var resolvent, _a, result, waitForNextUpdate;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
resolvent = ["foo"];
mockQuery.mockReturnValueOnce(Promise.resolve(resolvent));
_a = renderDamlHook(function () { return (0, index_1.useQuery)(Foo); }), result = _a.result, waitForNextUpdate = _a.waitForNextUpdate;
expect(mockQuery).toHaveBeenCalledTimes(1);
expect(mockQuery).toHaveBeenLastCalledWith(Foo, undefined);
mockQuery.mockClear();
expect(result.current.contracts).toEqual([]);
expect(result.current.loading).toBe(true);
return [4 /*yield*/, waitForNextUpdate()];
case 1:
_b.sent();
expect(mockQuery).not.toHaveBeenCalled();
expect(result.current.contracts).toBe(resolvent);
expect(result.current.loading).toBe(false);
return [2 /*return*/];
}
});
}); });
test("change to query", function () { return __awaiter(void 0, void 0, void 0, function () {
var query1, query2, resolvent1, resolvent2, _a, result, waitForNextUpdate;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
query1 = "foo-query";
query2 = "bar-query";
resolvent1 = ["foo"];
resolvent2 = ["bar"];
// First rendering works?
mockQuery.mockReturnValueOnce(Promise.resolve(resolvent1));
_a = renderDamlHook(function () {
var _a = (0, react_1.useState)(query1), query = _a[0], setQuery = _a[1];
var queryResult = (0, index_1.useQuery)(Foo, function () { return ({ query: query }); }, [query]);
return { queryResult: queryResult, query: query, setQuery: setQuery };
}), result = _a.result, waitForNextUpdate = _a.waitForNextUpdate;
expect(mockQuery).toHaveBeenCalledTimes(1);
expect(mockQuery).toHaveBeenLastCalledWith(Foo, { query: query1 });
mockQuery.mockClear();
expect(result.current.queryResult).toEqual({
contracts: [],
loading: true,
});
expect(result.current.query).toBe(query1);
return [4 /*yield*/, waitForNextUpdate()];
case 1:
_b.sent();
expect(result.current.queryResult).toEqual({
contracts: resolvent1,
loading: false,
});
// Change to query triggers another call to JSON API?
mockQuery.mockReturnValueOnce(Promise.resolve(resolvent2));
(0, react_hooks_1.act)(function () { return result.current.setQuery(query2); });
expect(mockQuery).toHaveBeenCalledTimes(1);
expect(mockQuery).toHaveBeenLastCalledWith(Foo, { query: query2 });
mockQuery.mockClear();
expect(result.current.queryResult).toEqual({
contracts: [],
loading: true,
});
expect(result.current.query).toBe(query2);
return [4 /*yield*/, waitForNextUpdate()];
case 2:
_b.sent();
expect(result.current.queryResult).toEqual({
contracts: resolvent2,
loading: false,
});
return [2 /*return*/];
}
});
}); });
test("rerendering without query change", function () { return __awaiter(void 0, void 0, void 0, function () {
var query, resolvent, _a, result, waitForNextUpdate;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
query = "query";
resolvent = ["foo"];
// First rendering works?
mockQuery.mockReturnValueOnce(Promise.resolve(resolvent));
_a = renderDamlHook(function () {
var setState = (0, react_1.useState)("state")[1];
var queryResult = (0, index_1.useQuery)(Foo, function () { return ({ query: query }); }, [query]);
return { queryResult: queryResult, setState: setState };
}), result = _a.result, waitForNextUpdate = _a.waitForNextUpdate;
expect(mockQuery).toHaveBeenCalledTimes(1);
mockQuery.mockClear();
return [4 /*yield*/, waitForNextUpdate()];
case 1:
_b.sent();
expect(result.current.queryResult).toEqual({
contracts: resolvent,
loading: false,
});
// Change to unrelated state does _not_ trigger another call to JSON API?
(0, react_hooks_1.act)(function () { return result.current.setState("new-state"); });
expect(mockQuery).not.toHaveBeenCalled();
expect(result.current.queryResult).toEqual({
contracts: resolvent,
loading: false,
});
return [2 /*return*/];
}
});
}); });
test("useReload", function () { return __awaiter(void 0, void 0, void 0, function () {
var resolvent1, resolvent2, _a, result, waitForNextUpdate;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
resolvent1 = ["foo"];
resolvent2 = ["bar"];
mockQuery.mockReturnValueOnce(Promise.resolve(resolvent1));
_a = renderDamlHook(function () {
var reload = (0, index_1.useReload)();
var queryResult = (0, index_1.useQuery)(Foo);
return { reload: reload, queryResult: queryResult };
}), result = _a.result, waitForNextUpdate = _a.waitForNextUpdate;
// first query
expect(mockQuery).toHaveBeenCalledTimes(1);
expect(mockQuery).toHaveBeenLastCalledWith(Foo, undefined);
return [4 /*yield*/, waitForNextUpdate()];
case 1:
_b.sent();
expect(result.current.queryResult).toEqual({
contracts: resolvent1,
loading: false,
});
mockQuery.mockClear();
// query result changes
mockQuery.mockReturnValueOnce(Promise.resolve(resolvent2));
// user reloads
(0, react_hooks_1.act)(function () { return result.current.reload(); });
return [4 /*yield*/, waitForNextUpdate()];
case 2:
_b.sent();
expect(mockQuery).toHaveBeenCalledTimes(1);
expect(mockQuery).toHaveBeenLastCalledWith(Foo, undefined);
expect(result.current.queryResult).toEqual({
contracts: resolvent2,
loading: false,
});
return [2 /*return*/];
}
});
}); });
});
describe("useFetch", function () {
test("one shot", function () { return __awaiter(void 0, void 0, void 0, function () {
var contract, contractId, _a, result, waitForNextUpdate;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
contract = { owner: "Alice" };
contractId = "1";
mockFetch.mockReturnValueOnce(Promise.resolve(contract));
_a = renderDamlHook(function () {
return (0, index_1.useFetch)(Foo, contractId);
}), result = _a.result, waitForNextUpdate = _a.waitForNextUpdate;
expect(mockFetch).toHaveBeenCalledTimes(1);
expect(mockFetch).toHaveBeenLastCalledWith(Foo, contractId);
mockFetch.mockClear();
expect(result.current).toEqual({ contract: null, loading: true });
return [4 /*yield*/, waitForNextUpdate()];
case 1:
_b.sent();
expect(mockFetch).not.toHaveBeenCalled();
expect(result.current).toEqual({ contract: contract, loading: false });
return [2 /*return*/];
}
});
}); });
});
describe("useFetchByKey", function () {
test("one shot", function () { return __awaiter(void 0, void 0, void 0, function () {
var contract, key, _a, result, waitForNextUpdate;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
contract = { owner: "Alice" };
key = contract.owner;
mockFetchByKey.mockReturnValueOnce(Promise.resolve(contract));
_a = renderDamlHook(function () {
return (0, index_1.useFetchByKey)(Foo, function () { return key; }, [key]);
}), result = _a.result, waitForNextUpdate = _a.waitForNextUpdate;
expect(mockFetchByKey).toHaveBeenCalledTimes(1);
expect(mockFetchByKey).toHaveBeenLastCalledWith(Foo, key);
mockFetchByKey.mockClear();
expect(result.current).toEqual({ contract: null, loading: true });
return [4 /*yield*/, waitForNextUpdate()];
case 1:
_b.sent();
expect(mockFetchByKey).not.toHaveBeenCalled();
expect(result.current).toEqual({ contract: contract, loading: false });
return [2 /*return*/];
}
});
}); });
test("change to key", function () { return __awaiter(void 0, void 0, void 0, function () {
var contract1, key1, contract2, key2, _a, result, waitForNextUpdate;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
contract1 = { owner: "Alice" };
key1 = contract1.owner;
contract2 = { owner: "Bob" };
key2 = contract2.owner;
// First rendering works?
mockFetchByKey.mockReturnValueOnce(Promise.resolve(contract1));
_a = renderDamlHook(function () {
var _a = (0, react_1.useState)(key1), key = _a[0], setKey = _a[1];
var queryResult = (0, index_1.useFetchByKey)(Foo, function () { return key; }, [key]);
return { queryResult: queryResult, key: key, setKey: setKey };
}), result = _a.result, waitForNextUpdate = _a.waitForNextUpdate;
expect(mockFetchByKey).toHaveBeenCalledTimes(1);
expect(mockFetchByKey).toHaveBeenLastCalledWith(Foo, key1);
mockFetchByKey.mockClear();
expect(result.current.queryResult).toEqual({
contract: null,
loading: true,
});
expect(result.current.key).toBe(key1);
return [4 /*yield*/, waitForNextUpdate()];
case 1:
_b.sent();
expect(result.current.queryResult).toEqual({
contract: contract1,
loading: false,
});
// Change to key triggers another call to JSON API?
mockFetchByKey.mockReturnValueOnce(Promise.resolve(contract2));
(0, react_hooks_1.act)(function () { return result.current.setKey(key2); });
expect(mockFetchByKey).toHaveBeenCalledTimes(1);
expect(mockFetchByKey).toHaveBeenLastCalledWith(Foo, key2);
mockFetchByKey.mockClear();
expect(result.current.queryResult).toEqual({
contract: null,
loading: true,
});
expect(result.current.key).toBe(key2);
return [4 /*yield*/, waitForNextUpdate()];
case 2:
_b.sent();
expect(result.current.queryResult).toEqual({
contract: contract2,
loading: false,
});
return [2 /*return*/];
}
});
}); });
test("rerendering without key change", function () { return __awaiter(void 0, void 0, void 0, function () {
var contract, key, _a, result, waitForNextUpdate;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
contract = { owner: "Alice" };
key = contract.owner;
// First rendering works?
mockFetchByKey.mockReturnValueOnce(Promise.resolve(contract));
_a = renderDamlHook(function () {
var setState = (0, react_1.useState)("state")[1];
var queryResult = (0, index_1.useFetchByKey)(Foo, function () { return key; }, [key]);
return { queryResult: queryResult, setState: setState };
}), result = _a.result, waitForNextUpdate = _a.waitForNextUpdate;
expect(mockFetchByKey).toHaveBeenCalledTimes(1);
mockFetchByKey.mockClear();
return [4 /*yield*/, waitForNextUpdate()];
case 1:
_b.sent();
expect(result.current.queryResult).toEqual({ contract: contract, loading: false });
// Change to unrelated state does _not_ trigger another call to JSON API?
(0, react_hooks_1.act)(function () { return result.current.setState("new-state"); });
expect(mockFetchByKey).not.toHaveBeenCalled();
expect(result.current.queryResult).toEqual({ contract: contract, loading: false });
return [2 /*return*/];
}
});
}); });
test("useReload", function () { return __awaiter(void 0, void 0, void 0, function () {
var contract1, key1, contract2, _a, result, waitForNextUpdate;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
contract1 = { owner: "Alice" };
key1 = contract1.owner;
contract2 = { owner: "Bob" };
mockFetchByKey.mockReturnValueOnce(Promise.resolve(contract1));
_a = renderDamlHook(function () {
var reload = (0, index_1.useReload)();
var fetchResult = (0, index_1.useFetchByKey)(Foo, function () { return key1; }, [key1]);
return { reload: reload, fetchResult: fetchResult };
}), result = _a.result, waitForNextUpdate = _a.waitForNextUpdate;
// first fetchByKey
expect(mockFetchByKey).toHaveBeenCalledTimes(1);
expect(mockFetchByKey).toHaveBeenLastCalledWith(Foo, key1);
return [4 /*yield*/, waitForNextUpdate()];
case 1:
_b.sent();
expect(result.current.fetchResult).toEqual({
contract: contract1,
loading: false,
});
mockFetchByKey.mockClear();
// fetchByKey result changes
mockFetchByKey.mockReturnValueOnce(Promise.resolve(contract2));
// user reloads
(0, react_hooks_1.act)(function () { return result.current.reload(); });
return [4 /*yield*/, waitForNextUpdate()];
case 2:
_b.sent();
expect(mockFetchByKey).toHaveBeenCalledTimes(1);
expect(mockFetchByKey).toHaveBeenLastCalledWith(Foo, key1);
expect(result.current.fetchResult).toEqual({
contract: contract2,
loading: false,
});
return [2 /*return*/];
}
});
}); });
});
/*
* Note: LyingToTheCompiler should really be QueryResult here. However, that
* maps to `{loading: boolean; contracts: CreateEvent<>[]}`, where each
* `CreateEvent` has the contract data in a `payload` field. The existing tests
* have been written against mocked streams returning `{loading: boolean;
* contracts: payload[]}` directly, and I don't see much benefit in changing
* that in the context of mocking all stream operations.
*/
function streamq(useFn, mkQuery) {
return function () {
test("live event changes loading status", function () {
// setup
var query = "foo-query";
var _a = mockStream(), stream = _a[0], emitter = _a[1];
mockStreamQueries.mockReturnValueOnce(stream);
var hookResult = renderDamlHook(function () {
return useFn(Foo, mkQuery(query), [query]);
});
expect(mockStreamQueries).toHaveBeenCalledTimes(1);
expect(mockStreamQueries).toHaveBeenLastCalledWith(Foo, [{ query: query }]);
// no events have been emitted.
expect(hookResult.result.current).toEqual({
contracts: [],
loading: true,
});
// live event
(0, react_hooks_1.act)(function () { return void emitter.emit("live", []); });
expect(hookResult.result.current).toEqual({
contracts: [],
loading: false,
});
});
test("live event changes loading status", function () {
// setup
var query = "foo-query";
var _a = mockStream(), stream = _a[0], emitter = _a[1];
mockStreamQueries.mockReturnValueOnce(stream);
var hookResult = renderDamlHook(function () {
return useFn(Foo, mkQuery(query), [query]);
});
expect(mockStreamQueries).toHaveBeenCalledTimes(1);
expect(mockStreamQueries).toHaveBeenLastCalledWith(Foo, [{ query: query }]);
// no events have been emitted.
expect(hookResult.result.current).toEqual({
contracts: [],
loading: true,
});
// live event
(0, react_hooks_1.act)(function () { return void emitter.emit("live", []); });
expect(hookResult.result.current).toEqual({
contracts: [],
loading: false,
});
});
test("closeHandler gets called", function () {
// setup
var query = "foo-query";
var _a = mockStream(), stream = _a[0], emitter = _a[1];
mockStreamQueries.mockReturnValueOnce(stream);
var closeHandler = jest.fn();
var hookResult = renderDamlHook(function () {
return useFn(Foo, mkQuery(query), [query], closeHandler);
});
expect(mockStreamQueries).toHaveBeenCalledTimes(1);
expect(mockStreamQueries).toHaveBeenLastCalledWith(Foo, [{ query: query }]);
// no events have been emitted.
expect(hookResult.result.current).toEqual({
contracts: [],
loading: true,
});
expect(closeHandler).toHaveBeenCalledTimes(0);
(0, react_hooks_1.act)(function () { return void emitter.emit("close", { code: 4000, reason: "" }); });
expect(closeHandler).toHaveBeenCalledTimes(1);
expect(closeHandler).toHaveBeenLastCalledWith({ code: 4000, reason: "" });
});
test("empty stream", function () {
// setup
var query = "foo-query";
var _a = mockStream(), stream = _a[0], emitter = _a[1];
mockStreamQueries.mockReturnValueOnce(stream);
var hookResult = renderDamlHook(function () {
return useFn(Foo, mkQuery(query), [query]);
});
expect(mockStreamQueries).toHaveBeenCalledTimes(1);
expect(mockStreamQueries).toHaveBeenLastCalledWith(Foo, [{ query: query }]);
// live event
(0, react_hooks_1.act)(function () { return void emitter.emit("live", []); });
// no events have been emitted.
expect(hookResult.result.current).toEqual({
contracts: [],
loading: false,
});
// empty events
(0, react_hooks_1.act)(function () { return void emitter.emit("change", []); });
expect(hookResult.result.current).toEqual({
contracts: [],
loading: false,
});
});
test("new events", function () {
// setup
var query = "foo-query";
var _a = mockStream(), stream = _a[0], emitter = _a[1];
mockStreamQueries.mockReturnValueOnce(stream);
var hookResult = renderDamlHook(function () {
return useFn(Foo, mkQuery(query), [query]);
});
expect(mockStreamQueries).toHaveBeenCalledTimes(1);
expect(mockStreamQueries).toHaveBeenLastCalledWith(Foo, [
{ query: query },
]);
expect(hookResult.result.current.contracts).toEqual([]);
// live event
(0, react_hooks_1.act)(function () { return void emitter.emit("live", []); });
expect(hookResult.result.current.loading).toBe(false);
// one new event
(0, react_hooks_1.act)(function () { return void emitter.emit("change", ["event1"]); });
expect(hookResult.result.current.contracts).toEqual(["event1"]);
expect(hookResult.result.current.loading).toBe(false);
// two new events replacing old one.
(0, react_hooks_1.act)(function () { return void emitter.emit("change", ["event2", "event3"]); });
expect(hookResult.result.current).toEqual({
contracts: ["event2", "event3"],
loading: false,
});
});
test("changed query triggers reload", function () {
// setup
var query1 = "foo-query";
var query2 = "bar-query";
var _a = mockStream(), stream = _a[0], emitter = _a[1];
mockStreamQueries.mockReturnValueOnce(stream);
var result = renderDamlHook(function () {
var _a = (0, react_1.useState)(query1), query = _a[0], setQuery = _a[1];
var queryResult = useFn(Foo, mkQuery(query), [query]);
return { queryResult: queryResult, query: query, setQuery: setQuery };
}).result;
expect(mockStreamQueries).toHaveBeenCalledTimes(1);
expect(mockStreamQueries).toHaveBeenLastCalledWith(Foo, [
{ query: query1 },
]);
// live event
(0, react_hooks_1.act)(function () { return void emitter.emit("live", []); });
expect(result.current.queryResult).toEqual({
contracts: [],
loading: false,
});
// new events
(0, react_hooks_1.act)(function () { return void emitter.emit("change", ["foo"]); });
expect(result.current.queryResult).toEqual({
contracts: ["foo"],
loading: false,
});
// change query, expect stream to have been called with new query.
mockStreamQueries.mockClear();
mockStreamQueries.mockReturnValueOnce(stream);
(0, react_hooks_1.act)(function () { return result.current.setQuery(query2); });
// live event
(0, react_hooks_1.act)(function () { return void emitter.emit("live", null); });
// change event
(0, react_hooks_1.act)(function () { return void emitter.emit("change", ["bar"]); });
expect(mockStreamQueries).toHaveBeenCalledTimes(1);
expect(mockStreamQueries).toHaveBeenLastCalledWith(Foo, [
{ query: query2 },
]);
expect(result.current.queryResult).toEqual({
contracts: ["bar"],
loading: false,
});
});
};
}
describe("useStreamQuery", streamq(index_1.useStreamQuery, function (query) {
return function () { return ({ query: query }); };
}));
describe("useStreamQueries", streamq(index_1.useStreamQueries, function (query) {
return function () {
return [{ query: query }];
};
}));
/*
* Note: Ignored here should really be R. However, because all of the exiting
* tests have been written to completely skip over CreateEvent and go straight
* to payload (see `streamq` note), init and found need to be a different type
* from Ignored.
*/
function streamk(useFn, mkQ, init, found) {
return function () {
test("empty stream", function () {
var contract = { owner: "Alice" };
var key = contract.owner;
var _a = mockStream(), stream = _a[0], emitter = _a[1];
mockStreamFetchByKeys.mockReturnValueOnce(stream);
var result = renderDamlHook(function () { return useFn(Foo, mkQ(key), [key]); }).result;
expect(mockStreamFetchByKeys).toHaveBeenCalledTimes(1);
expect(mockStreamFetchByKeys).toHaveBeenLastCalledWith(Foo, [key]);
expect(result.current).toEqual(init);
(0, react_hooks_1.act)(function () { return void emitter.emit("live"); });
expect(result.current).toEqual(__assign(__assign({}, init), { loading: false }));
(0, react_hooks_1.act)(function () { return void emitter.emit("change", [null]); });
expect(result.current).toEqual(found(null));
}),
test("new event", function () {
var contract = { owner: "Alice" };
var key = contract.owner;
var _a = mockStream(), stream = _a[0], emitter = _a[1];
mockStreamFetchByKeys.mockReturnValueOnce(stream);
var result = renderDamlHook(function () { return useFn(Foo, mkQ(key), [key]); }).result;
expect(mockStreamFetchByKeys).toHaveBeenCalledTimes(1);
expect(mockStreamFetchByKeys).toHaveBeenLastCalledWith(Foo, [key]);
expect(result.current).toEqual(init);
(0, react_hooks_1.act)(function () { return void emitter.emit("live"); });
expect(result.current).toEqual(__assign(__assign({}, init), { loading: false }));
(0, react_hooks_1.act)(function () { return void emitter.emit("change", [contract]); });
expect(result.current).toEqual(found(contract));
}),
test("changed key triggers reload", function () {
var contract = { k1: "Alice", k2: "Bob" };
var key1 = contract.k1;
var key2 = contract.k2;
var _a = mockStream(), stream = _a[0], emitter = _a[1];
mockStreamFetchByKeys.mockReturnValueOnce(stream);
var result = renderDamlHook(function () {
var _a = (0, react_1.useState)(key1), key = _a[0], setKey = _a[1];
var fetchResult = useFn(Foo, mkQ(key), [key]);
return { fetchResult: fetchResult, key: key, setKey: setKey };
}).result;
(0, react_hooks_1.act)(function () { return void emitter.emit("live"); });
(0, react_hooks_1.act)(function () { return void emitter.emit("change", [contract]); });
expect(mockStreamFetchByKeys).toHaveBeenCalledTimes(1);
expect(mockStreamFetchByKeys).toHaveBeenLastCalledWith(Foo, [key1]);
expect(result.current.fetchResult).toEqual(found(contract));
mockStreamFetchByKeys.mockClear();
mockStreamFetchByKeys.mockReturnValueOnce(stream);
(0, react_hooks_1.act)(function () { return result.current.setKey(key2); });
expect(mockStreamFetchByKeys).toHaveBeenCalledTimes(1);
expect(mockStreamFetchByKeys).toHaveBeenLastCalledWith(Foo, [key2]);
});
describe("createLedgerContext", function () {
test("contexts can nest", function () {
var innerLedger = (0, index_1.createLedgerContext)();
var innerTOKEN = "inner_TOKEN";
var innerPARTY = "inner_PARTY";
var innerUSER = { userId: "inner_USER" };
var outerLedger = (0, index_1.createLedgerContext)("Outer");
var outerTOKEN = "outer_TOKEN";
var outerPARTY = "outer_PARTY";
var outerUSER = { userId: "outer_USER" };
var innerWrapper = function (_a) {
var children = _a.children;
return react_1.default.createElement(innerLedger.DamlLedger, { token: innerTOKEN, party: innerPARTY, user: innerUSER }, children);
};
var r1 = (0, react_hooks_1.renderHook)(function () { return innerLedger.useParty(); }, {
wrapper: innerWrapper,
});
expect(r1.result.current).toBe(innerPARTY);
var outerWrapper = function (_a) {
var children = _a.children;
return react_1.default.createElement(outerLedger.DamlLedger, { token: outerTOKEN, party: outerPARTY, user: outerUSER }, innerWrapper({ children: children }));
};
var r2 = (0, react_hooks_1.renderHook)(function () { return outerLedger.useParty(); }, {
wrapper: outerWrapper,
});
expect(r2.result.current).toBe(outerPARTY);
var r3 = (0, react_hooks_1.renderHook)(function () { return innerLedger.useParty(); }, {
wrapper: outerWrapper,
});
expect(r3.result.current).toBe(innerPARTY);
});
});
};
}
describe("useStreamFetchByKey", streamk(index_1.useStreamFetchByKey, function (k) {
return function () {
return k;
};
}, { loading: true, contract: null }, function (c) { return ({
loading: false,
contract: c,
}); }));
describe("useStreamFetchByKeys", streamk(index_1.useStreamFetchByKeys, function (k) {
return function () {
return [k];
};
}, { loading: true, contracts: [] }, function (c) { return ({
loading: false,
contracts: [c],
}); }));
//# sourceMappingURL=index.test.js.map