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

Feature/2708/show changed files in delta mode #2890

Merged
merged 32 commits into from
Jul 27, 2022
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
538ba0f
Improve delta generator spec #2708
knoffi Jul 15, 2022
c7feb84
Improve nodePath spec #2708
knoffi Jul 15, 2022
0b37caa
Fix grammar in file count display #2708
knoffi Jul 15, 2022
1a154cc
Add mocked display of changed files #2708
knoffi Jul 15, 2022
9fd665c
Fix information display about changed files #2708
knoffi Jul 15, 2022
97861ab
Add file comparing in delta generator #2708
knoffi Jul 18, 2022
5acb25e
Add metricsChanged by delta generator #2708
knoffi Jul 19, 2022
f871d85
Merge branch 'main' into feature/2708/show-changed-files-in-delta-mode
MW-Friedrich Jul 21, 2022
abdc1d5
Add display of changed files in html from store #2708
knoffi Jul 21, 2022
40b33cb
Fix fileCount selector spec #2708
knoffi Jul 21, 2022
ce64b72
Add collecting of metric changes from children #2708
knoffi Jul 21, 2022
9825e07
Merge branch 'feature/2708/show-changed-files-in-delta-mode' of https…
knoffi Jul 21, 2022
642af10
Refactor FileCount property #2708
knoffi Jul 21, 2022
47d512c
Fix snapshots for delta generator spec #2708
knoffi Jul 22, 2022
9d19757
Fix logic of delta generator #2708
knoffi Jul 22, 2022
27221f5
Document changelog #2708
knoffi Jul 25, 2022
71bc9c6
Refactor deltaGenerator internally #2708
knoffi Jul 25, 2022
5a13982
Fix file-changed-logic in deltaGenerator #2708
knoffi Jul 26, 2022
675e7dd
Merge branch 'main' into feature/2708/show-changed-files-in-delta-mode
knoffi Jul 26, 2022
f371c7d
Merge branch 'main' into feature/2708/show-changed-files-in-delta-mode
MW-Friedrich Jul 26, 2022
aa4eeec
Merge branch 'main' into feature/2708/show-changed-files-in-delta-mode
jannikr Jul 26, 2022
c3d7d95
Change google link to https #2708
knoffi Jul 26, 2022
4840d25
Adjust test mocks and snapshots #2708
knoffi Jul 26, 2022
66464d8
Merge branch 'main' into feature/2708/show-changed-files-in-delta-mode
MW-Friedrich Jul 26, 2022
58aff39
Refactor test mock objects #2708
knoffi Jul 27, 2022
21e0ba0
Refactor mock objects for unit tests #2708
knoffi Jul 27, 2022
ee2dd60
Refactor test mock objects #2707
knoffi Jul 27, 2022
d9f0293
Refactor mock files in deltaGenerator spec #2708
knoffi Jul 27, 2022
f2492c5
Merge branch 'main' into feature/2708/show-changed-files-in-delta-mode
knoffi Jul 27, 2022
d446965
Try out comment to disable sonar in line #2708
knoffi Jul 27, 2022
72d612d
fix SonarQube not excluding dataMocks.ts
MW-Friedrich Jul 27, 2022
bf191c6
Merge branch 'main' into feature/2708/show-changed-files-in-delta-mode
MW-Friedrich Jul 27, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions visualization/app/codeCharta/codeCharta.model.ts
Expand Up @@ -37,6 +37,7 @@ export interface FileCount {
all?: number
added: number
removed: number
metricsChanged: number
}

interface squarifiedNode {
Expand Down
Expand Up @@ -55,6 +55,10 @@ cc-attribute-side-bar-header-section {
.removed-files {
color: rgb(255, 14, 14);
}

.changed-files {
color: rgb(14, 46, 255);
}
}
}

Expand Down
Expand Up @@ -10,7 +10,8 @@ export const getFileCount = (node?: Pick<CodeMapNode, "attributes" | "fileCount"
return {
all: node.attributes?.unary ?? 0,
added: node.fileCount?.added ?? 0,
removed: node.fileCount?.removed ?? 0
removed: node.fileCount?.removed ?? 0,
metricsChanged: node.fileCount?.metricsChanged ?? 0
}
}

