Skip to content

Commit

Permalink
Improved test coverage for AccountSettingsComponent
Browse files Browse the repository at this point in the history
  • Loading branch information
zaychenko-sergei committed Sep 8, 2023
1 parent 37303e3 commit d3be42a
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 109 deletions.
4 changes: 2 additions & 2 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AddPollingSourceComponent } from "./dataset-view/additional-components/metadata-component/components/add-polling-source/add-polling-source.component";
import { MetadataBlockComponent } from "./dataset-block/metadata-block/metadata-block.component";
import { AuthenticatedGuard } from "./auth/guards/authenticated.guard";
import { SettingsComponent } from "./auth/settings/settings.component";
import { AccountSettingsComponent } from "./auth/settings/account-settings.component";
import { PageNotFoundComponent } from "./components/page-not-found/page-not-found.component";
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
Expand Down Expand Up @@ -52,7 +52,7 @@ export const routes: Routes = [
children: [
{
path: `:${ProjectLinks.URL_PARAM_CATEGORY}`,
component: SettingsComponent,
component: AccountSettingsComponent,
},
],
},
Expand Down
4 changes: 2 additions & 2 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ import { SpinnerModule } from "./components/spinner/spinner.module";
import { DatasetApi } from "./api/dataset.api";
import { ErrorHandlerService } from "./services/error-handler.service";

