Skip to content

Commit

Permalink
test(module): Add test for module & category (#3390)
Browse files Browse the repository at this point in the history
- update some browser & worker module as function to facilitate test
- add test case for internal/category

Ref #3333
  • Loading branch information
netil authored Aug 30, 2023
1 parent 17f5058 commit 3fdc518
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 33 deletions.
16 changes: 16 additions & 0 deletions karma.conf.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,22 @@ module.exports = function(config) {
target: ["web", "es5"],
module: {
rules: [
{
test: require.resolve("./src/module/browser.ts"),
loader: "exports-loader",
options: {
type: "module",
exports: ["getGlobal", "getFallback"]
}
},
{
test: require.resolve("./src/module/worker.ts"),
loader: "exports-loader",
options: {
type: "module",
exports: "getWorker"
}
},
{
test: /(\.[jt]s)$/,
loader: "babel-loader",
Expand Down
4 changes: 2 additions & 2 deletions src/ChartInternal/internals/category.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ export default {
* @private
*/
categoryName(i: number): string {
const {axis_x_categories: categories = []} = this.config;
const {axis_x_categories} = this.config;

return categories[i] ?? i;
return axis_x_categories?.[i] ?? i;
},
};
49 changes: 35 additions & 14 deletions src/module/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,43 @@ export {
requestIdleCallback, cancelIdleCallback
};

const win = (() => {
const root = (typeof globalThis === "object" && globalThis !== null && globalThis.Object === Object && globalThis) ||
/**
* Get global object
* @param {Array} g global object candidates

Check warning on line 19 in src/module/browser.ts

View workflow job for this annotation

GitHub Actions / test (16.x)

@param "g" does not match an existing function parameter

Check warning on line 19 in src/module/browser.ts

View workflow job for this annotation

GitHub Actions / test (17.x)

@param "g" does not match an existing function parameter

Check warning on line 19 in src/module/browser.ts

View workflow job for this annotation

GitHub Actions / test (18.x)

@param "g" does not match an existing function parameter
* @returns {object} window object
* @private
*/
function getGlobal() {
return (typeof globalThis === "object" && globalThis !== null && globalThis.Object === Object && globalThis) ||
(typeof global === "object" && global !== null && global.Object === Object && global) ||
(typeof self === "object" && self !== null && self.Object === Object && self);

return root || Function("return this")();
})();
/* eslint-enable no-new-func, no-undef */
(typeof self === "object" && self !== null && self.Object === Object && self) ||
Function("return this")();
}

// fallback for non-supported environments
const hasRAF = typeof win.requestAnimationFrame === "function";
const hasRIC = typeof win.requestIdleCallback === "function";
/**
* Get fallback object
* @param {object} w global object
* @returns {Array} fallback object array
* @private
*/
function getFallback(w) {
const hasRAF = typeof w?.requestAnimationFrame === "function";
const hasRIC = typeof w?.requestIdleCallback === "function";

const requestAnimationFrame = hasRAF ? win.requestAnimationFrame : (cb => setTimeout(cb, 1));
const cancelAnimationFrame = hasRAF ? win.cancelAnimationFrame : (id => clearTimeout(id));
const requestIdleCallback = hasRIC ? win.requestIdleCallback : requestAnimationFrame;
const cancelIdleCallback = hasRIC ? win.cancelIdleCallback : cancelAnimationFrame;
return [
hasRAF ? w.requestAnimationFrame : (cb => setTimeout(cb, 1)),
hasRAF ? w.cancelAnimationFrame : (id => clearTimeout(id)),
hasRIC ? w.requestIdleCallback : requestAnimationFrame,
hasRIC ? w.cancelIdleCallback : cancelAnimationFrame
];
}

const win = getGlobal();
const doc = win?.document;

const [
requestAnimationFrame,
cancelAnimationFrame,
requestIdleCallback,
cancelIdleCallback
] = getFallback(win);
38 changes: 24 additions & 14 deletions src/module/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,24 @@ function getObjectURL(fn: Function, depsFn?: Function[]): string {
return window.URL.createObjectURL(blob[key]);
}

/**
* Get WebWorker instance
* @param {string} src URL object as string
* @returns {object} WebWorker instance
* @private
*/
function getWorker(src) {
const worker = new window.Worker(src);

// handle error
worker.onerror = function(e) {
// eslint-disable-next-line no-console
console.error ? console.error(e) : console.log(e);
};

return worker;
}

/**
* Create and run on Web Worker
* @param {boolean} useWorker Use Web Worker
Expand All @@ -61,11 +79,15 @@ function getObjectURL(fn: Function, depsFn?: Function[]): string {
export function runWorker(
useWorker = true, fn: Function, callback: Function, depsFn?: Function[]
): Function {
let runFn;
let runFn = function(...args) {
const res = fn(...args);

callback(res);
};

if (window.Worker && useWorker) {
const src = getObjectURL(fn, depsFn);
const worker = new window.Worker(src);
const worker = getWorker(src);

runFn = function(...args) {
// trigger worker
Expand All @@ -79,23 +101,11 @@ export function runWorker(
return callback(e.data);
};

// handle error
worker.onerror = function(e) {
// eslint-disable-next-line no-console
console.error ? console.error(e) : console.log(e);
};

// return new Promise((resolve, reject) => {
// worker.onmessage = ({data}) => resolve(data);
// worker.onerror = reject;
// });
};
} else {
runFn = function(...args) {
const res = fn(...args);

callback(res);
};
}

return runFn;
Expand Down
26 changes: 25 additions & 1 deletion test/api/category-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe("API category", () => {
},
axis: {
x: {
type: "category"
type: "category",
}
}
};
Expand Down Expand Up @@ -117,6 +117,30 @@ describe("API category", () => {
expect(chart.$.tooltip.html()).to.be.empty;
});

it("set options: axis.x.categories=[]", () => {
args.axis.x.categories = [];
});

it("should return categories correctly.", () => {
const indexed = chart.data.values("loading").map((v, i) => i);

expect(chart.categories()).to.be.deep.equal(indexed);

});

it("should load without error when categories=null is given.", done => {
chart.load({
columns: [
["data1", 20,30,33, 22]
],
categories: null,
done() {
expect(true).to.be.ok;
done();
}
});
});

it("set options", () => {
args = {
data: {
Expand Down
58 changes: 56 additions & 2 deletions test/module/module-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
import {expect} from "chai";
import sinon from "sinon";
import util from "../assets/util";
import {window, document, requestAnimationFrame, cancelAnimationFrame, requestIdleCallback, cancelIdleCallback} from "../../src/module/browser";
import {getGlobal, getFallback} from "../../src/module/browser";
import {getWorker} from "../../src/module/worker";

describe("MODULE", function() {
let chart;
Expand All @@ -21,7 +22,7 @@ describe("MODULE", function() {
chart.destroy();
});

describe("Cache", () => {
describe("Cache", () => {
before(() => {
args = {
data: {
Expand Down Expand Up @@ -67,4 +68,57 @@ describe("MODULE", function() {
expect(cache.get([rowData.id], true)).to.be.empty;
});
});

describe("Browser", () => {
it("check global & fallback returns correctly when no default param is given.", () => {
// set nullish value for test
globalThis = global = self = null;

const win = getGlobal();

expect(win.document).to.be.ok;

// restore global
globalThis = global = self = window;
});

it("check fallback", done => {
const spy = sinon.spy();

const [
requestAnimationFrame,
cancelAnimationFrame,
requestIdleCallback,
cancelIdleCallback
] = getFallback();

const raf = requestAnimationFrame(spy);
const ric = requestIdleCallback(spy);

expect(raf > 0).to.be.true;
expect(ric > 0).to.be.true;

setTimeout(() => {
cancelAnimationFrame(raf);
cancelIdleCallback(ric);

expect(spy.callCount).to.be.equal(2);

done();
}, 100);
});
});

describe("Worker", () => {
it("check worker onerror handler call.", () => {
const worker = getWorker("test");
const errorStub = sinon.stub(console, "error");

worker.onerror({e: {message: "ERR MSG"}});

expect(errorStub.called).to.be.true;

errorStub.restore();
});
});
});

0 comments on commit 3fdc518

Please sign in to comment.