diff --git a/src/main/webapp/app/exercises/programming/hestia/testwise-coverage-report/testwise-coverage-file.component.html b/src/main/webapp/app/exercises/programming/hestia/testwise-coverage-report/testwise-coverage-file.component.html
index 3dd96e458a67..3690bfdf0e3b 100644
--- a/src/main/webapp/app/exercises/programming/hestia/testwise-coverage-report/testwise-coverage-file.component.html
+++ b/src/main/webapp/app/exercises/programming/hestia/testwise-coverage-report/testwise-coverage-file.component.html
@@ -1,9 +1,11 @@
-
+
{{ fileName }}
- {{ (proportionCoveredLines * 100).toFixed(1) + ' %' }}
+ {{ proportionString }}
-
+
+
+
diff --git a/src/main/webapp/app/exercises/programming/hestia/testwise-coverage-report/testwise-coverage-file.component.scss b/src/main/webapp/app/exercises/programming/hestia/testwise-coverage-report/testwise-coverage-file.component.scss
index 578c1305d263..915e18b1199e 100644
--- a/src/main/webapp/app/exercises/programming/hestia/testwise-coverage-report/testwise-coverage-file.component.scss
+++ b/src/main/webapp/app/exercises/programming/hestia/testwise-coverage-report/testwise-coverage-file.component.scss
@@ -4,7 +4,6 @@
.mat-expansion-panel .mat-expansion-panel-body {
padding: 0 !important;
- text-align: center;
}
.mat-expansion-panel-header-description {
@@ -15,3 +14,7 @@
margin-right: 2px !important;
margin-left: 2px !important;
}
+
+.covered-line-highlight {
+ background-color: var(--monaco-editor-test-coverage-highlight);
+}
diff --git a/src/main/webapp/app/exercises/programming/hestia/testwise-coverage-report/testwise-coverage-file.component.ts b/src/main/webapp/app/exercises/programming/hestia/testwise-coverage-report/testwise-coverage-file.component.ts
index 337075e280b4..b9fc28de4fbf 100644
--- a/src/main/webapp/app/exercises/programming/hestia/testwise-coverage-report/testwise-coverage-file.component.ts
+++ b/src/main/webapp/app/exercises/programming/hestia/testwise-coverage-report/testwise-coverage-file.component.ts
@@ -1,12 +1,12 @@
-import { Component, Input, OnChanges, OnInit, SimpleChanges, ViewChild } from '@angular/core';
-import { AceEditorComponent } from 'app/shared/markdown-editor/ace-editor/ace-editor.component';
-import ace from 'brace';
+import { Component, Input, OnChanges, OnInit, SimpleChanges, ViewChild, ViewEncapsulation } from '@angular/core';
import { CoverageFileReport } from 'app/entities/hestia/coverage-file-report.model';
+import { MonacoEditorComponent } from 'app/shared/monaco-editor/monaco-editor.component';
@Component({
selector: 'jhi-testwise-coverage-file',
templateUrl: './testwise-coverage-file.component.html',
styleUrls: ['./testwise-coverage-file.component.scss'],
+ encapsulation: ViewEncapsulation.None,
})
export class TestwiseCoverageFileComponent implements OnInit, OnChanges {
@Input()
@@ -19,13 +19,17 @@ export class TestwiseCoverageFileComponent implements OnInit, OnChanges {
fileReport: CoverageFileReport;
@ViewChild('editor', { static: true })
- editor: AceEditorComponent;
+ editor: MonacoEditorComponent;
proportionCoveredLines: number;
+ proportionString: string;
+ editorHeight: number = 20;
+
+ static readonly COVERED_LINE_HIGHLIGHT_CLASS = 'covered-line-highlight';
ngOnInit(): void {
- this.setupEditor();
this.renderFile();
+ this.editorHeight = this.editor.getContentHeight();
}
ngOnChanges(changes: SimpleChanges): void {
@@ -48,6 +52,7 @@ export class TestwiseCoverageFileComponent implements OnInit, OnChanges {
// set the covered line ratio accordingly
this.proportionCoveredLines = orderedLines.length / this.fileReport!.lineCount!;
+ this.proportionString = `${(this.proportionCoveredLines * 100).toFixed(1)} %`;
let index = 0;
while (index < orderedLines.length) {
@@ -76,25 +81,11 @@ export class TestwiseCoverageFileComponent implements OnInit, OnChanges {
return [...Array(lineCount).keys()].map((i) => i + startLine - 1);
}
- private setupEditor(): void {
- this.editor.getEditor().setOptions({
- animatedScroll: true,
- maxLines: Infinity,
- highlightActiveLine: false,
- showPrintMargin: false,
- });
- ace.Range = ace.acequire('ace/range').Range;
- }
-
private renderFile() {
- const session = this.editor.getEditor().getSession();
- session.setValue(this.fileContent ?? '');
-
- Object.entries(session.getMarkers() ?? {}).forEach(([, v]) => session.removeMarker((v as any).id));
-
+ this.editor.changeModel(this.fileName, this.fileContent ?? '');
+ this.editor.disposeLineHighlights();
this.aggregateCoveredLinesBlocks(this.fileReport).forEach((blockLength, lineNumber) => {
- const range = new ace.Range(lineNumber, 0, lineNumber + blockLength - 1, 1);
- session.addMarker(range, 'ace_highlight-marker', 'fullLine');
+ this.editor.highlightLines(lineNumber + 1, lineNumber + blockLength, 'covered-line-highlight', 'covered-line-highlight');
});
}
}
diff --git a/src/main/webapp/app/exercises/programming/hestia/testwise-coverage-report/testwise-coverage-report.module.ts b/src/main/webapp/app/exercises/programming/hestia/testwise-coverage-report/testwise-coverage-report.module.ts
index 4cfd72937fc3..04e5a60b0ad6 100644
--- a/src/main/webapp/app/exercises/programming/hestia/testwise-coverage-report/testwise-coverage-report.module.ts
+++ b/src/main/webapp/app/exercises/programming/hestia/testwise-coverage-report/testwise-coverage-report.module.ts
@@ -1,13 +1,13 @@
import { NgModule } from '@angular/core';
import { ArtemisSharedModule } from 'app/shared/shared.module';
-import { AceEditorModule } from 'app/shared/markdown-editor/ace-editor/ace-editor.module';
import { TestwiseCoverageReportModalComponent } from 'app/exercises/programming/hestia/testwise-coverage-report/testwise-coverage-report-modal.component';
import { TestwiseCoverageReportComponent } from 'app/exercises/programming/hestia/testwise-coverage-report/testwise-coverage-report.component';
import { TestwiseCoverageFileComponent } from 'app/exercises/programming/hestia/testwise-coverage-report/testwise-coverage-file.component';
import { MatExpansionModule } from '@angular/material/expansion';
+import { MonacoEditorModule } from 'app/shared/monaco-editor/monaco-editor.module';
@NgModule({
- imports: [ArtemisSharedModule, AceEditorModule, MatExpansionModule],
+ imports: [ArtemisSharedModule, MatExpansionModule, MonacoEditorModule],
declarations: [TestwiseCoverageFileComponent, TestwiseCoverageReportComponent, TestwiseCoverageReportModalComponent],
exports: [TestwiseCoverageFileComponent, TestwiseCoverageReportModalComponent, TestwiseCoverageReportComponent],
})
diff --git a/src/main/webapp/app/exercises/shared/exercise-hint/shared/code-hint-container.component.html b/src/main/webapp/app/exercises/shared/exercise-hint/shared/code-hint-container.component.html
index 0129d293e184..d62c18f4e20e 100644
--- a/src/main/webapp/app/exercises/shared/exercise-hint/shared/code-hint-container.component.html
+++ b/src/main/webapp/app/exercises/shared/exercise-hint/shared/code-hint-container.component.html
@@ -1,9 +1,9 @@
@for (solutionEntry of sortedSolutionEntries; track solutionEntry) {
-
-
+
+
@if (enableEditing) {
-
+
-
+
+
+
diff --git a/src/main/webapp/app/exercises/shared/exercise-hint/shared/solution-entry.component.scss b/src/main/webapp/app/exercises/shared/exercise-hint/shared/solution-entry.component.scss
new file mode 100644
index 000000000000..5a51c7d082f5
--- /dev/null
+++ b/src/main/webapp/app/exercises/shared/exercise-hint/shared/solution-entry.component.scss
@@ -0,0 +1,3 @@
+.solution-entry-editor {
+ border: 1px solid var(--border-color);
+}
diff --git a/src/main/webapp/app/exercises/shared/exercise-hint/shared/solution-entry.component.ts b/src/main/webapp/app/exercises/shared/exercise-hint/shared/solution-entry.component.ts
index 5107f4ba59d1..314fce704776 100644
--- a/src/main/webapp/app/exercises/shared/exercise-hint/shared/solution-entry.component.ts
+++ b/src/main/webapp/app/exercises/shared/exercise-hint/shared/solution-entry.component.ts
@@ -1,17 +1,16 @@
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
-import { ActivatedRoute } from '@angular/router';
-
-import { AceEditorComponent } from 'app/shared/markdown-editor/ace-editor/ace-editor.component';
import { faTimes } from '@fortawesome/free-solid-svg-icons';
import { ProgrammingExerciseSolutionEntry } from 'app/entities/hestia/programming-exercise-solution-entry.model';
+import { MonacoEditorComponent } from 'app/shared/monaco-editor/monaco-editor.component';
@Component({
selector: 'jhi-solution-entry',
templateUrl: './solution-entry.component.html',
+ styleUrls: ['./solution-entry.component.scss'],
})
export class SolutionEntryComponent implements OnInit {
@ViewChild('editor', { static: true })
- editor: AceEditorComponent;
+ editor: MonacoEditorComponent;
@Input()
solutionEntry: ProgrammingExerciseSolutionEntry;
@@ -21,40 +20,28 @@ export class SolutionEntryComponent implements OnInit {
@Output()
onRemoveEntry: EventEmitter
= new EventEmitter();
- faTimes = faTimes;
+ editorHeight = 20;
- constructor(protected route: ActivatedRoute) {}
+ protected readonly faTimes = faTimes;
- ngOnInit() {
+ ngOnInit(): void {
this.setupEditor();
}
- emitRemovalEvent() {
- this.onRemoveEntry.emit();
+ onEditorContentChange(value: string): void {
+ this.solutionEntry.code = value;
}
- onEditorContentChange(value: any) {
- this.solutionEntry.code = value;
+ onContentSizeChange(contentHeight: number): void {
+ this.editorHeight = contentHeight;
}
- private setupEditor() {
- const line = this.solutionEntry.line;
-
- this.editor.getEditor().setOptions({
- animatedScroll: true,
- maxLines: Infinity,
- showPrintMargin: false,
- });
- // Ensure that the line counter is according to the solution entry
- this.editor.getEditor().session.gutterRenderer = {
- getWidth(session: any, lastLineNumber: number, config: any) {
- return this.getText(session, lastLineNumber).toString().length * config.characterWidth;
- },
- getText(session: any, row: number): string | number {
- return !line ? '' : row + line;
- },
- };
- this.editor.getEditor().getSession().setValue(this.solutionEntry.code);
- this.editor.getEditor().resize();
+ setupEditor(): void {
+ const startLine = this.solutionEntry.line ?? 1;
+ this.editor.setStartLineNumber(startLine);
+ this.editor.changeModel(this.solutionEntry.filePath ?? 'file', this.solutionEntry.code ?? '');
+ this.editor.layout();
+ // We manually fetch the initial content height, as the editor does not provide it immediately
+ this.editorHeight = this.editor.getContentHeight();
}
}
diff --git a/src/main/webapp/app/shared/monaco-editor/monaco-editor.component.ts b/src/main/webapp/app/shared/monaco-editor/monaco-editor.component.ts
index ad022f283729..e7c5908d1a9a 100644
--- a/src/main/webapp/app/shared/monaco-editor/monaco-editor.component.ts
+++ b/src/main/webapp/app/shared/monaco-editor/monaco-editor.component.ts
@@ -164,6 +164,10 @@ export class MonacoEditorComponent implements OnInit, OnDestroy {
return this._editor.getValue();
}
+ getContentHeight(): number {
+ return this._editor.getContentHeight() + this._editor.getOption(monaco.editor.EditorOption.lineHeight);
+ }
+
setText(text: string): void {
if (this.getText() !== text) {
this._editor.setValue(text);
@@ -379,6 +383,16 @@ export class MonacoEditorComponent implements OnInit, OnDestroy {
});
}
+ /**
+ * Sets the line number from which the editor should start counting.
+ * @param startLineNumber The line number to start counting from (starting at 1).
+ */
+ setStartLineNumber(startLineNumber: number): void {
+ this._editor.updateOptions({
+ lineNumbers: (number) => `${startLineNumber + number - 1}`,
+ });
+ }
+
/**
* Enables a text field mode for the editor. This will make the editor look more like a text field and less like a code editor.
* In particular, line numbers, margins, and highlights will be disabled.
diff --git a/src/main/webapp/content/scss/themes/_dark-variables.scss b/src/main/webapp/content/scss/themes/_dark-variables.scss
index 04eba6a88e49..fe7182454138 100644
--- a/src/main/webapp/content/scss/themes/_dark-variables.scss
+++ b/src/main/webapp/content/scss/themes/_dark-variables.scss
@@ -442,6 +442,7 @@ $monaco-editor-build-annotation-outdated-background: scale-color($gray-500, $alp
$monaco-editor-build-annotation-outdated-glyph: $gray-500;
$monaco-editor-diff-highlight-green: $success;
$monaco-editor-diff-line-highlight: scale-color($monaco-editor-diff-highlight-green, $alpha: -80%, $lightness: -20%);
+$monaco-editor-test-coverage-highlight: scale-color($warning, $alpha: -80%);
$monaco-editor-add-feedback-button-background: $gray-600;
$monaco-editor-add-feedback-button-hover-background: lighten($gray-600, 10%);
$monaco-editor-add-feedback-button-text: $gray-300;
diff --git a/src/main/webapp/content/scss/themes/_default-variables.scss b/src/main/webapp/content/scss/themes/_default-variables.scss
index 0806dbdff88b..a0c05c0c757f 100644
--- a/src/main/webapp/content/scss/themes/_default-variables.scss
+++ b/src/main/webapp/content/scss/themes/_default-variables.scss
@@ -368,6 +368,7 @@ $monaco-editor-build-annotation-outdated-background: scale-color($gray-500, $alp
$monaco-editor-build-annotation-outdated-glyph: $gray-500;
$monaco-editor-diff-highlight-green: rgb(63, 185, 80);
$monaco-editor-diff-line-highlight: scale-color($monaco-editor-diff-highlight-green, $alpha: -60%);
+$monaco-editor-test-coverage-highlight: scale-color($warning, $alpha: -80%);
$monaco-editor-add-feedback-button-background: $gray-400;
$monaco-editor-add-feedback-button-hover-background: $gray-500;
$monaco-editor-add-feedback-button-text: $black;
diff --git a/src/test/javascript/spec/component/exercise-hint/shared/solution-entry.component.spec.ts b/src/test/javascript/spec/component/exercise-hint/shared/solution-entry.component.spec.ts
index f4ef508f827f..4b6bc884a62e 100644
--- a/src/test/javascript/spec/component/exercise-hint/shared/solution-entry.component.spec.ts
+++ b/src/test/javascript/spec/component/exercise-hint/shared/solution-entry.component.spec.ts
@@ -1,19 +1,20 @@
import { ArtemisTestModule } from '../../../test.module';
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { AceEditorComponent } from 'app/shared/markdown-editor/ace-editor/ace-editor.component';
import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe';
-import { MockPipe } from 'ng-mocks';
+import { MockComponent, MockPipe } from 'ng-mocks';
import { SolutionEntryComponent } from 'app/exercises/shared/exercise-hint/shared/solution-entry.component';
import { ProgrammingExerciseSolutionEntry } from 'app/entities/hestia/programming-exercise-solution-entry.model';
+import { MonacoEditorComponent } from 'app/shared/monaco-editor/monaco-editor.component';
describe('Solution Entry Component', () => {
let comp: SolutionEntryComponent;
let fixture: ComponentFixture;
+ let solutionEntry: ProgrammingExerciseSolutionEntry;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ArtemisTestModule],
- declarations: [SolutionEntryComponent, AceEditorComponent, MockPipe(ArtemisTranslatePipe)],
+ declarations: [SolutionEntryComponent, MockComponent(MonacoEditorComponent), MockPipe(ArtemisTranslatePipe)],
}).compileComponents();
fixture = TestBed.createComponent(SolutionEntryComponent);
comp = fixture.componentInstance;
@@ -23,35 +24,32 @@ describe('Solution Entry Component', () => {
comp.solutionEntry.filePath = '/src/de/Test.java';
comp.solutionEntry.line = 1;
comp.solutionEntry.code = 'ABC';
+
+ solutionEntry = comp.solutionEntry;
});
afterEach(() => {
jest.restoreAllMocks();
});
- it('should setup editors', () => {
- jest.spyOn(comp.editor.getEditor(), 'setOptions');
- jest.spyOn(comp.editor.getEditor().getSession(), 'setValue');
-
- comp.ngOnInit();
+ it('should correctly setup editors', () => {
+ const setStartLineNumberStub = jest.spyOn(comp.editor, 'setStartLineNumber').mockImplementation();
+ const changeModelStub = jest.spyOn(comp.editor, 'changeModel').mockImplementation();
+ fixture.detectChanges();
- expect(comp.editor.getEditor().setOptions).toHaveBeenCalledOnce();
- expect(comp.editor.getEditor().setOptions).toHaveBeenCalledWith({
- animatedScroll: true,
- maxLines: Infinity,
- showPrintMargin: false,
- });
-
- expect(comp.editor.getEditor().getSession().setValue).toHaveBeenCalledOnce();
- expect(comp.editor.getEditor().getSession().setValue).toHaveBeenCalledWith('ABC');
+ expect(setStartLineNumberStub).toHaveBeenCalledExactlyOnceWith(solutionEntry.line);
+ expect(changeModelStub).toHaveBeenCalledExactlyOnceWith(solutionEntry.filePath, solutionEntry.code);
});
- it('should give correct line for gutter', () => {
- comp.ngOnInit();
- const gutterRendererNow = comp.editor.getEditor().session.gutterRenderer;
- const config = { characterWidth: 1 };
+ it('should update the editor height', () => {
+ const contentHeight = 123;
+ comp.onContentSizeChange(contentHeight);
+ expect(comp.editorHeight).toEqual(contentHeight);
+ });
- expect(gutterRendererNow.getText(null, 2)).toBe(3);
- expect(gutterRendererNow.getWidth(null, 2, config)).toBe(1);
+ it('should update the solution entry code', () => {
+ const newCode = 'DEF';
+ comp.onEditorContentChange(newCode);
+ expect(comp.solutionEntry.code).toEqual(newCode);
});
});
diff --git a/src/test/javascript/spec/component/hestia/generation-overview/manual-solution-entry-creation-modal.component.spec.ts b/src/test/javascript/spec/component/hestia/generation-overview/manual-solution-entry-creation-modal.component.spec.ts
index de5420595017..34c79f31899d 100644
--- a/src/test/javascript/spec/component/hestia/generation-overview/manual-solution-entry-creation-modal.component.spec.ts
+++ b/src/test/javascript/spec/component/hestia/generation-overview/manual-solution-entry-creation-modal.component.spec.ts
@@ -7,6 +7,8 @@ import { ProgrammingExerciseTestCase } from 'app/entities/programming-exercise-t
import { of } from 'rxjs';
import { ProgrammingExerciseSolutionEntry } from 'app/entities/hestia/programming-exercise-solution-entry.model';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { SolutionEntryComponent } from 'app/exercises/shared/exercise-hint/shared/solution-entry.component';
+import { MockComponent } from 'ng-mocks';
describe('ManualSolutionEntryCreationModal Component', () => {
let comp: ManualSolutionEntryCreationModalComponent;
@@ -25,6 +27,7 @@ describe('ManualSolutionEntryCreationModal Component', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ArtemisTestModule],
+ declarations: [ManualSolutionEntryCreationModalComponent, MockComponent(SolutionEntryComponent)],
}).compileComponents();
fixture = TestBed.createComponent(ManualSolutionEntryCreationModalComponent);
comp = fixture.componentInstance;
@@ -85,4 +88,10 @@ describe('ManualSolutionEntryCreationModal Component', () => {
comp.clear();
expect(closedSpy).toHaveBeenCalledOnce();
});
+
+ it('should setup editor when file path changes', () => {
+ comp.solutionEntryComponent = { setupEditor: jest.fn() } as unknown as SolutionEntryComponent;
+ comp.onUpdateFilePath();
+ expect(comp.solutionEntryComponent.setupEditor).toHaveBeenCalledOnce();
+ });
});
diff --git a/src/test/javascript/spec/component/hestia/testwise-coverage-report/testwise-coverage-file.component.spec.ts b/src/test/javascript/spec/component/hestia/testwise-coverage-report/testwise-coverage-file.component.spec.ts
index 9f8f8b390591..d837ef16643a 100644
--- a/src/test/javascript/spec/component/hestia/testwise-coverage-report/testwise-coverage-file.component.spec.ts
+++ b/src/test/javascript/spec/component/hestia/testwise-coverage-report/testwise-coverage-file.component.spec.ts
@@ -6,8 +6,8 @@ import { ProgrammingExerciseTestCase } from 'app/entities/programming-exercise-t
import { TestwiseCoverageReportEntry } from 'app/entities/hestia/testwise-coverage-report-entry.model';
import { CoverageFileReport } from 'app/entities/hestia/coverage-file-report.model';
import { MatExpansionModule } from '@angular/material/expansion';
-import ace from 'brace';
-import { AceEditorModule } from 'app/shared/markdown-editor/ace-editor/ace-editor.module';
+import { MockComponent } from 'ng-mocks';
+import { MonacoEditorComponent } from 'app/shared/monaco-editor/monaco-editor.component';
describe('TestwiseCoverageFile Component', () => {
let comp: TestwiseCoverageFileComponent;
@@ -15,23 +15,17 @@ describe('TestwiseCoverageFile Component', () => {
let reportEntry1: TestwiseCoverageReportEntry;
let reportEntry2: TestwiseCoverageReportEntry;
let fileReport: CoverageFileReport;
- let range1: ace.Range;
- let range2: ace.Range;
beforeEach(() => {
TestBed.configureTestingModule({
- imports: [ArtemisTestModule, MatExpansionModule, AceEditorModule, NoopAnimationsModule],
- declarations: [TestwiseCoverageFileComponent],
+ imports: [ArtemisTestModule, MatExpansionModule, NoopAnimationsModule],
+ declarations: [TestwiseCoverageFileComponent, MockComponent(MonacoEditorComponent)],
})
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(TestwiseCoverageFileComponent);
comp = fixture.componentInstance;
- ace.Range = ace.acequire('ace/range').Range;
- range1 = new ace.Range(3, 0, 4, 1);
- range2 = new ace.Range(6, 0, 7, 1);
-
const testCase1 = {
id: 1,
testName: 'testBubbleSort()',
@@ -72,33 +66,51 @@ describe('TestwiseCoverageFile Component', () => {
});
it('should initially create and add all ranges correctly', () => {
- const addMarkerSpy = jest.spyOn(comp.editor.getEditor().getSession(), 'addMarker');
+ const highlightLinesSpy = jest.spyOn(comp.editor, 'highlightLines');
comp.ngOnInit();
- // the row values are equal to (line number - 1) because the row counting starts for the editor at 0
- expect(addMarkerSpy).toHaveBeenCalledTimes(2);
- expect(addMarkerSpy).toHaveBeenCalledWith(range1, 'ace_highlight-marker', 'fullLine');
- expect(addMarkerSpy).toHaveBeenCalledWith(range2, 'ace_highlight-marker', 'fullLine');
+
+ expect(highlightLinesSpy).toHaveBeenCalledTimes(2);
+ expect(highlightLinesSpy).toHaveBeenCalledWith(
+ 4,
+ 5,
+ TestwiseCoverageFileComponent.COVERED_LINE_HIGHLIGHT_CLASS,
+ TestwiseCoverageFileComponent.COVERED_LINE_HIGHLIGHT_CLASS,
+ );
+ expect(highlightLinesSpy).toHaveBeenCalledWith(
+ 7,
+ 8,
+ TestwiseCoverageFileComponent.COVERED_LINE_HIGHLIGHT_CLASS,
+ TestwiseCoverageFileComponent.COVERED_LINE_HIGHLIGHT_CLASS,
+ );
});
it('should calculate covered line ratio correctly', () => {
comp.fileReport.testwiseCoverageEntries = [reportEntry1];
comp.ngOnInit();
expect(comp.proportionCoveredLines).toBe(0.2);
+ expect(comp.proportionString).toBe('20.0 %');
});
it('should update on input coverage data changes', () => {
comp.fileReport.testwiseCoverageEntries = [reportEntry1, reportEntry2];
comp.ngOnInit();
expect(comp.proportionCoveredLines).toBe(0.4);
- const addMarkerSpy = jest.spyOn(comp.editor.getEditor().getSession(), 'addMarker');
+ expect(comp.proportionString).toBe('40.0 %');
+
+ const highlightLinesSpy = jest.spyOn(comp.editor, 'highlightLines');
fileReport.testwiseCoverageEntries = [reportEntry1];
comp.fileReport = fileReport;
fixture.detectChanges();
expect(comp.proportionCoveredLines).toBe(0.2);
- expect(addMarkerSpy).toHaveBeenCalledOnce();
- expect(addMarkerSpy).toHaveBeenCalledWith(range1, 'ace_highlight-marker', 'fullLine');
+ expect(comp.proportionString).toBe('20.0 %');
+ expect(highlightLinesSpy).toHaveBeenCalledExactlyOnceWith(
+ 4,
+ 5,
+ TestwiseCoverageFileComponent.COVERED_LINE_HIGHLIGHT_CLASS,
+ TestwiseCoverageFileComponent.COVERED_LINE_HIGHLIGHT_CLASS,
+ );
});
});
diff --git a/src/test/javascript/spec/component/shared/monaco-editor/monaco-editor.component.spec.ts b/src/test/javascript/spec/component/shared/monaco-editor/monaco-editor.component.spec.ts
index bf593c248a16..dc9f7fb8b33c 100644
--- a/src/test/javascript/spec/component/shared/monaco-editor/monaco-editor.component.spec.ts
+++ b/src/test/javascript/spec/component/shared/monaco-editor/monaco-editor.component.spec.ts
@@ -267,6 +267,17 @@ describe('MonacoEditorComponent', () => {
expect(model.isDisposed()).toBeTrue();
});
+ it('should correctly set the start line number', () => {
+ fixture.detectChanges();
+ comp.changeModel('file', multiLineText);
+ comp.setStartLineNumber(5);
+ // Ensure that the editor is large enough to display all lines.
+ comp.layoutWithFixedSize(400, 400);
+ const lineNumbers = fixture.debugElement.nativeElement.querySelectorAll('.line-numbers');
+ expect(lineNumbers).toHaveLength(5);
+ expect([...lineNumbers].map((elem: HTMLElement) => elem.textContent)).toContainAllValues(['5', '6', '7', '8', '9']);
+ });
+
it('should apply option presets to the editor', () => {
fixture.detectChanges();
const preset = new MonacoEditorOptionPreset({ lineNumbers: 'off' });