import { SettingsComponent } from "./auth/settings/settings.component";
import { AccountSettingsComponent } from "./auth/settings/account-settings.component";
import { MatButtonToggleModule } from "@angular/material/button-toggle";
import { DatasetListModule } from "./components/dataset-list-component/dataset-list.module";
import { PaginationModule } from "./components/pagination-component/pagination.module";
Expand Down Expand Up @@ -171,7 +171,7 @@ const MatModules = [
GithubCallbackComponent,
AccountComponent,
NotificationIndicatorComponent,
SettingsComponent,
AccountSettingsComponent,
DatasetsTabComponent,
],
imports: [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="pt-4 container-xl p-responsive clearfix">
<div class="pt-4 container-xl p-responsive clearfix" *ngIf="user$ | async as user">
<div class="d-md-flex align-items-center justify-content-between mt-1 mb-4">
<div class="d-flex align-items-center mb-2 mb-md-0">
<img
Expand All @@ -12,7 +12,11 @@
/>
<div class="flex-auto mx-4 mt-3">
<div class="h3-custom lh-condensed">
<a [routerLink]="['/', user.accountName]" class="color-fg-default fw-bold-custom fs-5">
<a
[routerLink]="['/', user.accountName]"
class="color-fg-default fw-bold-custom fs-5"
data-test-id="user-name-link"
>
{{ user.displayName }}
</a>
<span class="sr-only">settings</span>
Expand All @@ -35,13 +39,13 @@
data-item-id="settings_user_profile"
data-view-component="true"
[ngClass]="{
'action-list-item--nav__active': activeTab === settingsTabs.PROFILE
'action-list-item--nav__active': activeTab === SettingsTabs.PROFILE
}"
class="action-list-item"
>
<a
routerLinkActive="active"
[routerLink]="getRouteLink(settingsTabs.PROFILE)"
[routerLink]="getRouteLink(SettingsTabs.PROFILE)"
aria-current="page"
data-view-component="true"
class="action-list-content"
Expand All @@ -58,13 +62,13 @@
data-item-id=""
data-view-component="true"
[ngClass]="{
'action-list-item--nav__active': activeTab === settingsTabs.ACCOUNT
'action-list-item--nav__active': activeTab === SettingsTabs.ACCOUNT
}"
class="action-list-item"
>
<a
routerLinkActive="active"
[routerLink]="getRouteLink(settingsTabs.ACCOUNT)"
[routerLink]="getRouteLink(SettingsTabs.ACCOUNT)"
data-view-component="true"
class="action-list-content"
>
Expand All @@ -80,13 +84,13 @@
data-item-id=""
data-view-component="true"
[ngClass]="{
'action-list-item--nav__active': activeTab === settingsTabs.APPEARANCE
'action-list-item--nav__active': activeTab === SettingsTabs.APPEARANCE
}"
class="action-list-item"
>
<a
routerLinkActive="active"
[routerLink]="getRouteLink(settingsTabs.APPEARANCE)"
[routerLink]="getRouteLink(SettingsTabs.APPEARANCE)"
data-view-component="true"
class="action-list-content"
>
Expand All @@ -102,13 +106,13 @@
data-item-id=""
data-view-component="true"
[ngClass]="{
'action-list-item--nav__active': activeTab === settingsTabs.ACCESSIBILITY
'action-list-item--nav__active': activeTab === SettingsTabs.ACCESSIBILITY
}"
class="action-list-item"
>
<a
routerLinkActive="active"
[routerLink]="getRouteLink(settingsTabs.ACCESSIBILITY)"
[routerLink]="getRouteLink(SettingsTabs.ACCESSIBILITY)"
data-view-component="true"
class="action-list-content"
>
Expand All @@ -124,13 +128,13 @@
data-item-id=""
data-view-component="true"
[ngClass]="{
'action-list-item--nav__active': activeTab === settingsTabs.NOTIFICATIONS
'action-list-item--nav__active': activeTab === SettingsTabs.NOTIFICATIONS
}"
class="action-list-item"
>
<a
routerLinkActive="active"
[routerLink]="getRouteLink(settingsTabs.NOTIFICATIONS)"
[routerLink]="getRouteLink(SettingsTabs.NOTIFICATIONS)"
data-view-component="true"
class="action-list-content"
>
Expand Down Expand Up @@ -168,12 +172,12 @@
data-view-component="true"
class="action-list-item"
[ngClass]="{
'action-list-item--nav__active': activeTab === settingsTabs.BILLING
'action-list-item--nav__active': activeTab === SettingsTabs.BILLING
}"
>
<a
routerLinkActive="active"
[routerLink]="getRouteLink(settingsTabs.BILLING)"
[routerLink]="getRouteLink(SettingsTabs.BILLING)"
data-view-component="true"
class="action-list-content"
>
Expand All @@ -190,12 +194,12 @@
data-view-component="true"
class="action-list-item"
[ngClass]="{
'action-list-item--nav__active': activeTab === settingsTabs.EMAILS
'action-list-item--nav__active': activeTab === SettingsTabs.EMAILS
}"
>
<a
routerLinkActive="active"
[routerLink]="getRouteLink(settingsTabs.EMAILS)"
[routerLink]="getRouteLink(SettingsTabs.EMAILS)"
data-view-component="true"
class="action-list-content"
>
Expand All @@ -212,12 +216,12 @@
data-view-component="true"
class="action-list-item"
[ngClass]="{
'action-list-item--nav__active': activeTab === settingsTabs.SECURITY
'action-list-item--nav__active': activeTab === SettingsTabs.SECURITY
}"
>
<a
routerLinkActive="active"
[routerLink]="getRouteLink(settingsTabs.SECURITY)"
[routerLink]="getRouteLink(SettingsTabs.SECURITY)"
data-view-component="true"
class="action-list-content"
>
Expand All @@ -234,12 +238,12 @@
data-view-component="true"
class="action-list-item"
[ngClass]="{
'action-list-item--nav__active': activeTab === settingsTabs.ORGANIZATIONS
'action-list-item--nav__active': activeTab === SettingsTabs.ORGANIZATIONS
}"
>
<a
routerLinkActive="active"
[routerLink]="getRouteLink(settingsTabs.ORGANIZATIONS)"
[routerLink]="getRouteLink(SettingsTabs.ORGANIZATIONS)"
data-view-component="true"
class="action-list-content"
>
Expand Down
100 changes: 100 additions & 0 deletions src/app/auth/settings/account-settings.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { mockAccountDetails } from "../../api/mock/auth.mock";
import { RouterTestingModule } from "@angular/router/testing";
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { ActivatedRoute, NavigationEnd, Router, RouterEvent } from "@angular/router";
import { ApolloTestingModule } from "apollo-angular/testing";
import { AccountSettingsComponent } from "./account-settings.component";
import { AngularSvgIconModule } from "angular-svg-icon";
import { HttpClientTestingModule } from "@angular/common/http/testing";
import { LoggedUserService } from "../logged-user.service";
import { findElementByDataTestId, getElementByDataTestId } from "src/app/common/base-test.helpers.spec";
import { AuthApi } from "src/app/api/auth.api";
import { SettingsTabs } from "./settings.constants";
import { Subject, of } from "rxjs";
import ProjectLinks from "src/app/project-links";

describe("AccountSettingsComponent", () => {
let component: AccountSettingsComponent;
let fixture: ComponentFixture<AccountSettingsComponent>;
let loggedUserService: LoggedUserService;
let authApi: AuthApi;
let activatedRoute: ActivatedRoute;
let router: Router;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [AccountSettingsComponent],
imports: [
ApolloTestingModule,
RouterTestingModule,
AngularSvgIconModule.forRoot(),
HttpClientTestingModule,
],
}).compileComponents();

