mirror of
https://github.com/qlik-oss/nebula.js.git
synced 2025-12-19 17:58:43 -05:00
test: add component test (#204)
This enables to run component tests with fixtures
This commit is contained in:
committed by
GitHub
parent
b8e33eaa40
commit
f0462f6670
@@ -28,7 +28,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["**/*.{int,spec}.{js,jsx}"],
|
||||
"files": ["**/*.{int,comp,spec}.{js,jsx}"],
|
||||
"env": {
|
||||
"browser": false,
|
||||
"node": true,
|
||||
@@ -47,7 +47,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["**/*.int.js"],
|
||||
"files": ["**/*.{int,comp}.js"],
|
||||
"env": {
|
||||
"browser": true
|
||||
}
|
||||
@@ -56,7 +56,8 @@
|
||||
"files": ["**/templates/**/*.js"],
|
||||
"rules": {
|
||||
"import/no-unresolved": 0,
|
||||
"import/extensions": 0
|
||||
"import/extensions": 0,
|
||||
"import/no-extraneous-dependencies": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -35,12 +35,12 @@ export default function Error({ title = 'Error', message = '', data = [] }) {
|
||||
<WarningTriangle style={{ fontSize: '38px' }} />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Typography variant="h6" align="center">
|
||||
<Typography variant="h6" align="center" data-tid="error-title">
|
||||
{title}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Typography variant="subtitle1" align="center">
|
||||
<Typography variant="subtitle1" align="center" data-tid="error-message">
|
||||
{message}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
@@ -1,19 +1,13 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
test: {
|
||||
presets: [
|
||||
['@babel/preset-env', { targets: { node: 'current' } }],
|
||||
],
|
||||
presets: [['@babel/preset-env', { targets: { node: 'current' } }]],
|
||||
plugins: [
|
||||
['@babel/plugin-transform-react-jsx'],
|
||||
[
|
||||
'istanbul',
|
||||
{
|
||||
exclude: [
|
||||
'**/test/**',
|
||||
'**/__test__/**',
|
||||
'**/dist/**',
|
||||
],
|
||||
exclude: ['**/test/**', '**/__test__/**', '**/dist/**'],
|
||||
},
|
||||
],
|
||||
],
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
class Inject {
|
||||
constructor(options = {}) {
|
||||
this.options = options;
|
||||
this.stylesheets = options.stylesheets || [];
|
||||
this.scripts = options.scripts || [];
|
||||
}
|
||||
|
||||
apply(compiler) {
|
||||
if (!this.scripts.length || !this.stylesheets.length) {
|
||||
return;
|
||||
}
|
||||
compiler.hooks.compilation.tap('Inject', compilation => {
|
||||
compilation.hooks.htmlWebpackPluginAlterAssetTags.tap('Inject', htmlPluginData => {
|
||||
this.scripts.forEach(s => {
|
||||
htmlPluginData.head.unshift({
|
||||
tagName: 'script',
|
||||
closeTag: true,
|
||||
attributes: { type: 'text/javascript', src: s },
|
||||
});
|
||||
});
|
||||
this.stylesheets.forEach(s => {
|
||||
htmlPluginData.head.unshift({
|
||||
tagName: 'link',
|
||||
closeTag: true,
|
||||
attributes: { rel: 'stylesheet', type: 'text/css', href: s },
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Inject;
|
||||
@@ -7,8 +7,6 @@ const babelPresetReactPath = require.resolve('@babel/preset-react');
|
||||
const sourceMapLoaderPath = require.resolve('source-map-loader');
|
||||
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
|
||||
|
||||
const Inject = require('./head-injector');
|
||||
|
||||
const favicon = path.resolve(__dirname, '../../../docs/assets/njs.png');
|
||||
|
||||
const cfg = ({ srcDir, distDir, dev = false, serveConfig = {} }) => {
|
||||
@@ -37,6 +35,7 @@ const cfg = ({ srcDir, distDir, dev = false, serveConfig = {} }) => {
|
||||
'@nebula.js/locale': path.resolve(process.cwd(), 'apis/locale/src'),
|
||||
}
|
||||
: {}),
|
||||
fixtures: path.resolve(process.cwd(), 'test/component'),
|
||||
},
|
||||
extensions: ['.js', '.jsx'],
|
||||
},
|
||||
@@ -83,6 +82,8 @@ const cfg = ({ srcDir, distDir, dev = false, serveConfig = {} }) => {
|
||||
filename: 'eRender.html',
|
||||
chunks: ['eRender'],
|
||||
favicon,
|
||||
scripts: serveConfig.scripts,
|
||||
stylesheets: serveConfig.stylesheets,
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.resolve(srcDir, 'eDev.html'),
|
||||
@@ -96,7 +97,6 @@ const cfg = ({ srcDir, distDir, dev = false, serveConfig = {} }) => {
|
||||
chunks: ['eHub'],
|
||||
favicon,
|
||||
}),
|
||||
new Inject(serveConfig),
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
const path = require('path');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
|
||||
const Inject = require('./head-injector');
|
||||
|
||||
const isSrc = /^([.]{2}\/)/;
|
||||
const namespace = /^webpack:\/\/([^/]+)\//;
|
||||
const NM = /node_modules/;
|
||||
@@ -43,18 +41,24 @@ const cfg = ({ srcDir = path.resolve(__dirname, '../dist'), serveConfig = {} })
|
||||
return `webpack://${info.namespace}/${info.resourcePath}`;
|
||||
},
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
fixtures: path.resolve(process.cwd(), 'test/component'),
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.resolve(srcDir, 'eRender.html'),
|
||||
filename: 'eRender.html',
|
||||
inject: 'head',
|
||||
scripts: serveConfig.scripts,
|
||||
stylesheets: serveConfig.stylesheets,
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.resolve(srcDir, 'eDev.html'),
|
||||
filename: 'eDev.html',
|
||||
inject: 'head',
|
||||
}),
|
||||
new Inject(serveConfig),
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@@ -1,45 +1,50 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<base href="/">
|
||||
<title>Nebula render</title>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<base href="/" />
|
||||
<title>Nebula render</title>
|
||||
|
||||
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:light" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:semibold" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro" rel="stylesheet" />
|
||||
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:light" rel="stylesheet" />
|
||||
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:semibold" rel="stylesheet" />
|
||||
<% for (var stylesheet in htmlWebpackPlugin.options.stylesheets) { %>
|
||||
<script type="text/javascript" src="<%= htmlWebpackPlugin.options.stylesheets[stylesheet] %>"></script>
|
||||
<% } %> <% for (var script in htmlWebpackPlugin.options.scripts) { %>
|
||||
<script type="text/javascript" src="<%= htmlWebpackPlugin.options.scripts[script] %>"></script>
|
||||
<% } %>
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
<style>
|
||||
html, body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
body {
|
||||
background: linear-gradient(110deg, #92498f 0%, #45b3b2 100%);
|
||||
font: normal 14px/16px 'Source Sans Pro', Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
body {
|
||||
background: linear-gradient(110deg, #92498F 0%, #45B3B2 100%);
|
||||
font: normal 14px/16px "Source Sans Pro", Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
#chart-container {
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
bottom: 8px;
|
||||
right: 8px;
|
||||
top: 64px;
|
||||
}
|
||||
|
||||
#chart-container {
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
bottom: 8px;
|
||||
right: 8px;
|
||||
top: 64px;
|
||||
}
|
||||
|
||||
#chart-container.full {
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="chart-container"></div>
|
||||
</body>
|
||||
#chart-container.full {
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="chart-container"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import nucleus from '@nebula.js/nucleus';
|
||||
|
||||
import { openApp, params, info as serverInfo } from './connect';
|
||||
import runFixture from './run-fixture';
|
||||
|
||||
const nuke = async ({ app, supernova: { name }, themes, theme }) => {
|
||||
const nuked = nucleus.configured({
|
||||
@@ -11,15 +11,15 @@ const nuke = async ({ app, supernova: { name }, themes, theme }) => {
|
||||
}))
|
||||
: undefined,
|
||||
theme,
|
||||
});
|
||||
const nebbie = nuked(app, {
|
||||
load: (type, config) => config.Promise.resolve(window[type.name]),
|
||||
types: [
|
||||
{
|
||||
name,
|
||||
},
|
||||
],
|
||||
});
|
||||
const nebbie = nuked(app, {
|
||||
load: (type, config) => config.Promise.resolve(window[type.name]),
|
||||
});
|
||||
return nebbie;
|
||||
};
|
||||
|
||||
@@ -114,7 +114,70 @@ async function renderSnapshot() {
|
||||
window.onHotChange(info.supernova.name, () => render());
|
||||
}
|
||||
|
||||
if (params.snapshot) {
|
||||
const renderFixture = async () => {
|
||||
const element = document.querySelector('#chart-container');
|
||||
const { theme } = params;
|
||||
const { themes } = await serverInfo;
|
||||
const fixture = runFixture(params.fixture);
|
||||
const { instanceConfig, type, sn, object, snConfig } = fixture();
|
||||
const config = {
|
||||
themes: themes
|
||||
? themes.map(t => ({
|
||||
key: t,
|
||||
load: async () => (await fetch(`/theme/${t}`)).json(),
|
||||
}))
|
||||
: undefined,
|
||||
theme,
|
||||
};
|
||||
let mockedProps = {};
|
||||
let mockedLayout = {};
|
||||
const mockedObject = {
|
||||
...mockedProps,
|
||||
...object,
|
||||
// beginSelections: async () => {},
|
||||
// selectHyperCubeValues: async (path, dimNo, values, toggleMode) => {
|
||||
// console.log(path, dimNo, values, toggleMode);
|
||||
// },
|
||||
// resetMadeSelections: async () => {},
|
||||
getLayout:
|
||||
object && object.getLayout
|
||||
? async () => {
|
||||
const layout = await object.getLayout();
|
||||
mockedLayout = {
|
||||
...mockedProps,
|
||||
...layout,
|
||||
};
|
||||
return mockedLayout;
|
||||
}
|
||||
: async () => ({
|
||||
...mockedProps,
|
||||
}),
|
||||
on() {},
|
||||
once() {},
|
||||
};
|
||||
|
||||
const mockedApp = {
|
||||
// eslint-disable-next-line no-return-assign
|
||||
createSessionObject: async p => (mockedProps = p),
|
||||
getObject: async () => mockedObject,
|
||||
};
|
||||
|
||||
const nebbie = nucleus(mockedApp, {
|
||||
...config,
|
||||
...instanceConfig,
|
||||
types: [
|
||||
{
|
||||
name: type,
|
||||
load: async () => sn,
|
||||
},
|
||||
],
|
||||
});
|
||||
nebbie.create({ type }, { ...snConfig, element });
|
||||
};
|
||||
|
||||
if (params.fixture) {
|
||||
renderFixture();
|
||||
} else if (params.snapshot) {
|
||||
renderSnapshot();
|
||||
} else {
|
||||
renderWithEngine();
|
||||
|
||||
13
commands/serve/web/run-fixture.js
Normal file
13
commands/serve/web/run-fixture.js
Normal file
@@ -0,0 +1,13 @@
|
||||
const runFixture = key => {
|
||||
// const info = await serverInfo;
|
||||
// see: https://webpack.js.org/guides/dependency-management/#requirecontext
|
||||
try {
|
||||
const context = require.context('fixtures', true, /\.fix\.js$/);
|
||||
// context.keys().forEach(console.log);
|
||||
return context(key).default;
|
||||
} catch (_) {
|
||||
return () => console.log('No fixtures found in test/component');
|
||||
}
|
||||
};
|
||||
|
||||
export default runFixture;
|
||||
@@ -55,7 +55,10 @@
|
||||
"husky": "3.1.0",
|
||||
"lerna": "3.18.5",
|
||||
"lint-staged": "9.4.3",
|
||||
"picasso.js": "0.29.0",
|
||||
"picasso-plugin-q": "0.29.0",
|
||||
"prettier": "1.19.1",
|
||||
"qix-faker": "^0.3.0",
|
||||
"rollup": "1.27.2",
|
||||
"rollup-plugin-babel": "4.3.3",
|
||||
"rollup-plugin-commonjs": "10.1.0",
|
||||
@@ -76,6 +79,7 @@
|
||||
"generated/*",
|
||||
"packages/*",
|
||||
"commands/*",
|
||||
"apis/*"
|
||||
"apis/*",
|
||||
"test/component/*"
|
||||
]
|
||||
}
|
||||
|
||||
25
test/component/barchart/barchart.fix.js
Normal file
25
test/component/barchart/barchart.fix.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import { hypercube } from 'qix-faker';
|
||||
import sn from './src';
|
||||
|
||||
export default function fixture() {
|
||||
return {
|
||||
type: 'barchart',
|
||||
sn,
|
||||
snConfig: {
|
||||
context: {
|
||||
permissions: ['passive', 'interact'],
|
||||
},
|
||||
},
|
||||
object: {
|
||||
getLayout: async () => ({
|
||||
qHyperCubeDef: null,
|
||||
qHyperCube: hypercube({
|
||||
seed: 13,
|
||||
numRows: 20,
|
||||
dimensions: [{ value: f => f.address.country(), maxCardinalRatio: 0.2 }],
|
||||
measures: [f => f.commerce.price(10, 5000, 0, '$')],
|
||||
}),
|
||||
}),
|
||||
},
|
||||
};
|
||||
}
|
||||
15
test/component/barchart/src/data.js
Normal file
15
test/component/barchart/src/data.js
Normal file
@@ -0,0 +1,15 @@
|
||||
export default {
|
||||
targets: [
|
||||
{
|
||||
path: 'qHyperCubeDef',
|
||||
dimensions: {
|
||||
min: 1,
|
||||
max: 1,
|
||||
},
|
||||
measures: {
|
||||
min: 1,
|
||||
max: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
49
test/component/barchart/src/index.js
Normal file
49
test/component/barchart/src/index.js
Normal file
@@ -0,0 +1,49 @@
|
||||
import picassojs from 'picasso.js';
|
||||
import picassoQ from 'picasso-plugin-q';
|
||||
|
||||
import properties from './object-properties';
|
||||
import data from './data';
|
||||
import picSelections from './pic-selections';
|
||||
import definition from './pic-definition';
|
||||
|
||||
export default function supernova(/* env */) {
|
||||
const picasso = picassojs();
|
||||
picasso.use(picassoQ);
|
||||
|
||||
return {
|
||||
qae: {
|
||||
properties,
|
||||
data,
|
||||
},
|
||||
component: {
|
||||
created() {},
|
||||
mounted(element) {
|
||||
this.pic = picasso.chart({
|
||||
element,
|
||||
data: [],
|
||||
settings: {},
|
||||
});
|
||||
this.picsel = picSelections({
|
||||
selections: this.selections,
|
||||
brush: this.pic.brush('selection'),
|
||||
picassoQ,
|
||||
});
|
||||
},
|
||||
render({ layout, context }) {
|
||||
this.pic.update({
|
||||
data: [
|
||||
{
|
||||
type: 'q',
|
||||
key: 'qHyperCube',
|
||||
data: layout.qHyperCube,
|
||||
},
|
||||
],
|
||||
settings: definition({ layout, context }),
|
||||
});
|
||||
},
|
||||
resize() {},
|
||||
willUnmount() {},
|
||||
destroy() {},
|
||||
},
|
||||
};
|
||||
}
|
||||
15
test/component/barchart/src/object-properties.js
Normal file
15
test/component/barchart/src/object-properties.js
Normal file
@@ -0,0 +1,15 @@
|
||||
const properties = {
|
||||
qHyperCubeDef: {
|
||||
qDimensions: [],
|
||||
qMeasures: [],
|
||||
qInitialDataFetch: [{ qWidth: 2, qHeight: 5000 }],
|
||||
qSuppressZero: false,
|
||||
qSuppressMissing: true,
|
||||
},
|
||||
showTitles: true,
|
||||
title: '',
|
||||
subtitle: '',
|
||||
footnote: '',
|
||||
};
|
||||
|
||||
export default properties;
|
||||
68
test/component/barchart/src/pic-definition.js
Normal file
68
test/component/barchart/src/pic-definition.js
Normal file
@@ -0,0 +1,68 @@
|
||||
export default function picassoDefinition({ layout, context }) {
|
||||
if (!layout.qHyperCube) {
|
||||
throw new Error('Layout is missing a hypercube');
|
||||
}
|
||||
return {
|
||||
scales: {
|
||||
x: { data: { extract: { field: 'qDimensionInfo/0' } } },
|
||||
y: {
|
||||
data: { field: 'qMeasureInfo/0' },
|
||||
expand: 0.2,
|
||||
include: [0],
|
||||
invert: true,
|
||||
},
|
||||
},
|
||||
components: [
|
||||
{
|
||||
type: 'axis',
|
||||
dock: 'left',
|
||||
scale: 'y',
|
||||
},
|
||||
{
|
||||
type: 'axis',
|
||||
dock: 'bottom',
|
||||
scale: 'x',
|
||||
},
|
||||
{
|
||||
type: 'box',
|
||||
data: {
|
||||
extract: {
|
||||
field: 'qDimensionInfo/0',
|
||||
props: {
|
||||
start: 0,
|
||||
end: { field: 'qMeasureInfo/0' },
|
||||
},
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
major: { scale: 'x' },
|
||||
minor: { scale: 'y' },
|
||||
box: {
|
||||
width: 0.7,
|
||||
},
|
||||
},
|
||||
brush:
|
||||
context.permissions.indexOf('interact') !== -1 && context.permissions.indexOf('select') !== -1
|
||||
? {
|
||||
trigger: [
|
||||
{
|
||||
contexts: ['selection'],
|
||||
},
|
||||
],
|
||||
consume: [
|
||||
{
|
||||
context: 'selection',
|
||||
data: ['', 'end'],
|
||||
style: {
|
||||
inactive: {
|
||||
opacity: 0.3,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
: {},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
131
test/component/barchart/src/pic-selections.js
Normal file
131
test/component/barchart/src/pic-selections.js
Normal file
@@ -0,0 +1,131 @@
|
||||
/* eslint no-param-reassign: 0 */
|
||||
|
||||
// --- enable keyboard accessibility ---
|
||||
// pressing enter (escape) key should confirm (cancel) selections
|
||||
const KEYS = {
|
||||
ENTER: 'Enter',
|
||||
ESCAPE: 'Escape',
|
||||
IE11_ESC: 'Esc',
|
||||
SHIFT: 'Shift',
|
||||
};
|
||||
|
||||
const instances = [];
|
||||
let expando = 0;
|
||||
const confirmOrCancelSelection = e => {
|
||||
const active = instances.filter(a => a.selections && a.selections.isActive());
|
||||
if (!active.length) {
|
||||
return;
|
||||
}
|
||||
if (e.key === KEYS.ENTER) {
|
||||
active.forEach(a => a.selections.confirm());
|
||||
} else if (e.key === KEYS.ESCAPE || e.key === KEYS.IE11_ESC) {
|
||||
active.forEach(a => a.selections.cancel());
|
||||
}
|
||||
};
|
||||
|
||||
const setup = () => {
|
||||
document.addEventListener('keyup', confirmOrCancelSelection);
|
||||
};
|
||||
|
||||
const teardown = () => {
|
||||
document.removeEventListener('keyup', confirmOrCancelSelection);
|
||||
};
|
||||
// ------------------------------------------------------
|
||||
|
||||
const addListeners = (emitter, listeners) => {
|
||||
Object.keys(listeners).forEach(type => {
|
||||
emitter.on(type, listeners[type]);
|
||||
});
|
||||
};
|
||||
|
||||
const removeListeners = (emitter, listeners) => {
|
||||
Object.keys(listeners).forEach(type => {
|
||||
emitter.removeListener(type, listeners[type]);
|
||||
});
|
||||
};
|
||||
|
||||
export default function({ selections, brush, picassoQ } = {}, { path = '/qHyperCubeDef' } = {}) {
|
||||
if (!selections) {
|
||||
return {
|
||||
release: () => {},
|
||||
};
|
||||
}
|
||||
const key = ++expando;
|
||||
|
||||
let layout = null;
|
||||
|
||||
// interceptors primary job is to ensure selections only occur on either values OR ranges
|
||||
const valueInterceptor = added => {
|
||||
const brushes = brush.brushes();
|
||||
brushes.forEach(b => {
|
||||
if (b.type === 'range') {
|
||||
// has range selections
|
||||
brush.clear([]);
|
||||
} else if (added[0] && added[0].key !== b.id) {
|
||||
// has selections in another dimension
|
||||
brush.clear([]);
|
||||
}
|
||||
});
|
||||
return added.filter(t => t.value !== -2); // do not allow selection on null value
|
||||
};
|
||||
|
||||
const rangeInterceptor = a => {
|
||||
const v = brush.brushes().filter(b => b.type === 'value');
|
||||
if (v.length) {
|
||||
// has dimension values selected
|
||||
brush.clear([]);
|
||||
return a;
|
||||
}
|
||||
return a;
|
||||
};
|
||||
|
||||
brush.intercept('set-ranges', rangeInterceptor);
|
||||
brush.intercept('toggle-ranges', rangeInterceptor);
|
||||
|
||||
brush.intercept('toggle-values', valueInterceptor);
|
||||
brush.intercept('set-values', valueInterceptor);
|
||||
brush.intercept('add-values', valueInterceptor);
|
||||
|
||||
brush.on('start', () => selections.begin(path));
|
||||
|
||||
const selectionListeners = {
|
||||
activate: () => {
|
||||
// TODO - check if we can select in the current chart,
|
||||
},
|
||||
deactivated: () => brush.end(),
|
||||
cleared: () => brush.clear(),
|
||||
canceled: () => brush.end(),
|
||||
};
|
||||
addListeners(selections, selectionListeners);
|
||||
|
||||
brush.on('update', () => {
|
||||
const generated = picassoQ.selections(brush, {}, layout);
|
||||
generated.forEach(s => selections.select(s));
|
||||
});
|
||||
|
||||
if (instances.length === 0) {
|
||||
setup();
|
||||
}
|
||||
|
||||
instances.push({
|
||||
key,
|
||||
selections,
|
||||
});
|
||||
|
||||
return {
|
||||
layout: lt => {
|
||||
layout = lt;
|
||||
},
|
||||
release: () => {
|
||||
layout = null;
|
||||
const idx = instances.indexOf(instances.filter(i => i.key === key)[0]);
|
||||
if (idx !== -1) {
|
||||
instances.splice(idx, 1);
|
||||
}
|
||||
if (!instances.length) {
|
||||
teardown();
|
||||
}
|
||||
removeListeners(selections, selectionListeners);
|
||||
},
|
||||
};
|
||||
}
|
||||
10
test/component/object/incomplete-sn.comp.js
Normal file
10
test/component/object/incomplete-sn.comp.js
Normal file
@@ -0,0 +1,10 @@
|
||||
describe('sn', () => {
|
||||
const selector = '.nebulajs-cell [data-tid="error-title"';
|
||||
it('should show incomplete visualization', async () => {
|
||||
await page.goto('http://localhost:8000/render/?fixture=./object/incomplete-sn.fix.js&theme=dark');
|
||||
|
||||
await page.waitForSelector(selector, { visible: true });
|
||||
const text = await page.$eval(selector, el => el.textContent);
|
||||
expect(text).to.equal('Incomplete visualization');
|
||||
});
|
||||
});
|
||||
13
test/component/object/incomplete-sn.fix.js
Normal file
13
test/component/object/incomplete-sn.fix.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import incompleteSn from './incomplete-sn';
|
||||
|
||||
export default function fixture() {
|
||||
return {
|
||||
type: 'incomplete-sn',
|
||||
sn: incompleteSn,
|
||||
snConfig: {
|
||||
context: {
|
||||
permissions: ['passive', 'interact'],
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
20
test/component/object/incomplete-sn.js
Normal file
20
test/component/object/incomplete-sn.js
Normal file
@@ -0,0 +1,20 @@
|
||||
export default {
|
||||
component: {
|
||||
mounted(element) {
|
||||
element.textContent = 'Hello engine!'; // eslint-disable-line no-param-reassign
|
||||
},
|
||||
},
|
||||
qae: {
|
||||
data: {
|
||||
targets: [
|
||||
{
|
||||
path: '/qHyperCubeDef',
|
||||
dimensions: {
|
||||
min: 1,
|
||||
max: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
13
test/component/object/sn.fix.js
Normal file
13
test/component/object/sn.fix.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import sn from './sn';
|
||||
|
||||
export default function fixture() {
|
||||
return {
|
||||
type: 'sn',
|
||||
sn,
|
||||
snConfig: {
|
||||
context: {
|
||||
permissions: ['passive', 'interact'],
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
20
test/component/object/sn.js
Normal file
20
test/component/object/sn.js
Normal file
@@ -0,0 +1,20 @@
|
||||
export default {
|
||||
component: {
|
||||
mounted(element) {
|
||||
element.textContent = 'Hello engine!'; // eslint-disable-line no-param-reassign
|
||||
},
|
||||
},
|
||||
qae: {
|
||||
data: {
|
||||
targets: [
|
||||
{
|
||||
path: '/qHyperCubeDef',
|
||||
dimensions: {
|
||||
min: 0,
|
||||
max: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
22
yarn.lock
22
yarn.lock
@@ -7829,6 +7829,11 @@ extsprintf@^1.2.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
|
||||
|
||||
faker@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/faker/-/faker-4.1.0.tgz#1e45bbbecc6774b3c195fad2835109c6d748cc3f"
|
||||
integrity sha1-HkW7vsxndLPBlfrSg1EJxtdIzD8=
|
||||
|
||||
fast-deep-equal@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
|
||||
@@ -12302,6 +12307,16 @@ phin@^2.9.1:
|
||||
version "2.9.3"
|
||||
resolved "https://registry.yarnpkg.com/phin/-/phin-2.9.3.tgz#f9b6ac10a035636fb65dfc576aaaa17b8743125c"
|
||||
|
||||
picasso-plugin-q@0.29.0:
|
||||
version "0.29.0"
|
||||
resolved "https://registry.yarnpkg.com/picasso-plugin-q/-/picasso-plugin-q-0.29.0.tgz#5ac428605e7efde8f732079b6d5e5c6614b0c52a"
|
||||
integrity sha512-zNWvGab7V7uw/mpAEuCbG7A6PUvM9bTHmvr9WoYGyT92evvvpcGGVafoTuct9qw6yK2HjK2rDwUjdq6+iZ20fg==
|
||||
|
||||
picasso.js@0.29.0:
|
||||
version "0.29.0"
|
||||
resolved "https://registry.yarnpkg.com/picasso.js/-/picasso.js-0.29.0.tgz#9c0b08cdb913ab6d82bf71b44f956a4f6eb00a49"
|
||||
integrity sha512-AincOxuu6rE4Yx3+jY7jDd1wJlfAIYSNPjpfMOlqtn+JWM1Z+QBALpNIa/cWhvhdLxD7rFFVnto1Ciiikjahpg==
|
||||
|
||||
picomatch@^2.0.4, picomatch@^2.0.5:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6"
|
||||
@@ -13090,6 +13105,13 @@ q@^1.1.2, q@^1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
|
||||
|
||||
qix-faker@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/qix-faker/-/qix-faker-0.3.0.tgz#63911eff5f2153bf93b6176faea8ffd833922435"
|
||||
integrity sha512-S1oK/8Bl+MhIJHrn0KrPqmP6fqhNPNThPxaOLzKwDYHzF/st0wUfT+UBOhCyxpZJhhKmrp8SwJs0t3rpqRPo4A==
|
||||
dependencies:
|
||||
faker "^4.1.0"
|
||||
|
||||
qs@6.7.0:
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
|
||||
|
||||
Reference in New Issue
Block a user