diff --git a/src/portal/src/app/account/password-setting/forgot-password/forgot-password.component.html b/src/portal/src/app/account/password-setting/forgot-password/forgot-password.component.html
index 70fc8e12c..847b0da4b 100644
--- a/src/portal/src/app/account/password-setting/forgot-password/forgot-password.component.html
+++ b/src/portal/src/app/account/password-setting/forgot-password/forgot-password.component.html
@@ -17,6 +17,6 @@
\ No newline at end of file
diff --git a/src/portal/src/app/account/password-setting/forgot-password/forgot-password.component.spec.ts b/src/portal/src/app/account/password-setting/forgot-password/forgot-password.component.spec.ts
index 0cf02cee8..1c4483f17 100644
--- a/src/portal/src/app/account/password-setting/forgot-password/forgot-password.component.spec.ts
+++ b/src/portal/src/app/account/password-setting/forgot-password/forgot-password.component.spec.ts
@@ -5,19 +5,25 @@ import { ClarityModule } from "@clr/angular";
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { PasswordSettingService } from '../password-setting.service';
+import { InlineAlertComponent } from '../../../shared/inline-alert/inline-alert.component';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { of } from 'rxjs';
describe('ForgotPasswordComponent', () => {
let component: ForgotPasswordComponent;
let fixture: ComponentFixture;
- let fakePasswordSettingService = null;
+ let fakePasswordSettingService = {
+ sendResetPasswordMail: () => of(null)
+ };
beforeEach(async(() => {
TestBed.configureTestingModule({
- declarations: [ForgotPasswordComponent],
+ declarations: [ForgotPasswordComponent, InlineAlertComponent],
imports: [
FormsModule,
ClarityModule,
- TranslateModule.forRoot()
+ TranslateModule.forRoot(),
+ BrowserAnimationsModule
],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
providers: [
@@ -26,14 +32,53 @@ describe('ForgotPasswordComponent', () => {
]
}).compileComponents();
}));
-
+ let el;
beforeEach(() => {
fixture = TestBed.createComponent(ForgotPasswordComponent);
component = fixture.componentInstance;
- fixture.detectChanges();
+ component.inlineAlert = TestBed.createComponent(InlineAlertComponent).componentInstance;
+ component.open();
+ el = fixture.debugElement;
+ fixture.autoDetectChanges();
+
});
it('should create', () => {
expect(component).toBeTruthy();
});
+
+ it('should validate email', async () => {
+ await fixture.whenStable();
+ let resetPwdInput: HTMLInputElement = fixture.nativeElement.querySelector('#reset_pwd_email');
+ expect(resetPwdInput).toBeTruthy();
+ resetPwdInput.value = '1234567';
+ resetPwdInput.dispatchEvent(new Event('input'));
+ resetPwdInput.dispatchEvent(new Event('blur'));
+ await fixture.whenStable();
+ const resetPwdError = fixture.nativeElement.querySelector('#reset_pwd_email-error');
+ expect(resetPwdError.innerText).toEqual(' TOOLTIP.EMAIL ');
+ // success
+ resetPwdInput.value = '1234567@qq.com';
+ resetPwdInput.dispatchEvent(new Event('input'));
+ resetPwdInput.dispatchEvent(new Event('blur'));
+ await fixture.whenStable();
+ const resetPwdError1 = fixture.nativeElement.querySelector('#reset_pwd_email-error');
+ expect(resetPwdError1).toBeNull();
+
+ });
+ it('should send email to back end', async () => {
+ await fixture.whenStable();
+ let resetPwdInput: HTMLInputElement = fixture.nativeElement.querySelector('#reset_pwd_email');
+ resetPwdInput.value = '1234567@qq.com';
+ resetPwdInput.dispatchEvent(new Event('input'));
+ resetPwdInput.dispatchEvent(new Event('blur'));
+ await fixture.whenStable();
+ expect(el.nativeElement.querySelector('#submit-btn').disabled).toBeFalsy();
+ const submitBtn = fixture.nativeElement.querySelector('#submit-btn');
+ submitBtn.dispatchEvent(new Event('click'));
+ await fixture.whenStable();
+ const alertText: HTMLSpanElement = fixture.nativeElement.querySelector('.alert-text');
+ expect(alertText.innerText).toEqual(' RESET_PWD.SUCCESS ');
+ });
+
});
diff --git a/src/portal/src/app/account/password-setting/password-setting.component.html b/src/portal/src/app/account/password-setting/password-setting.component.html
index 050dde885..044b70f61 100644
--- a/src/portal/src/app/account/password-setting/password-setting.component.html
+++ b/src/portal/src/app/account/password-setting/password-setting.component.html
@@ -33,7 +33,7 @@
diff --git a/src/portal/src/app/account/password-setting/password-setting.component.spec.ts b/src/portal/src/app/account/password-setting/password-setting.component.spec.ts
index a50888ce0..1347d3cf3 100644
--- a/src/portal/src/app/account/password-setting/password-setting.component.spec.ts
+++ b/src/portal/src/app/account/password-setting/password-setting.component.spec.ts
@@ -1,4 +1,4 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { async, ComponentFixture, TestBed, flush } from '@angular/core/testing';
import { PasswordSettingService } from './password-setting.service';
import { SessionService } from '../../shared/session.service';
import { MessageHandlerService } from '../../shared/message-handler/message-handler.service';
@@ -8,20 +8,29 @@ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { FormsModule } from '@angular/forms';
import { InlineAlertComponent } from '../../shared/inline-alert/inline-alert.component';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { of } from 'rxjs';
describe('PasswordSettingComponent', () => {
let component: PasswordSettingComponent;
let fixture: ComponentFixture;
- let fakePasswordSettingService = null;
- let fakeSessionService = null;
- let fakeMessageHandlerService = null;
+ let fakePasswordSettingService = {
+ changePassword: () => of(null)
+ };
+ let fakeSessionService = {
+ getCurrentUser: () => true
+ };
+ let fakeMessageHandlerService = {
+ showSuccess: () => { }
+ };
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
ClarityModule,
TranslateModule.forRoot(),
- FormsModule
+ FormsModule,
+ BrowserAnimationsModule
],
declarations: [PasswordSettingComponent, InlineAlertComponent],
providers: [
@@ -38,11 +47,86 @@ describe('PasswordSettingComponent', () => {
fixture = TestBed.createComponent(PasswordSettingComponent);
component = fixture.componentInstance;
component.inlineAlert =
- TestBed.createComponent(InlineAlertComponent).componentInstance;
- fixture.detectChanges();
+ TestBed.createComponent(InlineAlertComponent).componentInstance;
+ component.oldPwd = "Harbor12345";
+ component.open();
+ fixture.autoDetectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
+ it('should verify new Password invalid', async () => {
+ await fixture.whenStable();
+ const newPasswordInput: HTMLInputElement = fixture.nativeElement.querySelector("#newPassword");
+ newPasswordInput.value = "HarborHarbor";
+ newPasswordInput.dispatchEvent(new Event("input"));
+ await fixture.whenStable();
+ newPasswordInput.dispatchEvent(new Event("blur"));
+ await fixture.whenStable();
+ const newPasswordInputError: any = fixture.nativeElement.querySelector("#newPassword-error");
+ expect(newPasswordInputError.innerText)
+ .toEqual(' TOOLTIP.PASSWORD ');
+ });
+ it('should verify new Password valid', async () => {
+ await fixture.whenStable();
+ const newPasswordInput: HTMLInputElement = fixture.nativeElement.querySelector("#newPassword");
+ newPasswordInput.value = "Harbor123456";
+ newPasswordInput.dispatchEvent(new Event("input"));
+ await fixture.whenStable();
+ newPasswordInput.dispatchEvent(new Event("blur"));
+ await fixture.whenStable();
+ const newPasswordInputError: any = fixture.nativeElement.querySelector("#newPassword-error");
+ expect(newPasswordInputError)
+ .toBeNull();
+ });
+ it('should verify comfirm Password invalid', async () => {
+ await fixture.whenStable();
+ const newPasswordInput: HTMLInputElement = fixture.nativeElement.querySelector("#newPassword");
+ newPasswordInput.value = "Harbor123456";
+ newPasswordInput.dispatchEvent(new Event("blur"));
+ await fixture.whenStable();
+ const reNewPasswordInput: HTMLInputElement = fixture.nativeElement.querySelector("#reNewPassword");
+ reNewPasswordInput.value = "Harbor12345";
+ reNewPasswordInput.dispatchEvent(new Event("blur"));
+ await fixture.whenStable();
+ const reNewPasswordInputError: any = fixture.nativeElement.querySelector("#reNewPassword-error");
+ expect(reNewPasswordInputError.innerText)
+ .toEqual(' TOOLTIP.CONFIRM_PWD ');
+ });
+ it('should verify comfirm Password valid', async () => {
+ await fixture.whenStable();
+ const newPasswordInput: HTMLInputElement = fixture.nativeElement.querySelector("#newPassword");
+ newPasswordInput.value = "Harbor123456";
+ newPasswordInput.dispatchEvent(new Event("blur"));
+ await fixture.whenStable();
+ const reNewPasswordInput: HTMLInputElement = fixture.nativeElement.querySelector("#reNewPassword");
+ reNewPasswordInput.value = "Harbor123456";
+ reNewPasswordInput.dispatchEvent(new Event("input"));
+ reNewPasswordInput.dispatchEvent(new Event("blur"));
+ await fixture.whenStable();
+ const reNewPasswordInputError: any = fixture.nativeElement.querySelector("#reNewPassword-error");
+ expect(reNewPasswordInputError)
+ .toBeNull();
+ });
+ it('should save new password', async () => {
+ await fixture.whenStable();
+ const newPasswordInput: HTMLInputElement = fixture.nativeElement.querySelector("#newPassword");
+ newPasswordInput.value = "Harbor123456";
+ newPasswordInput.dispatchEvent(new Event("input"));
+ newPasswordInput.dispatchEvent(new Event("blur"));
+ await fixture.whenStable();
+ const reNewPasswordInput: HTMLInputElement = fixture.nativeElement.querySelector("#reNewPassword");
+ reNewPasswordInput.value = "Harbor123456";
+ reNewPasswordInput.dispatchEvent(new Event("input"));
+ reNewPasswordInput.dispatchEvent(new Event("blur"));
+ await fixture.whenStable();
+ const okBtn: HTMLButtonElement = fixture.nativeElement.querySelector("#ok-btn");
+ okBtn.dispatchEvent(new Event("click"));
+ await fixture.whenStable();
+
+ const newPasswordInput1: HTMLInputElement = fixture.nativeElement.querySelector("#newPassword");
+ expect(newPasswordInput1)
+ .toBeNull();
+ });
});
diff --git a/src/portal/src/app/account/password-setting/password-setting.service.spec.ts b/src/portal/src/app/account/password-setting/password-setting.service.spec.ts
index 495f76116..9a20127de 100644
--- a/src/portal/src/app/account/password-setting/password-setting.service.spec.ts
+++ b/src/portal/src/app/account/password-setting/password-setting.service.spec.ts
@@ -1,8 +1,11 @@
-import { TestBed, inject } from '@angular/core/testing';
-import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { TestBed, inject, getTestBed } from '@angular/core/testing';
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { PasswordSettingService } from './password-setting.service';
describe('PasswordSettingService', () => {
+ let injector: TestBed;
+ let service: PasswordSettingService;
+ let httpMock: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
@@ -10,9 +13,45 @@ describe('PasswordSettingService', () => {
],
providers: [PasswordSettingService]
});
+ injector = getTestBed();
+ service = injector.get(PasswordSettingService);
+ httpMock = injector.get(HttpTestingController);
});
- it('should be created', inject([PasswordSettingService], (service: PasswordSettingService) => {
- expect(service).toBeTruthy();
+ it('should be created', inject([PasswordSettingService], (service1: PasswordSettingService) => {
+ expect(service1).toBeTruthy();
}));
+
+ const mockPasswordSetting = {
+ old_password: 'string',
+ new_password: 'string1'
+ };
+
+ it('changePassword() should success', () => {
+ service.changePassword(1, mockPasswordSetting).subscribe((res) => {
+ expect(res).toEqual(null);
+ });
+
+ const req = httpMock.expectOne('/api/users/1/password');
+ expect(req.request.method).toBe('PUT');
+ req.flush(null);
+ });
+ it('sendResetPasswordMail() should return data', () => {
+ service.sendResetPasswordMail("123").subscribe((res) => {
+ expect(res).toEqual(null);
+ });
+
+ const req = httpMock.expectOne('/c/sendEmail?email=123');
+ expect(req.request.method).toBe('GET');
+ req.flush(null);
+ });
+ it('resetPassword() should return data', () => {
+ service.resetPassword('1234', 'Harbor12345').subscribe((res) => {
+ expect(res).toEqual(null);
+ });
+
+ const req = httpMock.expectOne('/c/reset');
+ expect(req.request.method).toBe('POST');
+ req.flush(null);
+ });
});
diff --git a/src/portal/src/app/account/password-setting/reset-password/reset-password.component.spec.ts b/src/portal/src/app/account/password-setting/reset-password/reset-password.component.spec.ts
index b07c008a7..db510a4f0 100644
--- a/src/portal/src/app/account/password-setting/reset-password/reset-password.component.spec.ts
+++ b/src/portal/src/app/account/password-setting/reset-password/reset-password.component.spec.ts
@@ -6,6 +6,9 @@ import { FormsModule } from '@angular/forms';
import { PasswordSettingService } from '../password-setting.service';
import { RouterTestingModule } from '@angular/router/testing';
import { MessageHandlerService } from '../../../shared/message-handler/message-handler.service';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { ClarityModule } from '@clr/angular';
+import { InlineAlertComponent } from '../../../shared/inline-alert/inline-alert.component';
describe('ResetPasswordComponent', () => {
let component: ResetPasswordComponent;
@@ -18,9 +21,11 @@ describe('ResetPasswordComponent', () => {
imports: [
TranslateModule.forRoot(),
FormsModule,
- RouterTestingModule
+ RouterTestingModule,
+ BrowserAnimationsModule,
+ ClarityModule
],
- declarations: [ResetPasswordComponent],
+ declarations: [ResetPasswordComponent, InlineAlertComponent],
providers: [
TranslateService,
{ provide: PasswordSettingService, useValue: fakePasswordSettingService },
@@ -33,7 +38,9 @@ describe('ResetPasswordComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(ResetPasswordComponent);
component = fixture.componentInstance;
- fixture.detectChanges();
+ component.inlineAlert = TestBed.createComponent(InlineAlertComponent).componentInstance;
+ component.open();
+ fixture.autoDetectChanges();
});
it('should create', () => {
diff --git a/src/portal/src/app/account/password-setting/reset-password/reset-password.component.ts b/src/portal/src/app/account/password-setting/reset-password/reset-password.component.ts
index ee962422c..f3673265b 100644
--- a/src/portal/src/app/account/password-setting/reset-password/reset-password.component.ts
+++ b/src/portal/src/app/account/password-setting/reset-password/reset-password.component.ts
@@ -37,7 +37,7 @@ export class ResetPasswordComponent implements OnInit {
resetOk: boolean = false;
confirmPwd: string = "";
- @ViewChild("resetPwdForm", {static: false}) resetPwdForm: NgForm;
+ @ViewChild("resetPwdForm", {static: true}) resetPwdForm: NgForm;
@ViewChild(InlineAlertComponent, {static: false})
inlineAlert: InlineAlertComponent;
diff --git a/src/portal/src/app/account/sign-up/sign-up.component.html b/src/portal/src/app/account/sign-up/sign-up.component.html
index 957122873..bd1e972e5 100644
--- a/src/portal/src/app/account/sign-up/sign-up.component.html
+++ b/src/portal/src/app/account/sign-up/sign-up.component.html
@@ -6,7 +6,7 @@
\ No newline at end of file
diff --git a/src/portal/src/app/account/sign-up/sign-up.component.spec.ts b/src/portal/src/app/account/sign-up/sign-up.component.spec.ts
index edcac1b8f..838c97fca 100644
--- a/src/portal/src/app/account/sign-up/sign-up.component.spec.ts
+++ b/src/portal/src/app/account/sign-up/sign-up.component.spec.ts
@@ -8,20 +8,41 @@ import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { NewUserFormComponent } from '../../shared/new-user-form/new-user-form.component';
import { FormsModule } from '@angular/forms';
import { InlineAlertComponent } from '../../shared/inline-alert/inline-alert.component';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { of } from 'rxjs';
describe('SignUpComponent', () => {
let component: SignUpComponent;
let fixture: ComponentFixture;
- let fakeSessionService = null;
- let fakeUserService = null;
-
+ let fakeSessionService = {
+ checkUserExisting: () => of(true)
+ };
+ let fakeUserService = {
+ addUser: () => of(null)
+ };
+ const mockUser = {
+ user_id: 1,
+ username: 'string',
+ realname: 'string',
+ email: 'string',
+ password: 'string',
+ comment: 'string',
+ deleted: false,
+ role_name: 'string',
+ role_id: 1,
+ has_admin_role: true,
+ reset_uuid: 'string',
+ creation_time: 'string',
+ update_time: 'string',
+ };
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [SignUpComponent, NewUserFormComponent, InlineAlertComponent],
imports: [
FormsModule,
ClarityModule,
- TranslateModule.forRoot()
+ TranslateModule.forRoot(),
+ BrowserAnimationsModule
],
providers: [
TranslateService,
@@ -39,10 +60,35 @@ describe('SignUpComponent', () => {
TestBed.createComponent(NewUserFormComponent).componentInstance;
component.inlineAlert =
TestBed.createComponent(InlineAlertComponent).componentInstance;
- fixture.detectChanges();
+ component.opened = true;
+ fixture.autoDetectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
+
+ it('should close when no form change', async () => {
+ component.open();
+ await fixture.whenStable();
+ const closeBtn: HTMLButtonElement = fixture.nativeElement.querySelector("#close-btn");
+ expect(closeBtn).toBeTruthy();
+ closeBtn.dispatchEvent(new Event('click'));
+ await fixture.whenStable();
+ const closeBtn1: HTMLButtonElement = fixture.nativeElement.querySelector("#close-btn");
+ expect(closeBtn1).toBeNull();
+
+ });
+ it('should create new user', async () => {
+ component.open();
+ component.getNewUser = () => mockUser;
+ await fixture.whenStable();
+ const createBtn = fixture.nativeElement.querySelector('#create-btn');
+ createBtn.dispatchEvent(new Event('click'));
+
+ await fixture.whenStable();
+ const closeBtn1: HTMLButtonElement = fixture.nativeElement.querySelector("#close-btn");
+ expect(closeBtn1).toBeNull();
+
+ });
});
diff --git a/src/portal/src/app/app-config.service.spec.ts b/src/portal/src/app/app-config.service.spec.ts
index 30f8b8cb9..44eacda88 100644
--- a/src/portal/src/app/app-config.service.spec.ts
+++ b/src/portal/src/app/app-config.service.spec.ts
@@ -1,12 +1,17 @@
-import { TestBed, inject } from '@angular/core/testing';
-import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { TestBed, inject, getTestBed } from '@angular/core/testing';
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { CookieService } from 'ngx-cookie';
import { AppConfigService } from './app-config.service';
+import { AppConfig } from './app-config';
+import { Component } from '@angular/core';
describe('AppConfigService', () => {
+ let injector: TestBed;
+ let service: AppConfigService;
+ let httpMock: HttpTestingController;
let fakeCookieService = {
get: function (key) {
- return key;
+ return null;
}
};
@@ -16,9 +21,27 @@ describe('AppConfigService', () => {
providers: [AppConfigService,
{ provide: CookieService, useValue: fakeCookieService }]
});
+ injector = getTestBed();
+ service = injector.get(AppConfigService);
+ httpMock = injector.get(HttpTestingController);
});
-
- it('should be created', inject([AppConfigService], (service: AppConfigService) => {
- expect(service).toBeTruthy();
+ let systeminfo = new AppConfig();
+ it('should be created', inject([AppConfigService], (service1: AppConfigService) => {
+ expect(service1).toBeTruthy();
}));
+
+ it('load() should return data', () => {
+ service.load().subscribe((res) => {
+ expect(res).toEqual(systeminfo);
+ });
+
+ const req = httpMock.expectOne('/api/systeminfo');
+ expect(req.request.method).toBe('GET');
+ req.flush(systeminfo);
+ expect(service.getConfig()).toEqual(systeminfo);
+ expect(service.isIntegrationMode()).toBeFalsy();
+ expect(service.isLdapMode()).toBeFalsy();
+ expect(service.isHttpAuthMode()).toBeFalsy();
+ expect(service.isOidcMode()).toBeFalsy();
+ });
});
diff --git a/src/portal/src/app/base/global-search/global-search.service.spec.ts b/src/portal/src/app/base/global-search/global-search.service.spec.ts
index 9672d2ac0..d3789e49b 100644
--- a/src/portal/src/app/base/global-search/global-search.service.spec.ts
+++ b/src/portal/src/app/base/global-search/global-search.service.spec.ts
@@ -1,8 +1,15 @@
-import { TestBed, inject } from '@angular/core/testing';
-import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { TestBed, inject, getTestBed } from '@angular/core/testing';
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { GlobalSearchService } from './global-search.service';
+import { Injector } from '@angular/core';
+import { SearchResults } from './search-results';
describe('GlobalSearchService', () => {
+ let injector: TestBed;
+ let service: GlobalSearchService;
+ let httpMock: HttpTestingController;
+
+
beforeEach(() => {
TestBed.configureTestingModule({
providers: [GlobalSearchService],
@@ -10,9 +17,22 @@ describe('GlobalSearchService', () => {
HttpClientTestingModule
]
});
+ injector = getTestBed();
+ service = injector.get(GlobalSearchService);
+ httpMock = injector.get(HttpTestingController);
+
});
- it('should be created', inject([GlobalSearchService], (service: GlobalSearchService) => {
- expect(service).toBeTruthy();
+ it('should be created', inject([GlobalSearchService], (service1: GlobalSearchService) => {
+ expect(service1).toBeTruthy();
}));
+ it('doSearch should return data', () => {
+ service.doSearch("library").subscribe((res) => {
+ expect(res).toEqual(new SearchResults());
+ });
+
+ const req = httpMock.expectOne('/api/search?q=library');
+ expect(req.request.method).toBe('GET');
+ req.flush(new SearchResults());
+ });
});
diff --git a/src/portal/src/app/base/global-search/search-result.component.spec.ts b/src/portal/src/app/base/global-search/search-result.component.spec.ts
index 2f20cebb8..fd2ef1d45 100644
--- a/src/portal/src/app/base/global-search/search-result.component.spec.ts
+++ b/src/portal/src/app/base/global-search/search-result.component.spec.ts
@@ -5,59 +5,97 @@ import { SearchTriggerService } from './search-trigger.service';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { AppConfigService } from './../../app-config.service';
+import { ListProjectROComponent } from '../../shared/list-project-ro/list-project-ro.component';
import { MessageHandlerService } from '../../shared/message-handler/message-handler.service';
import { SearchResultComponent } from './search-result.component';
import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { of } from 'rxjs';
+import { AppConfig } from '../../app-config';
+import { ClarityModule } from '@clr/angular';
describe('SearchResultComponent', () => {
let component: SearchResultComponent;
let fixture: ComponentFixture;
let fakeSearchResults = null;
- let fakeGlobalSearchService = null;
- let fakeAppConfigService = null;
- let fakeMessageHandlerService = null;
- let fakeSearchTriggerService = {
- searchTriggerChan$: {
- pipe() {
- return {
- subscribe() {
- }
- };
- }
- },
- searchCloseChan$: {
- subscribe() {
- }
+ const project = {
+ project_id: 1,
+ owner_id: 1,
+ name: 'library',
+ creation_time: Date,
+ creation_time_str: 'string',
+ deleted: 1,
+ owner_name: 'string',
+ togglable: true,
+ update_time: Date,
+ current_user_role_id: 1,
+ repo_count: 1,
+ chart_count: 1,
+ has_project_admin_role: true,
+ is_member: true,
+ role_name: 'string',
+ metadata: {
+ public: 'string',
+ enable_content_trust: 'string',
+ prevent_vul: 'string',
+ severity: 'string',
+ auto_scan: 'string',
+ retention_id: 1
}
};
-
+ let fakeGlobalSearchService = {
+ doSearch: () => of({
+ project: [project],
+ repository: [],
+ chart: []
+ })
+ };
+ let fakeAppConfigService = {
+ getConfig: () => new AppConfig()
+ };
+ let searchResult = "";
+ let fakeMessageHandlerService = null;
+ let fakeSearchTriggerService = {
+ searchTriggerChan$: of(searchResult),
+ searchCloseChan$: of(null),
+ clear: () => null
+ };
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
- HttpClientTestingModule
- ],
- declarations: [SearchResultComponent],
- providers: [
- TranslateService,
- { provide: GlobalSearchService, useValue: fakeGlobalSearchService },
- { provide: AppConfigService, useValue: fakeAppConfigService },
- { provide: MessageHandlerService, useValue: fakeMessageHandlerService },
- { provide: SearchTriggerService, useValue: fakeSearchTriggerService },
- { provide: SearchResults, fakeSearchResults }
-
+ HttpClientTestingModule,
+ ClarityModule
],
+ declarations: [SearchResultComponent, ListProjectROComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
+ }).overrideComponent(SearchResultComponent, {
+ set: {
+ providers: [
+ TranslateService,
+ { provide: AppConfigService, useValue: fakeAppConfigService },
+ { provide: MessageHandlerService, useValue: fakeMessageHandlerService },
+ { provide: SearchTriggerService, useValue: fakeSearchTriggerService },
+ { provide: GlobalSearchService, useValue: fakeGlobalSearchService },
+ { provide: SearchResults, useValue: fakeSearchResults }
+ ]
+ }
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SearchResultComponent);
component = fixture.componentInstance;
- fixture.detectChanges();
+ component.stateIndicator = true;
+ fixture.autoDetectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
+ it('should search library', async () => {
+ searchResult = 'library';
+ component.doSearch(searchResult);
+ await fixture.whenStable();
+ expect(component.searchResults.project[0].name).toEqual('library');
+ });
});
diff --git a/src/portal/src/app/base/global-search/search-result.component.ts b/src/portal/src/app/base/global-search/search-result.component.ts
index cc03b710c..116fe326b 100644
--- a/src/portal/src/app/base/global-search/search-result.component.ts
+++ b/src/portal/src/app/base/global-search/search-result.component.ts
@@ -140,7 +140,13 @@ export class SearchResultComponent implements OnInit, OnDestroy {
// Call search service to complete the search request
doSearch(term: string): void {
// Only search none empty term
+ // If term is empty, then clear the results
if (!term || term.trim() === "") {
+ this.searchResults.project = [];
+ this.searchResults.repository = [];
+ if (this.withHelmChart) {
+ this.searchResults.chart = [];
+ }
return;
}
// Do nothing if search is ongoing
@@ -154,15 +160,6 @@ export class SearchResultComponent implements OnInit, OnDestroy {
this.currentTerm = term;
- // If term is empty, then clear the results
- if (term === "") {
- this.searchResults.project = [];
- this.searchResults.repository = [];
- if (this.withHelmChart) {
- this.searchResults.chart = [];
- }
- return;
- }
// Show spinner
this.onGoing = true;
diff --git a/src/portal/src/app/base/harbor-shell/harbor-shell.component.spec.ts b/src/portal/src/app/base/harbor-shell/harbor-shell.component.spec.ts
index ee35e610e..9c192922b 100644
--- a/src/portal/src/app/base/harbor-shell/harbor-shell.component.spec.ts
+++ b/src/portal/src/app/base/harbor-shell/harbor-shell.component.spec.ts
@@ -10,6 +10,16 @@ import { HarborShellComponent } from './harbor-shell.component';
import { ClarityModule } from "@clr/angular";
import { of } from 'rxjs';
import { ConfigScannerService } from "../../config/scanner/config-scanner.service";
+import { modalEvents } from '../modal-events.const';
+import { AccountSettingsModalComponent } from '../../account/account-settings/account-settings-modal.component';
+import { PasswordSettingComponent } from '../../account/password-setting/password-setting.component';
+import { AboutDialogComponent } from '../../shared/about-dialog/about-dialog.component';
+import { FormsModule } from '@angular/forms';
+import { MessageHandlerService } from '../../shared/message-handler/message-handler.service';
+import { AccountSettingsModalService } from '../../account/account-settings/account-settings-modal-service.service';
+import { PasswordSettingService } from '../../account/password-setting/password-setting.service';
+import { SkinableConfig } from '../../skinable-config.service';
+import { InlineAlertComponent } from '../../shared/inline-alert/inline-alert.component';
describe('HarborShellComponent', () => {
let component: HarborShellComponent;
@@ -20,13 +30,18 @@ describe('HarborShellComponent', () => {
}
};
let fakeSearchTriggerService = {
- searchTriggerChan$: {
- subscribe: function () {
- }
- },
- searchCloseChan$: {
- subscribe: function () {
- }
+ searchTriggerChan$: of('null')
+ ,
+ searchCloseChan$: of(null)
+ };
+ let mockMessageHandlerService = null;
+ let mockAccountSettingsModalService = null;
+ let mockPasswordSettingService = null;
+ let mockSkinableConfig = {
+ getProject: function () {
+ return {
+ introduction: {}
+ };
}
};
let fakeAppConfigService = {
@@ -56,15 +71,21 @@ describe('HarborShellComponent', () => {
RouterTestingModule,
TranslateModule.forRoot(),
ClarityModule,
- BrowserAnimationsModule
+ BrowserAnimationsModule,
+ FormsModule
],
- declarations: [HarborShellComponent],
+ declarations: [HarborShellComponent, AccountSettingsModalComponent
+ , PasswordSettingComponent, AboutDialogComponent, InlineAlertComponent],
providers: [
TranslateService,
{ provide: SessionService, useValue: fakeSessionService },
{ provide: SearchTriggerService, useValue: fakeSearchTriggerService },
{ provide: AppConfigService, useValue: fakeAppConfigService },
- { provide: ConfigScannerService, useValue: fakeConfigScannerService }
+ { provide: ConfigScannerService, useValue: fakeConfigScannerService },
+ { provide: MessageHandlerService, useValue: mockMessageHandlerService },
+ { provide: AccountSettingsModalService, useValue: mockAccountSettingsModalService },
+ { provide: PasswordSettingService, useValue: mockPasswordSettingService },
+ { provide: SkinableConfig, useValue: mockSkinableConfig },
],
schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA]
}).compileComponents();
@@ -74,10 +95,32 @@ describe('HarborShellComponent', () => {
fixture = TestBed.createComponent(HarborShellComponent);
component = fixture.componentInstance;
component.showScannerInfo = true;
- fixture.detectChanges();
+ component.accountSettingsModal = TestBed.createComponent(AccountSettingsModalComponent).componentInstance;
+ component.accountSettingsModal.inlineAlert = TestBed.createComponent(InlineAlertComponent).componentInstance;
+ component.pwdSetting = TestBed.createComponent(PasswordSettingComponent).componentInstance;
+ component.aboutDialog = TestBed.createComponent(AboutDialogComponent).componentInstance;
+ fixture.autoDetectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
+ it('should open users profile', async () => {
+ component.openModal({modalName: modalEvents.USER_PROFILE, modalFlag: false });
+ await fixture.whenStable();
+ const accountSettingsUsernameInput = fixture.nativeElement.querySelector("#account_settings_username");
+ expect(accountSettingsUsernameInput).toBeTruthy();
+ });
+ it('should open users changPwd', async () => {
+ component.openModal({modalName: modalEvents.CHANGE_PWD, modalFlag: false });
+ await fixture.whenStable();
+ const oldPasswordInput = fixture.nativeElement.querySelector("#oldPassword");
+ expect(oldPasswordInput).toBeTruthy();
+ });
+ it('should open users about-dialog', async () => {
+ component.openModal({modalName: modalEvents.ABOUT, modalFlag: false });
+ await fixture.whenStable();
+ const aboutVersionEl = fixture.nativeElement.querySelector(".about-version");
+ expect(aboutVersionEl).toBeTruthy();
+ });
});
diff --git a/src/portal/src/app/config/auth/config-auth.component.html b/src/portal/src/app/config/auth/config-auth.component.html
index 1aecd99fc..794249a8c 100644
--- a/src/portal/src/app/config/auth/config-auth.component.html
+++ b/src/portal/src/app/config/auth/config-auth.component.html
@@ -399,7 +399,7 @@
[disabled]="!isValid() || !hasChanges()">{{'BUTTON.SAVE' | translate}}
-
\ No newline at end of file
diff --git a/src/portal/src/app/config/auth/config-auth.component.spec.ts b/src/portal/src/app/config/auth/config-auth.component.spec.ts
index 74032eed9..0a5f1cd7a 100644
--- a/src/portal/src/app/config/auth/config-auth.component.spec.ts
+++ b/src/portal/src/app/config/auth/config-auth.component.spec.ts
@@ -5,18 +5,29 @@ import { AppConfigService } from '../../app-config.service';
import { ConfigurationService } from '../config.service';
import { ConfigurationAuthComponent } from './config-auth.component';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
-import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { CUSTOM_ELEMENTS_SCHEMA, SimpleChange } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { of } from 'rxjs';
import { ErrorHandler } from "../../../lib/utils/error-handler";
import { SystemInfoService } from "../../../lib/services";
+import { Configuration } from '../../../lib/components/config/config';
+import { clone } from '../../../lib/utils/utils';
+import { CONFIG_AUTH_MODE } from '../../../lib/entities/shared.const';
describe('ConfigurationAuthComponent', () => {
let component: ConfigurationAuthComponent;
let fixture: ComponentFixture;
- let fakeMessageHandlerService = null;
- let fakeConfigurationService = null;
- let fakeAppConfigService = null;
+ let fakeMessageHandlerService = {
+ showSuccess: () => null
+ };
+ let fakeConfigurationService = {
+ saveConfiguration: () => of(null),
+ testLDAPServer: () => of(null),
+ testOIDCServer: () => of(null)
+ };
+ let fakeAppConfigService = {
+ load: () => of(null)
+ };
let fakeConfirmMessageService = null;
let fakeSystemInfoService = {
getSystemInfo: function () {
@@ -49,10 +60,46 @@ describe('ConfigurationAuthComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(ConfigurationAuthComponent);
component = fixture.componentInstance;
- fixture.detectChanges();
+ (component as any).originalConfig = clone(component.currentConfig);
+ fixture.autoDetectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
+
+ it('should save configuration', async () => {
+ const selfRegInput: HTMLInputElement = fixture.nativeElement.querySelector("#selfReg");
+ selfRegInput.dispatchEvent(new Event('click'));
+ component.currentConfig.self_registration.value = true;
+ await fixture.whenStable();
+ const configAuthSaveBtn: HTMLButtonElement = fixture.nativeElement.querySelector("#config_auth_save");
+ component.onGoing = true;
+ configAuthSaveBtn.dispatchEvent(new Event('click'));
+ await fixture.whenStable();
+ expect(component.onGoing).toBeFalsy();
+ });
+ it('should select ldap or uaa', () => {
+ component.handleOnChange({target: {value: 'ldap_auth'}});
+ expect(component.currentConfig.self_registration.value).toEqual(false);
+ });
+ it('should ping test server when ldap', async () => {
+ component.currentConfig.auth_mode.value = CONFIG_AUTH_MODE.LDAP_AUTH;
+ component.currentConfig.ldap_scope.value = 123456;
+ await fixture.whenStable();
+ const pingTestBtn = fixture.nativeElement.querySelector("#ping-test");
+ expect(pingTestBtn).toBeTruthy();
+ pingTestBtn.dispatchEvent(new Event('click'));
+ await fixture.whenStable();
+ expect(component.testingOnGoing).toBeFalsy();
+ });
+ it('should ping test server when oidc', async () => {
+ component.currentConfig.auth_mode.value = CONFIG_AUTH_MODE.OIDC_AUTH;
+ await fixture.whenStable();
+ const pingTestBtn = fixture.nativeElement.querySelector("#ping-test");
+ expect(pingTestBtn).toBeTruthy();
+ pingTestBtn.dispatchEvent(new Event('click'));
+ await fixture.whenStable();
+ expect(component.testingOnGoing).toBeFalsy();
+ });
});
diff --git a/src/portal/src/app/config/config.component.spec.ts b/src/portal/src/app/config/config.component.spec.ts
index b08f679c4..53bde1217 100644
--- a/src/portal/src/app/config/config.component.spec.ts
+++ b/src/portal/src/app/config/config.component.spec.ts
@@ -8,17 +8,43 @@ import { ClarityModule } from "@clr/angular";
import { AppConfigService } from '../app-config.service';
import { ConfigurationService } from './config.service';
import { ConfigurationComponent } from './config.component';
+import { of } from 'rxjs';
+import { ConfirmationAcknowledgement } from '../shared/confirmation-dialog/confirmation-state-message';
+import { ConfirmationState, ConfirmationTargets } from '../shared/shared.const';
+import { Configuration } from '../../lib/components/config/config';
describe('ConfigurationComponent', () => {
let component: ConfigurationComponent;
let fixture: ComponentFixture;
- let fakeConfirmationDialogService = {
- confirmationConfirm$: {
- subscribe: function () {
- }
- }
+ let confirmationConfirmFlag = true;
+ let confirmationConfirm = () => {
+ return confirmationConfirmFlag ? of(new ConfirmationAcknowledgement(ConfirmationState.CONFIRMED, {}, ConfirmationTargets.CONFIG))
+ : of(new ConfirmationAcknowledgement(ConfirmationState.CONFIRMED
+ , {change: { email_password: 'Harbor12345' }, tabId: '1'}, ConfirmationTargets.CONFIG_TAB));
+ };
+ let fakeConfirmationDialogService = {
+ confirmationConfirm$: confirmationConfirm()
+ };
+ let mockConfigurationService = {
+ getConfiguration: () => of(new Configuration()),
+ confirmationConfirm$: of(new ConfirmationAcknowledgement(ConfirmationState.CONFIRMED, {}, ConfirmationTargets.CONFIG))
+ };
+ let fakeSessionService = {
+ getCurrentUser: function () {
+ return {
+ has_admin_role: true,
+ user_id: 1,
+ username: 'admin',
+ email: "",
+ realname: "admin",
+ role_name: "admin",
+ role_id: 1,
+ comment: "string",
+ };
+ },
+ updateAccountSettings: () => of(null),
+ renameAdmin: () => of(null),
};
-
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
@@ -37,6 +63,7 @@ describe('ConfigurationComponent', () => {
}
},
{ provide: ConfirmationDialogService, useValue: fakeConfirmationDialogService },
+ { provide: SessionService, useValue: fakeSessionService },
{ provide: MessageHandlerService, useValue: null },
{
provide: AppConfigService, useValue: {
@@ -46,12 +73,7 @@ describe('ConfigurationComponent', () => {
}
},
{
- provide: ConfigurationService, useValue: {
- confirmationConfirm$: {
- subscribe: function () {
- }
- }
- }
+ provide: ConfigurationService, useValue: mockConfigurationService
}
]
}).compileComponents();
@@ -66,4 +88,16 @@ describe('ConfigurationComponent', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
+ it('should reset part of allConfig ', async () => {
+ confirmationConfirmFlag = false;
+ component.originalCopy.email_password.value = 'Harbor12345';
+ component.reset({
+ email_password: {
+ value: 'Harbor12345',
+ editable: true
+ }
+ });
+ await fixture.whenStable();
+ expect(component.allConfig.email_password.value).toEqual('Harbor12345');
+ });
});
diff --git a/src/portal/src/app/config/config.component.ts b/src/portal/src/app/config/config.component.ts
index 2d5ef8921..86acbf585 100644
--- a/src/portal/src/app/config/config.component.ts
+++ b/src/portal/src/app/config/config.component.ts
@@ -70,13 +70,6 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
return this.appConfigService.getConfig().with_admiral;
}
- isCurrentTabLink(tabId: string): boolean {
- return this.currentTabId === tabId;
- }
-
- isCurrentTabContent(contentId: string): boolean {
- return TabLinkContentMap[this.currentTabId] === contentId;
- }
refreshAllconfig() {
this.retrieveConfig();
}
@@ -124,10 +117,6 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
, error => console.error('Failed to reload bootstrap option with error: ', error));
}
- public tabLinkClick(tabLink: string) {
- this.currentTabId = tabLink;
- }
-
retrieveConfig(): void {
this.onGoing = true;
this.configService.getConfiguration()
diff --git a/src/portal/src/app/config/email/config-email.component.html b/src/portal/src/app/config/email/config-email.component.html
index 2e8aaa57e..b5a4ae5a4 100644
--- a/src/portal/src/app/config/email/config-email.component.html
+++ b/src/portal/src/app/config/email/config-email.component.html
@@ -79,7 +79,7 @@
| translate}}
-