codecharta-visualization 1.86.0 → 1.87.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/Dockerfile +1 -1
  2. package/app/app.module.ts +6 -2
  3. package/app/codeCharta/codeCharta.model.ts +1 -1
  4. package/app/codeCharta/state/store/dynamicSettings/dynamicSettings.splitter.ts +2 -2
  5. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/currentFocused.selector.ts +8 -0
  6. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.actions.ts +27 -7
  7. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.reducer.spec.ts +27 -11
  8. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.reducer.ts +11 -5
  9. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.selector.ts +4 -0
  10. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.service.spec.ts +2 -2
  11. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.service.ts +1 -1
  12. package/app/codeCharta/state/store/fileSettings/markedPackages/markedPackages.actions.ts +9 -10
  13. package/app/codeCharta/state/store/fileSettings/markedPackages/markedPackages.reducer.spec.ts +37 -7
  14. package/app/codeCharta/state/store/fileSettings/markedPackages/markedPackages.reducer.ts +7 -3
  15. package/app/codeCharta/state/store/fileSettings/markedPackages/util/findIndexOfMarkedPackageOrParent.spec.ts +39 -0
  16. package/app/codeCharta/state/store/fileSettings/markedPackages/util/findIndexOfMarkedPackageOrParent.ts +19 -0
  17. package/app/codeCharta/state/store/state.splitter.spec.ts +4 -4
  18. package/app/codeCharta/state/store.service.spec.ts +3 -3
  19. package/app/codeCharta/state/store.service.ts +5 -0
  20. package/app/codeCharta/ui/artificialIntelligence/__snapshots__/artificialIntelligence.component.spec.ts.snap +13 -16
  21. package/app/codeCharta/ui/artificialIntelligence/artificialIntelligence.component.html +4 -4
  22. package/app/codeCharta/ui/artificialIntelligence/artificialIntelligence.component.scss +0 -4
  23. package/app/codeCharta/ui/artificialIntelligence/artificialIntelligence.component.spec.ts +82 -52
  24. package/app/codeCharta/ui/artificialIntelligence/artificialIntelligence.component.ts +41 -101
  25. package/app/codeCharta/ui/codeMap/codeMap.actions.service.ts +1 -40
  26. package/app/codeCharta/ui/codeMap/codeMap.mouseEvent.service.ts +10 -16
  27. package/app/codeCharta/ui/colorPicker/colorPicker.component.html +16 -7
  28. package/app/codeCharta/ui/colorPicker/colorPicker.component.spec.ts +55 -16
  29. package/app/codeCharta/ui/colorPicker/colorPicker.component.ts +32 -1
  30. package/app/codeCharta/ui/colorPicker/colorPicker.module.ts +3 -1
  31. package/app/codeCharta/ui/customConfigs/customConfigs.component.html +21 -3
  32. package/app/codeCharta/ui/customConfigs/customConfigs.component.scss +1 -0
  33. package/app/codeCharta/ui/customConfigs/customConfigs.component.spec.ts +123 -2
  34. package/app/codeCharta/ui/customConfigs/customConfigs.component.ts +56 -2
  35. package/app/codeCharta/ui/labelledColorPicker/labelledColorPicker.component.html +21 -13
  36. package/app/codeCharta/ui/labelledColorPicker/labelledColorPicker.component.spec.ts +11 -24
  37. package/app/codeCharta/ui/labelledColorPicker/labelledColorPicker.component.ts +1 -40
  38. package/app/codeCharta/ui/labelledColorPicker/labelledColorPicker.module.ts +1 -2
  39. package/app/codeCharta/ui/legendPanel/legendMarkedPackages/legendMarkedPackages.component.ts +2 -2
  40. package/app/codeCharta/ui/nodeContextMenu/focusButtons/focusButtons.component.html +24 -0
  41. package/app/codeCharta/ui/nodeContextMenu/focusButtons/focusButtons.component.spec.ts +55 -0
  42. package/app/codeCharta/ui/nodeContextMenu/focusButtons/focusButtons.component.ts +38 -0
  43. package/app/codeCharta/ui/nodeContextMenu/focusButtons/focusButtons.module.ts +13 -0
  44. package/app/codeCharta/ui/nodeContextMenu/focusButtons/isNodeFocused.pipe.spec.ts +31 -0
  45. package/app/codeCharta/ui/nodeContextMenu/focusButtons/isNodeFocused.pipe.ts +25 -0
  46. package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.html +8 -4
  47. package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.component.ts +1 -21
  48. package/app/codeCharta/ui/nodeContextMenu/markFolderColorPicker/markFolderColorPicker.module.ts +1 -2
  49. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.html +2 -12
  50. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.scss +3 -1
  51. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.spec.ts +28 -125
  52. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.component.ts +29 -55
  53. package/app/codeCharta/ui/nodeContextMenu/nodeContextMenu.module.ts +2 -0
  54. package/app/codeCharta/ui/ui.ts +0 -2
  55. package/app/codeCharta/util/algorithm/streetLayout/strip/strip.ts +2 -2
  56. package/app/codeCharta/util/algorithm/streetLayout/treeMap.ts +1 -1
  57. package/app/codeCharta/util/algorithm/treeMapLayout/treeMapGenerator.spec.ts +1 -1
  58. package/app/codeCharta/util/algorithm/treeMapLayout/treeMapHelper.spec.ts +2 -2
  59. package/app/codeCharta/util/algorithm/treeMapLayout/treeMapHelper.ts +1 -1
  60. package/app/codeCharta/util/customConfigBuilder.ts +1 -1
  61. package/app/codeCharta/util/dataMocks.ts +2 -2
  62. package/app/codeCharta/util/fileExtensionCalculator.ts +1 -1
  63. package/dist/webpack/bundle.js +963 -934
  64. package/dist/webpack/bundle.js.map +1 -1
  65. package/package.json +6 -5
  66. package/app/codeCharta/state/store/dynamicSettings/focusedNodePath/focusedNodePath.splitter.ts +0 -8
  67. package/app/codeCharta/ui/codeMap/codeMap.actions.service.spec.ts +0 -147
  68. package/app/codeCharta/ui/unfocusButton/unfocusButton.component.html +0 -15
  69. package/app/codeCharta/ui/unfocusButton/unfocusButton.component.scss +0 -5
  70. package/app/codeCharta/ui/unfocusButton/unfocusButton.component.spec.ts +0 -106
  71. package/app/codeCharta/ui/unfocusButton/unfocusButton.component.ts +0 -62
  72. package/app/codeCharta/ui/unfocusButton/unfocusButton.module.ts +0 -7
