Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions jest-addon.config.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
require('dotenv').config({ path: __dirname + '/.env' })
require('dotenv').config({ path: __dirname + '/.env' });

const fs = require('fs')
const path = require('path')
const fs = require('fs');
const path = require('path');

const voltoSlatePath = fs.existsSync(
path.join(__dirname, '../../../node_modules/@plone/volto-slate/src'),
)
? '<rootDir>/node_modules/@plone/volto-slate/src'
: '<rootDir>/node_modules/@plone/volto/packages/volto-slate/src'
: '<rootDir>/node_modules/@plone/volto/packages/volto-slate/src';

module.exports = {
testMatch: ['**/src/addons/**/?(*.)+(spec|test).[jt]s?(x)'],
collectCoverageFrom: [
'src/addons/**/src/**/*.{js,jsx,ts,tsx}',
'src/addons/volto-plotlycharts/src/**/*.{js,jsx,ts,tsx}',
'!src/**/*.d.ts',
'!**/*.test.{js,jsx,ts,tsx}',
'!**/*.stories.{js,jsx,ts,tsx}',
'!**/*.spec.{js,jsx,ts,tsx}',
],
moduleNameMapper: {
'\\.(css|less|scss|sass)$': 'identity-obj-proxy',
Expand Down Expand Up @@ -55,4 +58,4 @@ module.exports = {
'<rootDir>/node_modules/@eeacms/volto-plotlycharts/jest.setup.js',
],
}),
}
};
80 changes: 80 additions & 0 deletions src/Blocks/EmbedVisualization/Edit.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React from 'react';
import renderer, { act } from 'react-test-renderer';
import Edit from './Edit';

jest.mock('semantic-ui-react', () => ({
Message: ({ children }) => <div className="mock-message">{children}</div>,
}));

jest.mock('@plone/volto/components/manage/Sidebar/SidebarPortal', () => ({
__esModule: true,
default: ({ children, selected }) => (
<aside className="mock-sidebar" data-selected={selected}>
{children}
</aside>
),
}));

jest.mock('@plone/volto/components/manage/Form/BlockDataForm', () => ({
__esModule: true,
default: (props) => (
<form className="mock-block-data-form" data-props={props} />
),
}));

jest.mock('@eeacms/volto-plotlycharts/PlotlyComponent', () => (props) => (
<div className="mock-plotly-component" data-props={props} />
));

describe('EmbedVisualization Edit', () => {
it('shows a message until a visualization is selected', () => {
const component = renderer.create(
<Edit data={{}} block="block-id" onChangeBlock={jest.fn()} />,
);

expect(
component.root.findByProps({ className: 'mock-message' }),
).toBeTruthy();
expect(
component.root.findByProps({ className: 'mock-block-data-form' }),
).toBeTruthy();
});

it('renders PlotlyComponent and updates block data from the sidebar form', () => {
const onChangeBlock = jest.fn();
const component = renderer.create(
<Edit
selected
block="block-id"
data={{ vis_url: '/visualization', with_notes: false }}
onChangeBlock={onChangeBlock}
/>,
);
const plotly = component.root.findByProps({
className: 'mock-plotly-component',
});
const form = component.root.findByProps({
className: 'mock-block-data-form',
});

expect(plotly.props['data-props'].mode).toBe('edit');
expect(plotly.props['data-props'].data).toMatchObject({
vis_url: '/visualization',
download_button: true,
has_data_query_by_context: true,
with_sources: true,
with_more_info: true,
with_notes: false,
});

act(() => {
form.props['data-props'].onChangeField('title', 'Updated');
});

expect(onChangeBlock).toHaveBeenCalledWith('block-id', {
vis_url: '/visualization',
with_notes: false,
title: 'Updated',
});
});
});
36 changes: 36 additions & 0 deletions src/Blocks/EmbedVisualization/View.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';
import renderer from 'react-test-renderer';
import View from './View';

jest.mock('@eeacms/volto-plotlycharts/PlotlyComponent', () => (props) => (
<div className="mock-plotly-component" data-props={props} />
));

describe('EmbedVisualization View', () => {
it('passes embedded visualization defaults to PlotlyComponent', () => {
const component = renderer.create(
<View
mode="preview"
data={{
title: 'Embedded chart',
properties: { llm_summary: 'Summary' },
}}
/>,
);
const plotly = component.root.findByProps({
className: 'mock-plotly-component',
});

expect(
component.root.findByProps({ className: 'embed-visualization view' }),
).toBeTruthy();
expect(plotly.props['data-props']).toMatchObject({ mode: 'preview' });
expect(plotly.props['data-props'].data).toMatchObject({
title: 'Embedded chart',
download_button: true,
has_data_query_by_context: true,
with_sources: true,
llm_summary: 'Summary',
});
});
});
104 changes: 104 additions & 0 deletions src/Blocks/PlotlyChart/Edit.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import React from 'react';
import renderer, { act } from 'react-test-renderer';
import Edit from './Edit';

jest.mock('semantic-ui-react', () => {
const Modal = ({ children, open, className }) => (
<div className={className} data-open={open}>
{children}
</div>
);
Modal.Content = ({ children, scrolling }) => (
<div className="mock-modal-content" data-scrolling={scrolling}>
{children}
</div>
);

return {
Button: ({ children, onClick }) => (
<button type="button" onClick={onClick}>
{children}
</button>
),
Modal,
};
});

jest.mock('@plone/volto/components/manage/Sidebar/SidebarPortal', () => ({
__esModule: true,
default: ({ children }) => <aside className="mock-sidebar">{children}</aside>,
}));

