Files
2026-07-13 12:25:07 +08:00

155 lines
7.1 KiB
JavaScript

// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
// ┃ This file is part of the Perspective library, distributed under the terms ┃
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
import { test, expect } from "@perspective-dev/test";
import perspective from "../perspective_client";
import * as common from "./common.js";
/**
* Tests the correctness of user-defined vectors inside expressions.
*
* @param {*} perspective
*/
((perspective) => {
test.describe("Vectors", () => {
test("Create vector and return value", async () => {
const table = await perspective.table(common.int_float_data);
const view = await table.view({
expressions: { a: `var vec[3] := {1, "w", 2}; vec[1]` },
});
expect(await view.expression_schema()).toEqual({
a: "float",
});
const result = await view.to_columns();
expect(result["a"]).toEqual(result["w"]);
await view.delete();
await table.delete();
});
test("Return from empty vector should be 0", async () => {
const table = await perspective.table(common.int_float_data);
const view = await table.view({
expressions: { a: `var vec[3]; vec[1]` },
});
expect(await view.expression_schema()).toEqual({
a: "float",
});
const result = await view.to_columns();
expect(result["a"]).toEqual(Array(4).fill(0));
await view.delete();
await table.delete();
});
test("Dynamic return types from vector", async () => {
const table = await perspective.table(common.int_float_data);
const view = await table.view({
expressions: {
[`a`]: `var vec[3] := {'abc', 123, today()}; vec[0]`,
[`b`]: `var vec[3] := {'abc', 123, today()}; vec[1]`,
[`c`]: `var vec[3] := {'abc', 123, date(2020, 5, 23)}; vec[2]`,
[`d`]: `var vec[3] := {'abc', 123, is_null(null)}; vec[2]`,
},
});
expect(await view.expression_schema()).toEqual({
a: "string",
b: "float",
c: "date",
d: "boolean",
});
const result = await view.to_columns();
expect(result["a"]).toEqual(Array(4).fill("abc"));
expect(result["b"]).toEqual(Array(4).fill(123));
expect(result["c"]).toEqual(
Array(4).fill(new Date(2020, 4, 23).getTime()),
);
expect(result["d"]).toEqual(Array(4).fill(true));
await view.delete();
await table.delete();
});
test("Use vector items as inputs", async () => {
const table = await perspective.table(common.int_float_data);
const view = await table.view({
expressions: {
[`a`]: `var vec[2] := {"w", "x"}; vec[0] * vec[1]`,
},
});
expect(await view.expression_schema()).toEqual({
a: "float",
});
const result = await view.to_columns();
expect(result["a"]).toEqual(
result["w"].map((item, idx) => item * result["x"][idx]),
);
await view.delete();
await table.delete();
});
test("Custom function takes vector item input", async () => {
const table = await perspective.table(common.int_float_data);
const view = await table.view({
expressions: {
[`a`]: `var vec[2] := {"w", "x"}; max(vec[0], vec[1])`,
},
});
expect(await view.expression_schema()).toEqual({
a: "float",
});
const result = await view.to_columns();
expect(result["a"]).toEqual(
result["w"].map((item, idx) =>
Math.max(item, result["x"][idx]),
),
);
await view.delete();
await table.delete();
});
test("`norm3` with a vector shorter than 3 is rejected", async () => {
const table = await perspective.table(common.int_float_data);
await expect(
table.view({
expressions: { a: `var v[2] := {1, 2}; norm3(v)` },
}),
).rejects.toThrow();
await table.delete();
});
test("`diff3` with vectors shorter than 3 is rejected", async () => {
const table = await perspective.table(common.int_float_data);
await expect(
table.view({
expressions: {
a: `var x[2] := {1, 2}; var y[2] := {3, 4}; var o[2]; diff3(x, y, o)`,
},
}),
).rejects.toThrow();
await table.delete();
});
test("`norm3` with a 3-element vector still computes", async () => {
const table = await perspective.table(common.int_float_data);
const view = await table.view({
expressions: { a: `var v[3] := {3, 4, 0}; norm3(v)` },
});
const result = await view.to_columns();
expect(result["a"]).toEqual(Array(4).fill(5)); // sqrt(9+16+0)
await view.delete();
await table.delete();
});
});
})(perspective);