@@ -0,0 +1,55 @@
1
+ import { render } from "@testing-library/angular"
2
+ import { TestBed } from "@angular/core/testing"
3
+
4
+ import { FocusButtonsComponent } from "./focusButtons.component"
5
+ import { FocusButtonsModule } from "./focusButtons.module"
6
+ import { focusedNodePathSelector } from "../../../state/store/dynamicSettings/focusedNodePath/focusedNodePath.selector"
7
+
8
+ jest.mock("../../../state/store/dynamicSettings/focusedNodePath/focusedNodePath.selector", () => ({
9
+ focusedNodePathSelector: jest.fn()
10
+ }))
11
+ const mockedFocusedNodePathSelector = focusedNodePathSelector as jest.Mock
12
+
13
+ describe("focusButton", () => {
14
+ beforeEach(() => {
15
+ TestBed.configureTestingModule({
16
+ imports: [FocusButtonsModule]
17
+ })
18
+ })
19
+ it("should render only 'focus' button if neither node nor one of its parents is focused", async () => {
20
+ const { container } = await render(FocusButtonsComponent, {
21
+ excludeComponentDeclaration: true,
22
+ componentProperties: { codeMapNode: { path: "/root/foo" } }
23
+ })
24
+
25
+ const buttons = container.querySelectorAll("button")
26
+ expect(buttons.length).toBe(1)
27
+ expect(buttons[0].textContent).toMatch(" FOCUS ")
28
+ })
29
+
30
+ it("should render 'focus' and 'unfocus parent' buttons if a parent is focused", async () => {
31
+ mockedFocusedNodePathSelector.mockImplementation(() => ["/root/foo"])
32
+ const { container } = await render(FocusButtonsComponent, {
33
+ excludeComponentDeclaration: true,
34
+ componentProperties: { codeMapNode: { path: "/root/foo/bar" } }
35
+ })
36
+
37
+ const buttons = container.querySelectorAll("button")
38
+ expect(buttons.length).toBe(2)
39
+ expect(buttons[0].textContent).toMatch(" FOCUS ")
40
+ expect(buttons[1].textContent).toMatch("UNFOCUS PARENT")
41
+ })
42
+
43
+ it("should render 'unfocus' and 'unfocus all' buttons if node is focused and there was node focused before", async () => {
44
+ mockedFocusedNodePathSelector.mockImplementation(() => ["/root/foo", "/root/bar"])
45
+ const { container } = await render(FocusButtonsComponent, {
46
+ excludeComponentDeclaration: true,
47
+ componentProperties: { codeMapNode: { path: "/root/foo" } }
48
+ })
49
+
50
+ const buttons = container.querySelectorAll("button")
51
+ expect(buttons.length).toBe(2)
52
+ expect(buttons[0].textContent).toMatch("UNFOCUS")
53
+ expect(buttons[1].textContent).toMatch("UNFOCUS ALL")
54
+ })
55
+ })
@@ -0,0 +1,38 @@
1
+ import { Component, Inject, Input } from "@angular/core"
2
+ import { Observable, map } from "rxjs"
3
+
4
+ import { CodeMapNode } from "../../../codeCharta.model"
5
+ import { Store } from "../../../state/angular-redux/store"
6
+ import { currentFocusedNodePathSelector } from "../../../state/store/dynamicSettings/focusedNodePath/currentFocused.selector"
7
+ import { focusNode, unfocusAllNodes, unfocusNode } from "../../../state/store/dynamicSettings/focusedNodePath/focusedNodePath.actions"
8
+ import { focusedNodePathSelector } from "../../../state/store/dynamicSettings/focusedNodePath/focusedNodePath.selector"
9
+
10
+ @Component({
11
+ selector: "cc-focus-buttons",
12
+ template: require("./focusButtons.component.html")
13
+ })
14
+ export class FocusButtonsComponent {
15
+ @Input() codeMapNode: Pick<CodeMapNode, "path">
16
+
17
+ currentFocusedNodePath$: Observable<string | undefined>
18
+ hasPreviousFocusedNodePath$: Observable<boolean>
19
+
20
+ constructor(@Inject(Store) private store: Store) {
21
+ this.currentFocusedNodePath$ = this.store.select(currentFocusedNodePathSelector)
22
+ this.hasPreviousFocusedNodePath$ = this.store
23
+ .select(focusedNodePathSelector)
24
+ .pipe(map(focusedNodePaths => focusedNodePaths.length > 1))
25
+ }
26
+
27
+ handleFocusNodeClicked() {
28
+ this.store.dispatch(focusNode(this.codeMapNode.path))
29
+ }
30
+
31
+ handleUnfocusNodeClicked() {
32
+ this.store.dispatch(unfocusNode())
33
+ }
34
+
35
+ handleUnfocusAllNodesClicked() {
36
+ this.store.dispatch(unfocusAllNodes())
37
+ }
38
+ }
@@ -0,0 +1,13 @@
1
+ import { CommonModule } from "@angular/common"
2
+ import { NgModule } from "@angular/core"
3
+
4
+ import { MaterialModule } from "../../../../material/material.module"
5
+ import { FocusButtonsComponent } from "./focusButtons.component"
6
+ import { IsNodeFocusedPipe } from "./isNodeFocused.pipe"
7
+
8
+ @NgModule({
9
+ imports: [CommonModule, MaterialModule],
10
+ declarations: [FocusButtonsComponent, IsNodeFocusedPipe],
11
+ exports: [FocusButtonsComponent]
12
+ })
13
+ export class FocusButtonsModule {}
@@ -0,0 +1,31 @@
1
+ import { IsNodeFocusedPipe } from "./isNodeFocused.pipe"
2
+
3
+ describe("isNodeFocused pipe", () => {
4
+ it("should return not focused if there is no focused node path", () => {
5
+ expect(new IsNodeFocusedPipe().transform(undefined, { path: "/root" })).toEqual({
6
+ isNodeFocused: false,
7
+ isParentFocused: false
8
+ })
9
+ })
10
+
11
+ it("should return not focused if focused node path isn't given node nor a parent", () => {
12
+ expect(new IsNodeFocusedPipe().transform("root/foo", { path: "/root/bar" })).toEqual({
13
+ isNodeFocused: false,
14
+ isParentFocused: false
15
+ })
16
+ })
17
+
18
+ it("should mark node as focused", () => {
19
+ expect(new IsNodeFocusedPipe().transform("/root/foo", { path: "/root/foo" })).toEqual({
20
+ isNodeFocused: true,
21
+ isParentFocused: false
22
+ })
23
+ })
24
+
25
+ it("should mark parent as focused", () => {
26
+ expect(new IsNodeFocusedPipe().transform("/root/foo", { path: "/root/foo/bar" })).toEqual({
27
+ isNodeFocused: false,
28
+ isParentFocused: true
29
+ })
30
+ })
31
+ })
@@ -0,0 +1,25 @@
1
+ import { Pipe, PipeTransform } from "@angular/core"
2
+
3
+ import { CodeMapNode } from "../../../codeCharta.model"
4
+
5
+ type IsNodeFocusedType = {
6
+ isNodeFocused: boolean
7
+ isParentFocused: boolean
8
+ }
9
+
10
+ @Pipe({ name: "isNodeFocused" })
11
+ export class IsNodeFocusedPipe implements PipeTransform {
12
+ transform(focusedNodePath: string | undefined, node: Pick<CodeMapNode, "path">): IsNodeFocusedType {
13
+ if (!focusedNodePath)
14
+ return {
15
+ isNodeFocused: false,
16
+ isParentFocused: false
17
+ }
18
+
19
+ const isNodeFocused = focusedNodePath === node.path
20
+ return {
21
+ isNodeFocused,
22
+ isParentFocused: !isNodeFocused && node.path.startsWith(focusedNodePath)
23
+ }
24
+ }
25
+ }
@@ -1,5 +1,9 @@
1
- <div class="cc-color-picker-trigger fa fa-paint-brush" [matMenuTriggerFor]="menu" #colorPickerMenuTrigger="matMenuTrigger"></div>
1
+ <cc-color-picker
2
+ [hexColor]="'#ff0000'"
3
+ (onColorChange)="markFolder($event)"
4
+ [triggerTemplate]="colorPickerTriggerTemplate"
5
+ ></cc-color-picker>
2
6
 
