Skip to content

Commit

Permalink
Development: Migrate client code for edit modals of posts (#10198)
Browse files Browse the repository at this point in the history
  • Loading branch information
cremertim authored Jan 27, 2025
1 parent b3711ab commit a98da8c
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 24 deletions.
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 { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms';
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 Down Expand Up @@ -37,6 +37,7 @@ describe('AnswerPostCreateEditModalComponent', () => {
component = fixture.componentInstance;
metisService = TestBed.inject(MetisService);
viewContainerRef = TestBed.inject(ViewContainerRef);

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

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, () => {
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

0 comments on commit a98da8c

Please sign in to comment.