activatedRoute = TestBed.inject(ActivatedRoute);
router = TestBed.inject(Router);

authApi = TestBed.inject(AuthApi);
spyOn(authApi, "accountChanged").and.returnValue(of(mockAccountDetails));
loggedUserService = TestBed.inject(LoggedUserService);

fixture = TestBed.createComponent(AccountSettingsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

enum Elements {
UserNameLink = "user-name-link",
}

it("should create", () => {
expect(component).toBeTruthy();
});

it("should see logged user", () => {
const userNameLinKElement: HTMLElement = getElementByDataTestId(fixture, Elements.UserNameLink);
expect(userNameLinKElement.innerText).toEqual(mockAccountDetails.displayName);
});

it("should not show user data for logged off case", () => {
loggedUserService.logout();
fixture.detectChanges();

expect(findElementByDataTestId(fixture, Elements.UserNameLink)).toBeFalsy();
});

it("should open profile tab by default", () => {
expect(component.activeTab).toEqual(SettingsTabs.PROFILE);
});

[
SettingsTabs.ACCESSIBILITY,
SettingsTabs.ACCOUNT,
SettingsTabs.APPEARANCE,
SettingsTabs.BILLING,
SettingsTabs.EMAILS,
SettingsTabs.NOTIFICATIONS,
SettingsTabs.ORGANIZATIONS,
SettingsTabs.PROFILE,
SettingsTabs.SECURITY,
].forEach((tab: SettingsTabs) => {
it(`should activate ${tab} tab`, () => {
activatedRoute.snapshot.params = {
[ProjectLinks.URL_PARAM_CATEGORY]: tab,
};
(router.events as Subject<RouterEvent>).next(new NavigationEnd(1, "", ""));

expect(component.activeTab).toEqual(tab);
});
});

it("should open profile tab for a wrong tab", () => {
activatedRoute.snapshot.params = {
[ProjectLinks.URL_PARAM_CATEGORY]: "wrong",
};
(router.events as Subject<RouterEvent>).next(new NavigationEnd(1, "", ""));

expect(component.activeTab).toEqual(SettingsTabs.PROFILE);
});
});
59 changes: 59 additions & 0 deletions src/app/auth/settings/account-settings.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import ProjectLinks from "src/app/project-links";
import { AccountDetailsFragment } from "src/app/api/kamu.graphql.interface";
import { SettingsTabs } from "./settings.constants";
import { ChangeDetectionStrategy, Component, OnInit } from "@angular/core";
import { ActivatedRoute, NavigationEnd, Router } from "@angular/router";
import { filter } from "rxjs/operators";
import { BaseComponent } from "src/app/common/base.component";
import AppValues from "src/app/common/app.values";
import { LoggedUserService } from "../logged-user.service";
import { MaybeNull, MaybeUndefined } from "src/app/common/app.types";
import { Observable } from "rxjs";

@Component({
selector: "app-settings",
templateUrl: "./account-settings.component.html",
styleUrls: ["./account-settings.component.sass"],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AccountSettingsComponent extends BaseComponent implements OnInit {
public readonly DEFAULT_AVATAR_URL = AppValues.DEFAULT_AVATAR_URL;
public readonly SettingsTabs: typeof SettingsTabs = SettingsTabs;

public activeTab: SettingsTabs = SettingsTabs.PROFILE;
public user$: Observable<MaybeNull<AccountDetailsFragment>>;

constructor(private router: Router, private route: ActivatedRoute, private loggedUserService: LoggedUserService) {
super();
}

public ngOnInit(): void {
this.trackSubscription(
this.router.events.pipe(filter((event) => event instanceof NavigationEnd)).subscribe(() => {
this.extractActiveTabFromRoute();
}),
);
this.extractActiveTabFromRoute();
this.user$ = this.loggedUserService.onLoggedInUserChanges;
}

public getRouteLink(tab: SettingsTabs): string {
return `/${ProjectLinks.URL_SETTINGS}/${tab}`;
}

private extractActiveTabFromRoute(): void {
const categoryParam: MaybeUndefined<string> = this.route.snapshot.params[
ProjectLinks.URL_PARAM_CATEGORY
] as MaybeUndefined<string>;

if (categoryParam) {
const category = categoryParam as SettingsTabs;
if (Object.values(SettingsTabs).includes(category)) {
this.activeTab = category;
return;
}
}

this.activeTab = SettingsTabs.PROFILE;
}
}
Loading

0 comments on commit d3be42a

Please sign in to comment.