Expand Down
Expand Up @@ -3,12 +3,11 @@
{{ node.path }}
<span *ngIf="node.children?.length && fileCount$ | async as fileCount" class="cc-node-file-count">
(
{{ fileCount.all > 1 ? fileCount.all + " files" : fileCount.all + " file" }}
{{ fileCount.all }} {{ fileCount.all === 1 ? "file" : "files" }}
<span *ngIf="node.children?.length && (isDeltaMode$ | async)" class="cc-node-file-count">
| <span class="added-files" title="Number of added files"> Δ{{ fileCount.added }}</span> |
<span class="removed-files" title="Number of removed files">
Δ{{ fileCount.removed > 0 ? -fileCount.removed : 0 }}</span
></span
<span class="removed-files" title="Number of removed files"> Δ{{ fileCount.removed > 0 ? -fileCount.removed : 0 }}</span> |
<span class="files-with-metric-changes" title="Number of files with metric changes"> Δ{{ 0 }}</span> </span
>)
</span>
</span>
Expand Down
Expand Up @@ -62,6 +62,40 @@ describe("nodePathComponent", () => {

const { container } = await render(NodePathComponent, { componentProperties: { node } })

expect(container.textContent.replace(/\s+/g, " ")).toContain("some/folder ( 2 files | Δ1 | Δ-2)")
expect(container.textContent.replace(/\s+/g, " ")).toContain("some/folder ( 2 files | Δ1 | Δ-2 | Δ0)")
})
it("should display amount of files with correct english grammar, when an empty folder is selected and delta mode is enabled", async () => {
const node = {
children: [{}] as CodeMapNode[],
path: "some/emptyFolder",
attributes: { unary: 0 },
fileCount: {
added: 0,
removed: 2
}
}
isDeltaStateSelectorMock.mockImplementationOnce(() => true)
selectedNodeSelectorMock.mockImplementation(() => node)

const { container } = await render(NodePathComponent, { componentProperties: { node } })

expect(container.textContent).toContain(" 0 files ") // because "zero file" is not grammatically correct
})
it("should display amount of files with correct english grammar, when a folder with 1 file is selected and delta mode is enabled", async () => {
const node = {
children: [{}] as CodeMapNode[],
path: "some/folderWithOneFile",
attributes: { unary: 1 },
fileCount: {
added: 1,
removed: 0
}
}
isDeltaStateSelectorMock.mockImplementationOnce(() => true)
selectedNodeSelectorMock.mockImplementation(() => node)

const { container } = await render(NodePathComponent, { componentProperties: { node } })

expect(container.textContent).toContain(" 1 file ") // because "one files" is not grammatically correct
})
})
128 changes: 107 additions & 21 deletions visualization/app/codeCharta/util/dataMocks.ts
Expand Up @@ -1238,7 +1238,7 @@ export const VALID_NODE_WITH_PATH_AND_DELTAS: CodeMapNode = {
name: "root",
attributes: {},
deltas: {},
fileCount: { added: 0, removed: 0 },
fileCount: { added: 0, removed: 0, metricsChanged: 0 },
type: NodeType.FOLDER,
path: "/root",
isExcluded: false,
Expand All @@ -1250,7 +1250,7 @@ export const VALID_NODE_WITH_PATH_AND_DELTAS: CodeMapNode = {
path: "/root/big leaf.jpg",
attributes: { rloc: 100, functions: 10, mcc: 1 },
deltas: { rloc: 300, functions: -15, mcc: 12 },
fileCount: { added: 0, removed: 1 },
fileCount: { added: 0, removed: 1, metricsChanged: 0 },
isExcluded: false,
isFlattened: false
},
Expand All @@ -1260,7 +1260,7 @@ export const VALID_NODE_WITH_PATH_AND_DELTAS: CodeMapNode = {
path: "/root/another big leaf.java",
attributes: { rloc: 120, functions: 20, mcc: 2 },
deltas: { rloc: -150, functions: 9, mcc: 33 },
fileCount: { added: 0, removed: 1 },
fileCount: { added: 0, removed: 1, metricsChanged: 0 },
isExcluded: false,
isFlattened: false
},
Expand All @@ -1269,7 +1269,7 @@ export const VALID_NODE_WITH_PATH_AND_DELTAS: CodeMapNode = {
type: NodeType.FOLDER,
attributes: {},
deltas: {},
fileCount: { added: 0, removed: 0 },
fileCount: { added: 0, removed: 0, metricsChanged: 0 },
path: "/root/Parent Leaf",
isExcluded: false,
isFlattened: false,
Expand All @@ -1280,7 +1280,7 @@ export const VALID_NODE_WITH_PATH_AND_DELTAS: CodeMapNode = {
path: "/root/Parent Leaf/small leaf.json",
attributes: { rloc: 30, functions: 100, mcc: 100 },
deltas: { rloc: -55, functions: 38, mcc: -40 },
fileCount: { added: 0, removed: 1 },
fileCount: { added: 0, removed: 1, metricsChanged: 1 },
isExcluded: false,
isFlattened: false
},
Expand All @@ -1290,7 +1290,7 @@ export const VALID_NODE_WITH_PATH_AND_DELTAS: CodeMapNode = {
path: "/root/Parent Leaf/other small leaf.json",
attributes: { rloc: 70, functions: 1000, mcc: 10 },
deltas: { rloc: 200, functions: -27, mcc: 65 },
fileCount: { added: 1, removed: 0 },
fileCount: { added: 1, removed: 0, metricsChanged: 2 },
isExcluded: false,
isFlattened: false
}
Expand Down Expand Up @@ -1576,21 +1576,6 @@ export const TEST_DELTA_MAP_D: CCFile = {
attributes: { rloc: 400, functions: 30, mcc: 20, more: 20 },
isExcluded: false,
isFlattened: false
},
{
name: "D file 1.2",
type: NodeType.FILE,
attributes: { rloc: 40, functions: 3 },
isExcluded: false,
isFlattened: false
},
{
name: "D file 1.3",
type: NodeType.FILE,
attributes: { rloc: 200, functions: 20, mcc: 30 },
link: "https://www.google.de",
isExcluded: false,
isFlattened: false
}
]
}
Expand All @@ -1606,6 +1591,107 @@ export const TEST_DELTA_MAP_D: CCFile = {
}
}