jest.mock('@plone/volto/components/manage/Form/BlockDataForm', () => ({
__esModule: true,
default: (props) => (
<form className="mock-block-data-form" data-props={props} />
),
}));

jest.mock('./View', () => (props) => (
<div className="mock-plotly-view" data-props={props} />
));

describe('PlotlyChart Edit', () => {
beforeEach(() => {
global.__SERVER__ = false;
});

it('renders editor controls, block view, and sidebar form', () => {
const component = renderer.create(
<Edit data={{ visualization: { data: [] } }} block="block-id" />,
);

expect(component.root.findByType('button').children).toEqual([
'Open Chart Editor',
]);
expect(
component.root.findByProps({ className: 'mock-plotly-view' }).props[
'data-props'
].mode,
).toBe('edit');
expect(
component.root.findByProps({ className: 'mock-block-data-form' }),
).toBeTruthy();
});

it('opens the chart editor modal and updates fields from the sidebar form', () => {
const onChangeBlock = jest.fn();
const preventDefault = jest.fn();
const stopPropagation = jest.fn();
const component = renderer.create(
<Edit
data={{ title: 'Chart', visualization: { data: [] } }}
block="block-id"
onChangeBlock={onChangeBlock}
/>,
);

act(() => {
component.root.findByType('button').props.onClick({
preventDefault,
stopPropagation,
});
});

expect(preventDefault).toHaveBeenCalled();
expect(stopPropagation).toHaveBeenCalled();
expect(
component.root.findByProps({
className: 'chart-editor-modal plotly-editor--theme-provider',
}),
).toBeTruthy();

act(() => {
component.root
.findByProps({ className: 'mock-block-data-form' })
.props['data-props'].onChangeField('title', 'Updated');
});

expect(onChangeBlock).toHaveBeenCalledWith('block-id', {
title: 'Updated',
visualization: { data: [] },
});
});
});
28 changes: 28 additions & 0 deletions src/Blocks/PlotlyChart/View.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';
import renderer from 'react-test-renderer';
import View from './View';

jest.mock('@eeacms/volto-plotlycharts/PlotlyComponent', () => (props) => (
<div className="mock-plotly-component" data-props={props} />
));

describe('PlotlyChart View', () => {
it('renders PlotlyComponent with default print/export options', () => {
const component = renderer.create(
<View data={{ title: 'Chart', with_sources: false }} />,
);
const plotly = component.root.findByProps({
className: 'mock-plotly-component',
});

expect(
component.root.findByProps({ className: 'plotly-chart' }),
).toBeTruthy();
expect(plotly.props['data-props'].data).toMatchObject({
title: 'Chart',
download_button: true,
has_data_query_by_context: true,
with_sources: false,
});
});
});
79 changes: 79 additions & 0 deletions src/Blocks/Treemap/Edit.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React from 'react';
import renderer, { act } from 'react-test-renderer';
import Edit from './Edit';

jest.mock('redux', () => ({
compose:
(...fns) =>
(value) =>
fns.reduceRight((acc, fn) => fn(acc), value),
}));

jest.mock('@eeacms/volto-datablocks/hocs', () => ({
connectToProviderData: () => (Component) => (props) => (
<Component
{...props}
provider_data={props.provider_data ?? { size: [1], label: ['A'] }}
/>
),
}));

jest.mock('@plone/volto/components/manage/Sidebar/SidebarPortal', () => ({
__esModule: true,
default: ({ children }) => <aside className="mock-sidebar">{children}</aside>,
}));

jest.mock('@plone/volto/components/manage/Form/BlockDataForm', () => ({
__esModule: true,
default: (props) => (
<form className="mock-block-data-form" data-props={props} />
),
}));

jest.mock('./View', () => (props) => (
<div className="mock-treemap-view" data-props={props} />
));

describe('Treemap Edit', () => {
it('renders TreemapView and builds schema choices from provider data', () => {
const component = renderer.create(
<Edit data={{ url: '/data' }} block="block-id" />,
);
const form = component.root.findByProps({
className: 'mock-block-data-form',
});

expect(
component.root.findByProps({ className: 'mock-treemap-view' }),
).toBeTruthy();
expect(
form.props['data-props'].schema.properties.size_column.choices,
).toEqual([
['size', 'size'],
['label', 'label'],
]);
});

it('updates block data from the sidebar form', () => {
const onChangeBlock = jest.fn();
const component = renderer.create(
<Edit
data={{ url: '/data' }}
block="block-id"
onChangeBlock={onChangeBlock}
/>,
);
const form = component.root.findByProps({
className: 'mock-block-data-form',
});

act(() => {
form.props['data-props'].onChangeField('size_column', 'size');
});

expect(onChangeBlock).toHaveBeenCalledWith('block-id', {
url: '/data',
size_column: 'size',
});
});
});
23 changes: 23 additions & 0 deletions src/Blocks/Treemap/View.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import renderer from 'react-test-renderer';
import View from './View';

jest.mock('./Treemap', () => (props) => (
<div className="mock-treemap" data-props={props} />
));

jest.mock('@eeacms/volto-datablocks/hocs', () => ({
withBlockData: (Component) => (props) => (
<Component {...props} provider_data={{ value: [1] }} />
),
}));

describe('Treemap View', () => {
it('renders Treemap with block data props', () => {
const component = renderer.create(<View data={{ title: 'Treemap' }} />);
const treemap = component.root.findByProps({ className: 'mock-treemap' });

expect(treemap.props['data-props'].data).toEqual({ title: 'Treemap' });
expect(treemap.props['data-props'].provider_data).toEqual({ value: [1] });
});
});
Loading