897 lines
35 KiB
JavaScript
897 lines
35 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";
|
|
|
|
const data = {
|
|
w: [1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5],
|
|
x: [1, 2, 3, 4, 4, 3, 2, 1],
|
|
y: ["a", "b", "c", "d", "a", "b", "c", "d"],
|
|
z: [true, false, true, false, true, false, true, false],
|
|
};
|
|
|
|
const data2 = {
|
|
w: [3.5, 4.5, null, null, null, null, 1.5, 2.5],
|
|
x: [1, 2, 3, 4, 4, 3, 2, 1],
|
|
y: ["a", "b", "c", "d", "e", "f", "g", "h"],
|
|
};
|
|
|
|
const data3 = {
|
|
w: [3.5, 4.5, null, null, null, null, 1.5, 2.5],
|
|
x: [1, 2, 3, 4, 4, 3, 2, 1],
|
|
y: ["a", "a", "a", "a", "b", "b", "b", "b"],
|
|
};
|
|
|
|
((perspective) => {
|
|
test.describe("Sorts", function () {
|
|
test.describe("With nulls", () => {
|
|
test("asc", async function () {
|
|
var table = await perspective.table(data2);
|
|
var view = await table.view({
|
|
columns: ["x", "w"],
|
|
sort: [["w", "asc"]],
|
|
});
|
|
|
|
const json = await view.to_columns();
|
|
expect(json).toEqual({
|
|
w: [null, null, null, null, 1.5, 2.5, 3.5, 4.5],
|
|
x: [3, 4, 4, 3, 2, 1, 1, 2],
|
|
});
|
|
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("desc", async function () {
|
|
var table = await perspective.table(data2);
|
|
var view = await table.view({
|
|
columns: ["x", "w"],
|
|
sort: [["w", "desc"]],
|
|
});
|
|
|
|
const json = await view.to_columns();
|
|
expect(json).toEqual({
|
|
w: [4.5, 3.5, 2.5, 1.5, null, null, null, null],
|
|
x: [2, 1, 1, 2, 3, 4, 4, 3],
|
|
});
|
|
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("asc datetime", async function () {
|
|
var table = await perspective.table({
|
|
w: [
|
|
new Date(2020, 0, 1, 12, 30, 45),
|
|
new Date(2020, 0, 1),
|
|
null,
|
|
null,
|
|
null,
|
|
null,
|
|
new Date(2008, 0, 1, 12, 30, 45),
|
|
new Date(2020, 12, 1, 12, 30, 45),
|
|
],
|
|
x: [1, 2, 3, 4, 4, 3, 2, 1],
|
|
y: ["a", "b", "c", "d", "e", "f", "g", "h"],
|
|
});
|
|
|
|
var view = await table.view({
|
|
columns: ["x", "w"],
|
|
sort: [["w", "asc"]],
|
|
});
|
|
|
|
const json = await view.to_columns();
|
|
expect(json).toEqual({
|
|
w: [
|
|
null,
|
|
null,
|
|
null,
|
|
null,
|
|
new Date(2008, 0, 1, 12, 30, 45).getTime(),
|
|
new Date(2020, 0, 1).getTime(),
|
|
new Date(2020, 0, 1, 12, 30, 45).getTime(),
|
|
new Date(2020, 12, 1, 12, 30, 45).getTime(),
|
|
],
|
|
x: [3, 4, 4, 3, 2, 2, 1, 1],
|
|
});
|
|
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("desc datetime", async function () {
|
|
var table = await perspective.table({
|
|
w: [
|
|
new Date(2020, 0, 1, 12, 30, 45),
|
|
new Date(2020, 0, 1),
|
|
null,
|
|
null,
|
|
null,
|
|
null,
|
|
new Date(2008, 0, 1, 12, 30, 45),
|
|
new Date(2020, 12, 1, 12, 30, 45),
|
|
],
|
|
x: [1, 2, 3, 4, 4, 3, 2, 1],
|
|
y: ["a", "b", "c", "d", "e", "f", "g", "h"],
|
|
});
|
|
|
|
var view = await table.view({
|
|
columns: ["x", "w"],
|
|
sort: [["w", "desc"]],
|
|
});
|
|
|
|
const json = await view.to_columns();
|
|
expect(json).toEqual({
|
|
w: [
|
|
new Date(2020, 12, 1, 12, 30, 45).getTime(),
|
|
new Date(2020, 0, 1, 12, 30, 45).getTime(),
|
|
new Date(2020, 0, 1).getTime(),
|
|
new Date(2008, 0, 1, 12, 30, 45).getTime(),
|
|
null,
|
|
null,
|
|
null,
|
|
null,
|
|
],
|
|
x: [1, 1, 2, 2, 3, 4, 4, 3],
|
|
});
|
|
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
});
|
|
|
|
test.describe("With aggregates", function () {
|
|
test.describe("aggregates, in a sorted column with nulls", function () {
|
|
test("sum", async function () {
|
|
var table = await perspective.table(data2);
|
|
var view = await table.view({
|
|
columns: ["x", "w"],
|
|
group_by: ["y"],
|
|
aggregates: {
|
|
w: "sum",
|
|
x: "unique",
|
|
},
|
|
sort: [["w", "asc"]],
|
|
});
|
|
|
|
const json = await view.to_columns();
|
|
expect(json).toEqual({
|
|
__ROW_PATH__: [
|
|
[],
|
|
["c"],
|
|
["d"],
|
|
["e"],
|
|
["f"],
|
|
["g"],
|
|
["h"],
|
|
["a"],
|
|
["b"],
|
|
],
|
|
w: [12, 0, 0, 0, 0, 1.5, 2.5, 3.5, 4.5],
|
|
x: [null, 3, 4, 4, 3, 2, 1, 1, 2],
|
|
});
|
|
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("sum of floats", async function () {
|
|
var table = await perspective.table({
|
|
w: [3.25, 4.51, null, null, null, null, 1.57, 2.59],
|
|
x: [1, 2, 3, 4, 4, 3, 2, 1],
|
|
y: ["a", "b", "c", "d", "e", "f", "g", "h"],
|
|
});
|
|
var view = await table.view({
|
|
columns: ["x", "w"],
|
|
group_by: ["y"],
|
|
aggregates: {
|
|
w: "sum",
|
|
x: "unique",
|
|
},
|
|
sort: [["w", "asc"]],
|
|
});
|
|
|
|
const json = await view.to_columns();
|
|
expect(json).toEqual({
|
|
__ROW_PATH__: [
|
|
[],
|
|
["c"],
|
|
["d"],
|
|
["e"],
|
|
["f"],
|
|
["g"],
|
|
["h"],
|
|
["a"],
|
|
["b"],
|
|
],
|
|
w: [11.92, 0, 0, 0, 0, 1.57, 2.59, 3.25, 4.51],
|
|
x: [null, 3, 4, 4, 3, 2, 1, 1, 2],
|
|
});
|
|
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("unique", async function () {
|
|
var table = await perspective.table(data2);
|
|
var view = await table.view({
|
|
columns: ["x", "w"],
|
|
group_by: ["y"],
|
|
aggregates: {
|
|
w: "unique",
|
|
x: "unique",
|
|
},
|
|
sort: [["w", "asc"]],
|
|
});
|
|
|
|
const json = await view.to_columns();
|
|
expect(json).toEqual({
|
|
__ROW_PATH__: [
|
|
[],
|
|
["c"],
|
|
["d"],
|
|
["e"],
|
|
["f"],
|
|
["g"],
|
|
["h"],
|
|
["a"],
|
|
["b"],
|
|
],
|
|
w: [null, null, null, null, null, 1.5, 2.5, 3.5, 4.5],
|
|
x: [null, 3, 4, 4, 3, 2, 1, 1, 2],
|
|
});
|
|
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("avg", async function () {
|
|
var table = await perspective.table(data2);
|
|
var view = await table.view({
|
|
columns: ["x", "w"],
|
|
group_by: ["y"],
|
|
aggregates: {
|
|
w: "avg",
|
|
x: "unique",
|
|
},
|
|
sort: [["w", "asc"]],
|
|
});
|
|
|
|
const json = await view.to_columns();
|
|
expect(json).toEqual({
|
|
__ROW_PATH__: [
|
|
[],
|
|
["c"],
|
|
["d"],
|
|
["e"],
|
|
["f"],
|
|
["g"],
|
|
["h"],
|
|
["a"],
|
|
["b"],
|
|
],
|
|
w: [3, null, null, null, null, 1.5, 2.5, 3.5, 4.5],
|
|
x: [null, 3, 4, 4, 3, 2, 1, 1, 2],
|
|
});
|
|
|
|
// Broken result:
|
|
// {
|
|
// __ROW_PATH__: [[], ["a"], ["b"], ["c"], ["d"], ["e"], ["f"], ["g"], ["h"]],
|
|
// w: [3, 3.5, 4.5, null, null, null, null, 1.5, 2.5],
|
|
// x: [null, 1, 2, 3, 4, 4, 3, 2, 1]
|
|
// };
|
|
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test.describe("Multiple hidden sort", () => {
|
|
test("sum", async function () {
|
|
var table = await perspective.table(data3);
|
|
var view = await table.view({
|
|
columns: ["x", "w"],
|
|
group_by: ["y"],
|
|
aggregates: {
|
|
w: "sum",
|
|
},
|
|
sort: [
|
|
["x", "desc"],
|
|
["w", "desc"],
|
|
],
|
|
});
|
|
|
|
const json = await view.to_columns();
|
|
expect(json).toEqual({
|
|
__ROW_PATH__: [[], ["a"], ["b"]],
|
|
w: [12, 8, 4],
|
|
x: [20, 10, 10],
|
|
});
|
|
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("sum of floats", async function () {
|
|
var table = await perspective.table({
|
|
w: [3.25, 4.51, null, null, null, null, 1.57, 2.59],
|
|
x: [1, 2, 3, 4, 4, 3, 2, 1],
|
|
y: ["a", "a", "a", "a", "b", "b", "b", "b"],
|
|
});
|
|
var view = await table.view({
|
|
columns: ["x", "w"],
|
|
group_by: ["y"],
|
|
aggregates: {
|
|
w: "sum",
|
|
},
|
|
sort: [
|
|
["x", "desc"],
|
|
["w", "desc"],
|
|
],
|
|
});
|
|
|
|
const json = await view.to_columns();
|
|
expect(json).toEqual({
|
|
__ROW_PATH__: [[], ["a"], ["b"]],
|
|
w: [11.92, 7.76, 4.16],
|
|
x: [20, 10, 10],
|
|
});
|
|
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("unique", async function () {
|
|
var table = await perspective.table(data3);
|
|
var view = await table.view({
|
|
columns: ["x", "w"],
|
|
group_by: ["y"],
|
|
aggregates: {
|
|
w: "unique",
|
|
},
|
|
sort: [
|
|
["x", "desc"],
|
|
["w", "desc"],
|
|
],
|
|
});
|
|
|
|
const json = await view.to_columns();
|
|
expect(json).toEqual({
|
|
__ROW_PATH__: [[], ["a"], ["b"]],
|
|
w: [null, null, null],
|
|
x: [20, 10, 10],
|
|
});
|
|
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("avg", async function () {
|
|
var table = await perspective.table(data3);
|
|
var view = await table.view({
|
|
columns: ["x", "w"],
|
|
group_by: ["y"],
|
|
aggregates: {
|
|
w: "avg",
|
|
},
|
|
sort: [
|
|
["x", "desc"],
|
|
["w", "desc"],
|
|
],
|
|
});
|
|
|
|
const json = await view.to_columns();
|
|
expect(json).toEqual({
|
|
__ROW_PATH__: [[], ["a"], ["b"]],
|
|
// 4 and 2 are the avg of the non-null rows
|
|
w: [3, 4, 2],
|
|
x: [20, 10, 10],
|
|
});
|
|
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
test.describe("On hidden columns", function () {
|
|
test("Column path should not emit hidden sorts", async function () {
|
|
var table = await perspective.table(data);
|
|
var view = await table.view({
|
|
columns: ["w", "y"],
|
|
sort: [["x", "desc"]],
|
|
});
|
|
const paths = await view.column_paths();
|
|
expect(paths).toEqual(["w", "y"]);
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("Column path should not emit hidden column sorts", async function () {
|
|
var table = await perspective.table(data);
|
|
var view = await table.view({
|
|
columns: ["w"],
|
|
group_by: ["y"],
|
|
split_by: ["z"],
|
|
sort: [["x", "col desc"]],
|
|
});
|
|
const paths = await view.column_paths();
|
|
expect(paths).toEqual(["false|w", "true|w"]);
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("Column path should not emit hidden regular and column sorts", async function () {
|
|
var table = await perspective.table(data);
|
|
var view = await table.view({
|
|
columns: ["w"],
|
|
group_by: ["y"],
|
|
split_by: ["z"],
|
|
sort: [
|
|
["x", "col desc"],
|
|
["y", "desc"],
|
|
],
|
|
});
|
|
const paths = await view.column_paths();
|
|
expect(paths).toEqual(["false|w", "true|w"]);
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("unpivoted", async function () {
|
|
var table = await perspective.table(data);
|
|
var view = await table.view({
|
|
columns: ["w", "y"],
|
|
sort: [["x", "desc"]],
|
|
});
|
|
var answer = [
|
|
{ w: 4.5, y: "d" },
|
|
{ w: 5.5, y: "a" },
|
|
{ w: 3.5, y: "c" },
|
|
{ w: 6.5, y: "b" },
|
|
{ w: 2.5, y: "b" },
|
|
{ w: 7.5, y: "c" },
|
|
{ w: 1.5, y: "a" },
|
|
{ w: 8.5, y: "d" },
|
|
];
|
|
let result = await view.to_json();
|
|
expect(result).toEqual(answer);
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("group by ['y']", async function () {
|
|
var table = await perspective.table(data);
|
|
var view = await table.view({
|
|
columns: ["w"],
|
|
group_by: ["y"],
|
|
sort: [["x", "desc"]],
|
|
});
|
|
var answer = [
|
|
{ __ROW_PATH__: [], w: 40 },
|
|
{ __ROW_PATH__: ["a"], w: 7 },
|
|
{ __ROW_PATH__: ["b"], w: 9 },
|
|
{ __ROW_PATH__: ["c"], w: 11 },
|
|
{ __ROW_PATH__: ["d"], w: 13 },
|
|
];
|
|
let result = await view.to_json();
|
|
expect(result).toEqual(answer);
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("group by and hidden sort ['y'] with aggregates specified", async function () {
|
|
const table = await perspective.table({
|
|
x: [1, 2, 3, 4, 5],
|
|
y: ["a", "b", "b", "b", "c"],
|
|
});
|
|
// Aggregate should be overriden if the sort column is hidden
|
|
// AND also in group by
|
|
const view = await table.view({
|
|
aggregates: {
|
|
x: "sum",
|
|
y: "count",
|
|
},
|
|
columns: ["x"],
|
|
group_by: ["y"],
|
|
sort: [["y", "desc"]],
|
|
});
|
|
const answer = [
|
|
{ __ROW_PATH__: [], x: 15 },
|
|
{ __ROW_PATH__: ["c"], x: 5 },
|
|
{ __ROW_PATH__: ["b"], x: 9 },
|
|
{ __ROW_PATH__: ["a"], x: 1 },
|
|
];
|
|
const result = await view.to_json();
|
|
expect(result).toEqual(answer);
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("group by and hidden sort ['y'] without aggregates specified", async function () {
|
|
const table = await perspective.table({
|
|
x: [1, 2, 3, 4, 5],
|
|
y: ["a", "b", "b", "b", "c"],
|
|
});
|
|
const view = await table.view({
|
|
columns: ["x"],
|
|
group_by: ["y"],
|
|
sort: [["y", "desc"]],
|
|
});
|
|
const answer = [
|
|
{ __ROW_PATH__: [], x: 15 },
|
|
{ __ROW_PATH__: ["c"], x: 5 },
|
|
{ __ROW_PATH__: ["b"], x: 9 },
|
|
{ __ROW_PATH__: ["a"], x: 1 },
|
|
];
|
|
const result = await view.to_json();
|
|
expect(result).toEqual(answer);
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("group by with multiple hidden sorts emits all visible columns in to_columns()", async function () {
|
|
// https://github.com/perspective-dev/perspective/issues/3195
|
|
const table = await perspective.table({
|
|
v1: [1, 2, 3, 4],
|
|
v2: [10, 20, 30, 40],
|
|
v3: [100, 200, 300, 400],
|
|
h1: [1.5, 2.5, 3.5, 4.5],
|
|
h2: [4.5, 3.5, 2.5, 1.5],
|
|
g: ["a", "a", "b", "b"],
|
|
});
|
|
const view = await table.view({
|
|
columns: ["v1", "v2", "v3"],
|
|
group_by: ["g"],
|
|
sort: [
|
|
["h1", "desc"],
|
|
["h2", "desc"],
|
|
],
|
|
});
|
|
const result = await view.to_columns();
|
|
expect(result).toEqual({
|
|
__ROW_PATH__: [[], ["b"], ["a"]],
|
|
v1: [10, 7, 3],
|
|
v2: [100, 70, 30],
|
|
v3: [1000, 700, 300],
|
|
});
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("group by with more hidden sorts than visible columns does not emit hidden columns in to_columns()", async function () {
|
|
// https://github.com/perspective-dev/perspective/issues/3195
|
|
const table = await perspective.table({
|
|
v1: [1, 2, 3, 4],
|
|
h1: [1.5, 2.5, 3.5, 4.5],
|
|
h2: [4.5, 3.5, 2.5, 1.5],
|
|
g: ["a", "a", "b", "b"],
|
|
});
|
|
const view = await table.view({
|
|
columns: ["v1"],
|
|
group_by: ["g"],
|
|
sort: [
|
|
["h1", "desc"],
|
|
["h2", "desc"],
|
|
],
|
|
});
|
|
const result = await view.to_columns();
|
|
expect(result).toEqual({
|
|
__ROW_PATH__: [[], ["b"], ["a"]],
|
|
v1: [10, 7, 3],
|
|
});
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("split by ['y']", async function () {
|
|
const table = await perspective.table(data);
|
|
const view = await table.view({
|
|
columns: ["w"],
|
|
split_by: ["y"],
|
|
sort: [["x", "desc"]],
|
|
});
|
|
const paths = await view.column_paths();
|
|
expect(paths).toEqual(["a|w", "b|w", "c|w", "d|w"]);
|
|
const answer = [
|
|
{ "a|w": null, "b|w": null, "c|w": null, "d|w": 4.5 },
|
|
{ "a|w": 5.5, "b|w": null, "c|w": null, "d|w": null },
|
|
{ "a|w": null, "b|w": null, "c|w": 3.5, "d|w": null },
|
|
{ "a|w": null, "b|w": 6.5, "c|w": null, "d|w": null },
|
|
{ "a|w": null, "b|w": 2.5, "c|w": null, "d|w": null },
|
|
{ "a|w": null, "b|w": null, "c|w": 7.5, "d|w": null },
|
|
{ "a|w": 1.5, "b|w": null, "c|w": null, "d|w": null },
|
|
{ "a|w": null, "b|w": null, "c|w": null, "d|w": 8.5 },
|
|
];
|
|
const result = await view.to_json();
|
|
expect(result).toEqual(answer);
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("split by ['y'], col desc sort", async function () {
|
|
const table = await perspective.table(data);
|
|
const view = await table.view({
|
|
columns: ["w"],
|
|
split_by: ["y"],
|
|
sort: [["x", "col desc"]],
|
|
});
|
|
const paths = await view.column_paths();
|
|
expect(paths).toEqual(["d|w", "c|w", "b|w", "a|w"]);
|
|
const answer = {
|
|
"d|w": [null, null, null, 4.5, null, null, null, 8.5],
|
|
"c|w": [null, null, 3.5, null, null, null, 7.5, null],
|
|
"b|w": [null, 2.5, null, null, null, 6.5, null, null],
|
|
"a|w": [1.5, null, null, null, 5.5, null, null, null],
|
|
};
|
|
const result = await view.to_columns();
|
|
expect(result).toEqual(answer);
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("split by and hidden sort ['y']", async function () {
|
|
const table = await perspective.table({
|
|
x: [1, 2, 3, 4],
|
|
y: ["a", "a", "a", "b"],
|
|
});
|
|
const view = await table.view({
|
|
columns: ["x"],
|
|
split_by: ["y"],
|
|
sort: [["y", "desc"]],
|
|
});
|
|
|
|
const paths = await view.column_paths();
|
|
// regular non-col sort should not change order of column paths
|
|
expect(paths).toEqual(["a|x", "b|x"]);
|
|
|
|
const result = await view.to_columns();
|
|
expect(result).toEqual({
|
|
"a|x": [null, 1, 2, 3],
|
|
"b|x": [4, null, null, null],
|
|
});
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("split by and hidden col sort ['y']", async function () {
|
|
const table = await perspective.table({
|
|
x: [1, 2, 3, 4],
|
|
y: ["a", "a", "a", "b"],
|
|
});
|
|
const view = await table.view({
|
|
columns: ["x"],
|
|
split_by: ["y"],
|
|
sort: [["y", "col desc"]],
|
|
});
|
|
|
|
const paths = await view.column_paths();
|
|
expect(paths).toEqual(["b|x", "a|x"]);
|
|
|
|
const result = await view.to_columns();
|
|
expect(result).toEqual({
|
|
"b|x": [null, null, null, 4],
|
|
"a|x": [1, 2, 3, null],
|
|
});
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("split by and hidden sort ['y'] with aggregates specified", async function () {
|
|
const table = await perspective.table({
|
|
x: [1, 2, 3, 4],
|
|
y: ["a", "a", "a", "b"],
|
|
});
|
|
|
|
// Aggregate for hidden sort should be ignored in column-only,
|
|
// so just make sure we stick to that.
|
|
const view = await table.view({
|
|
columns: ["x"],
|
|
split_by: ["y"],
|
|
sort: [["y", "desc"]],
|
|
aggregates: {
|
|
y: "count",
|
|
},
|
|
});
|
|
|
|
const paths = await view.column_paths();
|
|
// regular non-col sort should not change order of column paths
|
|
expect(paths).toEqual(["a|x", "b|x"]);
|
|
|
|
const result = await view.to_columns();
|
|
expect(result).toEqual({
|
|
"a|x": [null, 1, 2, 3],
|
|
"b|x": [4, null, null, null],
|
|
});
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("split by and hidden col sort ['y'] with aggregates specified", async function () {
|
|
const table = await perspective.table({
|
|
x: [1, 2, 3, 4],
|
|
y: ["a", "a", "a", "b"],
|
|
});
|
|
|
|
// Aggregate for hidden sort should be ignored in column-only,
|
|
// so just make sure we stick to that.
|
|
const view = await table.view({
|
|
columns: ["x"],
|
|
split_by: ["y"],
|
|
sort: [["y", "col desc"]],
|
|
aggregates: {
|
|
y: "count",
|
|
},
|
|
});
|
|
|
|
const paths = await view.column_paths();
|
|
expect(paths).toEqual(["b|x", "a|x"]);
|
|
|
|
const result = await view.to_columns();
|
|
expect(result).toEqual({
|
|
"b|x": [null, null, null, 4],
|
|
"a|x": [1, 2, 3, null],
|
|
});
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("split by ['y'] with overridden aggregates", async function () {
|
|
const table = await perspective.table({
|
|
x: [1, 2, 3, 4],
|
|
y: ["a", "a", "a", "b"],
|
|
});
|
|
const view = await table.view({
|
|
columns: ["x"],
|
|
split_by: ["y"],
|
|
aggregates: { y: "count" },
|
|
sort: [["y", "col desc"]],
|
|
});
|
|
|
|
const paths = await view.column_paths();
|
|
// Col sort will override aggregate
|
|
expect(paths).toEqual(["b|x", "a|x"]);
|
|
|
|
let result = await view.to_columns();
|
|
expect(result).toEqual({
|
|
"b|x": [null, null, null, 4],
|
|
"a|x": [1, 2, 3, null],
|
|
});
|
|
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("split by ['y'] with extra aggregates", async function () {
|
|
var table = await perspective.table(data);
|
|
var view = await table.view({
|
|
columns: ["w"],
|
|
split_by: ["y"],
|
|
aggregates: { w: "sum", z: "last" },
|
|
sort: [["x", "desc"]],
|
|
});
|
|
var answer = [
|
|
{ "a|w": null, "b|w": null, "c|w": null, "d|w": 4.5 },
|
|
{ "a|w": 5.5, "b|w": null, "c|w": null, "d|w": null },
|
|
{ "a|w": null, "b|w": null, "c|w": 3.5, "d|w": null },
|
|
{ "a|w": null, "b|w": 6.5, "c|w": null, "d|w": null },
|
|
{ "a|w": null, "b|w": 2.5, "c|w": null, "d|w": null },
|
|
{ "a|w": null, "b|w": null, "c|w": 7.5, "d|w": null },
|
|
{ "a|w": 1.5, "b|w": null, "c|w": null, "d|w": null },
|
|
{ "a|w": null, "b|w": null, "c|w": null, "d|w": 8.5 },
|
|
];
|
|
let result = await view.to_json();
|
|
expect(result).toEqual(answer);
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("group by ['x'], split by ['y'], both hidden and asc sorted", async function () {
|
|
const table = await perspective.table({
|
|
x: ["a", "a", "b", "c"],
|
|
y: ["x", "x", "y", "x"],
|
|
z: [1, 2, 3, 4],
|
|
});
|
|
const view = await table.view({
|
|
columns: ["z"],
|
|
group_by: ["x"],
|
|
split_by: ["y"],
|
|
sort: [
|
|
["x", "asc"],
|
|
["y", "col asc"],
|
|
],
|
|
});
|
|
const paths = await view.column_paths();
|
|
expect(paths).toEqual(["x|z", "y|z"]);
|
|
const expected = {
|
|
__ROW_PATH__: [[], ["a"], ["b"], ["c"]],
|
|
"x|z": [7, 3, null, 4],
|
|
"y|z": [3, null, 3, null],
|
|
};
|
|
const result = await view.to_columns();
|
|
expect(result).toEqual(expected);
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("group by ['x'], split by ['y'], both hidden and desc sorted", async function () {
|
|
const table = await perspective.table({
|
|
x: ["a", "a", "b", "c"],
|
|
y: ["x", "x", "y", "x"],
|
|
z: [1, 2, 3, 4],
|
|
});
|
|
const view = await table.view({
|
|
columns: ["z"],
|
|
group_by: ["x"],
|
|
split_by: ["y"],
|
|
sort: [
|
|
["x", "desc"],
|
|
["y", "col desc"],
|
|
],
|
|
});
|
|
const paths = await view.column_paths();
|
|
expect(paths).toEqual(["y|z", "x|z"]);
|
|
const expected = {
|
|
__ROW_PATH__: [[], ["c"], ["b"], ["a"]],
|
|
"y|z": [3, null, 3, null],
|
|
"x|z": [7, 4, null, 3],
|
|
};
|
|
const result = await view.to_columns();
|
|
expect(result).toEqual(expected);
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("group by ['x'], split by ['y'], hidden sorted on group by", async function () {
|
|
const table = await perspective.table({
|
|
x: ["a", "a", "b", "c"],
|
|
y: ["x", "x", "y", "x"],
|
|
z: [1, 2, 3, 4],
|
|
});
|
|
const view = await table.view({
|
|
columns: ["z"],
|
|
group_by: ["y"],
|
|
split_by: ["x"],
|
|
sort: [["x", "desc"]],
|
|
});
|
|
const paths = await view.column_paths();
|
|
expect(paths).toEqual(["a|z", "b|z", "c|z"]);
|
|
const expected = {
|
|
__ROW_PATH__: [[], ["x"], ["y"]],
|
|
"a|z": [3, 3, null],
|
|
"b|z": [3, null, 3],
|
|
"c|z": [4, 4, null],
|
|
};
|
|
const result = await view.to_columns();
|
|
expect(result).toEqual(expected);
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
|
|
test("split by ['y'] has correct # of columns", async function () {
|
|
var table = await perspective.table(data);
|
|
var view = await table.view({
|
|
columns: ["w"],
|
|
split_by: ["y"],
|
|
sort: [["x", "desc"]],
|
|
});
|
|
let to_cols = await view.to_columns();
|
|
let result = await view.num_columns();
|
|
expect(result).toEqual(4);
|
|
view.delete();
|
|
table.delete();
|
|
});
|
|
});
|
|
});
|
|
})(perspective);
|