Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor/2318/migrate code map component #3049

Merged
merged 9 commits into from
Sep 26, 2022
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/)
- Uncheck the box when 'reset invert height' icon is clicked [#3048](https://github.com/MaibornWolff/codecharta/pull/3048)
- Update ReadMe and GitHub pages for MetricGardener [#3045](https://github.com/MaibornWolff/codecharta/pull/3045)

### Chore 👨‍💻 👩‍💻

- Migrate codeMap.component to Angular with minor internal improvements [#3049](https://github.com/MaibornWolff/codecharta/pull/3049)

## [1.106.1] - 2022-09-20

### Fixed 🐞
Expand Down
21 changes: 9 additions & 12 deletions visualization/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { UpgradeModule } from "@angular/upgrade/static"
import { FormsModule, ReactiveFormsModule } from "@angular/forms"
import { MaterialModule } from "./material/material.module"
import { AttributeSideBarModule } from "./codeCharta/ui/attributeSideBar/attributeSideBar.module"
import { AttributeSideBarComponent } from "./codeCharta/ui/attributeSideBar/attributeSideBar.component"
import { LegendPanelComponent } from "./codeCharta/ui/legendPanel/legendPanel.component"
import { LegendPanelModule } from "./codeCharta/ui/legendPanel/legendPanel.module"
import { ColorPickerForMapColorModule } from "./codeCharta/ui/colorPickerForMapColor/colorPickerForMapColor.module"
Expand All @@ -18,10 +17,12 @@ import { AddBlacklistItemsIfNotResultsInEmptyMapEffect } from "./codeCharta/stat
import { dialogs } from "./codeCharta/ui/dialogs/dialogs"
import {
codeChartaServiceProvider,
CodeMapMouseEventServiceTokenProvider,
threeCameraServiceProvider,
threeOrbitControlsServiceProvider,
threeRendererServiceProvider,
threeSceneServiceProvider
threeSceneServiceProvider,
threeViewerServiceTokenProvider
} from "./codeCharta/services/ajs-upgraded-providers"
import { NodeContextMenuCardModule } from "./codeCharta/state/effects/nodeContextMenu/nodeContextMenuCard/nodeContextMenuCard.module"
import { OpenNodeContextMenuEffect } from "./codeCharta/state/effects/nodeContextMenu/openNodeContextMenu.effect"
Expand All @@ -42,10 +43,10 @@ import { ChangelogDialogModule } from "./codeCharta/ui/dialogs/changelogDialog/c
import { VersionService } from "./codeCharta/services/version/version.service"
import { ActionIconModule } from "./codeCharta/ui/actionIcon/actionIcon.module"
import { SplitStateActionsEffect } from "./codeCharta/state/effects/splitStateActionsEffect/splitStateActions.effect"
import { ViewCubeModule } from "./codeCharta/ui/viewCube/viewCube.module"
import { ToolBarModule } from "./codeCharta/ui/toolBar/toolBar.module"
import { RenderCodeMapEffect } from "./codeCharta/state/effects/renderCodeMapEffect/renderCodeMap.effect"
import { AutoFitCodeMapOnFileSelectionChangeEffect } from "./codeCharta/state/effects/autoFitCodeMapOnFileSelectionChange/autoFitCodeMapOnFileSelectionChange.effect"
import { CodeChartaModule } from "./codeCharta/codeCharta.module"
import { UpdateVisibleTopLabelsEffect } from "./codeCharta/state/effects/updateVisibleTopLabels/updateVisibleTopLabels.effect"

@NgModule({
Expand Down Expand Up @@ -75,14 +76,14 @@ import { UpdateVisibleTopLabelsEffect } from "./codeCharta/state/effects/updateV
NodeContextMenuCardModule,
ReactiveFormsModule,
LoadingFileProgressSpinnerModule,
ViewCubeModule,
FileExtensionBarModule,
MetricChooserModule,
RibbonBarModule,
ChangelogDialogModule,
ActionIconModule,
ToolBarModule,
RibbonBarModule
RibbonBarModule,
CodeChartaModule
],
providers: [
threeSceneServiceProvider,
Expand All @@ -91,6 +92,8 @@ import { UpdateVisibleTopLabelsEffect } from "./codeCharta/state/effects/updateV
threeCameraServiceProvider,
threeOrbitControlsServiceProvider,
threeRendererServiceProvider,
threeViewerServiceTokenProvider,
CodeMapMouseEventServiceTokenProvider,
VersionService,
{
provide: APP_INITIALIZER,
Expand All @@ -100,13 +103,7 @@ import { UpdateVisibleTopLabelsEffect } from "./codeCharta/state/effects/updateV
}
],
declarations: [...dialogs],
entryComponents: [
AttributeSideBarComponent,
LegendPanelComponent,
FocusButtonsComponent,
LoadingFileProgressSpinnerComponent,
...dialogs
]
entryComponents: [LegendPanelComponent, FocusButtonsComponent, LoadingFileProgressSpinnerComponent, ...dialogs]
})
export class AppModule {
constructor(@Inject(UpgradeModule) private upgrade: UpgradeModule) {}
Expand Down
2 changes: 1 addition & 1 deletion visualization/app/codeCharta/codeCharta.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<cc-file-extension-bar></cc-file-extension-bar>
<cc-ribbon-bar></cc-ribbon-bar>

<code-map-component></code-map-component>
<cc-code-map></cc-code-map>

<cc-legend-panel></cc-legend-panel>

Expand Down
11 changes: 11 additions & 0 deletions visualization/app/codeCharta/codeCharta.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ import { LoadingFileProgressSpinnerComponent } from "./ui/loadingFileProgressSpi
import { FileExtensionBarComponent } from "./ui/fileExtensionBar/fileExtensionBar.component"
import { ToolBarComponent } from "./ui/toolBar/toolBar.component"
import { RibbonBarComponent } from "./ui/ribbonBar/ribbonBar.component"
import { NgModule } from "@angular/core"
import { CommonModule } from "@angular/common"
import { CodeMapComponent } from "./ui/codeMap/codeMap.component"
import { CodeMapModule } from "./ui/codeMap/codeMap.module"

angular.module("app.codeCharta", ["app.codeCharta.state", "app.codeCharta.ui"])

Expand All @@ -24,3 +28,10 @@ angular
.directive("ccFileExtensionBar", downgradeComponent({ component: FileExtensionBarComponent }))
.directive("ccToolBar", downgradeComponent({ component: ToolBarComponent }))
.directive("ccRibbonBar", downgradeComponent({ component: RibbonBarComponent }))
.directive("ccCodeMap", downgradeComponent({ component: CodeMapComponent }))

@NgModule({
imports: [CommonModule, CodeMapModule],
entryComponents: [CodeMapComponent]
})
export class CodeChartaModule {}
18 changes: 18 additions & 0 deletions visualization/app/codeCharta/services/ajs-upgraded-providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,21 @@ export const threeRendererServiceProvider = {
},
deps: ["$injector"]
}

export const ThreeViewerServiceToken = new InjectionToken("ThreeViewerService")
export const threeViewerServiceTokenProvider = {
provide: ThreeViewerServiceToken,
useFactory: function ThreeViewerServiceTokenFactory(injector: Injector) {
return injector.get("threeViewerService")
},
deps: ["$injector"]
}

export const CodeMapMouseEventServiceToken = new InjectionToken("CodeMapMouseEventService")
export const CodeMapMouseEventServiceTokenProvider = {
provide: CodeMapMouseEventServiceToken,
useFactory: function CodeMapMouseEventServiceTokenFactory(injector: Injector) {
return injector.get("codeMapMouseEventService")
},
deps: ["$injector"]
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div id="codeMap" ng-hide="$ctrl._viewModel.isLoadingFile">
<cc-view-cube ng-class="{ sideBarVisible: $ctrl._viewModel.isSideBarVisible }"></cc-view-cube>
<div id="codeMap" [class.hidden]="isLoadingFile$ | async">
<cc-view-cube [class.sideBarVisible]="isAttributeSidebarVisible$ | async"></cc-view-cube>
<cc-attribute-side-bar></cc-attribute-side-bar>
</div>
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
code-map-component {
cc-code-map {
.hidden {
display: none;
}

cc-view-cube {
position: absolute;
z-index: 11;
Expand Down
137 changes: 43 additions & 94 deletions visualization/app/codeCharta/ui/codeMap/codeMap.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,105 +1,54 @@
import "./codeMap.module"
import "../../codeCharta.module"
import { IRootScopeService } from "angular"
import { getService, instantiateModule } from "../../../../mocks/ng.mockhelper"
import { CodeMapController } from "./codeMap.component"
import { ThreeViewerService } from "./threeViewer/threeViewerService"
import { ElementRef } from "@angular/core"
import { Subject } from "rxjs"
import { Store } from "../../state/angular-redux/store"
import { sharpnessModeSelector } from "../../state/store/appSettings/sharpnessMode/sharpnessMode.selector"
import { CodeMapComponent } from "./codeMap.component"
import { CodeMapMouseEventService } from "./codeMap.mouseEvent.service"
import { IsLoadingFileService } from "../../state/store/appSettings/isLoadingFile/isLoadingFile.service"
import { ThreeViewerService } from "./threeViewer/threeViewerService"

describe("ColorSettingsPanelController", () => {
let codeMapController: CodeMapController
let $rootScope: IRootScopeService
let $element: Element
let threeViewerService: ThreeViewerService
let codeMapMouseEventService: CodeMapMouseEventService
describe("CodeMapComponent", () => {
let mockedThreeViewService: ThreeViewerService
let mockedCodeMapMouseEventService: CodeMapMouseEventService
let mockedElementReference: ElementRef
let mockedSharpnessModeSelector$: Subject<string>
const mockedStore = {
select: (selector: unknown) => {
switch (selector) {
case sharpnessModeSelector:
return mockedSharpnessModeSelector$
default:
return jest.fn()
}
}
} as unknown as Store

beforeEach(() => {
restartSystem()
rebuildController()
mockElement()
withMockedThreeViewerService()
mockedThreeViewService = { init: jest.fn(), restart: jest.fn() } as unknown as ThreeViewerService
mockedCodeMapMouseEventService = { start: jest.fn() } as unknown as CodeMapMouseEventService
mockedElementReference = { nativeElement: { querySelector: jest.fn() } }
mockedSharpnessModeSelector$ = new Subject()
})

function restartSystem() {
instantiateModule("app.codeCharta.ui.codeMap")

$rootScope = getService<IRootScopeService>("$rootScope")
threeViewerService = getService<ThreeViewerService>("threeViewerService")
codeMapMouseEventService = getService<CodeMapMouseEventService>("codeMapMouseEventService")
}

function mockElement() {
// @ts-ignore we only care about few properties for the tests.
$element = [{ children: [{ clientWidth: 50, clientHeight: 100 }] }]
}

function withMockedThreeViewerService() {
threeViewerService = codeMapController["threeViewerService"] = jest.fn().mockReturnValue({
destroy: jest.fn(),
animate: jest.fn(),
stopAnimate: jest.fn(),
autoFitTo: jest.fn(),
animateStats: jest.fn(),
dispose: jest.fn()
})()
}

function rebuildController() {
codeMapController = new CodeMapController($rootScope, $element, threeViewerService, codeMapMouseEventService)
codeMapController.$postLink = jest.fn()
}

describe("constructor", () => {
it("should subscribe to IsLoadingFileService", () => {
IsLoadingFileService.subscribe = jest.fn()

rebuildController()

expect(IsLoadingFileService.subscribe).toHaveBeenCalledWith($rootScope, codeMapController)
})

it("should set attribute isLoadingFile to true", () => {
rebuildController()

expect(codeMapController["_viewModel"].isLoadingFile).toBeTruthy()
})
it("should init threeViewerService and start codeMapMouseService after view init", () => {
const codeMapComponent = new CodeMapComponent(
mockedStore,
mockedThreeViewService,
mockedCodeMapMouseEventService,
mockedElementReference
)
codeMapComponent.ngAfterViewInit()
expect(mockedThreeViewService.init).toHaveBeenCalled()
expect(mockedCodeMapMouseEventService.start).toHaveBeenCalled()
})

describe("onIsLoadingFileChanged", () => {
it("should set isLoadingFile in viewModel to true", () => {
codeMapController.onIsLoadingFileChanged(true)

expect(codeMapController["_viewModel"].isLoadingFile).toBe(true)
})

it("should set isLoadingFile in viewModel to false", () => {
codeMapController.onIsLoadingFileChanged(false)

expect(codeMapController["_viewModel"].isLoadingFile).toBe(false)
})
})

describe("onSharpnessModeChanged", () => {
const sharpnessTests = [
{ func: "stopAnimate" },
{ func: "destroy" },
{ func: "autoFitTo" },
{ func: "animate" },
{ func: "animateStats" }
]
beforeEach(() => {
codeMapController.onSharpnessModeChanged()
})

for (const test of sharpnessTests) {
it(`should call threeViewerService ${test.func}`, () => {
expect(threeViewerService[`${test.func}`]).toHaveBeenCalled()
})
}
it("should restart on sharpnessModeChanges but not on first one as it will get started then", () => {
new CodeMapComponent(mockedStore, mockedThreeViewService, mockedCodeMapMouseEventService, mockedElementReference)
mockedSharpnessModeSelector$.next("High")
expect(mockedThreeViewService.restart).not.toHaveBeenCalled()
expect(mockedCodeMapMouseEventService.start).not.toHaveBeenCalled()

it("should call CodeMapController $postLink", () => {
expect(codeMapController.$postLink).toHaveBeenCalled()
})
mockedSharpnessModeSelector$.next("Low")
expect(mockedThreeViewService.restart).toHaveBeenCalled()
expect(mockedCodeMapMouseEventService.start).toHaveBeenCalled()
})
})