3
- <mat-menu #menu="matMenu" [hasBackdrop]="false" class="cc-color-picker-menu">
4
- <cc-color-picker [hexColor]="'#ff0000'" (onColorChange)="markFolder($event)"></cc-color-picker>
5
- </mat-menu>
7
+ <ng-template #colorPickerTriggerTemplate>
8
+ <div class="cc-color-picker-trigger fa fa-paint-brush"></div>
9
+ </ng-template>
@@ -1,7 +1,5 @@
1
- import { Component, HostListener, Input, ViewChild } from "@angular/core"
2
- import { MatMenuTrigger } from "@angular/material/menu"
3
-
4
1
  import "./markFolderColorPicker.component.scss"
2
+ import { Component, Input } from "@angular/core"
5
3
 
6
4
  @Component({
7
5
  selector: "cc-mark-folder-color-picker",
@@ -9,22 +7,4 @@ import "./markFolderColorPicker.component.scss"
9
7
  })
10
8
  export class MarkFolderColorPickerComponent {
11
9
  @Input() markFolder: (hexColor: string) => void
12
-
13
- @ViewChild("colorPickerMenuTrigger") colorPickerMenuTrigger: MatMenuTrigger
14
-
15
- private isClickInside = false
16
-
17
- @HostListener("click")
18
- onClick() {
19
- this.isClickInside = true
20
- }
21
-
22
- @HostListener("document:click")
23
- handleDocumentClick() {
24
- if (!this.isClickInside && this.colorPickerMenuTrigger && this.colorPickerMenuTrigger.menuOpen) {
25
- this.colorPickerMenuTrigger.closeMenu()
26
- }
27
-
28
- this.isClickInside = false
29
- }
30
10
  }
