Merge pull request 'angular tests' (#19) from feature/tests into develop
Reviewed-on: Natlinux/DotNetAngular#19
This commit was merged in pull request #19.
This commit is contained in:
+55
-31
@@ -19,10 +19,33 @@
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="1ac72a4a-52ad-4e70-9b15-c330b1ed3e7a" name="Changes" comment="">
|
||||
<change afterPath="$PROJECT_DIR$/src/ClientApp/src/app/infrastructure/utilities/reset-password-validator.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/.idea.DotNetAngular/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.DotNetAngular/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tests/Application.FunctionalTest/UnitTest1.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tests/Application.UnitTest/Application.UnitTest.csproj" beforeDir="false" afterPath="$PROJECT_DIR$/tests/Application.UnitTest/Application.UnitTest.csproj" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tests/Application.UnitTest/UnitTest1.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/package-lock.json" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/package-lock.json" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/package.json" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/app.component.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/app.component.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/infrastructure/services/auth-service.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/infrastructure/services/auth-service.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/infrastructure/services/dark-mode.service.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/infrastructure/services/dark-mode.service.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/infrastructure/services/loading.service.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/infrastructure/services/loading.service.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/infrastructure/services/reset-password.service.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/infrastructure/services/reset-password.service.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/infrastructure/services/toast.service.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/infrastructure/services/toast.service.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/infrastructure/services/user-store.service.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/infrastructure/services/user-store.service.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/infrastructure/services/user.service.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/infrastructure/services/user.service.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/infrastructure/utilities/password-validator.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/infrastructure/utilities/password-validator.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/infrastructure/utilities/validate-form.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/infrastructure/utilities/validate-form.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/authentication/forget-password-popup/forget-password-popup.component.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/authentication/forget-password-popup/forget-password-popup.component.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/authentication/login/login.component.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/authentication/login/login.component.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/authentication/register/register.component.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/authentication/register/register.component.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/authentication/reset-password/reset-password.component.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/authentication/reset-password/reset-password.component.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/components/admin-dashboard/admin-dashboard.component.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/components/admin-dashboard/admin-dashboard.component.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/components/footer/footer.component.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/components/footer/footer.component.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/components/header/header.component.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/components/header/header.component.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/components/user-dashboard/user-dashboard.component.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/components/user-dashboard/user-dashboard.component.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/components/user-table/user-table.component.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/components/user-table/user-table.component.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/guards/admin.guard.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/guards/admin.guard.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/guards/authentication.guard.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/guards/authentication.guard.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/guards/guest.guard.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/guards/guest.guard.spec.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/interceptors/token.interceptor.spec.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ClientApp/src/app/presentation/interceptors/token.interceptor.spec.ts" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
@@ -33,13 +56,13 @@
|
||||
<option name="firstShow" value="false" />
|
||||
</component>
|
||||
<component name="EmbeddingIndexingInfo">
|
||||
<option name="cachedIndexableFilesCount" value="7" />
|
||||
<option name="cachedIndexableFilesCount" value="1" />
|
||||
<option name="fileBasedEmbeddingIndicesEnabled" value="true" />
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_BRANCH_BY_REPOSITORY">
|
||||
<map>
|
||||
<entry key="$PROJECT_DIR$" value="feature/angular" />
|
||||
<entry key="$PROJECT_DIR$" value="develop" />
|
||||
</map>
|
||||
</option>
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
@@ -65,33 +88,33 @@
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent">{
|
||||
"keyToString": {
|
||||
".NET Launch Settings Profile.API: Angular_dev.executor": "Run",
|
||||
"RunOnceActivity.MCP Project settings loaded": "true",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
|
||||
"RunOnceActivity.cidr.known.project.marker": "true",
|
||||
"RunOnceActivity.git.unshallow": "true",
|
||||
"RunOnceActivity.readMode.enableVisualFormatting": "true",
|
||||
"RunOnceActivity.typescript.service.memoryLimit.init": "true",
|
||||
"cidr.known.project.marker": "true",
|
||||
"codeWithMe.voiceChat.enabledByDefault": "false",
|
||||
"com.intellij.ml.llm.matterhorn.ej.ui.settings.DefaultModelSelectionForGA.v1": "true",
|
||||
"git-widget-placeholder": "develop",
|
||||
"git.auto.fetch.suggestion.counter": "1",
|
||||
"junie.onboarding.icon.badge.shown": "true",
|
||||
"node.js.detected.package.eslint": "true",
|
||||
"node.js.detected.package.tslint": "true",
|
||||
"node.js.selected.package.eslint": "(autodetect)",
|
||||
"node.js.selected.package.tslint": "(autodetect)",
|
||||
"nodejs_package_manager_path": "npm",
|
||||
"settings.editor.selected.configurable": "vcs.Git",
|
||||
"to.speed.mode.migration.done": "true",
|
||||
"ts.external.directory.path": "/home/natlinux/RiderProjects/DotNetAngular/src/ClientApp/node_modules/typescript/lib",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
<component name="PropertiesComponent"><![CDATA[{
|
||||
"keyToString": {
|
||||
".NET Launch Settings Profile.API: Angular_dev.executor": "Run",
|
||||
"RunOnceActivity.MCP Project settings loaded": "true",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
|
||||
"RunOnceActivity.cidr.known.project.marker": "true",
|
||||
"RunOnceActivity.git.unshallow": "true",
|
||||
"RunOnceActivity.readMode.enableVisualFormatting": "true",
|
||||
"RunOnceActivity.typescript.service.memoryLimit.init": "true",
|
||||
"cidr.known.project.marker": "true",
|
||||
"codeWithMe.voiceChat.enabledByDefault": "false",
|
||||
"com.intellij.ml.llm.matterhorn.ej.ui.settings.DefaultModelSelectionForGA.v1": "true",
|
||||
"git-widget-placeholder": "feature/tests",
|
||||
"git.auto.fetch.suggestion.counter": "1",
|
||||
"junie.onboarding.icon.badge.shown": "true",
|
||||
"node.js.detected.package.eslint": "true",
|
||||
"node.js.detected.package.tslint": "true",
|
||||
"node.js.selected.package.eslint": "(autodetect)",
|
||||
"node.js.selected.package.tslint": "(autodetect)",
|
||||
"nodejs_package_manager_path": "npm",
|
||||
"settings.editor.selected.configurable": "vcs.Git",
|
||||
"to.speed.mode.migration.done": "true",
|
||||
"ts.external.directory.path": "/home/natlinux/RiderProjects/DotNetAngular/src/ClientApp/node_modules/typescript/lib",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
}
|
||||
}</component>
|
||||
}]]></component>
|
||||
<component name="RecapUselessUpdatesCounter">
|
||||
<option name="suspendCountdown" value="0" />
|
||||
</component>
|
||||
@@ -236,6 +259,7 @@
|
||||
<workItem from="1773678089390" duration="1025000" />
|
||||
<workItem from="1777730558210" duration="1422000" />
|
||||
<workItem from="1778341026510" duration="1284000" />
|
||||
<workItem from="1778343547356" duration="1390000" />
|
||||
</task>
|
||||
<task id="LOCAL-00001" summary="updating template">
|
||||
<option name="closed" value="true" />
|
||||
|
||||
Generated
+922
File diff suppressed because it is too large
Load Diff
@@ -38,8 +38,10 @@
|
||||
"karma": "~6.4.0",
|
||||
"karma-chrome-launcher": "~3.2.0",
|
||||
"karma-coverage": "~2.2.0",
|
||||
"karma-firefox-launcher": "^2.1.3",
|
||||
"karma-jasmine": "~5.1.0",
|
||||
"karma-jasmine-html-reporter": "~2.1.0",
|
||||
"puppeteer": "^24.43.0",
|
||||
"typescript": "~5.9.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,23 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {AppComponent} from './app.component';
|
||||
import {AuthService} from './infrastructure/services/auth-service';
|
||||
import {ActivatedRoute, provideRouter} from '@angular/router';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async () => {
|
||||
localStorage.clear();
|
||||
const authSpy = jasmine.createSpyObj('AuthService', [
|
||||
'getUsernameFromToken', 'getRoleFromToken', 'getEmailFromToken', 'getUserIdFromToken',
|
||||
'isLoggedIn', 'getToken', 'signOut', 'decodedToken'
|
||||
]);
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [AppComponent],
|
||||
providers: [
|
||||
provideRouter([]),
|
||||
{provide: AuthService, useValue: authSpy},
|
||||
{provide: ActivatedRoute, useValue: {snapshot: {data: {}}, firstChild: null}},
|
||||
]
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
@@ -19,11 +32,4 @@ describe('AppComponent', () => {
|
||||
const app = fixture.componentInstance;
|
||||
expect(app.title).toEqual('ClientApp');
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement as HTMLElement;
|
||||
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, ClientApp');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,22 +1,45 @@
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {provideHttpClient} from '@angular/common/http';
|
||||
import {AuthService} from './auth-service';
|
||||
import {TestBed} from "@angular/core/testing";
|
||||
import {provideHttpClient} from "@angular/common/http";
|
||||
import {ActivatedRoute} from "@angular/router";
|
||||
import {of} from "rxjs";
|
||||
|
||||
describe('AuthService', () => {
|
||||
let service: AuthService;
|
||||
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
TestBed.configureTestingModule({
|
||||
providers: [provideHttpClient(),
|
||||
{ provide: ActivatedRoute, useValue: { data: of({}), firstChild: null } }
|
||||
]
|
||||
providers: [provideHttpClient()]
|
||||
});
|
||||
service = TestBed.inject(AuthService);
|
||||
})
|
||||
});
|
||||
|
||||
it('should create an instance', () => {
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should store and retrieve token', () => {
|
||||
service.storeToken('test-token');
|
||||
expect(service.getToken()).toBe('test-token');
|
||||
});
|
||||
|
||||
it('should store and retrieve refresh token', () => {
|
||||
service.storeRefreshToken('test-refresh');
|
||||
expect(service.getRefreshToken()).toBe('test-refresh');
|
||||
});
|
||||
|
||||
it('should be logged in after storing token', () => {
|
||||
service.storeToken('some-token');
|
||||
expect(service.isLoggedIn()).toBeTrue();
|
||||
});
|
||||
|
||||
it('should not be logged in without token', () => {
|
||||
expect(service.isLoggedIn()).toBeFalse();
|
||||
});
|
||||
|
||||
it('should clear tokens on signOut', () => {
|
||||
service.storeToken('test-token');
|
||||
service.storeRefreshToken('test-refresh');
|
||||
service.signOut();
|
||||
expect(service.isLoggedIn()).toBeFalse();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
|
||||
import {DarkModeService} from './dark-mode.service';
|
||||
|
||||
describe('DarkModeService', () => {
|
||||
@@ -13,4 +12,16 @@ describe('DarkModeService', () => {
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should toggle from null to dark', () => {
|
||||
service.darkModeSignal.set(null);
|
||||
service.updateDarkMode();
|
||||
expect(service.darkModeSignal()).toBe('dark');
|
||||
});
|
||||
|
||||
it('should toggle from dark to null', () => {
|
||||
service.darkModeSignal.set('dark');
|
||||
service.updateDarkMode();
|
||||
expect(service.darkModeSignal()).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LoadingService } from './loading.service';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {LoadingService} from './loading.service';
|
||||
|
||||
describe('LoadingService', () => {
|
||||
let service: LoadingService;
|
||||
@@ -13,4 +12,26 @@ describe('LoadingService', () => {
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should start with loading false', () => {
|
||||
expect(service.loading()).toBeFalse();
|
||||
});
|
||||
|
||||
it('should set loading true on show()', () => {
|
||||
service.show();
|
||||
expect(service.loading()).toBeTrue();
|
||||
});
|
||||
|
||||
it('should set loading false on hide()', () => {
|
||||
service.show();
|
||||
service.hide();
|
||||
expect(service.loading()).toBeFalse();
|
||||
});
|
||||
|
||||
it('should track per-item loading state', () => {
|
||||
service.showItem('item-1');
|
||||
expect(service.itemLoading()['item-1']).toBeTrue();
|
||||
service.hideItem('item-1');
|
||||
expect(service.itemLoading()['item-1']).toBeFalse();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,23 +1,47 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ResetPasswordService } from './reset-password.service';
|
||||
import {provideHttpClient} from "@angular/common/http";
|
||||
import {ActivatedRoute} from "@angular/router";
|
||||
import {of} from "rxjs";
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {provideHttpClient} from '@angular/common/http';
|
||||
import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing';
|
||||
import {ResetPasswordService} from './reset-password.service';
|
||||
import {environment} from '../../../environments/environment.development';
|
||||
|
||||
describe('ResetPasswordService', () => {
|
||||
let service: ResetPasswordService;
|
||||
let httpTesting: HttpTestingController;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [provideHttpClient(),
|
||||
{ provide: ActivatedRoute, useValue: { data: of({}), firstChild: null } }
|
||||
providers: [
|
||||
provideHttpClient(),
|
||||
provideHttpClientTesting(),
|
||||
]
|
||||
});
|
||||
service = TestBed.inject(ResetPasswordService);
|
||||
httpTesting = TestBed.inject(HttpTestingController);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
httpTesting.verify();
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should POST to send-reset-email on sendResetPasswordLink', () => {
|
||||
service.sendResetPasswordLink('test@example.com').subscribe();
|
||||
|
||||
const req = httpTesting.expectOne(`${environment.baseUrl}auth/send-reset-email/test@example.com`);
|
||||
expect(req.request.method).toBe('POST');
|
||||
req.flush({value: 'Reset email sent successfully'});
|
||||
});
|
||||
|
||||
it('should POST to reset-password on resetPassword', () => {
|
||||
const resetObj = {email: 'test@example.com', emailToken: 'token', newPassword: 'NewPass1!', confirmPassword: 'NewPass1!'};
|
||||
service.resetPassword(resetObj).subscribe();
|
||||
|
||||
const req = httpTesting.expectOne(`${environment.baseUrl}auth/reset-password`);
|
||||
expect(req.request.method).toBe('POST');
|
||||
expect(req.request.body).toEqual(resetObj);
|
||||
req.flush({value: 'Password reset successfully'});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
|
||||
import {ToastService} from './toast.service';
|
||||
|
||||
describe('ToastService', () => {
|
||||
@@ -13,4 +12,29 @@ describe('ToastService', () => {
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should start with empty toasts', () => {
|
||||
expect(service.toasts.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should add a toast', () => {
|
||||
service.show('Test message');
|
||||
expect(service.toasts.length).toBe(1);
|
||||
expect(service.toasts[0].message).toBe('Test message');
|
||||
});
|
||||
|
||||
it('should add a toast with options', () => {
|
||||
service.show('Warning', {classname: 'bg-warning', delay: 3000});
|
||||
expect(service.toasts[0].classname).toBe('bg-warning');
|
||||
expect(service.toasts[0].delay).toBe(3000);
|
||||
});
|
||||
|
||||
it('should remove a toast', () => {
|
||||
service.show('Message 1');
|
||||
service.show('Message 2');
|
||||
const toastToRemove = service.toasts[0];
|
||||
service.remove(toastToRemove);
|
||||
expect(service.toasts.length).toBe(1);
|
||||
expect(service.toasts[0].message).toBe('Message 2');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
|
||||
import {UserStoreService} from './user-store.service';
|
||||
|
||||
describe('UserStoreService', () => {
|
||||
@@ -13,4 +12,35 @@ describe('UserStoreService', () => {
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should set and get username', (done) => {
|
||||
service.setUsernameForStore('testuser');
|
||||
service.getUsernameFromStore().subscribe(val => {
|
||||
expect(val).toBe('testuser');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should set and get role', (done) => {
|
||||
service.setRoleForStore('Admin');
|
||||
service.getRoleFromStore().subscribe(val => {
|
||||
expect(val).toBe('Admin');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should set and get email', (done) => {
|
||||
service.setEmailForStore('test@example.com');
|
||||
service.getEmailFromStore().subscribe(val => {
|
||||
expect(val).toBe('test@example.com');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should start with empty defaults', (done) => {
|
||||
service.getUsernameFromStore().subscribe(val => {
|
||||
expect(val).toBe('');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,23 +1,49 @@
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
|
||||
import {provideHttpClient} from '@angular/common/http';
|
||||
import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing';
|
||||
import {UserService} from './user.service';
|
||||
import {provideHttpClient} from "@angular/common/http";
|
||||
import {ActivatedRoute} from "@angular/router";
|
||||
import {of} from "rxjs";
|
||||
import {environment} from '../../../environments/environment.development';
|
||||
|
||||
describe('UserService', () => {
|
||||
let service: UserService;
|
||||
let httpTesting: HttpTestingController;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [provideHttpClient(),
|
||||
{ provide: ActivatedRoute, useValue: { data: of({}), firstChild: null } }
|
||||
providers: [
|
||||
provideHttpClient(),
|
||||
provideHttpClientTesting(),
|
||||
]
|
||||
});
|
||||
service = TestBed.inject(UserService);
|
||||
httpTesting = TestBed.inject(HttpTestingController);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
httpTesting.verify();
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should call GET with page params on getAllUsers', () => {
|
||||
service.getAllUsers(1, 10).subscribe();
|
||||
|
||||
const req = httpTesting.expectOne(r =>
|
||||
r.url === `${environment.baseUrl}user` &&
|
||||
r.params.get('pageNumber') === '1' &&
|
||||
r.params.get('pageSize') === '10'
|
||||
);
|
||||
expect(req.request.method).toBe('GET');
|
||||
req.flush({value: {items: [], totalPages: 1}});
|
||||
});
|
||||
|
||||
it('should call DELETE on deleteUser', () => {
|
||||
service.deleteUser(5).subscribe();
|
||||
|
||||
const req = httpTesting.expectOne(`${environment.baseUrl}user/5`);
|
||||
expect(req.request.method).toBe('DELETE');
|
||||
req.flush({value: 'User deleted successfully'});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,47 @@
|
||||
import { PasswordValidator } from './password-validator';
|
||||
import {FormControl} from '@angular/forms';
|
||||
import {PasswordValidator} from './password-validator';
|
||||
|
||||
describe('PasswordValidator', () => {
|
||||
it('should create an instance', () => {
|
||||
expect(new PasswordValidator()).toBeTruthy();
|
||||
it('should return null for a valid strong password', () => {
|
||||
const control = new FormControl('ValidP@ss1');
|
||||
const result = PasswordValidator.strong(control);
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('should return uppercase error when password has no uppercase', () => {
|
||||
const control = new FormControl('lowercase1@');
|
||||
const result = PasswordValidator.strong(control);
|
||||
expect(result?.['uppercase']).toBeTrue();
|
||||
});
|
||||
|
||||
it('should return lowercase error when password has no lowercase', () => {
|
||||
const control = new FormControl('UPPERCASE1@');
|
||||
const result = PasswordValidator.strong(control);
|
||||
expect(result?.['lowercase']).toBeTrue();
|
||||
});
|
||||
|
||||
it('should return number error when password has no digit', () => {
|
||||
const control = new FormControl('NoDigit@aa');
|
||||
const result = PasswordValidator.strong(control);
|
||||
expect(result?.['number']).toBeTrue();
|
||||
});
|
||||
|
||||
it('should return special error when password has no special character', () => {
|
||||
const control = new FormControl('NoSpecialChar1');
|
||||
const result = PasswordValidator.strong(control);
|
||||
expect(result?.['special']).toBeTrue();
|
||||
});
|
||||
|
||||
it('should return minlength error when password is too short', () => {
|
||||
const control = new FormControl('Sh0rt!');
|
||||
const result = PasswordValidator.strong(control);
|
||||
expect(result?.['minlength']).toBeTrue();
|
||||
});
|
||||
|
||||
it('should return multiple errors for a completely invalid password', () => {
|
||||
const control = new FormControl('');
|
||||
const result = PasswordValidator.strong(control);
|
||||
expect(result).not.toBeNull();
|
||||
expect(Object.keys(result!).length).toBeGreaterThan(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import {FormControl, FormGroup, ValidatorFn} from '@angular/forms';
|
||||
import {ConfirmPasswordValidator} from './reset-password-validator';
|
||||
|
||||
describe('ConfirmPasswordValidator', () => {
|
||||
const createForm = (password: string, confirm: string) => {
|
||||
return new FormGroup({
|
||||
password: new FormControl(password),
|
||||
confirmPassword: new FormControl(confirm),
|
||||
}, {validators: ConfirmPasswordValidator('password', 'confirmPassword') as ValidatorFn});
|
||||
};
|
||||
|
||||
it('should set error when passwords do not match', () => {
|
||||
const form = createForm('Pass123!', 'Different!');
|
||||
form.updateValueAndValidity();
|
||||
expect(form.get('confirmPassword')?.errors?.['ConfirmPasswordValidator']).toBeTrue();
|
||||
});
|
||||
|
||||
it('should not set error when passwords match', () => {
|
||||
const form = createForm('Pass123!', 'Pass123!');
|
||||
form.updateValueAndValidity();
|
||||
expect(form.get('confirmPassword')?.errors).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -1,7 +1,30 @@
|
||||
import {FormControl, FormGroup, Validators} from '@angular/forms';
|
||||
import ValidateForm from './validate-form';
|
||||
|
||||
describe('ValidateForm', () => {
|
||||
it('should create an instance', () => {
|
||||
expect(new ValidateForm()).toBeTruthy();
|
||||
it('should mark all controls as dirty', () => {
|
||||
const form = new FormGroup({
|
||||
name: new FormControl('', Validators.required),
|
||||
email: new FormControl('', Validators.required),
|
||||
});
|
||||
ValidateForm.validateAllFormFields(form);
|
||||
expect(form.get('name')?.dirty).toBeTrue();
|
||||
expect(form.get('email')?.dirty).toBeTrue();
|
||||
});
|
||||
|
||||
it('should recursively mark nested form groups', () => {
|
||||
const form = new FormGroup({
|
||||
user: new FormGroup({
|
||||
name: new FormControl('', Validators.required),
|
||||
}),
|
||||
});
|
||||
ValidateForm.validateAllFormFields(form);
|
||||
const userGroup = form.get('user') as FormGroup;
|
||||
expect(userGroup.get('name')?.dirty).toBeTrue();
|
||||
});
|
||||
|
||||
it('should not throw for empty form group', () => {
|
||||
const form = new FormGroup({});
|
||||
expect(() => ValidateForm.validateAllFormFields(form)).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
+53
-10
@@ -1,24 +1,32 @@
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import {ForgetPasswordPopupComponent} from './forget-password-popup.component';
|
||||
import {NgbActiveModal} from "@ng-bootstrap/ng-bootstrap";
|
||||
import {provideHttpClient} from "@angular/common/http";
|
||||
import {ActivatedRoute} from "@angular/router";
|
||||
import {of} from "rxjs";
|
||||
import {NgbActiveModal} from '@ng-bootstrap/ng-bootstrap';
|
||||
import {ResetPasswordService} from '../../../infrastructure/services/reset-password.service';
|
||||
import {ToastService} from '../../../infrastructure/services/toast.service';
|
||||
import {LoadingService} from '../../../infrastructure/services/loading.service';
|
||||
import {of, throwError} from 'rxjs';
|
||||
|
||||
describe('ForgetPasswordPopupComponent', () => {
|
||||
let component: ForgetPasswordPopupComponent;
|
||||
let fixture: ComponentFixture<ForgetPasswordPopupComponent>;
|
||||
let resetService: jasmine.SpyObj<ResetPasswordService>;
|
||||
let toastService: jasmine.SpyObj<ToastService>;
|
||||
let activeModal: jasmine.SpyObj<NgbActiveModal>;
|
||||
|
||||
beforeEach(async () => {
|
||||
resetService = jasmine.createSpyObj('ResetPasswordService', ['sendResetPasswordLink']);
|
||||
toastService = jasmine.createSpyObj('ToastService', ['show']);
|
||||
activeModal = jasmine.createSpyObj('NgbActiveModal', ['close']);
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ForgetPasswordPopupComponent],
|
||||
providers: [provideHttpClient(),
|
||||
{ provide: ActivatedRoute, useValue: { data: of({}), firstChild: null } },
|
||||
NgbActiveModal
|
||||
providers: [
|
||||
{provide: ResetPasswordService, useValue: resetService},
|
||||
{provide: ToastService, useValue: toastService},
|
||||
{provide: NgbActiveModal, useValue: activeModal},
|
||||
LoadingService,
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ForgetPasswordPopupComponent);
|
||||
component = fixture.componentInstance;
|
||||
@@ -28,4 +36,39 @@ describe('ForgetPasswordPopupComponent', () => {
|
||||
it('should create ForgetPasswordPopupComponent', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should validate email format', () => {
|
||||
expect(component.checkValidEmail('invalid')).toBeFalse();
|
||||
expect(component.checkValidEmail('test@example.com')).toBeTrue();
|
||||
expect(component.isValidEmail).toBeTrue();
|
||||
});
|
||||
|
||||
it('should call sendResetPasswordLink on confirm with valid email', () => {
|
||||
resetService.sendResetPasswordLink.and.returnValue(of({value: 'Email sent'}));
|
||||
component.resetPasswordEmail = 'test@example.com';
|
||||
component.isValidEmail = true;
|
||||
|
||||
component.confirmToSend();
|
||||
|
||||
expect(resetService.sendResetPasswordLink).toHaveBeenCalledWith('test@example.com');
|
||||
});
|
||||
|
||||
it('should not call API when email is invalid', () => {
|
||||
component.resetPasswordEmail = 'invalid-email';
|
||||
component.confirmToSend();
|
||||
|
||||
expect(resetService.sendResetPasswordLink).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should show error toast on failure', () => {
|
||||
resetService.sendResetPasswordLink.and.returnValue(throwError(() => ({
|
||||
error: {error: {message: 'User not found'}}
|
||||
})));
|
||||
component.resetPasswordEmail = 'test@example.com';
|
||||
component.isValidEmail = true;
|
||||
|
||||
component.confirmToSend();
|
||||
|
||||
expect(toastService.show).toHaveBeenCalledWith('User not found', jasmine.any(Object));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,23 +1,38 @@
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import {LoginComponent} from './login.component';
|
||||
import {ActivatedRoute, provideRouter, Router} from "@angular/router";
|
||||
import {Title} from "@angular/platform-browser";
|
||||
import {of} from "rxjs";
|
||||
import {provideHttpClient} from "@angular/common/http";
|
||||
import {AuthService} from '../../../infrastructure/services/auth-service';
|
||||
import {ToastService} from '../../../infrastructure/services/toast.service';
|
||||
import {UserStoreService} from '../../../infrastructure/services/user-store.service';
|
||||
import {LoadingService} from '../../../infrastructure/services/loading.service';
|
||||
import {ActivatedRoute, Router} from '@angular/router';
|
||||
import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
|
||||
import {of, throwError} from 'rxjs';
|
||||
|
||||
describe('LoginComponent', () => {
|
||||
let component: LoginComponent;
|
||||
let fixture: ComponentFixture<LoginComponent>;
|
||||
let authService: jasmine.SpyObj<AuthService>;
|
||||
let router: jasmine.SpyObj<Router>;
|
||||
let toastService: jasmine.SpyObj<ToastService>;
|
||||
|
||||
beforeEach(async () => {
|
||||
authService = jasmine.createSpyObj('AuthService', ['login', 'storeToken', 'storeRefreshToken', 'decodedToken']);
|
||||
router = jasmine.createSpyObj('Router', ['navigate']);
|
||||
toastService = jasmine.createSpyObj('ToastService', ['show']);
|
||||
const modalService = jasmine.createSpyObj('NgbModal', ['open']);
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [LoginComponent],
|
||||
providers: [provideHttpClient(),
|
||||
{ provide: ActivatedRoute, useValue: { data: of({}), firstChild: null } }
|
||||
providers: [
|
||||
{provide: AuthService, useValue: authService},
|
||||
{provide: Router, useValue: router},
|
||||
{provide: ToastService, useValue: toastService},
|
||||
{provide: NgbModal, useValue: modalService},
|
||||
{provide: ActivatedRoute, useValue: {snapshot: {data: {}}, firstChild: null}},
|
||||
UserStoreService,
|
||||
LoadingService,
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(LoginComponent);
|
||||
component = fixture.componentInstance;
|
||||
@@ -27,4 +42,63 @@ describe('LoginComponent', () => {
|
||||
it('should create LoginComponent', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should have an invalid form when fields are empty', () => {
|
||||
expect(component.loginForm.valid).toBeFalse();
|
||||
});
|
||||
|
||||
it('should validate email pattern', () => {
|
||||
const emailControl = component.loginForm.get('email');
|
||||
emailControl?.setValue('not-an-email');
|
||||
expect(emailControl?.valid).toBeFalse();
|
||||
emailControl?.setValue('test@example.com');
|
||||
expect(emailControl?.valid).toBeTrue();
|
||||
});
|
||||
|
||||
it('should require password', () => {
|
||||
const passwordControl = component.loginForm.get('password');
|
||||
expect(passwordControl?.valid).toBeFalse();
|
||||
passwordControl?.setValue('somepassword');
|
||||
expect(passwordControl?.valid).toBeTrue();
|
||||
});
|
||||
|
||||
it('should call login on submit when form is valid', () => {
|
||||
const tokenPayload = {username: 'testuser', email: 'test@example.com', role: 'User'};
|
||||
authService.login.and.returnValue(of({
|
||||
value: {token: {accessToken: 'access', refreshToken: 'refresh'}}
|
||||
}));
|
||||
authService.decodedToken.and.returnValue(tokenPayload);
|
||||
router.navigate.and.returnValue(Promise.resolve(true));
|
||||
|
||||
component.loginForm.setValue({
|
||||
email: 'test@example.com',
|
||||
password: 'Password1!',
|
||||
});
|
||||
component.onLogin();
|
||||
|
||||
expect(authService.login).toHaveBeenCalled();
|
||||
expect(authService.storeToken).toHaveBeenCalledWith('access');
|
||||
expect(authService.storeRefreshToken).toHaveBeenCalledWith('refresh');
|
||||
});
|
||||
|
||||
it('should show error toast on login failure', () => {
|
||||
authService.login.and.returnValue(throwError(() => ({
|
||||
error: {error: {message: 'Invalid credentials'}}
|
||||
})));
|
||||
|
||||
component.loginForm.setValue({
|
||||
email: 'test@example.com',
|
||||
password: 'wrong',
|
||||
});
|
||||
component.onLogin();
|
||||
|
||||
expect(toastService.show).toHaveBeenCalledWith('Invalid credentials', jasmine.any(Object));
|
||||
});
|
||||
|
||||
it('should toggle password visibility', () => {
|
||||
component.hideShowPassword();
|
||||
expect(component.isText).toBeFalse();
|
||||
component.hideShowPassword();
|
||||
expect(component.isText).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
+82
-6
@@ -1,19 +1,31 @@
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import {RegisterComponent} from './register.component';
|
||||
import {HttpClient, provideHttpClient} from "@angular/common/http";
|
||||
import {ActivatedRoute} from "@angular/router";
|
||||
import {of} from "rxjs";
|
||||
import {AuthService} from '../../../infrastructure/services/auth-service';
|
||||
import {ToastService} from '../../../infrastructure/services/toast.service';
|
||||
import {LoadingService} from '../../../infrastructure/services/loading.service';
|
||||
import {ActivatedRoute, Router} from '@angular/router';
|
||||
import {of, throwError} from 'rxjs';
|
||||
|
||||
describe('RegisterComponent', () => {
|
||||
let component: RegisterComponent;
|
||||
let fixture: ComponentFixture<RegisterComponent>;
|
||||
let authService: jasmine.SpyObj<AuthService>;
|
||||
let router: jasmine.SpyObj<Router>;
|
||||
let toastService: jasmine.SpyObj<ToastService>;
|
||||
|
||||
beforeEach(async () => {
|
||||
authService = jasmine.createSpyObj('AuthService', ['register']);
|
||||
router = jasmine.createSpyObj('Router', ['navigate']);
|
||||
toastService = jasmine.createSpyObj('ToastService', ['show']);
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [RegisterComponent],
|
||||
providers: [provideHttpClient(),
|
||||
{ provide: ActivatedRoute, useValue: { data: of({}), firstChild: null } }
|
||||
providers: [
|
||||
{provide: AuthService, useValue: authService},
|
||||
{provide: Router, useValue: router},
|
||||
{provide: ToastService, useValue: toastService},
|
||||
{provide: ActivatedRoute, useValue: {snapshot: {data: {}}, firstChild: null}},
|
||||
LoadingService,
|
||||
]
|
||||
}).compileComponents();
|
||||
|
||||
@@ -25,4 +37,68 @@ describe('RegisterComponent', () => {
|
||||
it('should create RegisterComponent', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should have an invalid form when fields are empty', () => {
|
||||
expect(component.registerForm.valid).toBeFalse();
|
||||
});
|
||||
|
||||
it('should validate username pattern', () => {
|
||||
const usernameControl = component.registerForm.get('username');
|
||||
usernameControl?.setValue('invalid username!');
|
||||
expect(usernameControl?.valid).toBeFalse();
|
||||
usernameControl?.setValue('valid_user');
|
||||
expect(usernameControl?.valid).toBeTrue();
|
||||
});
|
||||
|
||||
it('should validate email pattern', () => {
|
||||
const emailControl = component.registerForm.get('email');
|
||||
emailControl?.setValue('invalid');
|
||||
expect(emailControl?.valid).toBeFalse();
|
||||
emailControl?.setValue('test@example.com');
|
||||
expect(emailControl?.valid).toBeTrue();
|
||||
});
|
||||
|
||||
it('should validate password strength', () => {
|
||||
const passwordControl = component.registerForm.get('password');
|
||||
passwordControl?.setValue('weak');
|
||||
expect(passwordControl?.valid).toBeFalse();
|
||||
passwordControl?.setValue('StrongP@ss1');
|
||||
expect(passwordControl?.valid).toBeTrue();
|
||||
});
|
||||
|
||||
it('should call register on submit when form is valid', () => {
|
||||
authService.register.and.returnValue(of({isSuccess: true, value: 'Registered'}));
|
||||
router.navigate.and.returnValue(Promise.resolve(true));
|
||||
|
||||
component.registerForm.setValue({
|
||||
username: 'testuser',
|
||||
email: 'test@example.com',
|
||||
password: 'StrongP@ss1',
|
||||
});
|
||||
component.onSignUp();
|
||||
|
||||
expect(authService.register).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should show error toast on registration failure', () => {
|
||||
authService.register.and.returnValue(throwError(() => ({
|
||||
error: {error: {message: 'Email already exists'}}
|
||||
})));
|
||||
|
||||
component.registerForm.setValue({
|
||||
username: 'testuser',
|
||||
email: 'existing@example.com',
|
||||
password: 'StrongP@ss1',
|
||||
});
|
||||
component.onSignUp();
|
||||
|
||||
expect(toastService.show).toHaveBeenCalledWith('Email already exists', jasmine.any(Object));
|
||||
});
|
||||
|
||||
it('should toggle password visibility', () => {
|
||||
component.hideShowPassword();
|
||||
expect(component.isText).toBeFalse();
|
||||
component.hideShowPassword();
|
||||
expect(component.isText).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
+67
-14
@@ -1,32 +1,36 @@
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import {ResetPasswordComponent} from './reset-password.component';
|
||||
import {provideHttpClient} from "@angular/common/http";
|
||||
import {ActivatedRoute} from "@angular/router";
|
||||
import {of} from "rxjs";
|
||||
import {ReactiveFormsModule} from "@angular/forms";
|
||||
import {ResetPasswordService} from '../../../infrastructure/services/reset-password.service';
|
||||
import {ToastService} from '../../../infrastructure/services/toast.service';
|
||||
import {ActivatedRoute, Router} from '@angular/router';
|
||||
import {of, throwError} from 'rxjs';
|
||||
|
||||
describe('ResetPasswordComponent', () => {
|
||||
let component: ResetPasswordComponent;
|
||||
let fixture: ComponentFixture<ResetPasswordComponent>;
|
||||
let resetService: jasmine.SpyObj<ResetPasswordService>;
|
||||
let router: jasmine.SpyObj<Router>;
|
||||
let toastService: jasmine.SpyObj<ToastService>;
|
||||
|
||||
beforeEach(async () => {
|
||||
resetService = jasmine.createSpyObj('ResetPasswordService', ['resetPassword']);
|
||||
router = jasmine.createSpyObj('Router', ['navigate']);
|
||||
toastService = jasmine.createSpyObj('ToastService', ['show']);
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ResetPasswordComponent, ReactiveFormsModule],
|
||||
providers: [provideHttpClient(),
|
||||
{ provide: ActivatedRoute, useValue: { data: of({}), firstChild: null } },
|
||||
imports: [ResetPasswordComponent],
|
||||
providers: [
|
||||
{provide: ResetPasswordService, useValue: resetService},
|
||||
{provide: Router, useValue: router},
|
||||
{provide: ToastService, useValue: toastService},
|
||||
{
|
||||
provide: ActivatedRoute,
|
||||
useValue: {
|
||||
queryParams: of({
|
||||
email: 'test@example.com',
|
||||
code: 'test-token'
|
||||
})
|
||||
queryParams: of({email: 'test@example.com', code: 'test-token'})
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ResetPasswordComponent);
|
||||
component = fixture.componentInstance;
|
||||
@@ -36,4 +40,53 @@ describe('ResetPasswordComponent', () => {
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should read email and token from query params', () => {
|
||||
expect(component.emailToReset).toBe('test@example.com');
|
||||
expect(component.emailToken).toBe('test-token');
|
||||
});
|
||||
|
||||
it('should have an invalid form when fields are empty', () => {
|
||||
expect(component.resetForm.valid).toBeFalse();
|
||||
});
|
||||
|
||||
it('should validate password strength', () => {
|
||||
const passwordControl = component.resetForm.get('password');
|
||||
passwordControl?.setValue('weak');
|
||||
expect(passwordControl?.valid).toBeFalse();
|
||||
passwordControl?.setValue('StrongP@ss1');
|
||||
expect(passwordControl?.valid).toBeTrue();
|
||||
});
|
||||
|
||||
it('should validate password confirmation match', () => {
|
||||
component.resetForm.get('password')?.setValue('StrongP@ss1');
|
||||
component.resetForm.get('confirmPassword')?.setValue('Different!');
|
||||
expect(component.resetForm.valid).toBeFalse();
|
||||
component.resetForm.get('confirmPassword')?.setValue('StrongP@ss1');
|
||||
expect(component.resetForm.valid).toBeTrue();
|
||||
});
|
||||
|
||||
it('should call resetPassword on submit when form is valid', () => {
|
||||
resetService.resetPassword.and.returnValue(of({value: 'Password reset'}));
|
||||
router.navigate.and.returnValue(Promise.resolve(true));
|
||||
|
||||
component.resetForm.get('password')?.setValue('NewStrongP@ss1');
|
||||
component.resetForm.get('confirmPassword')?.setValue('NewStrongP@ss1');
|
||||
component.reset();
|
||||
|
||||
expect(resetService.resetPassword).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should show error alert on failure', () => {
|
||||
spyOn(window, 'alert');
|
||||
resetService.resetPassword.and.returnValue(throwError(() => ({
|
||||
error: {error: {message: 'Invalid token'}}
|
||||
})));
|
||||
|
||||
component.resetForm.get('password')?.setValue('NewStrongP@ss1');
|
||||
component.resetForm.get('confirmPassword')?.setValue('NewStrongP@ss1');
|
||||
component.reset();
|
||||
|
||||
expect(window.alert).toHaveBeenCalledWith('Invalid token');
|
||||
});
|
||||
});
|
||||
|
||||
+8
-6
@@ -1,6 +1,6 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { AdminDashboardComponent } from './admin-dashboard.component';
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {AdminDashboardComponent} from './admin-dashboard.component';
|
||||
import {ActivatedRoute} from '@angular/router';
|
||||
|
||||
describe('AdminDashboardComponent', () => {
|
||||
let component: AdminDashboardComponent;
|
||||
@@ -8,9 +8,11 @@ describe('AdminDashboardComponent', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [AdminDashboardComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
imports: [AdminDashboardComponent],
|
||||
providers: [
|
||||
{provide: ActivatedRoute, useValue: {snapshot: {data: {}}, firstChild: null}},
|
||||
]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(AdminDashboardComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import {FooterComponent} from './footer.component';
|
||||
import {provideHttpClient} from "@angular/common/http";
|
||||
import {ActivatedRoute} from "@angular/router";
|
||||
import {of} from "rxjs";
|
||||
import {ActivatedRoute} from '@angular/router';
|
||||
|
||||
describe('FooterComponent', () => {
|
||||
let component: FooterComponent;
|
||||
@@ -12,11 +9,10 @@ describe('FooterComponent', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [FooterComponent],
|
||||
providers: [provideHttpClient(),
|
||||
{ provide: ActivatedRoute, useValue: { data: of({}), firstChild: null } }
|
||||
providers: [
|
||||
{provide: ActivatedRoute, useValue: {snapshot: {data: {}}, firstChild: null}},
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(FooterComponent);
|
||||
component = fixture.componentInstance;
|
||||
@@ -26,4 +22,8 @@ describe('FooterComponent', () => {
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should have a version', () => {
|
||||
expect(component.version).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,22 +1,25 @@
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import {HeaderComponent} from './header.component';
|
||||
import {provideHttpClient} from "@angular/common/http";
|
||||
import {ActivatedRoute} from "@angular/router";
|
||||
import {of} from "rxjs";
|
||||
import {AuthService} from '../../../infrastructure/services/auth-service';
|
||||
import {ActivatedRoute} from '@angular/router';
|
||||
|
||||
describe('NavbarComponent', () => {
|
||||
describe('HeaderComponent', () => {
|
||||
let component: HeaderComponent;
|
||||
let fixture: ComponentFixture<HeaderComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
const authSpy = jasmine.createSpyObj('AuthService', [
|
||||
'getUsernameFromToken', 'getRoleFromToken', 'getEmailFromToken', 'getUserIdFromToken',
|
||||
'isLoggedIn', 'getToken', 'signOut', 'decodedToken'
|
||||
]);
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [HeaderComponent],
|
||||
providers: [provideHttpClient(),
|
||||
{ provide: ActivatedRoute, useValue: { data: of({}), firstChild: null } }
|
||||
providers: [
|
||||
{provide: AuthService, useValue: authSpy},
|
||||
{provide: ActivatedRoute, useValue: {snapshot: {data: {}}, firstChild: null}},
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(HeaderComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
+14
-6
@@ -1,16 +1,24 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { UserDashboardComponent } from './user-dashboard.component';
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {UserDashboardComponent} from './user-dashboard.component';
|
||||
import {AuthService} from '../../../infrastructure/services/auth-service';
|
||||
import {UserStoreService} from '../../../infrastructure/services/user-store.service';
|
||||
import {of} from 'rxjs';
|
||||
|
||||
describe('UserDashboardComponent', () => {
|
||||
let component: UserDashboardComponent;
|
||||
let fixture: ComponentFixture<UserDashboardComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
const authSpy = jasmine.createSpyObj('AuthService', [
|
||||
'getUsernameFromToken', 'getEmailFromToken'
|
||||
]);
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [UserDashboardComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
imports: [UserDashboardComponent],
|
||||
providers: [
|
||||
{provide: AuthService, useValue: authSpy},
|
||||
]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(UserDashboardComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
+135
-6
@@ -1,16 +1,38 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { UserTableComponent } from './user-table.component';
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {UserTableComponent} from './user-table.component';
|
||||
import {UserService} from '../../../infrastructure/services/user.service';
|
||||
import {ToastService} from '../../../infrastructure/services/toast.service';
|
||||
import {of, throwError} from 'rxjs';
|
||||
|
||||
describe('UserTableComponent', () => {
|
||||
let component: UserTableComponent;
|
||||
let fixture: ComponentFixture<UserTableComponent>;
|
||||
let userService: jasmine.SpyObj<UserService>;
|
||||
let toastService: jasmine.SpyObj<ToastService>;
|
||||
|
||||
const mockUsers = {
|
||||
value: {
|
||||
items: [
|
||||
{id: 1, username: 'user1', email: 'user1@test.com', lastLogin: new Date(), UserRoles: [{role: {name: 'Admin'}}]},
|
||||
{id: 2, username: 'user2', email: 'user2@test.com', lastLogin: new Date(), UserRoles: [{role: {name: 'User'}}]},
|
||||
],
|
||||
totalPages: 3,
|
||||
}
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
userService = jasmine.createSpyObj('UserService', ['getAllUsers', 'deleteUser']);
|
||||
toastService = jasmine.createSpyObj('ToastService', ['show']);
|
||||
|
||||
userService.getAllUsers.and.returnValue(of(mockUsers));
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [UserTableComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
imports: [UserTableComponent],
|
||||
providers: [
|
||||
{provide: UserService, useValue: userService},
|
||||
{provide: ToastService, useValue: toastService},
|
||||
]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(UserTableComponent);
|
||||
component = fixture.componentInstance;
|
||||
@@ -20,4 +42,111 @@ describe('UserTableComponent', () => {
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should load users on init', () => {
|
||||
expect(userService.getAllUsers).toHaveBeenCalledWith(1, 10);
|
||||
expect(component.users.length).toBe(2);
|
||||
expect(component.totalPages).toBe(3);
|
||||
});
|
||||
|
||||
it('should go to next page', () => {
|
||||
component.pageNumber = 1;
|
||||
component.totalPages = 3;
|
||||
component.nextPage();
|
||||
expect(component.pageNumber).toBe(2);
|
||||
expect(userService.getAllUsers).toHaveBeenCalledWith(2, 10);
|
||||
});
|
||||
|
||||
it('should not go beyond last page', () => {
|
||||
component.pageNumber = 3;
|
||||
component.totalPages = 3;
|
||||
component.nextPage();
|
||||
expect(component.pageNumber).toBe(3);
|
||||
});
|
||||
|
||||
it('should go to previous page', () => {
|
||||
component.pageNumber = 2;
|
||||
component.previousPage();
|
||||
expect(component.pageNumber).toBe(1);
|
||||
expect(userService.getAllUsers).toHaveBeenCalledWith(1, 10);
|
||||
});
|
||||
|
||||
it('should not go below first page', () => {
|
||||
component.pageNumber = 1;
|
||||
component.previousPage();
|
||||
expect(component.pageNumber).toBe(1);
|
||||
});
|
||||
|
||||
it('should go to specific page', () => {
|
||||
component.goToPage(2);
|
||||
expect(component.pageNumber).toBe(2);
|
||||
expect(userService.getAllUsers).toHaveBeenCalledWith(2, 10);
|
||||
});
|
||||
|
||||
it('should not go to invalid page', () => {
|
||||
component.goToPage(0);
|
||||
expect(component.pageNumber).toBe(1);
|
||||
component.goToPage(999);
|
||||
expect(component.pageNumber).toBe(1);
|
||||
});
|
||||
|
||||
it('should sort users by column ascending', () => {
|
||||
component.users = [
|
||||
{id: 2, username: 'b_user'} as any,
|
||||
{id: 1, username: 'a_user'} as any,
|
||||
];
|
||||
component.sort('username');
|
||||
expect(component.users[0].username).toBe('a_user');
|
||||
expect(component.users[1].username).toBe('b_user');
|
||||
expect(component.sortDirection).toBe('asc');
|
||||
});
|
||||
|
||||
it('should toggle sort direction on same column', () => {
|
||||
component.users = [
|
||||
{id: 1, username: 'a_user'} as any,
|
||||
{id: 2, username: 'b_user'} as any,
|
||||
];
|
||||
component.sort('username');
|
||||
component.sort('username');
|
||||
expect(component.users[0].username).toBe('b_user');
|
||||
expect(component.users[1].username).toBe('a_user');
|
||||
expect(component.sortDirection).toBe('desc');
|
||||
});
|
||||
|
||||
it('should delete user and remove from list', () => {
|
||||
userService.deleteUser.and.returnValue(of({value: 'User deleted successfully'}));
|
||||
component.users = [
|
||||
{id: 1, username: 'user1'} as any,
|
||||
{id: 2, username: 'user2'} as any,
|
||||
];
|
||||
|
||||
component.deleteUser(1);
|
||||
|
||||
expect(userService.deleteUser).toHaveBeenCalledWith(1);
|
||||
expect(component.users.length).toBe(1);
|
||||
expect(component.users[0].id).toBe(2);
|
||||
expect(toastService.show).toHaveBeenCalledWith('User deleted successfully', jasmine.any(Object));
|
||||
});
|
||||
|
||||
it('should show error toast on delete failure', () => {
|
||||
userService.deleteUser.and.returnValue(throwError(() => ({
|
||||
error: {error: {message: 'User not found'}}
|
||||
})));
|
||||
|
||||
component.deleteUser(99);
|
||||
|
||||
expect(toastService.show).toHaveBeenCalledWith('User not found', jasmine.any(Object));
|
||||
});
|
||||
|
||||
it('should select user and handle confirm deletion', () => {
|
||||
const user = {id: 1, username: 'user1'} as any;
|
||||
userService.deleteUser.and.returnValue(of({value: 'Deleted'}));
|
||||
component.users = [user];
|
||||
|
||||
component.selectUser(user);
|
||||
expect(component.selectedUser).toBe(user);
|
||||
|
||||
component.handleConfirm();
|
||||
expect(userService.deleteUser).toHaveBeenCalledWith(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,17 +1,62 @@
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {CanActivateFn} from '@angular/router';
|
||||
|
||||
import {Router} from '@angular/router';
|
||||
import {adminGuard} from './admin.guard';
|
||||
import {AuthService} from '../../infrastructure/services/auth-service';
|
||||
import {ToastService} from '../../infrastructure/services/toast.service';
|
||||
import {UserStoreService} from '../../infrastructure/services/user-store.service';
|
||||
|
||||
describe('adminGuard', () => {
|
||||
const executeGuard: CanActivateFn = (...guardParameters) =>
|
||||
TestBed.runInInjectionContext(() => adminGuard(...guardParameters));
|
||||
let authService: jasmine.SpyObj<AuthService>;
|
||||
let router: jasmine.SpyObj<Router>;
|
||||
let toastService: jasmine.SpyObj<ToastService>;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
authService = jasmine.createSpyObj('AuthService', ['getRoleFromToken']);
|
||||
router = jasmine.createSpyObj('Router', ['navigate']);
|
||||
toastService = jasmine.createSpyObj('ToastService', ['show']);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
UserStoreService,
|
||||
{provide: AuthService, useValue: authService},
|
||||
{provide: Router, useValue: router},
|
||||
{provide: ToastService, useValue: toastService},
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
const executeGuard = () =>
|
||||
TestBed.runInInjectionContext(() => adminGuard({} as any, {} as any));
|
||||
|
||||
it('should be created', () => {
|
||||
expect(executeGuard).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return true for Admin role', (done) => {
|
||||
const userStore = TestBed.inject(UserStoreService);
|
||||
userStore.setRoleForStore('Admin');
|
||||
(executeGuard() as any).subscribe((result: boolean) => {
|
||||
expect(result).toBeTrue();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return true for SuperAdmin role', (done) => {
|
||||
const userStore = TestBed.inject(UserStoreService);
|
||||
userStore.setRoleForStore('SuperAdmin');
|
||||
(executeGuard() as any).subscribe((result: boolean) => {
|
||||
expect(result).toBeTrue();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false and redirect for non-admin role', (done) => {
|
||||
const userStore = TestBed.inject(UserStoreService);
|
||||
userStore.setRoleForStore('User');
|
||||
(executeGuard() as any).subscribe((result: boolean) => {
|
||||
expect(result).toBeFalse();
|
||||
expect(router.navigate).toHaveBeenCalledWith(['/unauthorized']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,24 +1,45 @@
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
|
||||
import {Router} from '@angular/router';
|
||||
import {AuthenticationGuard} from './authentication.guard';
|
||||
import {provideHttpClient} from "@angular/common/http";
|
||||
import {ActivatedRoute} from "@angular/router";
|
||||
import {of} from "rxjs";
|
||||
import {AuthService} from '../../infrastructure/services/auth-service';
|
||||
import {ToastService} from '../../infrastructure/services/toast.service';
|
||||
|
||||
describe('AuthenticationGuard', () => {
|
||||
let guard: AuthenticationGuard;
|
||||
let authService: jasmine.SpyObj<AuthService>;
|
||||
let router: jasmine.SpyObj<Router>;
|
||||
|
||||
beforeEach(() => {
|
||||
const authSpy = jasmine.createSpyObj('AuthService', ['isLoggedIn']);
|
||||
const routerSpy = jasmine.createSpyObj('Router', ['navigate']);
|
||||
routerSpy.navigate.and.returnValue(Promise.resolve(true));
|
||||
const toastSpy = jasmine.createSpyObj('ToastService', ['show']);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
providers: [provideHttpClient(),
|
||||
{ provide: ActivatedRoute, useValue: { data: of({}), firstChild: null } },
|
||||
providers: [
|
||||
AuthenticationGuard,
|
||||
{provide: AuthService, useValue: authSpy},
|
||||
{provide: Router, useValue: routerSpy},
|
||||
{provide: ToastService, useValue: toastSpy},
|
||||
]
|
||||
});
|
||||
guard = TestBed.inject(AuthenticationGuard);
|
||||
|
||||
authService = TestBed.inject(AuthService) as jasmine.SpyObj<AuthService>;
|
||||
router = TestBed.inject(Router) as jasmine.SpyObj<Router>;
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(guard).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return true when user is logged in', () => {
|
||||
authService.isLoggedIn.and.returnValue(true);
|
||||
expect(guard.canActivate()).toBeTrue();
|
||||
});
|
||||
|
||||
it('should return false and redirect when user is not logged in', () => {
|
||||
authService.isLoggedIn.and.returnValue(false);
|
||||
expect(guard.canActivate()).toBeFalse();
|
||||
expect(router.navigate).toHaveBeenCalledWith(['/login']);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,17 +1,39 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { CanActivateFn } from '@angular/router';
|
||||
|
||||
import { guestGuard } from './guest.guard';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {Router} from '@angular/router';
|
||||
import {guestGuard} from './guest.guard';
|
||||
import {AuthService} from '../../infrastructure/services/auth-service';
|
||||
|
||||
describe('guestGuard', () => {
|
||||
const executeGuard: CanActivateFn = (...guardParameters) =>
|
||||
TestBed.runInInjectionContext(() => guestGuard(...guardParameters));
|
||||
let authService: jasmine.SpyObj<AuthService>;
|
||||
let router: jasmine.SpyObj<Router>;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
authService = jasmine.createSpyObj('AuthService', ['isLoggedIn']);
|
||||
router = jasmine.createSpyObj('Router', ['navigate']);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
{provide: AuthService, useValue: authService},
|
||||
{provide: Router, useValue: router},
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
const executeGuard = () =>
|
||||
TestBed.runInInjectionContext(() => guestGuard({} as any, {} as any));
|
||||
|
||||
it('should be created', () => {
|
||||
expect(executeGuard).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return true when user is not logged in', () => {
|
||||
authService.isLoggedIn.and.returnValue(false);
|
||||
expect(executeGuard()).toBeTrue();
|
||||
});
|
||||
|
||||
it('should return false and redirect when user is logged in', () => {
|
||||
authService.isLoggedIn.and.returnValue(true);
|
||||
expect(executeGuard()).toBeFalse();
|
||||
expect(router.navigate).toHaveBeenCalledWith(['/user-dashboard']);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,17 +1,50 @@
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {HttpInterceptorFn} from '@angular/common/http';
|
||||
|
||||
import {HttpClient, HttpInterceptorFn, provideHttpClient, withInterceptors} from '@angular/common/http';
|
||||
import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing';
|
||||
import {tokenInterceptor} from './token.interceptor';
|
||||
import {AuthService} from '../../infrastructure/services/auth-service';
|
||||
|
||||
describe('tokenInterceptor', () => {
|
||||
const interceptor: HttpInterceptorFn = (req, next) =>
|
||||
TestBed.runInInjectionContext(() => tokenInterceptor(req, next));
|
||||
let authService: jasmine.SpyObj<AuthService>;
|
||||
let httpClient: HttpClient;
|
||||
let httpTesting: HttpTestingController;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
authService = jasmine.createSpyObj('AuthService', ['getToken', 'getRefreshToken', 'getUserIdFromToken',
|
||||
'storeToken', 'storeRefreshToken', 'signOut', 'renewToken']);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
provideHttpClient(withInterceptors([tokenInterceptor])),
|
||||
provideHttpClientTesting(),
|
||||
{provide: AuthService, useValue: authService},
|
||||
]
|
||||
});
|
||||
httpClient = TestBed.inject(HttpClient);
|
||||
httpTesting = TestBed.inject(HttpTestingController);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(interceptor).toBeTruthy();
|
||||
afterEach(() => {
|
||||
httpTesting.verify();
|
||||
});
|
||||
|
||||
it('should add Authorization header when token exists', () => {
|
||||
authService.getToken.and.returnValue('test-jwt-token');
|
||||
|
||||
httpClient.get('/api/test').subscribe();
|
||||
|
||||
const req = httpTesting.expectOne('/api/test');
|
||||
expect(req.request.headers.get('Authorization')).toBe('Bearer test-jwt-token');
|
||||
req.flush({});
|
||||
});
|
||||
|
||||
it('should not add Authorization header when no token', () => {
|
||||
authService.getToken.and.returnValue(null);
|
||||
|
||||
httpClient.get('/api/test').subscribe();
|
||||
|
||||
const req = httpTesting.expectOne('/api/test');
|
||||
expect(req.request.headers.has('Authorization')).toBeFalse();
|
||||
req.flush({});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user