From e5dee415197ec17ca0cfa88f31baa9c648d4fe2b Mon Sep 17 00:00:00 2001 From: "AAVN\\pvquan" Date: Wed, 25 Dec 2024 16:18:42 +0700 Subject: [PATCH] FE Unit test --- .../release-preview.component.html | 2 +- .../release-preview.component.spec.ts | 159 ++++++++++++++++++ .../release-preview.component.ts | 58 +------ .../release-preview.service.spec.ts | 67 ++++++++ 4 files changed, 236 insertions(+), 50 deletions(-) diff --git a/marketplace-ui/src/app/modules/release-preview/release-preview.component.html b/marketplace-ui/src/app/modules/release-preview/release-preview.component.html index 810bca8ad..8865d9822 100644 --- a/marketplace-ui/src/app/modules/release-preview/release-preview.component.html +++ b/marketplace-ui/src/app/modules/release-preview/release-preview.component.html @@ -91,7 +91,7 @@

[lang]="languageService.selectedLanguage()" class="readme-content" [data]=" - getProductModuleContentValue(displayedTab) + getReadmeContentValue(displayedTab) | multilingualism: languageService.selectedLanguage() "> diff --git a/marketplace-ui/src/app/modules/release-preview/release-preview.component.spec.ts b/marketplace-ui/src/app/modules/release-preview/release-preview.component.spec.ts index e69de29bb..1bac76b5c 100644 --- a/marketplace-ui/src/app/modules/release-preview/release-preview.component.spec.ts +++ b/marketplace-ui/src/app/modules/release-preview/release-preview.component.spec.ts @@ -0,0 +1,159 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ReleasePreviewComponent } from './release-preview.component'; +import { ReleasePreviewService } from './release-preview.service'; +import { of, throwError } from 'rxjs'; +import { LanguageService } from '../../core/services/language/language.service'; +import { Language } from '../../shared/enums/language.enum'; +import { TranslateModule } from '@ngx-translate/core'; +import { MarkdownModule } from 'ngx-markdown'; +import { + provideHttpClient, + withInterceptorsFromDi +} from '@angular/common/http'; +import { provideHttpClientTesting } from '@angular/common/http/testing'; + +describe('ReleasePreviewComponent', () => { + let component: ReleasePreviewComponent; + let fixture: ComponentFixture; + let releasePreviewService: ReleasePreviewService; + let languageService: jasmine.SpyObj; + + beforeEach(async () => { + const routingQueryParamServiceSpy = jasmine.createSpyObj( + 'RoutingQueryParamService', + ['getDesignerVersionFromSessionStorage', 'isDesignerEnv'] + ); + + const languageServiceSpy = jasmine.createSpyObj('LanguageService', [ + 'selectedLanguage' + ]); + + await TestBed.configureTestingModule({ + imports: [ + ReleasePreviewComponent, + TranslateModule.forRoot(), + MarkdownModule.forRoot() + ], + providers: [ + provideHttpClient(withInterceptorsFromDi()), + provideHttpClientTesting(), + { + provide: LanguageService, + useValue: languageServiceSpy + } + ] + }).compileComponents(); + languageService = TestBed.inject( + LanguageService + ) as jasmine.SpyObj; + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReleasePreviewComponent); + component = fixture.componentInstance; + releasePreviewService = TestBed.inject(ReleasePreviewService); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should set selected file on file selection', () => { + const mockFile = new File(['content'], 'test.zip', { + type: 'application/zip' + }); + const event = { + target: { + files: [mockFile] + } + } as unknown as Event; + + component.onFileSelected(event); + + expect(component.selectedFile).toEqual(mockFile); + expect(component.isZipFile).toBeTrue(); + }); + + it('should check non-zip file', () => { + const mockFile = new File(['content'], 'test.txt', { type: 'text/plain' }); + const event = { + target: { + files: [mockFile] + } + } as unknown as Event; + + component.onFileSelected(event); + + expect(component.selectedFile).toEqual(mockFile); + expect(component.isZipFile).toBeFalse(); + }); + + it('should handle file upload and call service', () => { + spyOn(releasePreviewService, 'extractZipDetails').and.callThrough(); + + const mockFile = new File(['content'], 'test.zip', { + type: 'application/zip' + }); + component.selectedFile = mockFile; + component.isZipFile = true; + + component.onSubmit(); + + expect(releasePreviewService.extractZipDetails).toHaveBeenCalledWith( + mockFile + ); + }); + + it('should filter tabs based on available content', () => { + spyOn(component, 'getContent').and.callFake(tab => tab === 'description'); + + const displayedTabs = component.getDisplayedTabsSignal(); + + expect(displayedTabs.length).toBe(1); + expect(displayedTabs[0].value).toBe('description'); + }); + + it('should return true for description when in DE language it is not null and not undefined and not empty', () => { + component.readmeContent.set({ + description: { en: 'Description content' }, + setup: {}, + demo: {} + }); + + const selectedLanguage = Language.DE; + + languageService.selectedLanguage.and.returnValue(selectedLanguage); + + expect(component.getContent('description')).toBeTrue(); + expect(component.getContent('setup')).toBeFalse(); + expect(component.getContent('demo')).toBeFalse(); + }); + + it('should handle successful file upload', () => { + const mockResponse = { + description: { en: 'Description content' }, + setup: { en: 'Setup content' }, + demo: { en: 'Demo content' } + }; + spyOn(releasePreviewService, 'extractZipDetails').and.returnValue( + of(mockResponse) + ); + + component.selectedFile = new File(['content'], 'test.zip', { + type: 'application/zip' + }); + component.isZipFile = true; + component.handlePreviewPage(); + + expect(releasePreviewService.extractZipDetails).toHaveBeenCalledWith( + component.selectedFile + ); + expect(component.readmeContent()).toEqual(mockResponse); + }); + + it('should set activeTab when setActiveTab is called', () => { + component.setActiveTab('setup'); + expect(component.activeTab).toBe('setup'); + }); +}); diff --git a/marketplace-ui/src/app/modules/release-preview/release-preview.component.ts b/marketplace-ui/src/app/modules/release-preview/release-preview.component.ts index cbea55d72..855980177 100644 --- a/marketplace-ui/src/app/modules/release-preview/release-preview.component.ts +++ b/marketplace-ui/src/app/modules/release-preview/release-preview.component.ts @@ -41,14 +41,10 @@ const DEFAULT_ACTIVE_TAB = 'description'; }) export class ReleasePreviewComponent { selectedFile: File | null = null; - tabs: { label: string; content: string }[] = []; - loading = false; activeTab = DEFAULT_ACTIVE_TAB; - errorMessage = ''; - availableLanguages = ['en', 'de']; selectedLanguage = 'en'; isZipFile = false; - productModuleContent: WritableSignal = signal( + readmeContent: WritableSignal = signal( {} as ReleasePreviewData ); languageService = inject(LanguageService); @@ -71,65 +67,29 @@ export class ReleasePreviewComponent { // Check if the selected file is a ZIP file this.isZipFile = file.type === 'application/zip' || file.name.endsWith('.zip'); - - if (!this.isZipFile) { - this.errorMessage = 'Please upload a valid ZIP file.'; - } else { - this.errorMessage = ''; - } } } onSubmit(): void { - this.loading = true; this.handlePreviewPage(); } - setActiveTab(index: string): void { - this.activeTab = index; + setActiveTab(tab: string): void { + this.activeTab = tab; } onTabChange(event: string) { this.setActiveTab(event); } - updateTabs(response: ReleasePreviewData): void { - if (response) { - this.tabs = [ - { - label: 'Description', - content: response.description[this.selectedLanguage] || '' - }, - { - label: 'Setup', - content: response.setup[this.selectedLanguage] || '' - }, - { label: 'Demo', content: response.demo[this.selectedLanguage] || '' } - ]; - this.activeTab = DEFAULT_ACTIVE_TAB; - } - } - - private handlePreviewPage(): void { - if (!this.selectedFile) { - this.errorMessage = 'Please select a file to upload.'; + handlePreviewPage(): void { + if (!this.selectedFile || !this.isZipFile) { return; } - if (!this.isZipFile) { - this.errorMessage = 'Only ZIP files are allowed.'; - return; - } - this.errorMessage = ''; this.releasePreviewService.extractZipDetails(this.selectedFile).subscribe({ next: response => { - this.loading = false; - this.productModuleContent.set(response); - this.updateTabs(response); - }, - error: error => { - this.loading = false; - this.errorMessage = error.message || 'An error occurred.'; + this.readmeContent.set(response); } }); } @@ -146,7 +106,7 @@ export class ReleasePreviewComponent { } getContent(value: string): boolean { - const content = this.productModuleContent(); + const content = this.readmeContent(); if (!content || Object.keys(content).length === 0) { return false; @@ -180,9 +140,9 @@ export class ReleasePreviewComponent { return CommonUtils.getLabel(this.activeTab, PRODUCT_DETAIL_TABS); } - getProductModuleContentValue(key: ItemDropdown): DisplayValue | null { + getReadmeContentValue(key: ItemDropdown): DisplayValue | null { type tabName = 'description' | 'demo' | 'setup'; const value = key.value as tabName; - return this.productModuleContent()[value]; + return this.readmeContent()[value]; } } diff --git a/marketplace-ui/src/app/modules/release-preview/release-preview.service.spec.ts b/marketplace-ui/src/app/modules/release-preview/release-preview.service.spec.ts index e69de29bb..15123da32 100644 --- a/marketplace-ui/src/app/modules/release-preview/release-preview.service.spec.ts +++ b/marketplace-ui/src/app/modules/release-preview/release-preview.service.spec.ts @@ -0,0 +1,67 @@ +import { TestBed } from '@angular/core/testing'; +import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; +import { ReleasePreviewService } from './release-preview.service'; +import { environment } from '../../../environments/environment'; +import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; +import { ReleasePreviewData } from '../../shared/models/release-preview-data.model'; + +describe('SecurityMonitorService', () => { + let service: ReleasePreviewService; + let httpMock: HttpTestingController; + + const mockApiUrl = environment.apiUrl + '/api/release-preview'; + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + ReleasePreviewService, + provideHttpClient(withInterceptorsFromDi()), + provideHttpClientTesting() + ] + }); + service = TestBed.inject(ReleasePreviewService); + httpMock = TestBed.inject(HttpTestingController); + }); + + afterEach(() => { + httpMock.verify(); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); + + it('should call API and return Readme data', () => { + const mockFile = new File(['content'], 'test.zip', { + type: 'application/zip' + }); + const mockResponse: ReleasePreviewData = { + description: { + English: 'This is a description in English.', + Spanish: 'Esta es una descripción en español.', + French: 'Ceci est une description en français.' + }, + setup: { + English: 'To set up the application, follow these steps...', + Spanish: 'Para configurar la aplicación, siga estos pasos...', + French: "Pour configurer l'application, suivez ces étapes..." + }, + demo: { + English: 'To demo the app, use the following commands...', + Spanish: + 'Para mostrar la aplicación, use los siguientes comandos...', + French: + "Pour démontrer l'application, utilisez les commandes suivantes..." + } + }; + + service.extractZipDetails(mockFile).subscribe(data => { + expect(data).toEqual(mockResponse); + }); + + const req = httpMock.expectOne(mockApiUrl); + expect(req.request.method).toBe('POST'); + + req.flush(mockResponse); + }); +}); \ No newline at end of file