Fix OS switching not working on tree view UI
This commit resolves a rendering bug in the tree view component. Previously, updating the tree collection prior to node updates led to rendering errors due to the presence of non-existent nodes in the new collection. Changes: - Implement manual control over the rendering process in tree view. This includes clearing the rendering queue and currently rendered nodes before updates, aligning the rendering process with the updated collection. - Add Cypress E2E tests to test switching between all operating systems and script views, ensuring no uncaught errors and preventing regression. - Replace hardcoded operating system lists in the download URL list view with a unified `getSupportedOsList()` method from the application, reducing duplication and simplifying future updates. - Rename `initial-nodes` to `nodes` in `TreeView.vue` to reflect their mutable nature. - Centralize the function for getting operating system names into `OperatingSystemNames.ts`, improving reusability in E2E tests.
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { type Ref, shallowRef } from 'vue';
|
||||
import {
|
||||
type Ref, shallowRef, watch, nextTick,
|
||||
} from 'vue';
|
||||
import { useGradualNodeRendering } from '@/presentation/components/Scripts/View/Tree/TreeView/Rendering/UseGradualNodeRendering';
|
||||
import { TreeRoot } from '@/presentation/components/Scripts/View/Tree/TreeView/TreeRoot/TreeRoot';
|
||||
import { TreeRootStub } from '@tests/unit/shared/Stubs/TreeRootStub';
|
||||
@@ -70,9 +72,9 @@ describe('useGradualNodeRendering', () => {
|
||||
.withOldState(new TreeNodeStateDescriptorStub().withVisibility(oldVisibilityState))
|
||||
.withNewState(new TreeNodeStateDescriptorStub().withVisibility(newVisibilityState));
|
||||
// act
|
||||
const strategy = builder.call();
|
||||
const { renderingStrategy } = builder.call();
|
||||
aggregatorStub.notifyChange(change);
|
||||
const actualRenderStatus = strategy.shouldRender(node);
|
||||
const actualRenderStatus = renderingStrategy.shouldRender(node);
|
||||
// assert
|
||||
expect(actualRenderStatus).to.equal(expectedRenderStatus);
|
||||
});
|
||||
@@ -186,11 +188,11 @@ describe('useGradualNodeRendering', () => {
|
||||
.withSubsequentBatchSize(subsequentBatchSize)
|
||||
.withDelayScheduler(delaySchedulerStub);
|
||||
// act
|
||||
const strategy = builder.call();
|
||||
const { renderingStrategy } = builder.call();
|
||||
Array.from({ length: schedulerTicks }).forEach(
|
||||
() => delaySchedulerStub.runNextScheduled(),
|
||||
);
|
||||
const actualRenderStatuses = nodes.map((node) => strategy.shouldRender(node));
|
||||
const actualRenderStatuses = nodes.map((node) => renderingStrategy.shouldRender(node));
|
||||
// expect
|
||||
expect(actualRenderStatuses).to.deep.equal(expectedRenderStatuses);
|
||||
});
|
||||
@@ -218,9 +220,9 @@ describe('useGradualNodeRendering', () => {
|
||||
const actualOrder = new Set<ReadOnlyTreeNode>();
|
||||
// act
|
||||
ordererStub.orderNodes = () => expectedNodes[0];
|
||||
const strategy = builder.call();
|
||||
const { renderingStrategy } = builder.call();
|
||||
const updateOrder = () => allNodes
|
||||
.filter((node) => strategy.shouldRender(node))
|
||||
.filter((node) => renderingStrategy.shouldRender(node))
|
||||
.forEach((node) => actualOrder.add(node));
|
||||
updateOrder();
|
||||
for (let i = 1; i < expectedNodes.length; i++) {
|
||||
@@ -247,6 +249,48 @@ describe('useGradualNodeRendering', () => {
|
||||
// assert
|
||||
expect(delaySchedulerStub.nextCallback).toBeUndefined();
|
||||
});
|
||||
describe('clearRenderingStates', () => {
|
||||
it('clears all nodes from rendering states', () => {
|
||||
// arrange
|
||||
const nodesStub = [new TreeNodeStub(), new TreeNodeStub()];
|
||||
const rendering = new UseGradualNodeRenderingBuilder()
|
||||
.withCurrentTreeNodes(new UseCurrentTreeNodesStub()
|
||||
.withQueryableNodes(new QueryableNodesStub().withFlattenedNodes(nodesStub)))
|
||||
.call();
|
||||
|
||||
// act
|
||||
rendering.clearRenderingStates();
|
||||
|
||||
// assert
|
||||
const isAnyRendered = nodesStub
|
||||
.map((node) => rendering.renderingStrategy.shouldRender(node))
|
||||
.some(Boolean);
|
||||
expect(isAnyRendered).to.equal(false);
|
||||
});
|
||||
});
|
||||
describe('notifyRenderingUpdates', () => {
|
||||
it('triggers Vue reactivity update', async () => {
|
||||
// arrange
|
||||
const nodes = createNodesWithVisibility(true, 1);
|
||||
const rendering = new UseGradualNodeRenderingBuilder()
|
||||
.withCurrentTreeNodes(new UseCurrentTreeNodesStub()
|
||||
.withQueryableNodes(new QueryableNodesStub().withFlattenedNodes(nodes)))
|
||||
.withInitialBatchSize(nodes.length)
|
||||
.call();
|
||||
let isVueReactivityTriggered = false;
|
||||
watch(() => rendering.renderingStrategy.shouldRender(nodes[0]), () => {
|
||||
isVueReactivityTriggered = true;
|
||||
});
|
||||
|
||||
// act
|
||||
rendering.clearRenderingStates();
|
||||
rendering.notifyRenderingUpdates();
|
||||
await nextTick();
|
||||
|
||||
// assert
|
||||
expect(isVueReactivityTriggered).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function createNodesWithVisibility(
|
||||
|
||||
Reference in New Issue
Block a user