chore(deps): update material-ui monorepo to v7 (major) (#1598)

* fix(deps): update dependency webpack-cli to v7 (#1935)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* fix(deps): update minor and patch (#1934)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore: re-run spec (#1938)

* Potential fix for code scanning alert no. 98: Overly permissive regular expression range (#1936)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* fix: align requirements better with client (#1937)

* fix: aline requirements better with client

* fix: remove comment

* chore: fix for empty dims

* fix: prototype pollution vulnerabilities in json-patch.js (#1941)

* Initial plan

* Fix prototype pollution security vulnerabilities in json-patch.js

Co-authored-by: Caele <6318307+Caele@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Caele <6318307+Caele@users.noreply.github.com>

* chore: normalize yarn resolutions for renovate compatibility (#1943)

* chore: avoid renovate resolution lookup warnings

* chore: dedupe yarn resolutions and normalize ranges

Signed-off-by: Johan Enell <johan.enell@qlik.com>

---------

Signed-off-by: Johan Enell <johan.enell@qlik.com>

* fix(deps): update dependency puppeteer to v24.40.0 (#1947)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update material-ui monorepo to v7

* chore: perfrom mui v7 migration

* chore: store test results

* chore: adjust artifact storage

* chore: fix lint

* chore: fix report folder

* chore: fix classnames

---------

Signed-off-by: Johan Enell <johan.enell@qlik.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Tobias Åström <tsm@qlik.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Caele <6318307+Caele@users.noreply.github.com>
Co-authored-by: Johan Enell <johan.enell@qlik.com>
This commit is contained in:
renovate[bot]
2026-03-24 13:25:13 +01:00
committed by GitHub
parent b0ba759acd
commit 357a5863a9
37 changed files with 987 additions and 1110 deletions

View File

@@ -34,6 +34,9 @@ jobs:
validate:
runs-on: ubuntu-latest
needs: build
permissions:
contents: read
checks: write
steps:
- uses: actions/checkout@v6
- name: Enable Corepack
@@ -58,14 +61,26 @@ jobs:
JEST_JUNIT_OUTPUT_DIR: ./coverage/junit/
run: yarn test:unit --coverage
- name: Store junit results
if: always()
uses: actions/upload-artifact@v7
with:
name: junit
path: coverage/junit
- name: Publish junit test report
if: ${{ always() && hashFiles('coverage/junit/*.xml') != '' }}
uses: dorny/test-reporter@v2
with:
name: Unit Tests
path: coverage/junit/*.xml
reporter: jest-junit
fail-on-error: false
test-integration:
runs-on: ubuntu-latest
needs: build
permissions:
contents: read
checks: write
steps:
- uses: actions/checkout@v6
- name: Enable Corepack
@@ -84,7 +99,17 @@ jobs:
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Test component
env:
PLAYWRIGHT_JUNIT_OUTPUT_NAME: component-junit.xml
run: yarn run test:component
- name: Publish component test report
if: ${{ always() && hashFiles('test-results/component-junit.xml') != '' }}
uses: dorny/test-reporter@v2
with:
name: Component Tests
path: test-results/component-junit.xml
reporter: jest-junit
fail-on-error: false
- name: Test mashup
run: yarn run test:mashup
- name: Store mashup artifacts
@@ -93,8 +118,26 @@ jobs:
with:
name: mashup
path: ./test/mashup
- name: Publish mashup test report
if: ${{ always() && hashFiles('test/mashup/reports/xml/*.xml') != '' }}
uses: dorny/test-reporter@v2
with:
name: Mashup Tests
path: test/mashup/reports/xml/*.xml
reporter: jest-junit
fail-on-error: false
- name: Test integration
env:
PLAYWRIGHT_JUNIT_OUTPUT_NAME: integration-junit.xml
run: yarn run test:integration
- name: Publish integration test report
if: ${{ always() && hashFiles('test-results/integration-junit.xml') != '' }}
uses: dorny/test-reporter@v2
with:
name: Integration Tests
path: test-results/integration-junit.xml
reporter: jest-junit
fail-on-error: false
- name: Test rendering
run: yarn run test:rendering
- name: Store rendering artifacts
@@ -103,6 +146,14 @@ jobs:
with:
name: rendering
path: ./test/rendering
- name: Publish rendering test report
if: ${{ always() && hashFiles('test/rendering/reports/xml/*.xml') != '' }}
uses: dorny/test-reporter@v2
with:
name: Rendering Tests
path: test/rendering/reports/xml/*.xml
reporter: jest-junit
fail-on-error: false
test-create:
runs-on: ubuntu-latest

View File

@@ -6,14 +6,14 @@
"devDependencies": {
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@mui/icons-material": "^6.5.0",
"@mui/material": "^6.5.0",
"@mui/icons-material": "^7.3.9",
"@mui/material": "^7.3.9",
"@nebula.js/conversion": "^6.7.0",
"@nebula.js/locale": "^6.7.0",
"@nebula.js/supernova": "^6.7.0",
"@nebula.js/theme": "^6.7.0",
"@nebula.js/ui": "^6.7.0",
"@qlik/api": "2.4.1",
"@qlik/api": "2.5.0",
"@testing-library/dom": "^10.4.1",
"@testing-library/react": "^16.3.2",
"extend": "3.0.2",

View File

@@ -38,9 +38,9 @@ const ActionToolbarElement = {
const ActionsGroup = React.forwardRef(({ className, actions = [], addAnchor = false, isRtl = false }, ref) =>
actions.length > 0 ? (
<Grid item container gap={0} flexDirection={isRtl ? 'row-reverse' : 'row'} wrap="nowrap" className={className}>
<Grid container gap={0} flexDirection={isRtl ? 'row-reverse' : 'row'} wrap="nowrap" className={className}>
{actions.map((e, ix) => (
<Grid item key={e.key} className={`${classes.itemSpacing} ${classes.item}`}>
<Grid key={e.key} className={`${classes.itemSpacing} ${classes.item}`}>
<Item key={e.key} item={e} ref={ix === 0 ? ref : null} addAnchor={addAnchor} />
</Grid>
))}
@@ -192,7 +192,7 @@ function ActionsToolbar({
/>
)}
{showDivider && (
<Grid item className={classes.itemSpacing} style={dividerStyle}>
<Grid className={classes.itemSpacing} style={dividerStyle}>
<Divider orientation="vertical" />
</Grid>
)}

View File

@@ -142,9 +142,10 @@ const handleModal = ({ sn, layout, model }) => {
};
const filterData = (d) => (d.qError ? d.qError.qErrorCode === 7005 : true);
const hasError = (e) => e && e.qError && e.qError.qErrorCode !== 7005;
const validateInfo = (min, info, getDescription, translatedError, translatedCalcCond) =>
[...Array(min).keys()].map((i) => {
[...Array(Math.max(min, info.length)).keys()].map((i) => {
const exists = !!(info && info[i]);
const softError = exists && info[i].qError && info[i].qError.qErrorCode === 7005;
const error = exists && !softError && info[i].qError;
@@ -173,14 +174,14 @@ const validateTarget = (translator, layout, properties, def) => {
const reqDimErrors = validateInfo(
minD,
getInfo(c.qDimensionInfo || c.qItems),
(i) => def.dimensions.description(properties, i),
(i) => def.dimensions.description(properties, i, {}),
translator.get('Visualization.Invalid.Dimension'),
translator.get('Visualization.UnfulfilledCalculationCondition')
);
const reqMeasErrors = validateInfo(
minM,
getInfo(c.qMeasureInfo),
(i) => def.measures.description(properties, i),
(i) => def.measures.description(properties, i, {}),
translator.get('Visualization.Invalid.Measure'),
translator.get('Visualization.UnfulfilledCalculationCondition')
);
@@ -197,18 +198,29 @@ const validateCubes = (translator, targets, layout) => {
let hasLayoutErrors = false;
let hasLayoutUnfulfilledCalculcationCondition = false;
const layoutErrors = [];
for (let i = 0; i < targets.length; ++i) {
const def = targets[i];
const minD = def.dimensions.min();
const minM = def.measures.min();
const c = def.resolveLayout(layout);
const d = getInfo(c.qDimensionInfo || c.qItems).filter(filterData); // Filter out optional calc conditions
const m = getInfo(c.qMeasureInfo).filter(filterData); // Filter out optional calc conditions
const dims = getInfo(c.qDimensionInfo || c.qItems);
const meas = getInfo(c.qMeasureInfo);
const d = dims.filter(filterData); // Filter out optional calc conditions
const m = meas.filter(filterData); // Filter out optional calc conditions
aggMinD += minD;
aggMinM += minM;
if (d.length < minD || m.length < minM) {
hasUnfulfilledErrors = true;
}
// Check for all non-calc-cond errors
hasUnfulfilledErrors = hasUnfulfilledErrors || dims.some(hasError) || meas.some(hasError);
if (c.qError) {
hasLayoutErrors = true;
hasLayoutUnfulfilledCalculcationCondition = c.qError.qErrorCode === 7005;
@@ -683,8 +695,7 @@ const Cell = forwardRef(
<Grid
tabIndex={keyboardNavigation && !externalFocusManagement ? 0 : -1}
onKeyDown={keyboardNavigation && !externalFocusManagement ? handleKeyDown : null}
item
xs
size="grow"
className={CellBody.className}
style={{
height: '100%',

View File

@@ -22,9 +22,9 @@ function DescriptionRow({ d }) {
</Typography>
);
return (
<Grid item container alignItems="center" wrap="nowrap">
<Grid item>{WrappedIcon}</Grid>
<Grid container item zeroMinWidth wrap="nowrap">
<Grid container alignItems="center" wrap="nowrap">
<Grid>{WrappedIcon}</Grid>
<Grid container sx={{ minWidth: 0 }} wrap="nowrap">
<Typography noWrap component="p">
<Typography component="span" variant="subtitle2" color={color}>
{d.description}
@@ -47,14 +47,13 @@ function DescriptionRow({ d }) {
function Descriptions({ data }) {
const theme = useTheme();
return (
<Grid container item style={{ maxWidth: '300px', overflow: 'hidden' }}>
<Grid container style={{ maxWidth: '300px', overflow: 'hidden' }}>
{data.map((e, ix) => {
const Rows = e.descriptions.map((d, dix) => <DescriptionRow d={d} key={dix} />);
return (
Rows.length > 0 && (
<Grid
container
item
key={ix}
direction="column"
style={{
@@ -82,15 +81,15 @@ export default function Error({ title = 'Error', message = '', data = [] }) {
justifyContent="center"
style={{ position: 'relative', height: '100%', width: '100%' }}
>
<Grid item>
<Grid>
<WarningTriangle style={{ fontSize: '38px' }} />
</Grid>
<Grid item>
<Grid>
<Typography variant="h6" align="center" data-tid="error-title">
{title}
</Typography>
</Grid>
<Grid item>
<Grid>
<Typography variant="subtitle1" align="center" data-tid="error-message">
{message}
</Typography>

View File

@@ -40,7 +40,6 @@ function Footer({ layout, titleStyles = {}, translator, flags, isCardTheme, isRt
return layout && layout.showTitles && (layout.footnote || showFilters) ? (
<StyledGrid container>
<Grid
item
className={classes.itemStyle}
data-testid={CellFooter.className}
sx={{ paddingTop: (theme) => (themePaddingEnabled ? paddingTop : theme.spacing(1)) }}

View File

@@ -78,8 +78,8 @@ function Header({ id, layout, sn, anchorEl, hovering, focusHandler, titleStyles
/>
);
return (
<StyledGrid item container wrap="nowrap" className={cls.join(' ')}>
<Grid item zeroMinWidth xs dir={isRtl ? 'rtl' : 'ltr'}>
<StyledGrid container wrap="nowrap" className={cls.join(' ')}>
<Grid size="grow" sx={{ minWidth: 0 }} dir={isRtl ? 'rtl' : 'ltr'}>
<Grid container wrap="nowrap" direction="column">
{showTitle ? (
<Tooltip title={layout.title}>
@@ -109,7 +109,7 @@ function Header({ id, layout, sn, anchorEl, hovering, focusHandler, titleStyles
)}
</Grid>
</Grid>
<Grid item>{Toolbar}</Grid>
<Grid>{Toolbar}</Grid>
</StyledGrid>
);
}

View File

@@ -33,17 +33,17 @@ const StyledGrid = styled(Grid)(() => ({
export function Cancel({ cancel, translator, ...props }) {
return (
<>
<StyledGrid container item direction="column" alignItems="center" gap={2}>
<Grid item>
<StyledGrid container direction="column" alignItems="center" gap={2}>
<Grid>
<Progress />
</Grid>
<Grid item>
<Grid>
<Typography variant="h6" align="center" data-tid="update-active">
{translator.get('Object.Update.Active')}
</Typography>
</Grid>
</StyledGrid>
<Grid item {...props}>
<Grid {...props}>
<Button variant="contained" onClick={cancel}>
{translator.get('Cancel')}
</Button>
@@ -55,15 +55,15 @@ export function Cancel({ cancel, translator, ...props }) {
export function Retry({ retry, translator, ...props }) {
return (
<>
<Grid item>
<Grid>
<WarningTriangle style={{ fontSize: '38px' }} />
</Grid>
<Grid item>
<Grid>
<Typography variant="h6" align="center" data-tid="update-cancelled">
{translator.get('Object.Update.Cancelled')}
</Typography>
</Grid>
<Grid item>
<Grid>
<Button variant="contained" onClick={retry} {...props}>
{translator.get('Retry')}
</Button>

View File

@@ -395,6 +395,98 @@ describe('<Cell />', () => {
expect(ftypes[0].props.title).toBe('Visualization.Incomplete');
});
test('should not render requirements', async () => {
const localLayout = { visualization: 'sn', title: 'foo', foo: { qDimensionInfo: [{}], qMeasureInfo: [{}] } };
const sn = {
generator: {
qae: {
data: {
targets: [
{
resolveLayout: () => localLayout.foo,
dimensions: {
min: () => 1,
max: () => 1,
description: (_properties, ix) =>
ix === 0
? 'Column'
: 'Cells - dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd ',
},
measures: {
min: () => 1,
max: () => 1,
description: () => 'Size',
},
},
],
},
},
},
};
const types = {
get: jest.fn().mockReturnValue({
supernova: async () => ({ create: () => sn }),
}),
getSupportedVersion: jest.fn().mockReturnValue('1.0.0'),
};
const model = {
getProperties: async () => {},
};
await render({ types, model });
const ftypes = renderer.root.findAllByType(CError);
expect(ftypes).toHaveLength(0);
const renderedSn = renderer.root.findByType(Supernova);
expect(renderedSn.props.sn).toEqual(sn);
});
test('should render requirements for dim error', async () => {
const localLayout = {
visualization: 'sn',
foo: { qDimensionInfo: [{}, { qError: { qErrorCode: 7000 } }], qMeasureInfo: [{}] },
};
const sn = {
generator: {
qae: {
data: {
targets: [
{
resolveLayout: () => localLayout.foo,
dimensions: {
min: () => 1,
max: () => 2,
description: (_properties, ix) =>
ix === 0
? 'Column'
: 'Cells - dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd ',
},
measures: {
min: () => 1,
max: () => 1,
description: () => 'Size',
},
},
],
},
},
},
};
const types = {
get: jest.fn().mockReturnValue({
supernova: async () => ({ create: () => sn }),
}),
getSupportedVersion: jest.fn().mockReturnValue('1.0.0'),
};
const model = {
getProperties: async () => {},
};
await render({ types, model });
const ftypes = renderer.root.findAllByType(CError);
expect(ftypes).toHaveLength(1);
expect(ftypes[0].props.title).toBe('Visualization.Incomplete');
});
test('should render requirements for multiple cubes', async () => {
const localLayout = { visualization: 'sn', foo: { qDimensionInfo: [], qMeasureInfo: [] } };
const sn = {

View File

@@ -294,7 +294,6 @@ function ListBoxInline({ options, layout }) {
/>
{showAttachedToolbar && listBoxHeader}
<Grid
item
container
direction="column"
height="100%"
@@ -303,7 +302,7 @@ function ListBoxInline({ options, layout }) {
aria-label={translator.get('Listbox.ResultFilterLabel')}
ref={listboxChildRef}
>
<Grid item>
<Grid>
<ListBoxSearch
ref={searchInputRef}
selections={selections}
@@ -322,7 +321,7 @@ function ListBoxInline({ options, layout }) {
styles={styles}
/>
</Grid>
<Grid item xs className={classes.listboxWrapper}>
<Grid size="grow" className={classes.listboxWrapper}>
{isInvalid ? (
<ListBoxError text={errorText} />
) : (

View File

@@ -157,8 +157,8 @@ export default function ListBoxPopover({
direction={direction}
>
<Grid container direction="column" gap={0} ref={containerRef}>
<Grid item container style={{ direction, padding: theme.spacing(1) }}>
<Grid item>
<Grid container style={{ direction, padding: theme.spacing(1) }}>
<Grid>
{isLocked ? (
<IconButton
onClick={unlock}
@@ -181,8 +181,8 @@ export default function ListBoxPopover({
</IconButton>
)}
</Grid>
<Grid item xs />
<Grid item>
<Grid size="grow" />
<Grid>
<ActionsToolbar
layout={layout}
more={{
@@ -206,9 +206,9 @@ export default function ListBoxPopover({
/>
</Grid>
</Grid>
<Grid item xs>
<Grid size="grow">
<div ref={moreAlignTo} />
<Grid item>
<Grid>
<ListBoxSearch
ref={searchInputRef}
popoverOpen={open}

View File

@@ -240,7 +240,7 @@ export default function ListBoxHeader({
/>
)}
{showLeftIcon && (
<Grid item container alignItems="center" width={iconsWidth} className="header-action-container">
<Grid container alignItems="center" width={iconsWidth} className="header-action-container">
{lockedIconComp || (showSearchIcon && searchIconComp)}
<DimensionIcon
iconData={iconData}
@@ -252,9 +252,8 @@ export default function ListBoxHeader({
</Grid>
)}
<Grid
item
xs
minWidth={0} // needed to text-overflow see: https://css-tricks.com/flexbox-truncated-text/
size="grow"
sx={{ minWidth: 0 }} // needed to text-overflow see: https://css-tricks.com/flexbox-truncated-text/
justifyContent={isRtl ? 'flex-end' : 'flex-start'}
className={classes.listBoxHeader}
>
@@ -262,9 +261,7 @@ export default function ListBoxHeader({
{layout.title}
</HeaderTitle>
</Grid>
<Grid item display="flex">
{actionsToolbar}
</Grid>
<Grid display="flex">{actionsToolbar}</Grid>
</StyledGridHeader>
);
}

View File

@@ -222,10 +222,7 @@ function RowColumn({ index, rowIndex, columnIndex, style, data }) {
layoutOrder={layoutOrder}
itemPadding={itemPadding}
gap={0}
className={joinClassNames(['value', ...classArr])}
classes={{
root: classes.fieldRoot,
}}
className={joinClassNames(['value', classes.fieldRoot, ...classArr])}
onClick={onClick}
onMouseDown={onMouseDown}
onMouseUp={onMouseUp}
@@ -248,12 +245,7 @@ function RowColumn({ index, rowIndex, columnIndex, style, data }) {
frequencyMax={frequencyMax}
/>
)}
<Grid
item
style={cellStyle}
className={joinClassNames([classes.cell, classes.selectedCell])}
title={`${label}`}
>
<Grid style={cellStyle} className={joinClassNames([classes.cell, classes.selectedCell])} title={`${label}`}>
{labels ? (
<FieldWithRanges
onChange={onChange}
@@ -290,7 +282,7 @@ function RowColumn({ index, rowIndex, columnIndex, style, data }) {
{freqIsAllowed && <Frequency cell={cell} checkboxes={checkboxes} dense={dense} showGray={showGray} />}
{showAnyIcon && (
<Grid item className={classes.icon}>
<Grid className={classes.icon}>
{showLockIcon && <Lock style={iconStyles} size="small" />}
{showTickIcon && <Tick style={iconStyles} size="small" />}
</Grid>

View File

@@ -8,7 +8,6 @@ function Frequency({ cell, checkboxes, dense, showGray }) {
const frequencyText = getFrequencyText(cell?.qFrequency);
return (
<Grid
item
style={{ display: 'flex', alignItems: 'center' }}
className={classes.frequencyCount}
aria-label={frequencyText}

View File

@@ -25,14 +25,13 @@ function AppSelections({ app }) {
}}
>
<Grid
item
style={{
borderRight: `1px solid ${theme.palette.divider}`,
}}
>
<Nav api={appSelections} app={app} />
</Grid>
<Grid item xs style={{ backgroundColor: theme.palette.background.darker, overflow: 'hidden' }}>
<Grid size="grow" style={{ backgroundColor: theme.palette.background.darker, overflow: 'hidden' }}>
<SelectedFields api={appSelections} app={app} />
</Grid>
</Grid>

View File

@@ -80,7 +80,7 @@ export default function More({ items = [], api }) {
return (
<StyledGrid container gap={0} className={classes.item} onClick={handleShowMoreItems}>
<Grid item>
<Grid>
<Box
borderRadius={theme.shape.borderRadius}
style={{
@@ -94,7 +94,7 @@ export default function More({ items = [], api }) {
</Typography>
</Box>
</Grid>
<Grid item>
<Grid>
<IconButton size="large">
<DownArrow />
</IconButton>

View File

@@ -71,17 +71,17 @@ export default function MultiState({ field, api, moreAlignTo = null, onClose = (
if (!moreAlignTo) {
Header = (
<>
<Grid item xs zeroMinWidth>
<Grid sx={{ minWidth: 0, flexGrow: 1 }}>
<Badge style={{ padding: '0px 8px' }} color="secondary" badgeContent={field.states.length}>
<Typography component="span" noWrap style={{ fontSize: '12px', lineHeight: '16px', fontWeight: 600 }}>
{field.label}
</Typography>
</Badge>
</Grid>
<Grid item>
<Grid>
<div style={{ width: '12px' }} />
</Grid>
<Grid item>
<Grid>
<IconButton size="large">
<DownArrow />
</IconButton>

View File

@@ -23,7 +23,7 @@ export default function Nav({ api, app }) {
padding: '0 8px',
}}
>
<Grid item>
<Grid>
<IconButton
style={{ marginRight: '8px' }}
disabled={!navState || !navState.canGoBack}
@@ -34,7 +34,7 @@ export default function Nav({ api, app }) {
<SelectionsBack />
</IconButton>
</Grid>
<Grid item>
<Grid>
<IconButton
style={{ marginRight: '8px' }}
disabled={!navState || !navState.canGoForward}
@@ -45,7 +45,7 @@ export default function Nav({ api, app }) {
<SelectionsForward />
</IconButton>
</Grid>
<Grid item>
<Grid>
<IconButton
disabled={!navState || !navState.canClear}
title={translator.get('Selection.ClearAll')}

View File

@@ -90,7 +90,7 @@ export default function OneField({
let SegmentsIndicator = null;
if (!moreAlignTo) {
Header = (
<Grid item xs style={{ minWidth: 0, flexGrow: 1, opacity: selection.qLocked ? '0.3' : '' }}>
<Grid style={{ minWidth: 0, flexGrow: 1, opacity: selection.qLocked ? '0.3' : '' }}>
<Typography noWrap style={{ fontSize: '12px', lineHeight: '16px', fontWeight: 600 }}>
{field.label}
</Typography>
@@ -102,7 +102,7 @@ export default function OneField({
if (selection.qLocked) {
Icon = (
<Grid item>
<Grid>
<IconButton size="large">
<Lock />
</IconButton>
@@ -110,7 +110,7 @@ export default function OneField({
);
} else if (!selection.qOneAndOnlyOne) {
Icon = (
<Grid item>
<Grid>
<IconButton
title={translator.get('Selection.Clear')}
onClick={(e) => {

View File

@@ -128,7 +128,6 @@ export default function SelectedFields({ api, app }) {
<Grid ref={containerRef} container gap={0} wrap="nowrap" style={{ height: '100%' }}>
{more.length > 0 && (
<Grid
item
style={{
position: 'relative',
maxWidth: '98px',
@@ -142,7 +141,6 @@ export default function SelectedFields({ api, app }) {
)}
{items.map((s, index) => (
<Grid
item
// eslint-disable-next-line react/no-array-index-key
key={`${s.states.join('::')}::${s.qField ?? s.name}${index}`}
style={{

View File

@@ -1,5 +1,5 @@
{
"scriptappy": "1.1.0",
"scriptappy": "1.1.3",
"info": {
"name": "@nebula.js/stardust:listbox",
"description": "nebula listbox properties definition",

View File

@@ -1,5 +1,5 @@
{
"scriptappy": "1.1.0",
"scriptappy": "1.1.3",
"info": {
"name": "@nebula.js/stardust",
"description": "Product and framework agnostic integration API for Qlik's Associative Engine",
@@ -673,6 +673,84 @@
}
},
"definitions": {
"Translator": {
"kind": "class",
"constructor": {
"kind": "function",
"params": []
},
"entries": {
"language": {
"description": "Returns current locale.",
"kind": "function",
"params": [
{
"name": "lang",
"description": "language Locale to updated the currentLocale value",
"optional": true,
"type": "string"
}
],
"returns": {
"description": "current locale.",
"type": "string"
}
},
"add": {
"description": "Registers a string in multiple locales",
"kind": "function",
"params": [
{
"name": "item",
"kind": "object",
"entries": {
"id": {
"type": "string"
},
"locale": {
"type": "object",
"generics": [
{
"type": "string"
},
{
"type": "string"
}
]
}
}
}
],
"examples": [
"translator.add({\n id: 'company.hello_user',\n locale: {\n 'en-US': 'Hello {0}',\n 'sv-SE': 'Hej {0}'\n }\n});\ntranslator.get('company.hello_user', ['John']); // Hello John"
]
},
"get": {
"description": "Translates a string for current locale.",
"kind": "function",
"params": [
{
"name": "str",
"description": "ID of the registered string.",
"type": "string"
},
{
"name": "args",
"description": "Values passed down for string interpolation.",
"optional": true,
"kind": "array",
"items": {
"type": "string"
}
}
],
"returns": {
"description": "The translated string.",
"type": "string"
}
}
}
},
"Component": {
"kind": "interface",
"entries": {
@@ -1486,6 +1564,167 @@
"const viz = await embed(app).render({\n element,\n type: 'barchart'\n});\nviz.destroy();"
]
},
"ActionToolbarElement": {
"availability": {
"since": "2.1.0"
},
"extends": [
{
"type": "HTMLElement"
}
],
"kind": "interface",
"entries": {
"className": {
"value": "'njs-action-toolbar-popover'",
"kind": "literal"
}
}
},
"ActionElement": {
"availability": {
"since": "2.0.0"
},
"extends": [
{
"type": "HTMLElement"
}
],
"kind": "interface",
"entries": {
"className": {
"value": "'njs-cell-action'",
"kind": "literal"
}
}
},
"CellElement": {
"extends": [
{
"type": "HTMLElement"
}
],
"kind": "interface",
"entries": {
"className": {
"value": "'njs-cell'",
"kind": "literal"
}
}
},
"CellBody": {
"extends": [
{
"type": "HTMLElement"
}
],
"kind": "interface",
"entries": {
"className": {
"value": "'njs-cell-body'",
"kind": "literal"
}
}
},
"CellFooter": {
"availability": {
"since": "2.0.0"
},
"extends": [
{
"type": "HTMLElement"
}
],
"kind": "interface",
"entries": {
"className": {
"value": "'njs-cell-footer'",
"kind": "literal"
}
}
},
"CellTitle": {
"availability": {
"since": "2.0.0"
},
"extends": [
{
"type": "HTMLElement"
}
],
"kind": "interface",
"entries": {
"className": {
"value": "'njs-cell-title'",
"kind": "literal"
}
}
},
"CellSubTitle": {
"availability": {
"since": "2.0.0"
},
"extends": [
{
"type": "HTMLElement"
}
],
"kind": "interface",
"entries": {
"className": {
"value": "'njs-cell-sub-title'",
"kind": "literal"
}
}
},
"SheetElement": {
"stability": "experimental",
"availability": {
"since": "3.1.0"
},
"extends": [
{
"type": "HTMLElement"
}
],
"kind": "interface",
"entries": {
"className": {
"value": "'njs-sheet'",
"kind": "literal"
}
}
},
"VizElementAttributes": {
"extends": [
{
"type": "NamedNodeMap"
}
],
"kind": "interface",
"entries": {
"data-render-count": {
"type": "string"
}
}
},
"VizElement": {
"extends": [
{
"type": "HTMLElement"
}
],
"kind": "interface",
"entries": {
"attributes": {
"type": "#/definitions/VizElementAttributes"
},
"className": {
"value": "'njs-viz'",
"kind": "literal"
}
}
},
"Flags": {
"kind": "interface",
"entries": {
@@ -2056,167 +2295,6 @@
"const navigation = useNavigation();\n//...\nuseEffect(() => {\n const onSheetChanged = () => {\n // do something\n };\n if (navigation?.addListener) {\n navigation.addListener(\"sheetChanged\", onSheetChanged);\n }\n return () => {\n if (navigation?.removeListener) {\n navigation.removeListener(\"sheetChanged\", onSheetChanged);\n }\n };\n}, [navigation]);\n\nconst onSheetClick = (sheetId: string) => {\n navigation?.goToSheet(sheetId);\n};"
]
},
"ActionToolbarElement": {
"availability": {
"since": "2.1.0"
},
"extends": [
{
"type": "HTMLElement"
}
],
"kind": "interface",
"entries": {
"className": {
"value": "'njs-action-toolbar-popover'",
"kind": "literal"
}
}
},
"ActionElement": {
"availability": {
"since": "2.0.0"
},
"extends": [
{
"type": "HTMLElement"
}
],
"kind": "interface",
"entries": {
"className": {
"value": "'njs-cell-action'",
"kind": "literal"
}
}
},
"CellElement": {
"extends": [
{
"type": "HTMLElement"
}
],
"kind": "interface",
"entries": {
"className": {
"value": "'njs-cell'",
"kind": "literal"
}
}
},
"CellBody": {
"extends": [
{
"type": "HTMLElement"
}
],
"kind": "interface",
"entries": {
"className": {
"value": "'njs-cell-body'",
"kind": "literal"
}
}
},
"CellFooter": {
"availability": {
"since": "2.0.0"
},
"extends": [
{
"type": "HTMLElement"
}
],
"kind": "interface",
"entries": {
"className": {
"value": "'njs-cell-footer'",
"kind": "literal"
}
}
},
"CellTitle": {
"availability": {
"since": "2.0.0"
},
"extends": [
{
"type": "HTMLElement"
}
],
"kind": "interface",
"entries": {
"className": {
"value": "'njs-cell-title'",
"kind": "literal"
}
}
},
"CellSubTitle": {
"availability": {
"since": "2.0.0"
},
"extends": [
{
"type": "HTMLElement"
}
],
"kind": "interface",
"entries": {
"className": {
"value": "'njs-cell-sub-title'",
"kind": "literal"
}
}
},
"SheetElement": {
"stability": "experimental",
"availability": {
"since": "3.1.0"
},
"extends": [
{
"type": "HTMLElement"
}
],
"kind": "interface",
"entries": {
"className": {
"value": "'njs-sheet'",
"kind": "literal"
}
}
},
"VizElementAttributes": {
"extends": [
{
"type": "NamedNodeMap"
}
],
"kind": "interface",
"entries": {
"data-render-count": {
"type": "string"
}
}
},
"VizElement": {
"extends": [
{
"type": "HTMLElement"
}
],
"kind": "interface",
"entries": {
"attributes": {
"type": "#/definitions/VizElementAttributes"
},
"className": {
"value": "'njs-viz'",
"kind": "literal"
}
}
},
"Visualization": {
"description": "The entry point for defining a visualization.",
"kind": "interface",
@@ -2749,84 +2827,6 @@
}
}
},
"Translator": {
"kind": "class",
"constructor": {
"kind": "function",
"params": []
},
"entries": {
"language": {
"description": "Returns current locale.",
"kind": "function",
"params": [
{
"name": "lang",
"description": "language Locale to updated the currentLocale value",
"optional": true,
"type": "string"
}
],
"returns": {
"description": "current locale.",
"type": "string"
}
},
"add": {
"description": "Registers a string in multiple locales",
"kind": "function",
"params": [
{
"name": "item",
"kind": "object",
"entries": {
"id": {
"type": "string"
},
"locale": {
"type": "object",
"generics": [
{
"type": "string"
},
{
"type": "string"
}
]
}
}
}
],
"examples": [
"translator.add({\n id: 'company.hello_user',\n locale: {\n 'en-US': 'Hello {0}',\n 'sv-SE': 'Hej {0}'\n }\n});\ntranslator.get('company.hello_user', ['John']); // Hello John"
]
},
"get": {
"description": "Translates a string for current locale.",
"kind": "function",
"params": [
{
"name": "str",
"description": "ID of the registered string.",
"type": "string"
},
{
"name": "args",
"description": "Values passed down for string interpolation.",
"optional": true,
"kind": "array",
"items": {
"type": "string"
}
}
],
"returns": {
"description": "The translated string.",
"type": "string"
}
}
}
},
"Theme": {
"kind": "class",
"constructor": {

View File

@@ -1,8 +1,8 @@
{
"module": "esm/index.js",
"peerDependencies": {
"@mui/material": "^6.5.0",
"@mui/icons-material": "^6.5.0",
"@mui/material": "^7.3.9",
"@mui/icons-material": "^7.3.9",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"react": "^17.0.2 || ^18.1.0",

View File

@@ -43,8 +43,8 @@
"devDependencies": {
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@mui/icons-material": "^6.5.0",
"@mui/material": "^6.5.0",
"@mui/icons-material": "^7.3.9",
"@mui/material": "^7.3.9",
"@nebula.js/conversion": "^6.7.0",
"@nebula.js/enigma-mocker": "^6.7.0",
"@nebula.js/locale": "^6.7.0",
@@ -52,9 +52,9 @@
"@nebula.js/supernova": "^6.7.0",
"@nebula.js/theme": "^6.7.0",
"@nebula.js/ui": "^6.7.0",
"@qlik/api": "2.4.1",
"@scriptappy/cli": "0.10.1",
"@scriptappy/from-jsdoc": "0.19.1",
"@qlik/api": "2.5.0",
"@scriptappy/cli": "0.10.4",
"@scriptappy/from-jsdoc": "0.19.4",
"@scriptappy/to-dts": "1.0.0",
"extend": "3.0.2",
"node-event-emitter": "0.0.1",

View File

@@ -243,6 +243,33 @@ export namespace EnigmaMocker {
}
declare namespace stardust {
class Translator {
constructor();
/**
* Returns current locale.
* @param lang language Locale to updated the currentLocale value
*/
language(lang?: string): string;
/**
* Registers a string in multiple locales
* @param item
*/
add(item: {
id: string;
locale: object;
}): void;
/**
* Translates a string for current locale.
* @param str ID of the registered string.
* @param args Values passed down for string interpolation.
*/
get(str: string, args?: string[]): string;
}
interface Component {
key: string;
}
@@ -478,6 +505,47 @@ declare namespace stardust {
}
interface ActionToolbarElement extends HTMLElement{
className: "njs-action-toolbar-popover";
}
interface ActionElement extends HTMLElement{
className: "njs-cell-action";
}
interface CellElement extends HTMLElement{
className: "njs-cell";
}
interface CellBody extends HTMLElement{
className: "njs-cell-body";
}
interface CellFooter extends HTMLElement{
className: "njs-cell-footer";
}
interface CellTitle extends HTMLElement{
className: "njs-cell-title";
}
interface CellSubTitle extends HTMLElement{
className: "njs-cell-sub-title";
}
interface SheetElement extends HTMLElement{
className: "njs-sheet";
}
interface VizElementAttributes extends NamedNodeMap{
"data-render-count": string;
}
interface VizElement extends HTMLElement{
attributes: stardust.VizElementAttributes;
className: "njs-viz";
}
interface Flags {
/**
* Checks whether the specified flag is enabled.
@@ -650,47 +718,6 @@ declare namespace stardust {
}
interface ActionToolbarElement extends HTMLElement{
className: "njs-action-toolbar-popover";
}
interface ActionElement extends HTMLElement{
className: "njs-cell-action";
}
interface CellElement extends HTMLElement{
className: "njs-cell";
}
interface CellBody extends HTMLElement{
className: "njs-cell-body";
}
interface CellFooter extends HTMLElement{
className: "njs-cell-footer";
}
interface CellTitle extends HTMLElement{
className: "njs-cell-title";
}
interface CellSubTitle extends HTMLElement{
className: "njs-cell-sub-title";
}
interface SheetElement extends HTMLElement{
className: "njs-sheet";
}
interface VizElementAttributes extends NamedNodeMap{
"data-render-count": string;
}
interface VizElement extends HTMLElement{
attributes: stardust.VizElementAttributes;
className: "njs-viz";
}
/**
* The entry point for defining a visualization.
*/
@@ -837,33 +864,6 @@ declare namespace stardust {
removed?: stardust.fieldTargetRemovedCallback<T>;
}
class Translator {
constructor();
/**
* Returns current locale.
* @param lang language Locale to updated the currentLocale value
*/
language(lang?: string): string;
/**
* Registers a string in multiple locales
* @param item
*/
add(item: {
id: string;
locale: object;
}): void;
/**
* Translates a string for current locale.
* @param str ID of the registered string.
* @param args Values passed down for string interpolation.
*/
get(str: string, args?: string[]): string;
}
class Theme {
constructor();

View File

@@ -232,4 +232,43 @@ describe('JSON-Patch', () => {
});
});
});
describe('Security - Prototype Pollution', () => {
test('apply throws for __proto__ as the final key', () => {
const patches = [{ op: 'add', path: '/__proto__', value: { polluted: true } }];
expect(() => JSONPatch.apply(patchee, patches)).toThrow();
expect({}.polluted).toBeUndefined();
});
test('apply throws for constructor as the final key', () => {
const patches = [{ op: 'add', path: '/constructor', value: { polluted: true } }];
expect(() => JSONPatch.apply(patchee, patches)).toThrow();
});
test('apply throws for prototype as the final key', () => {
const patches = [{ op: 'add', path: '/prototype', value: { polluted: true } }];
expect(() => JSONPatch.apply(patchee, patches)).toThrow();
});
test('apply throws for __proto__ in the middle of a path', () => {
const patches = [{ op: 'add', path: '/__proto__/polluted', value: true }];
expect(() => JSONPatch.apply(patchee, patches)).toThrow();
expect({}.polluted).toBeUndefined();
});
test('apply throws for __proto__ in move patch from path', () => {
const patches = [{ op: 'move', path: '/simpleString', from: '/__proto__' }];
expect(() => JSONPatch.apply(patchee, patches)).toThrow();
});
test('apply does not pollute Object.prototype via __proto__ path', () => {
const before = Object.prototype.polluted;
try {
JSONPatch.apply(patchee, [{ op: 'add', path: '/__proto__', value: { polluted: true } }]);
} catch (e) {
// expected to throw
}
expect(Object.prototype.polluted).toBe(before);
});
});
});

View File

@@ -41,6 +41,18 @@ function isSpecialProperty(obj, key) {
return isFunction(obj[key]) || key.substring(0, 2) === '$$' || key.substring(0, 1) === '_';
}
/**
* Checks whether a key is safe to use as a property name to prevent
* prototype pollution attacks.
*
* @private
* @param {String} key The key to check
* @returns {Boolean} Whether the key is safe to use
*/
function isSafeKey(key) {
return key !== '__proto__' && key !== 'constructor' && key !== 'prototype';
}
/**
* Finds the parent object from a JSON-Pointer ("/foo/bar/baz" = "bar" is "baz" parent),
* also creates the object structure needed.
@@ -55,9 +67,9 @@ function getParent(data, str) {
const parts = str.substring(1).split(seperator).slice(0, -1);
let numPart;
parts.forEach((part, i) => {
if (i === parts.length) {
return;
parts.forEach((part) => {
if (!isSafeKey(part)) {
throw new Error(`Unsafe key in path: ${part}`);
}
numPart = +part;
const newPart = !isNaN(numPart) ? [] : {};
@@ -274,6 +286,11 @@ JSONPatch.apply = function apply(original, patches) {
let target = key && isNaN(+key) ? parent[key] : parent[+key] || parent;
const from = patch.from ? patch.from.split('/').splice(-1)[0] : null;
if (!isSafeKey(key) || (from !== null && !isSafeKey(from))) {
const unsafeKey = !isSafeKey(key) ? key : from;
throw new Error(`Unsafe key in patch path: ${unsafeKey}`);
}
if (patch.path === '/') {
parent = null;
target = original;

View File

@@ -17,8 +17,8 @@ import CSSColors from './css-colors';
// color formats
const rgb = /^rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)$/i;
const rgba = /^rgba\((\d{1,3}),(\d{1,3}),(\d{1,3}),(\d(\.\d+)?)\)$/i;
const hex = /^#([A-f0-9]{2})([A-f0-9]{2})([A-f0-9]{2})$/i;
const hexShort = /^#([A-f0-9])([A-f0-9])([A-f0-9])$/i;
const hex = /^#([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})$/i;
const hexShort = /^#([A-F0-9])([A-F0-9])([A-F0-9])$/i;
const hsl = /^hsl\(\s*(\d+(\.\d+)?)\s*,\s*(\d+(\.\d+)?%?)\s*,\s*(\d+(\.\d+)?%?)\s*\)$/i;
const hsla = /^hsla\(\s*(\d+(\.\d+)?)\s*,\s*(\d+(\.\d+)?%?)\s*,\s*(\d+(\.\d+)?%?)\s*,(\d(\.\d+)?)\)$/i;
const { floor } = Math;
@@ -825,11 +825,11 @@ export default class Color {
r = parseInt(matches[1], 10);
g = parseInt(matches[2], 10);
b = parseInt(matches[3], 10);
} else if ((matches = /^#([A-f0-9]{2})([A-f0-9]{2})([A-f0-9]{2})$/i.exec(colorString))) {
} else if ((matches = /^#([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})$/i.exec(colorString))) {
r = parseInt(matches[1], 16);
g = parseInt(matches[2], 16);
b = parseInt(matches[3], 16);
} else if ((matches = /^#([A-f0-9])([A-f0-9])([A-f0-9])$/i.exec(colorString))) {
} else if ((matches = /^#([A-F0-9])([A-F0-9])([A-F0-9])$/i.exec(colorString))) {
r = parseInt(matches[1] + matches[1], 16);
g = parseInt(matches[2] + matches[2], 16);
b = parseInt(matches[3] + matches[3], 16);

View File

@@ -24,7 +24,7 @@
"dependencies": {
"@babel/cli": "7.28.6",
"@babel/core": "7.29.0",
"@babel/preset-env": "7.29.0",
"@babel/preset-env": "7.29.2",
"@babel/preset-react": "7.28.5",
"@babel/preset-typescript": "7.28.5",
"@qlik/browserslist-config": "^3.0.0",

View File

@@ -30,7 +30,7 @@
"dependencies": {
"@babel/cli": "7.28.6",
"@babel/core": "7.29.0",
"@babel/preset-env": "7.29.0",
"@babel/preset-env": "7.29.2",
"@nebula.js/stardust": "^6.7.0",
"@rollup/plugin-babel": "7.0.0",
"@rollup/plugin-commonjs": "29.0.2",

View File

@@ -46,28 +46,28 @@
"extend": "3.0.2",
"html-webpack-plugin": "5.6.6",
"portfinder": "1.0.38",
"puppeteer": "24.38.0",
"puppeteer": "24.40.0",
"regenerator-runtime": "0.14.1",
"source-map-loader": "5.0.0",
"webpack": "5.105.4",
"webpack-cli": "6.0.1",
"webpack-cli": "7.0.2",
"webpack-dev-server": "5.2.3",
"ws": "8.19.0",
"yargs": "18.0.0"
},
"devDependencies": {
"@babel/core": "7.29.0",
"@babel/preset-env": "7.29.0",
"@babel/preset-env": "7.29.2",
"@babel/preset-react": "7.28.5",
"@mui/material": "^6.5.0",
"@mui/system": "^6.5.0",
"@mui/material": "^7.3.9",
"@mui/system": "^7.3.9",
"@nebula.js/enigma-mocker": "^6.7.0",
"@nebula.js/nucleus": "^6.7.0",
"@nebula.js/snapshooter": "^6.7.0",
"@nebula.js/stardust": "^6.7.0",
"@nebula.js/ui": "^6.7.0",
"autosuggest-highlight": "3.3.4",
"babel-loader": "10.1.0",
"babel-loader": "10.1.1",
"d3-require": "1.3.0",
"enigma.js": "2.14.0",
"eslint-import-resolver-alias": "1.1.2",

View File

@@ -39,10 +39,10 @@
"@babel/helper-plugin-utils": "7.28.6",
"@babel/plugin-proposal-object-rest-spread": "7.20.7",
"@babel/plugin-transform-react-jsx": "7.28.6",
"@babel/preset-env": "7.29.0",
"@babel/preset-env": "7.29.2",
"@babel/preset-react": "7.28.5",
"@commitlint/cli": "20.4.3",
"@commitlint/config-conventional": "20.4.3",
"@commitlint/cli": "20.5.0",
"@commitlint/config-conventional": "20.5.0",
"@jest/globals": "^30.3.0",
"@playwright/test": "1.58.2",
"@rollup/plugin-babel": "7.0.0",
@@ -55,7 +55,7 @@
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^14.6.1",
"babel-loader": "10.1.0",
"babel-loader": "10.1.1",
"babel-plugin-istanbul": "7.0.1",
"body-parser": "2.2.2",
"cross-env": "10.1.0",
@@ -78,13 +78,13 @@
"jest-junit": "^16.0.0",
"jest-location-mock": "^3.0.0",
"jimp": "^1.6.0",
"lerna": "9.0.5",
"lint-staged": "^16.3.2",
"lerna": "9.0.7",
"lint-staged": "^16.4.0",
"mocha-junit-reporter": "2.2.1",
"picasso-plugin-q": "2.10.0",
"picasso.js": "2.10.0",
"prettier": "3.8.1",
"puppeteer": "24.38.0",
"puppeteer": "24.40.0",
"qix-faker": "0.3.0",
"react-is": "18.3.1",
"rollup": "4.59.0",
@@ -94,24 +94,18 @@
"yargs": "18.0.0"
},
"resolutions": {
"caniuse-lite": "1.0.30001777",
"caniuse-lite": "1.0.30001780",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-is": "18.3.1",
"@playwright/test": "1.58.2",
"minimatch@3.x": "^3.1.5",
"minimatch@5.x": "^5.1.9",
"minimatch@9.x": "^9.0.7",
"minimatch@10.x": "^10.2.4",
"minimatch@npm:3.1.4": "^3.1.5",
"minimatch@npm:9.0.3": "^9.0.7",
"tar@7.x": "^7.5.11",
"tar@npm:7.4.3": "^7.5.11",
"tar@npm:7.5.8": "^7.5.11",
"glob@10.x": "^10.5.0",
"glob@11.x": "^11.1.0",
"glob@npm:^10.2.2": "^10.5.0",
"glob@npm:^11.0.3": "^11.1.0"
"minimatch@npm:^3.0.0": "^3.1.5",
"minimatch@npm:^5.0.0": "^5.1.9",
"minimatch@npm:^9.0.0": "^9.0.7",
"minimatch@npm:^10.0.0": "^10.2.4",
"tar@npm:^7.0.0": "^7.5.11",
"glob@npm:^10.0.0": "^10.5.0",
"glob@npm:^11.0.0": "^11.1.0"
},
"workspaces": [
"packages/*",

View File

@@ -9,16 +9,16 @@
"peerDependencies": {
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@mui/icons-material": "^6.5.0",
"@mui/material": "^6.5.0",
"@mui/icons-material": "^7.3.9",
"@mui/material": "^7.3.9",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@mui/icons-material": "^6.5.0",
"@mui/material": "^6.5.0",
"@mui/icons-material": "^7.3.9",
"@mui/material": "^7.3.9",
"react": "18.3.1",
"react-dom": "18.3.1"
}

View File

@@ -6,4 +6,8 @@ module.exports = {
headless: true,
},
testDir: './test',
reporter: [
['html'],
['junit', { outputFile: `./test-results/${process.env.PLAYWRIGHT_JUNIT_OUTPUT_NAME || 'junit.xml'}` }],
],
};

View File

@@ -4,7 +4,7 @@ export default defineConfig({
reporter: [
['dot'],
['html', { outputFolder: './reports/html' }],
['junit', { outputFile: './test/mashup/reports/xml/report.xml' }],
['junit', { outputFile: './reports/xml/report.xml' }],
],
testDir: './',
globalSetup: './setup.cjs',

View File

@@ -4,7 +4,7 @@ export default defineConfig({
reporter: [
['dot'],
['html', { outputFolder: './reports/html' }],
['junit', { outputFile: './test/rendering/reports/xml/report.xml' }],
['junit', { outputFile: './reports/xml/report.xml' }],
],
testDir: './',
forbidOnly: !!process.env.CI,

1041
yarn.lock

File diff suppressed because it is too large Load Diff