chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,896 @@
|
||||
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
||||
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
||||
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
||||
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
||||
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
||||
// ┃ 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);
|
||||
Reference in New Issue
Block a user