Skip to content

Commit

Permalink
chore(scene): detect dynamic scenes missing their root entity
Browse files Browse the repository at this point in the history
  • Loading branch information
haweston committed May 24, 2024
1 parent c4a98a5 commit c56522e
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 4 deletions.
34 changes: 34 additions & 0 deletions packages/scene-composer/src/components/SceneLayers.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import * as React from 'react';
import { render } from '@testing-library/react';
import { useQuery } from '@tanstack/react-query';

import { getGlobalSettings } from '../common/GlobalSettings';
import { accessStore } from '../store';
import { processQueries } from '../utils/entityModelUtils/processQueries';
import { checkIfEntityExists } from '../utils/entityModelUtils/sceneUtils';
import { KnownSceneProperty } from '../interfaces';
import { LAYER_DEFAULT_REFRESH_INTERVAL } from '../utils/entityModelUtils/sceneLayerUtils';
import { SceneLayers } from './SceneLayers';
Expand All @@ -13,19 +15,31 @@ jest.mock('../utils/entityModelUtils/processQueries', () => ({
processQueries: jest.fn(),
}));

jest.mock('../utils/entityModelUtils/sceneUtils', () => ({
... jest.requireActual('../utils/entityModelUtils/sceneUtils'),
checkIfEntityExists: jest.fn(),
}));

jest.mock('@tanstack/react-query', () => ({
useQuery: jest.fn(),
}));

jest.mock('../common/GlobalSettings', () => ({
getGlobalSettings: jest.fn(() => ({})),
}));

describe('SceneLayers', () => {
const renderSceneNodesMock = jest.fn();
const isViewingMock = jest.fn();
const getScenePropertyMock = jest.fn();
const addMessagesMock = jest.fn();
const baseState = {
getSceneProperty: getScenePropertyMock,
renderSceneNodes: renderSceneNodesMock,
isViewing: isViewingMock,
addMessages: addMessagesMock,
};
const mockSceneMetadataModule = {};

beforeEach(() => {
jest.clearAllMocks();
Expand Down Expand Up @@ -146,4 +160,24 @@ describe('SceneLayers', () => {
expect(renderSceneNodesMock).toBeCalledTimes(1);
expect(renderSceneNodesMock).toBeCalledWith(['random']);
});

it('should detect no Scene Root Entity', async () => {
accessStore('default').setState(baseState);
const globalSettings = getGlobalSettings as jest.Mock;
globalSettings.mockImplementation(() => ({
twinMakerSceneMetadataModule: {},
}));
let queryFunction;
(useQuery as jest.Mock).mockImplementation(({ queryFn, ..._ }) => {
queryFunction = queryFn;
return { data: [] };
});
(checkIfEntityExists as jest.Mock).mockImplementation(() => { return false});
render(<SceneLayers />);
await queryFunction();

expect(processQueries as jest.Mock).toBeCalledTimes(1);
expect(renderSceneNodesMock).toBeCalledTimes(0);
expect(addMessagesMock).toBeCalledTimes(1);
});
});
34 changes: 30 additions & 4 deletions packages/scene-composer/src/components/SceneLayers.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import React, { useContext, useEffect } from 'react';
import React, { useCallback, useContext, useEffect } from 'react';
import { useQuery } from '@tanstack/react-query';
import { useIntl } from 'react-intl';

import { getGlobalSettings } from '../common/GlobalSettings';
import { sceneComposerIdContext } from '../common/sceneComposerIdContext';
import { accessStore } from '../store';
import { fetchSceneNodes } from '../utils/entityModelUtils/sceneUtils';
import { checkIfEntityExists, fetchSceneNodes } from '../utils/entityModelUtils/sceneUtils';
import { KnownSceneProperty } from '../interfaces';
import { DisplayMessageCategory } from '../store/internalInterfaces';

export const SceneLayers: React.FC = () => {
const { formatMessage } = useIntl();
const sceneComposerId = useContext(sceneComposerIdContext);
const isViewing = accessStore(sceneComposerId)((state) => state.isViewing());
const autoUpdateInterval = accessStore(sceneComposerId)(
Expand All @@ -18,6 +22,7 @@ export const SceneLayers: React.FC = () => {
const sceneRootEntityId = accessStore(sceneComposerId)((state) =>
state.getSceneProperty(KnownSceneProperty.SceneRootEntityId),
) as string;
const addMessages = accessStore(sceneComposerId)((state) => state.addMessages);

const nodes = useQuery({
enabled: !!sceneRootEntityId,
Expand All @@ -31,11 +36,32 @@ export const SceneLayers: React.FC = () => {
refetchOnWindowFocus: false,
});

const checkForSceneRootEntity = useCallback(async () => {
const sceneMetadataModule = getGlobalSettings().twinMakerSceneMetadataModule;
if (sceneMetadataModule) {
if (!(await checkIfEntityExists(sceneRootEntityId, sceneMetadataModule))) {
addMessages([
{
category: DisplayMessageCategory.Error,
messageText: formatMessage({
description: 'Scene Entity Error',
defaultMessage: 'Dynamic Scene is missing root scene entity',
}),
},
]);
}
}
}, [sceneRootEntityId, addMessages, formatMessage]);

useEffect(() => {
if (nodes.data) {
renderSceneNodes(nodes.data);
if (nodes.data.length > 0) {
renderSceneNodes(nodes.data);
} else {
checkForSceneRootEntity();
}
}
}, [nodes.data, renderSceneNodes]);
}, [nodes.data, renderSceneNodes, checkForSceneRootEntity]);

return <></>;
};
Original file line number Diff line number Diff line change
Expand Up @@ -1299,6 +1299,10 @@
"note": "Light Type in a dropdown menu",
"text": "Directional"
},
"ytZC0H": {
"note": "Scene Entity Error",
"text": "Dynamic Scene is missing root scene entity"
},
"z4V95/": {
"note": "Expandable Section title",
"text": "Camera"
Expand Down

0 comments on commit c56522e

Please sign in to comment.