Skip to content

Commit

Permalink
feat: add structural Data Set and Data View checks (#498)
Browse files Browse the repository at this point in the history
* feat: add structural Data Set and Data View checks

* fix(structural-check): merge error
  • Loading branch information
Thomaash authored Oct 13, 2020
1 parent 25a4762 commit 8d21364
Show file tree
Hide file tree
Showing 10 changed files with 276 additions and 2 deletions.
4 changes: 4 additions & 0 deletions __snapshots__/package.test.ts.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@ exports['Package Exported files 1'] = {
" declarations/data-interface.d.ts.map",
" declarations/data-pipe.d.ts",
" declarations/data-pipe.d.ts.map",
" declarations/data-set-check.d.ts",
" declarations/data-set-check.d.ts.map",
" declarations/data-set-part.d.ts",
" declarations/data-set-part.d.ts.map",
" declarations/data-set.d.ts",
" declarations/data-set.d.ts.map",
" declarations/data-stream.d.ts",
" declarations/data-stream.d.ts.map",
" declarations/data-view-check.d.ts",
" declarations/data-view-check.d.ts.map",
" declarations/data-view.d.ts",
" declarations/data-view.d.ts.map",
" declarations/entry-esnext.d.ts",
Expand Down
90 changes: 90 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
"prettier": "2.1.2",
"rimraf": "3.0.2",
"rollup": "2.29.0",
"sazerac": "2.0.0",
"sinon": "9.2.0",
"snap-shot-it": "7.9.3",
"typedoc": "0.19.2",
Expand Down
3 changes: 3 additions & 0 deletions src/data-interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,9 @@ export interface DataInterface<
/** The number of items. */
length: number;

/** The key of id property. */
idProp: IdProp;

/**
* Add a universal event listener.
*
Expand Down
39 changes: 39 additions & 0 deletions src/data-set-check.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { PartItem } from "./data-interface";
import { DataSet } from "./data-set";

/**
* Check that given value is compatible with Vis Data Set interface.
*
* @param idProp - The expected property to contain item id.
* @param v - The value to be tested.
*
* @returns True if all expected values and methods match, false otherwise.
*/
export function isDataSetLike<
Item extends PartItem<IdProp>,
IdProp extends string = "id"
>(idProp: IdProp, v: any): v is DataSet<Item, IdProp> {
return (
typeof v === "object" &&
v !== null &&
idProp === v.idProp &&
typeof v.add === "function" &&
typeof v.clear === "function" &&
typeof v.distinct === "function" &&
typeof v.forEach === "function" &&
typeof v.get === "function" &&
typeof v.getDataSet === "function" &&
typeof v.getIds === "function" &&
typeof v.length === "number" &&
typeof v.map === "function" &&
typeof v.max === "function" &&
typeof v.min === "function" &&
typeof v.off === "function" &&
typeof v.on === "function" &&
typeof v.remove === "function" &&
typeof v.setOptions === "function" &&
typeof v.stream === "function" &&
typeof v.update === "function" &&
typeof v.updateOnly === "function"
);
}
4 changes: 4 additions & 0 deletions src/data-set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ export class DataSet<
public flush?: () => void;
/** @inheritDoc */
public length: number;
/** @inheritDoc */
public get idProp(): IdProp {
return this.#idProp;
}

readonly #options: DataSetInitialOptions<IdProp>;
readonly #data: Map<Id, FullItem<Item, IdProp>>;
Expand Down
32 changes: 32 additions & 0 deletions src/data-view-check.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { DataView } from "./data-view";
import { PartItem } from "./data-interface";
import { isDataSetLike } from "./data-set-check";

/**
* Check that given value is compatible with Vis Data View interface.
*
* @param idProp - The expected property to contain item id.
* @param v - The value to be tested.
*
* @returns True if all expected values and methods match, false otherwise.
*/
export function isDataViewLike<
Item extends PartItem<IdProp>,
IdProp extends string = "id"
>(idProp: IdProp, v: any): v is DataView<Item, IdProp> {
return (
typeof v === "object" &&
v !== null &&
idProp === v.idProp &&
typeof v.forEach === "function" &&
typeof v.get === "function" &&
typeof v.getDataSet === "function" &&
typeof v.getIds === "function" &&
typeof v.length === "number" &&
typeof v.map === "function" &&
typeof v.off === "function" &&
typeof v.on === "function" &&
typeof v.stream === "function" &&
isDataSetLike(idProp, v.getDataSet())
);
}
6 changes: 5 additions & 1 deletion src/data-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,12 @@ export class DataView<
implements DataInterface<Item, IdProp> {
/** @inheritDoc */
public length = 0;
readonly #listener: EventCallbacksWithAny<Item, IdProp>["*"];
/** @inheritDoc */
public get idProp(): IdProp {
return this.getDataSet().idProp;
}

readonly #listener: EventCallbacksWithAny<Item, IdProp>["*"];
#data!: DataInterface<Item, IdProp>; // constructor → setData
readonly #ids: Set<Id> = new Set(); // ids of the items currently in memory (just contains a boolean true)
readonly #options: DataViewOptions<Item, IdProp>;
Expand Down
4 changes: 3 additions & 1 deletion src/entry-esnext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ export {
} from "./data-interface";

export * from "./data-pipe";
export { DELETE } from "vis-util/esnext";
export { DataSet, DataSetOptions } from "./data-set";
export { DataStream } from "./data-stream";
export { DataView, DataViewOptions } from "./data-view";
export { Queue } from "./queue";
export { DELETE } from "vis-util/esnext";
export { isDataSetLike } from "./data-set-check";
export { isDataViewLike } from "./data-view-check";
95 changes: 95 additions & 0 deletions test/type-checks.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { expect } from "chai";
import { test, given } from "sazerac";

import {
DataSet,
DataView,
isDataSetLike,
isDataViewLike,
} from "../src/entry-esnext";

function createFakeDataSet(idProp: string): any {
const v = {
add: (): void => {},
clear: (): void => {},
distinct: (): void => {},
forEach: (): void => {},
get: (): void => {},
getDataSet: (): any => v,
getIds: (): void => {},
idProp,
length: 7,
map: (): void => {},
max: (): void => {},
min: (): void => {},
off: (): void => {},
on: (): void => {},
remove: (): void => {},
setOptions: (): void => {},
stream: (): void => {},
update: (): void => {},
updateOnly: (): void => {},
};
return v;
}
function createFakeDataView(idProp: string): any {
const v = {
forEach: (): void => {},
get: (): void => {},
getDataSet: (): any => createFakeDataSet(idProp),
getIds: (): void => {},
idProp,
length: 3,
map: (): void => {},
off: (): void => {},
on: (): void => {},
stream: (): void => {},
};
return v;
}

describe("Type checks", function (): void {
test(isDataViewLike, function (): void {
given("id").expect(false);
given("id", undefined).expect(false);
given("id", null).expect(false);
given("id", {}).expect(false);
given("id", []).expect(false);

given("id", new DataSet()).expect(true);
given("ds", new DataSet()).expect(false);
given("ds", new DataSet({ fieldId: "ds" })).expect(true);

given("id", new DataView(new DataSet())).expect(true);
given("dv", new DataView(new DataSet())).expect(false);
given("dv", new DataView(new DataSet({ fieldId: "dv" }))).expect(true);

given("id", createFakeDataSet("fds")).expect(false);
given("fds", createFakeDataSet("fds")).expect(true);

given("id", createFakeDataView("fdv")).expect(false);
given("fdv", createFakeDataView("fdv")).expect(true);
});

test(isDataSetLike, function (): void {
given("id").expect(false);
given("id", undefined).expect(false);
given("id", null).expect(false);
given("id", {}).expect(false);
given("id", []).expect(false);

given("id", new DataSet()).expect(true);
given("ds", new DataSet()).expect(false);
given("ds", new DataSet({ fieldId: "ds" })).expect(true);

given("id", new DataView(new DataSet())).expect(false);
given("dv", new DataView(new DataSet())).expect(false);
given("dv", new DataView(new DataSet({ fieldId: "dv" }))).expect(false);

given("id", createFakeDataSet("fds")).expect(false);
given("fds", createFakeDataSet("fds")).expect(true);

given("id", createFakeDataView("fdv")).expect(false);
given("fdv", createFakeDataView("fdv")).expect(false);
});
});

0 comments on commit 8d21364

Please sign in to comment.