export const TEST_DELTA_MAP_E: CCFile = {
fileMeta: {
fileName: "fileE",
fileChecksum: "md5-delta-fileE",
projectName: "Sample Project",
apiVersion: packageJson.codecharta.apiVersion,
exportedFileSize: 300_000
},
map: {
name: "root",
type: NodeType.FOLDER,
attributes: {},
isExcluded: false,
isFlattened: false,
children: [
{
name: "File with different attributes",
type: NodeType.FILE,
attributes: { rloc: 400, functions: 12 },
link: "https://www.google.de",
isExcluded: false,
isFlattened: false
},
{
name: "File without metric changes",
type: NodeType.FILE,
attributes: { rloc: 271 },
link: "https://www.google.de",
isExcluded: false,
isFlattened: false
},
{
name: "File with mcc changes",
type: NodeType.FILE,
attributes: { mcc: 4 },
link: "https://www.google.de",
isExcluded: false,
isFlattened: false
}
]
},
settings: {
fileSettings: {
attributeTypes: { nodes: {}, edges: {} },
blacklist: [],
edges: VALID_EDGES,
markedPackages: []
}
}
}
export const TEST_DELTA_MAP_F: CCFile = {
fileMeta: {
fileName: "fileF",
fileChecksum: "md5-delta-fileF",
projectName: "Sample Project",
apiVersion: packageJson.codecharta.apiVersion,
exportedFileSize: 300_000
},
map: {
name: "root",
type: NodeType.FOLDER,
attributes: {},
isExcluded: false,
isFlattened: false,
children: [
{
name: "File with different attributes",
type: NodeType.FILE,
attributes: { rloc: 400, mcc: 7 },
link: "https://www.google.de",
isExcluded: false,
isFlattened: false
},
{
name: "File without metric changes",
type: NodeType.FILE,
attributes: { rloc: 271 },
link: "https://www.google.de",
isExcluded: false,
isFlattened: false
},
{
name: "File with mcc changes",
type: NodeType.FILE,
attributes: { mcc: 9001 }, // its over 9000!!!
link: "https://www.google.de",
isExcluded: false,
isFlattened: false
}
]
},
settings: {
fileSettings: {
attributeTypes: { nodes: {}, edges: {} },
blacklist: [],
edges: VALID_EDGES,
markedPackages: []
}
}
}

