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

Development: Migrate client code for edit modals of posts #10198

Merged
merged 3 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, EventEmitter, Input, Output, ViewContainerRef, ViewEncapsulation } from '@angular/core';
import { Component, ViewContainerRef, ViewEncapsulation, input, output } from '@angular/core';
import { PostingButtonComponent } from 'app/shared/metis/posting-button/posting-button.component';
import { PostingCreateEditModalDirective } from 'app/shared/metis/posting-create-edit-modal/posting-create-edit-modal.directive';
import { AnswerPost } from 'app/entities/metis/answer-post.model';
Expand All @@ -16,24 +16,24 @@ import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe';
imports: [FormsModule, ReactiveFormsModule, PostingMarkdownEditorComponent, PostingButtonComponent, ArtemisTranslatePipe],
})
export class AnswerPostCreateEditModalComponent extends PostingCreateEditModalDirective<AnswerPost> {
@Input() createEditAnswerPostContainerRef: ViewContainerRef;
@Output() postingUpdated = new EventEmitter<Posting>();
createEditAnswerPostContainerRef = input<ViewContainerRef>();
postingUpdated = output<Posting>();
isInputOpen = false;

/**
* renders the ng-template to edit or create an answerPost
*/
open(): void {
this.close();
this.createEditAnswerPostContainerRef.createEmbeddedView(this.postingEditor);
this.createEditAnswerPostContainerRef()?.createEmbeddedView(this.postingEditor);
this.isInputOpen = true;
}

/**
* clears the container to remove the input field when the user clicks cancel
*/
close(): void {
this.createEditAnswerPostContainerRef.clear();
this.createEditAnswerPostContainerRef()?.clear();
this.resetFormGroup();
this.isInputOpen = false;
}
Expand All @@ -60,7 +60,7 @@ export class AnswerPostCreateEditModalComponent extends PostingCreateEditModalDi
this.resetFormGroup();
this.isLoading = false;
this.onCreate.emit(answerPost);
this.createEditAnswerPostContainerRef?.clear();
this.createEditAnswerPostContainerRef()?.clear();
},
error: () => {
this.isLoading = false;
Expand All @@ -79,7 +79,7 @@ export class AnswerPostCreateEditModalComponent extends PostingCreateEditModalDi
this.postingUpdated.emit(updatedPost);
this.isLoading = false;
this.isInputOpen = false;
this.createEditAnswerPostContainerRef?.clear();
this.createEditAnswerPostContainerRef()?.clear();
},
error: () => {
this.isLoading = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ <h4 class="modal-title">{{ modalTitle | artemisTranslate }}</h4>
</div>
<div class="modal-body">
<!-- info if announcement is created-->
@if (this.editType === EditType.CREATE && isCommunicationPage && getAsChannel(posting.conversation)?.isAnnouncementChannel) {
@if (this.editType === EditType.CREATE && isCommunicationPage() && getAsChannel(posting.conversation)?.isAnnouncementChannel) {
<div class="alert alert-warning" jhiTranslate="artemisApp.metis.post.announcementHint"></div>
}
<!-- title -->
Expand All @@ -20,7 +20,7 @@ <h4 class="modal-title">{{ modalTitle | artemisTranslate }}</h4>
</div>
</div>
<!-- tags -->
@if (pageType !== PageType.PLAGIARISM_CASE_INSTRUCTOR && pageType !== PageType.PLAGIARISM_CASE_STUDENT && !isCommunicationPage && !posting.conversation) {
@if (pageType !== PageType.PLAGIARISM_CASE_INSTRUCTOR && pageType !== PageType.PLAGIARISM_CASE_STUDENT && !isCommunicationPage() && !posting.conversation) {
<div class="position-relative mb-3">
<div>
<label jhiTranslate="artemisApp.metis.post.tags"></label>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, Input, OnChanges, OnInit } from '@angular/core';
import { Component, OnChanges, OnInit, input } from '@angular/core';
import { HelpIconComponent } from 'app/shared/components/help-icon.component';
import { TranslateDirective } from 'app/shared/language/translate.directive';
import { PostingButtonComponent } from 'app/shared/metis/posting-button/posting-button.component';
Expand Down Expand Up @@ -38,7 +38,7 @@ export interface ContextSelectorOption {
],
})
export class PostCreateEditModalComponent extends PostingCreateEditModalDirective<Post> implements OnInit, OnChanges {
@Input() isCommunicationPage: boolean;
isCommunicationPage = input<boolean>(false);

exercises?: Exercise[];
lectures?: Lecture[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class PostingFooterComponent implements OnInit, OnDestroy, AfterContentCh
}

ngOnDestroy(): void {
this.answerPostCreateEditModal?.createEditAnswerPostContainerRef?.clear();
this.answerPostCreateEditModal?.createEditAnswerPostContainerRef()?.clear();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { PostingMarkdownEditorComponent } from 'app/shared/metis/posting-markdown-editor/posting-markdown-editor.component';
import { PostingButtonComponent } from 'app/shared/metis/posting-button/posting-button.component';
import { HelpIconComponent } from 'app/shared/components/help-icon.component';
import { ViewContainerRef } from '@angular/core';
import { input, runInInjectionContext, ViewContainerRef } from '@angular/core';
import { MockViewContainerRef } from '../../../../../helpers/mocks/service/mock-view-container-ref.service';
import { metisAnswerPostToCreateUser1, metisAnswerPostUser2, metisResolvingAnswerPostUser1 } from '../../../../../helpers/sample/metis-sample-data';

Expand All @@ -16,7 +16,7 @@
let component: AnswerPostCreateEditModalComponent;
let fixture: ComponentFixture<AnswerPostCreateEditModalComponent>;
let metisService: MetisService;
let viewContainerRef: ViewContainerRef;

Check failure on line 19 in src/test/javascript/spec/component/shared/metis/postings-create-edit-modal/answer-post-create-edit-modal/answer-post-create-edit-modal.component.spec.ts

View workflow job for this annotation

GitHub Actions / client-tests

'viewContainerRef' is declared but its value is never read.

Check failure on line 19 in src/test/javascript/spec/component/shared/metis/postings-create-edit-modal/answer-post-create-edit-modal/answer-post-create-edit-modal.component.spec.ts

View workflow job for this annotation

GitHub Actions / client-tests-selected

'viewContainerRef' is declared but its value is never read.
let updatePostingMock: jest.SpyInstance;

beforeEach(() => {
Expand All @@ -37,6 +37,7 @@
component = fixture.componentInstance;
metisService = TestBed.inject(MetisService);
viewContainerRef = TestBed.inject(ViewContainerRef);

updatePostingMock = jest.spyOn(component, 'updatePosting');
});
});
Expand All @@ -61,20 +62,36 @@

it('should invoke create embedded view', () => {
component.posting = metisResolvingAnswerPostUser1;
const viewContainerRefCreateEmbeddedView = jest.spyOn(viewContainerRef, 'createEmbeddedView');
component.createEditAnswerPostContainerRef = viewContainerRef;
fixture.detectChanges();

const mockClear = jest.fn();
const mockCreateEmbeddedView = jest.fn();

runInInjectionContext(fixture.debugElement.injector, () => {
component.createEditAnswerPostContainerRef = input<ViewContainerRef>({
clear: mockClear,
createEmbeddedView: mockCreateEmbeddedView,
} as unknown as ViewContainerRef);
});
component.open();
expect(viewContainerRefCreateEmbeddedView).toHaveBeenCalledOnce();
fixture.detectChanges();
expect(mockCreateEmbeddedView).toHaveBeenCalledOnce();
});

it('should invoke clear embedded view', () => {
component.posting = metisResolvingAnswerPostUser1;
const viewContainerRefClear = jest.spyOn(viewContainerRef, 'clear');
component.createEditAnswerPostContainerRef = viewContainerRef;
fixture.detectChanges();

const mockClear = jest.fn();
const mockCreateEmbeddedView = jest.fn();

runInInjectionContext(fixture.debugElement.injector, () => {
PaRangger marked this conversation as resolved.
Show resolved Hide resolved
component.createEditAnswerPostContainerRef = input<ViewContainerRef>({
clear: mockClear,
createEmbeddedView: mockCreateEmbeddedView,
} as unknown as ViewContainerRef);
});
component.close();
expect(viewContainerRefClear).toHaveBeenCalledOnce();
fixture.detectChanges();
expect(mockClear).toHaveBeenCalledOnce();
});

it('should invoke updatePosting when confirming', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { metisPostExerciseUser1, post, unsortedAnswerArray } from '../../../../h
import { AnswerPost } from 'app/entities/metis/answer-post.model';
import { User } from 'app/core/user/user.model';
import dayjs from 'dayjs/esm';
import { Injector, input, runInInjectionContext } from '@angular/core';
import { Injector, input, runInInjectionContext, signal } from '@angular/core';
import { Posting } from 'app/entities/metis/posting.model';
import { PostingFooterComponent } from 'app/shared/metis/posting-footer/posting-footer.component';
import { Post } from 'app/entities/metis/post.model';
Expand Down Expand Up @@ -81,6 +81,10 @@ describe('PostingFooterComponent', () => {
runInInjectionContext(injector, () => {
component.sortedAnswerPosts = input<AnswerPost[]>(unsortedAnswerArray);
component.groupAnswerPosts();
const mockContainerRef = { clear: jest.fn() } as any;
component.answerPostCreateEditModal = {
createEditAnswerPostContainerRef: signal(mockContainerRef),
} as unknown as AnswerPostCreateEditModalComponent;
expect(component.groupedAnswerPosts.length).toBeGreaterThan(0);
expect(component.groupedAnswerPosts[0].posts.length).toBeGreaterThan(0);
});
Expand All @@ -91,6 +95,10 @@ describe('PostingFooterComponent', () => {
component.sortedAnswerPosts = input<AnswerPost[]>(unsortedAnswerArray);
const changeDetectorSpy = jest.spyOn(component['changeDetector'], 'detectChanges');
component.ngOnChanges({ sortedAnswerPosts: { currentValue: unsortedAnswerArray, previousValue: [], firstChange: true, isFirstChange: () => true } });
const mockContainerRef = { clear: jest.fn() } as any;
component.answerPostCreateEditModal = {
createEditAnswerPostContainerRef: signal(mockContainerRef),
} as unknown as AnswerPostCreateEditModalComponent;
expect(component.groupedAnswerPosts.length).toBeGreaterThan(0);
expect(changeDetectorSpy).toHaveBeenCalled();
});
Expand All @@ -99,8 +107,8 @@ describe('PostingFooterComponent', () => {
it('should clear answerPostCreateEditModal container on destroy', () => {
const mockContainerRef = { clear: jest.fn() } as any;
component.answerPostCreateEditModal = {
createEditAnswerPostContainerRef: mockContainerRef,
} as AnswerPostCreateEditModalComponent;
createEditAnswerPostContainerRef: signal(mockContainerRef),
} as unknown as AnswerPostCreateEditModalComponent;

const clearSpy = jest.spyOn(mockContainerRef, 'clear');
component.ngOnDestroy();
Expand Down Expand Up @@ -165,17 +173,28 @@ describe('PostingFooterComponent', () => {
const createAnswerPostModalOpen = jest.spyOn(component.createAnswerPostModalComponent, 'open');
component.openCreateAnswerPostModal();
expect(createAnswerPostModalOpen).toHaveBeenCalledOnce();
const mockContainerRef = { clear: jest.fn() } as any;
component.answerPostCreateEditModal = {
createEditAnswerPostContainerRef: signal(mockContainerRef),
} as unknown as AnswerPostCreateEditModalComponent;
});
});

it('should close create answer post modal', () => {
runInInjectionContext(injector, () => {
component.posting = input<Posting>(metisPostExerciseUser1);
component.ngOnInit();
const mockContainerRef = { clear: jest.fn() } as any;
component.answerPostCreateEditModal = {
createEditAnswerPostContainerRef: signal(mockContainerRef),
} as unknown as AnswerPostCreateEditModalComponent;
fixture.detectChanges();
const createAnswerPostModalClose = jest.spyOn(component.createAnswerPostModalComponent, 'close');
component.closeCreateAnswerPostModal();
expect(createAnswerPostModalClose).toHaveBeenCalledOnce();
component.answerPostCreateEditModal = {
createEditAnswerPostContainerRef: signal(mockContainerRef),
} as unknown as AnswerPostCreateEditModalComponent;
});
});

Expand All @@ -194,6 +213,10 @@ describe('PostingFooterComponent', () => {
component.sortedAnswerPosts = input<AnswerPost[]>([post3, post1, post5, post2, post4]);

component.groupAnswerPosts();
const mockContainerRef = { clear: jest.fn() } as any;
component.answerPostCreateEditModal = {
createEditAnswerPostContainerRef: signal(mockContainerRef),
} as unknown as AnswerPostCreateEditModalComponent;
expect(component.groupedAnswerPosts).toHaveLength(3);

const group1 = component.groupedAnswerPosts[0];
Expand Down
Loading