@@ -1,12 +1,11 @@
1
1
  import { CommonModule } from "@angular/common"
2
2
  import { NgModule } from "@angular/core"
3
3
 
4
- import { MaterialModule } from "../../../../material/material.module"
5
4
  import { ColorPickerModule } from "../../colorPicker/colorPicker.module"
6
5
  import { MarkFolderColorPickerComponent } from "./markFolderColorPicker.component"
7
6
 
8
7
  @NgModule({
9
- imports: [CommonModule, MaterialModule, ColorPickerModule],
8
+ imports: [CommonModule, ColorPickerModule],
10
9
  declarations: [MarkFolderColorPickerComponent],
11
10
  exports: [MarkFolderColorPickerComponent]
12
11
  })
@@ -21,18 +21,8 @@
21
21
  <md-button ng-disabled="true" title="{{ $ctrl._viewModel.nodePath }}">
22
22
  {{ $ctrl._viewModel.lastPartOfNodePath }}
23
23
  </md-button>
24
- <md-button
25
- ng-show="!$ctrl.isNodeFocused()"
26
- ng-click="$ctrl.focusNode()"
27
- id="focus-button"
28
- title="Only show selected nodes with children-nodes"
29
- ><i class="fa fa-bullseye"></i> Focus</md-button
30
- >
31
- <unfocus-button-component
32
- is-node-focused="$ctrl._viewModel.isNodeFocused"
33
- is-parent-focused="$ctrl._viewModel.isParentFocused"
34
- ng-show="$ctrl.isNodeOrParentFocused()"
35
- ></unfocus-button-component>
24
+
25
+ <cc-focus-buttons [code-map-node]="$ctrl._viewModel.codeMapNode"></cc-focus-buttons>
36
26
  <md-button