export const TEST_FILE_DATA_DOWNLOADED = {
projectName: "Sample Project",
apiVersion: packageJson.codecharta.apiVersion,
Expand Down
76 changes: 72 additions & 4 deletions visualization/app/codeCharta/util/deltaGenerator.spec.ts
@@ -1,6 +1,6 @@
import { DeltaGenerator } from "./deltaGenerator"
import { TEST_DELTA_MAP_A, TEST_DELTA_MAP_B, TEST_DELTA_MAP_C, TEST_DELTA_MAP_D } from "./dataMocks"
import { CCFile, KeyValuePair, NodeType } from "../codeCharta.model"
import { TEST_DELTA_MAP_A, TEST_DELTA_MAP_B, TEST_DELTA_MAP_C, TEST_DELTA_MAP_D, TEST_DELTA_MAP_E, TEST_DELTA_MAP_F } from "./dataMocks"
import { CCFile, CodeMapNode, FileCount, NodeType } from "../codeCharta.model"
import { NodeDecorator } from "./nodeDecorator"
import { clone } from "./clone"
import { hierarchy } from "d3-hierarchy"
Expand Down Expand Up @@ -99,7 +99,7 @@ describe("deltaGenerator", () => {
})

it("should detect added and removed files and add result to delta attributes", () => {
const actualAmountOfChangedFiles: KeyValuePair = { added: 0, removed: 0 }
const actualAmountOfChangedFiles: Pick<FileCount, "added" | "removed"> = { added: 0, removed: 0 }
const referenceMap = { ...TEST_DELTA_MAP_C }
const comparisonMap = { ...TEST_DELTA_MAP_D }
NodeDecorator.decorateMapWithPathAttribute(referenceMap)
Expand All @@ -112,7 +112,75 @@ describe("deltaGenerator", () => {
actualAmountOfChangedFiles.removed += data.fileCount.removed
}

expect(actualAmountOfChangedFiles).toEqual({ added: 5, removed: 5 })
expect(actualAmountOfChangedFiles).toEqual({ added: 3, removed: 5 })
})

it("should detect value differences in common attributes of two files", () => {
const fileA: CodeMapNode = { type: NodeType.FILE, attributes: { mcc: 5, functions: 0 }, name: "A" }
const fileB: CodeMapNode = { type: NodeType.FILE, attributes: { mcc: 0 }, name: "A" }

const result = DeltaGenerator["compareCommonAttributes"](fileA, fileB)

expect(result).toEqual({ differenceExists: true })
})

it("should not detect differences when comparing a folder and a file", () => {
const file: CodeMapNode = { type: NodeType.FOLDER, attributes: { mcc: 5 }, name: "one" }
const folder: CodeMapNode = { type: NodeType.FILE, attributes: { functions: 0 }, name: "two" }

const result = DeltaGenerator["compareCommonAttributes"](file, folder)

expect(result).toEqual({ differenceExists: false })
})

it("should not detect differences when comparing two folders", () => {
const folderA: CodeMapNode = { type: NodeType.FOLDER, attributes: { mcc: 12 }, name: "folder" }
const folderB: CodeMapNode = { type: NodeType.FOLDER, attributes: { mcc: 7 }, name: "other folder" }

const result = DeltaGenerator["compareCommonAttributes"](folderA, folderB)

expect(result).toEqual({ differenceExists: false })
})
it("should not detect differences when comparing a file withouit attributes to another file", () => {
const folderA: CodeMapNode = { type: NodeType.FILE, attributes: { mcc: 12 }, name: "folder" }
const folderB: CodeMapNode = { type: NodeType.FILE, name: "other folder" }

const result = DeltaGenerator["compareCommonAttributes"](folderA, folderB)

expect(result).toEqual({ differenceExists: false })
})

it("should not detect differences when comparing a file to a clone with less attributes", () => {
const file: CodeMapNode = { type: NodeType.FILE, attributes: { mcc: 5, functions: -3 }, name: "file" }
const cloneWithLessAttributes: CodeMapNode = { type: NodeType.FILE, attributes: { mcc: 5 }, name: "smaller clone" }

const result = DeltaGenerator["compareCommonAttributes"](file, cloneWithLessAttributes)

expect(result).toEqual({ differenceExists: false })
})
it("should not detect differences when comparing two files which have no attributes in common", () => {
const file: CodeMapNode = { type: NodeType.FILE, attributes: { mcc: 5, functions: 10 }, name: "file" }
const cloneWithLessAttributes: CodeMapNode = { type: NodeType.FILE, attributes: { comments: 2, staticMethods: 7 }, name: "file" }

const result = DeltaGenerator["compareCommonAttributes"](file, cloneWithLessAttributes)

expect(result).toEqual({ differenceExists: false })
})

it("should detect files with metric changes and add result to delta attributes", () => {
const actualAmountOfChangedFiles: Pick<FileCount, "metricsChanged"> = { metricsChanged: 0 }
const referenceMap = { ...TEST_DELTA_MAP_E }
const comparisonMap = { ...TEST_DELTA_MAP_F }
NodeDecorator.decorateMapWithPathAttribute(referenceMap)
NodeDecorator.decorateMapWithPathAttribute(comparisonMap)

const actualDeltaMap = DeltaGenerator.getDeltaFile(referenceMap, comparisonMap)

for (const { data } of hierarchy(actualDeltaMap.map)) {
actualAmountOfChangedFiles.metricsChanged += data.fileCount.metricsChanged
}

expect(actualAmountOfChangedFiles).toEqual({ metricsChanged: 1 })
})

it("should sum exported file size of the comparison and reference File", () => {
Expand Down