37
27
  ng-if="!$ctrl._viewModel.codeMapNode.isFlattened"
38
28
  ng-click="$ctrl.flattenNode()"
@@ -20,7 +20,9 @@ node-context-menu-component {
20
20
  background-repeat: no-repeat no-repeat;
21
21
  pointer-events: none;
22
22
  }
23
- .md-button:not(.colorButton) {
23
+ .md-button:not(.colorButton),
24
+ [mat-button] {
25
+ width: 100%;
24
26
  text-align: left;
25
27
  margin-top: 0;
26
28
  line-height: 30px;
@@ -2,7 +2,6 @@ import "./nodeContextMenu.module"
2
2
 
3
3
  import { IRootScopeService, IWindowService } from "angular"
4
4
  import { instantiateModule, getService } from "../../../../mocks/ng.mockhelper"
5
- import { CodeMapActionsService } from "../codeMap/codeMap.actions.service"
6
5
  import { NodeContextMenuController } from "./nodeContextMenu.component"
7
6
  import {
8
7
  CODE_MAP_BUILDING,
@@ -18,9 +17,7 @@ import { StoreService } from "../../state/store.service"
18
17
  import { setMarkedPackages } from "../../state/store/fileSettings/markedPackages/markedPackages.actions"
19
18
  import { BlacklistType, MarkedPackage, NodeType } from "../../codeCharta.model"
20
19
  import { addBlacklistItem } from "../../state/store/fileSettings/blacklist/blacklist.actions"
21
- import { focusNode, unfocusNode } from "../../state/store/dynamicSettings/focusedNodePath/focusedNodePath.actions"
22
20
  import { NodeDecorator } from "../../util/nodeDecorator"
23
- import { CodeMapMouseEventService } from "../codeMap/codeMap.mouseEvent.service"
24
21
  import { ThreeSceneService } from "../codeMap/threeViewer/threeSceneService"
25
22
  import { CodeMapBuilding } from "../codeMap/rendering/codeMapBuilding"
26
23
  import { setIdToBuilding } from "../../state/store/lookUp/idToBuilding/idToBuilding.actions"
@@ -33,7 +30,6 @@ describe("nodeContextMenuController", () => {
33
30
  let $window: IWindowService
34
31
  let $rootScope: IRootScopeService
35
32
  let storeService: StoreService
36
- let codeMapActionsService: CodeMapActionsService
37
33
  let codeMapPreRenderService: CodeMapPreRenderService
38
34
  let threeSceneService: ThreeSceneService
39
35
  let dialogService: DialogService
@@ -43,11 +39,9 @@ describe("nodeContextMenuController", () => {
43
39
  restartSystem()
44
40
  mockElement()
45
41
  mockWindow()
46
- withMockedCodeMapActionService()
47
42
  withMockedCodeMapPreRenderService()
48
43
  withMockedThreeSceneService()
49
44
  rebuildController()
50
- withMockedHideNodeContextMenuMethod()
51
45
 
52
46
  NodeDecorator.decorateMapWithPathAttribute(TEST_DELTA_MAP_A)
53
47
  })
@@ -58,7 +52,6 @@ describe("nodeContextMenuController", () => {
58
52
  $window = getService<IWindowService>("$window")
59
53
  $rootScope = getService<IRootScopeService>("$rootScope")
60
54
  storeService = getService<StoreService>("storeService")
61
- codeMapActionsService = getService<CodeMapActionsService>("codeMapActionsService")
62
55
  codeMapPreRenderService = getService<CodeMapPreRenderService>("codeMapPreRenderService")
63
56
  threeSceneService = getService<ThreeSceneService>("threeSceneService")
64
57
  dialogService = getService<DialogService>("dialogService")
@@ -80,7 +73,6 @@ describe("nodeContextMenuController", () => {
80
73
  $window,
81
74
  $rootScope,
82
75
  storeService,
83
- codeMapActionsService,
84
76
  codeMapPreRenderService,
85
77
  threeSceneService,
86
78
  dialogService,
@@ -88,19 +80,10 @@ describe("nodeContextMenuController", () => {
88
80
  )
89
81
  }
90
82
 
91
- function withMockedCodeMapActionService() {
92
- codeMapActionsService.markFolder = jest.fn()
93
- codeMapActionsService.unmarkFolder = jest.fn()
94
- }
95
-
96
83
  function withMockedCodeMapPreRenderService() {
97
84
  codeMapPreRenderService.getRenderMap = jest.fn().mockReturnValue(TEST_DELTA_MAP_A.map)
98
85
  }
99
86
 
100
- function withMockedHideNodeContextMenuMethod() {
101
- nodeContextMenuController.onHideNodeContextMenu = jest.fn()
102
- }
103
-
104
87
  function withMockedThreeSceneService() {
105
88
  threeSceneService = jest.fn().mockReturnValue({
106
89
  addNodeAndChildrenToConstantHighlight: jest.fn(),
@@ -131,28 +114,26 @@ describe("nodeContextMenuController", () => {
131
114
  })
132
115
 
133
116
  it("should subscribe to 'on-building-right-clicked' events", () => {
134
- NodeContextMenuController.subscribeToShowNodeContextMenu = jest.fn()
135
- CodeMapMouseEventService.subscribeToBuildingRightClickedEvents = jest.fn()
136
-
117
+ const documentAddEventListenerSpy = jest.spyOn(document, "addEventListener")
137
118
  rebuildController()
138
119
 
139
- expect(CodeMapMouseEventService.subscribeToBuildingRightClickedEvents).toHaveBeenCalledWith(
140
- $rootScope,
141
- nodeContextMenuController
120
+ expect(documentAddEventListenerSpy).toHaveBeenCalledWith(
121
+ "building-right-clicked",
122
+ nodeContextMenuController.onBuildingRightClicked
142
123
  )
143
124
  })
144
125
  })
145
126
 
146
127
  describe("onShowNodeContextMenu", () => {
147
- let elementMock
128
+ let mockedWheelTargetElement
148
129
  beforeEach(() => {
149
130
  nodeContextMenuController.setPosition = jest.fn()
150
131
  nodeContextMenuController.calculatePosition = jest.fn().mockReturnValue({ x: 1, y: 2 })
151
132
 
152
133
  document.body.addEventListener = jest.fn()
153
- elementMock = { addEventListener: jest.fn() }
134
+ mockedWheelTargetElement = { addEventListener: jest.fn(), removeEventListener: jest.fn() }
154
135
  // @ts-ignore
155
- jest.spyOn(document, "getElementById").mockImplementation(() => elementMock)
136
+ jest.spyOn(document, "getElementById").mockImplementation(() => mockedWheelTargetElement)
156
137
  })
157
138
 
158
139
  it("should set the correct building after some timeout", () => {
@@ -168,7 +149,7 @@ describe("nodeContextMenuController", () => {
168
149
  expect(document.body.addEventListener).toHaveBeenNthCalledWith(2, "mousedown", expect.anything(), expect.anything())
169
150
 
170
151
  expect(document.getElementById).toHaveBeenCalledWith("codeMap")
171
- expect(elementMock.addEventListener).toHaveBeenCalledWith("wheel", expect.anything(), expect.anything())
152
+ expect(mockedWheelTargetElement.addEventListener).toHaveBeenCalledWith("wheel", expect.anything(), expect.anything())
172
153
  })
173
154
 
174
155
  it("should not shorten the path if it has no sub paths", () => {
@@ -186,27 +167,26 @@ describe("nodeContextMenuController", () => {
186
167
  expect(nodeContextMenuController["_viewModel"].lastPartOfNodePath).toBe(`...${nodePath.slice(nodePath.lastIndexOf("/"))}`)
187
168
  })
188
169
 
189
- it("should set if the node is focused or it's parent is focuesd", () => {
190
- storeService.dispatch(unfocusNode())
191
- storeService.dispatch(focusNode("/root/big leaf"))
192
- nodeContextMenuController.onShowNodeContextMenu("/root/big leaf", NodeType.FILE, 521, 588)
193
- expect(nodeContextMenuController["_viewModel"].isNodeFocused).toEqual(true)
194
- expect(nodeContextMenuController["_viewModel"].isParentFocused).toEqual(false)
195
- storeService.dispatch(unfocusNode())
196
- storeService.dispatch(focusNode("/root/other big leaf"))
197
- nodeContextMenuController.onShowNodeContextMenu("/root/big leaf", NodeType.FILE, 521, 588)
198
- expect(nodeContextMenuController["_viewModel"].isNodeFocused).toEqual(false)
199
- expect(nodeContextMenuController["_viewModel"].isParentFocused).toEqual(false)
200
- storeService.dispatch(unfocusNode())
201
- storeService.dispatch(focusNode("/root"))
202
- nodeContextMenuController.onShowNodeContextMenu("/root/ParentLeaf/smallLeaf", NodeType.FILE, 521, 588)
203
- expect(nodeContextMenuController["_viewModel"].isNodeFocused).toEqual(false)
204
- expect(nodeContextMenuController["_viewModel"].isParentFocused).toEqual(true)
205
- storeService.dispatch(unfocusNode())
206
- storeService.dispatch(focusNode("/root/ParentLeaf"))
207
- nodeContextMenuController.onShowNodeContextMenu("/root/ParentLeaf/smallLeaf", NodeType.FOLDER, 521, 588)
208
- expect(nodeContextMenuController["_viewModel"].isNodeFocused).toEqual(false)
209
- expect(nodeContextMenuController["_viewModel"].isParentFocused).toEqual(true)
170
+ it("should remove all listener on hide", () => {
171
+ const documentRemoveEventListenerSpy = jest.spyOn(document.body, "removeEventListener")
172
+
173
+ nodeContextMenuController.onHideNodeContextMenu()
174
+
175
+ expect(documentRemoveEventListenerSpy).toHaveBeenCalledWith(
176
+ "click",
177
+ nodeContextMenuController.onBodyLeftClickHideNodeContextMenu,
178
+ true
179
+ )
180
+ expect(documentRemoveEventListenerSpy).toHaveBeenCalledWith(
181
+ "mousedown",
182
+ nodeContextMenuController.onBodyRightClickHideNodeContextMenu,
183
+ true
184
+ )
185
+ expect(mockedWheelTargetElement.removeEventListener).toHaveBeenCalledWith(
186
+ "wheel",
187
+ nodeContextMenuController.onMapWheelHideNodeContextMenu,
188
+ true
189
+ )
210
190
  })
211
191
  })
212
192
 
@@ -387,34 +367,6 @@ describe("nodeContextMenuController", () => {
387
367
  })
388
368
  })
389
369
 
390
- describe("markFolder", () => {
391
- it("should call hide and codeMapActionService.markFolder", () => {
392
- nodeContextMenuController.markFolder("color")
393
-
394
- expect(codeMapActionsService.markFolder).toHaveBeenCalledWith(nodeContextMenuController["_viewModel"].codeMapNode, "color")
395
- })
396
- })
397
-
398
- describe("unmarkFolder", () => {
399
- it("should call hide and codeMapActionService.unmarkFolder", () => {
400
- nodeContextMenuController.unmarkFolder()
401
-
402
- expect(codeMapActionsService.unmarkFolder).toHaveBeenCalledWith(nodeContextMenuController["_viewModel"].codeMapNode)
403
- })
404
- })
405
-
406
- describe("focusNode", () => {
407
- beforeEach(() => {
408
- nodeContextMenuController["_viewModel"].codeMapNode = VALID_NODE_WITH_PATH.children[1]
409
- })
410
-
411
- it("should set new focused path", () => {
412
- nodeContextMenuController.focusNode()
413
-
414
- expect(storeService.getState().dynamicSettings.focusedNodePath).toEqual(VALID_NODE_WITH_PATH.children[1].path)
415
- })
416
- })
417
-
418
370
  describe("excludeNode", () => {
419
371
  beforeEach(() => {
420
372
  nodeContextMenuController["_viewModel"].codeMapNode = VALID_NODE_WITH_PATH.children[1]
@@ -488,55 +440,6 @@ describe("nodeContextMenuController", () => {
488
440
  })
489
441
  })
490
442
 
491
- describe("isNodeFocused", () => {
492
- it("should return true if a node is focused", () => {
493
- storeService.dispatch(focusNode("/root/big leaf"))
494
- nodeContextMenuController["_viewModel"].codeMapNode = TEST_DELTA_MAP_A.map.children[0]
495
-
496
- const actual = nodeContextMenuController.isNodeFocused()
497
-
498
- expect(actual).toBeTruthy()
499
- })
500
-
501
- it("should return false if a node is not focused", () => {
502
- storeService.dispatch(unfocusNode())
503
- nodeContextMenuController["_viewModel"].codeMapNode = TEST_DELTA_MAP_A.map.children[0]
504
-
505
- const actual = nodeContextMenuController.isNodeFocused()
506
-
507
- expect(actual).toBeFalsy()
508
- })
509
- })
510
-
511
- describe("isNodeOrParentFocused", () => {
512
- it("should return true if a node is focused", () => {
513
- storeService.dispatch(focusNode("/root/big leaf"))
514
- nodeContextMenuController["_viewModel"].codeMapNode = TEST_DELTA_MAP_A.map.children[0]
515
-
516
- const actual = nodeContextMenuController.isNodeOrParentFocused()
517
-
518
- expect(actual).toBeTruthy()
519
- })
520
-
521
- it("should return true if a parent of a node is focused", () => {
522
- storeService.dispatch(focusNode("/root/Parent Leaf"))
523
- nodeContextMenuController["_viewModel"].codeMapNode = TEST_DELTA_MAP_A.map.children[1].children[0]
524
-
525
- const actual = nodeContextMenuController.isNodeOrParentFocused()
526
-
527
- expect(actual).toBeTruthy()
528
- })
529
-
530
- it("should return false if a node is not focused", () => {
531
- storeService.dispatch(unfocusNode())
532
- nodeContextMenuController["_viewModel"].codeMapNode = TEST_DELTA_MAP_A.map.children[0]
533
-
534
- const actual = nodeContextMenuController.isNodeOrParentFocused()
535
-
536
- expect(actual).toBeFalsy()
537
- })
538
- })
539
-
540
443
  describe("onBodyLeftClickHideNodeContextMenu", () => {
541
444
  it("should not hide if a click on color-picker tricker occurs", () => {
542
445
  const broadcastHideEventSpy = jest.spyOn(NodeContextMenuController, "broadcastHideEvent")