Skip to content

Commit

Permalink
refactor: determine salutation options for form select fields
Browse files Browse the repository at this point in the history
  • Loading branch information
SGrueber committed May 4, 2021
1 parent e11f905 commit 7fdd2fd
Show file tree
Hide file tree
Showing 21 changed files with 231 additions and 239 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormGroup } from '@angular/forms';
import { TranslateModule } from '@ngx-translate/core';
import { MockComponent } from 'ng-mocks';
import { of } from 'rxjs';
import { instance, mock, when } from 'ts-mockito';
import { instance, mock } from 'ts-mockito';

import { AppFacade } from 'ish-core/facades/app.facade';
import { Locale } from 'ish-core/models/locale/locale.model';
import { ErrorMessageComponent } from 'ish-shared/components/common/error-message/error-message.component';
import { FormlyTestingModule } from 'ish-shared/formly/dev/testing/formly-testing.module';
import { FormsService } from 'ish-shared/forms/utils/forms.service';

import { B2bUser } from '../../models/b2b-user/b2b-user.model';

Expand All @@ -18,23 +16,22 @@ describe('User Profile Form Component', () => {
let component: UserProfileFormComponent;
let fixture: ComponentFixture<UserProfileFormComponent>;
let element: HTMLElement;
let appFacade: AppFacade;
let formsService: FormsService;

beforeEach(async () => {
appFacade = mock(AppFacade);
formsService = mock(FormsService);

await TestBed.configureTestingModule({
imports: [FormlyTestingModule, TranslateModule.forRoot()],
declarations: [MockComponent(ErrorMessageComponent), UserProfileFormComponent],
providers: [{ provide: AppFacade, useFactory: () => instance(appFacade) }],
providers: [{ provide: FormsService, useFactory: () => instance(formsService) }],
}).compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(UserProfileFormComponent);
component = fixture.componentInstance;
element = fixture.nativeElement;
when(appFacade.currentLocale$).thenReturn(of({ lang: 'en_US' } as Locale));

component.form = new FormGroup({});
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { FormlyFieldConfig } from '@ngx-formly/core';
import { TranslateService } from '@ngx-translate/core';
import { pick } from 'lodash-es';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

import { AppFacade } from 'ish-core/facades/app.facade';
import { HttpError } from 'ish-core/models/http-error/http-error.model';
import { whenTruthy } from 'ish-core/utils/operators';
import { SelectOption } from 'ish-shared/forms/components/select/select.component';
import { determineSalutations } from 'ish-shared/forms/utils/form-utils';
import { FormsService } from 'ish-shared/forms/utils/forms.service';
import { SpecialValidators } from 'ish-shared/forms/validators/special-validators';

import { B2bUser } from '../../models/b2b-user/b2b-user.model';
Expand All @@ -30,19 +26,11 @@ export class UserProfileFormComponent implements OnInit {

titleOptions$: Observable<SelectOption[]>;

constructor(private appFacade: AppFacade, private translate: TranslateService) {}
constructor(private formsService: FormsService) {}

ngOnInit() {
// determine default language from session and available locales
this.titleOptions$ = this.appFacade.currentLocale$.pipe(
whenTruthy(),
map(locale =>
determineSalutations(locale.lang?.slice(3)).map(title => ({
value: this.translate.instant(title),
label: title,
}))
)
);
this.titleOptions$ = this.formsService.getSalutationOptions();

this.model = this.getModel(this.user);
this.fields = this.getFields();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<ish-account-profile-user
[currentUser]="currentUser$ | async"
[titles]="titles"
[countryCode]="currentCountryCode"
[error]="userError$ | async"
(updateUserProfile)="updateUserProfile($event)"
></ish-account-profile-user>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MockComponent } from 'ng-mocks';
import { EMPTY } from 'rxjs';
import { instance, mock, when } from 'ts-mockito';
import { instance, mock } from 'ts-mockito';

import { AccountFacade } from 'ish-core/facades/account.facade';
import { AppFacade } from 'ish-core/facades/app.facade';
import { LoadingComponent } from 'ish-shared/components/common/loading/loading.component';

import { AccountProfileUserPageComponent } from './account-profile-user-page.component';
Expand All @@ -16,19 +14,13 @@ describe('Account Profile User Page Component', () => {
let element: HTMLElement;

beforeEach(async () => {
const appFacade = mock(AppFacade);
when(appFacade.currentLocale$).thenReturn(EMPTY);

await TestBed.configureTestingModule({
declarations: [
AccountProfileUserPageComponent,
MockComponent(AccountProfileUserComponent),
MockComponent(LoadingComponent),
],
providers: [
{ provide: AccountFacade, useFactory: () => instance(mock(AccountFacade)) },
{ provide: AppFacade, useFactory: () => instance(appFacade) },
],
providers: [{ provide: AccountFacade, useFactory: () => instance(mock(AccountFacade)) }],
}).compileComponents();
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { take, takeUntil } from 'rxjs/operators';
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';

import { AccountFacade } from 'ish-core/facades/account.facade';
import { AppFacade } from 'ish-core/facades/app.facade';
import { HttpError } from 'ish-core/models/http-error/http-error.model';
import { Locale } from 'ish-core/models/locale/locale.model';
import { User } from 'ish-core/models/user/user.model';
import { whenTruthy } from 'ish-core/utils/operators';
import { determineSalutations } from 'ish-shared/forms/utils/form-utils';

/**
* The Account Profile User Page Container Component renders a page where the user can change his profile data using the {@link AccountProfileUserPageComponent}
Expand All @@ -18,38 +14,21 @@ import { determineSalutations } from 'ish-shared/forms/utils/form-utils';
templateUrl: './account-profile-user-page.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AccountProfileUserPageComponent implements OnInit, OnDestroy {
export class AccountProfileUserPageComponent implements OnInit {
currentUser$: Observable<User>;
userError$: Observable<HttpError>;
userLoading$: Observable<boolean>;
currentLocale$: Observable<Locale>;

titles: string[];
currentCountryCode = '';

private destroy$ = new Subject();

constructor(private accountFacade: AccountFacade, private appFacade: AppFacade) {}
constructor(private accountFacade: AccountFacade) {}

ngOnInit() {
this.currentUser$ = this.accountFacade.user$;
this.userError$ = this.accountFacade.userError$;
this.userLoading$ = this.accountFacade.userLoading$;
this.currentLocale$ = this.appFacade.currentLocale$;

// determine default language from session and available locales
this.currentLocale$.pipe(whenTruthy(), take(1), takeUntil(this.destroy$)).subscribe(locale => {
this.currentCountryCode = locale.lang.slice(3);
this.titles = locale.lang ? determineSalutations(this.currentCountryCode) : undefined;
});
}

updateUserProfile(user: User) {
this.accountFacade.updateUserProfile(user);
}

ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
}
Original file line number Diff line number Diff line change
@@ -1,38 +1,35 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { MockComponent } from 'ng-mocks';
import { of } from 'rxjs';
import { anything, instance, mock, spy, verify, when } from 'ts-mockito';
import { anything, instance, mock, spy, verify } from 'ts-mockito';

import { AppFacade } from 'ish-core/facades/app.facade';
import { Locale } from 'ish-core/models/locale/locale.model';
import { User } from 'ish-core/models/user/user.model';
import { ErrorMessageComponent } from 'ish-shared/components/common/error-message/error-message.component';
import { FormlyTestingModule } from 'ish-shared/formly/dev/testing/formly-testing.module';
import { FormsService } from 'ish-shared/forms/utils/forms.service';

import { AccountProfileUserComponent } from './account-profile-user.component';

describe('Account Profile User Component', () => {
let component: AccountProfileUserComponent;
let fixture: ComponentFixture<AccountProfileUserComponent>;
let element: HTMLElement;
let appFacade: AppFacade;
let formsService: FormsService;

beforeEach(async () => {
appFacade = mock(AppFacade);
formsService = mock(FormsService);

await TestBed.configureTestingModule({
imports: [FormlyTestingModule, TranslateModule.forRoot()],
declarations: [AccountProfileUserComponent, MockComponent(ErrorMessageComponent)],
providers: [{ provide: AppFacade, useFactory: () => instance(appFacade) }],
providers: [{ provide: FormsService, useFactory: () => instance(formsService) }],
}).compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(AccountProfileUserComponent);
component = fixture.componentInstance;
element = fixture.nativeElement;
when(appFacade.currentLocale$).thenReturn(of({ lang: 'en_US' } as Locale));
});

it('should be created', () => {
Expand Down Expand Up @@ -61,7 +58,6 @@ describe('Account Profile User Component', () => {
it('should emit updateUserProfile event if form is valid', () => {
const eventEmitter$ = spy(component.updateUserProfile);

component.countryCode = 'US';
component.currentUser = { firstName: 'Patricia', lastName: 'Miller' } as User;
fixture.detectChanges();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { FormlyFieldConfig } from '@ngx-formly/core';
import { TranslateService } from '@ngx-translate/core';
import { pick } from 'lodash-es';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

import { AppFacade } from 'ish-core/facades/app.facade';
import { HttpError } from 'ish-core/models/http-error/http-error.model';
import { User } from 'ish-core/models/user/user.model';
import { whenTruthy } from 'ish-core/utils/operators';
import { SelectOption } from 'ish-shared/forms/components/select/select.component';
import { determineSalutations, markAsDirtyRecursive } from 'ish-shared/forms/utils/form-utils';
import { markAsDirtyRecursive } from 'ish-shared/forms/utils/form-utils';
import { FormsService } from 'ish-shared/forms/utils/forms.service';
import { SpecialValidators } from 'ish-shared/forms/validators/special-validators';

/**
Expand All @@ -25,8 +22,6 @@ import { SpecialValidators } from 'ish-shared/forms/validators/special-validator
})
export class AccountProfileUserComponent implements OnInit {
@Input() currentUser: User;
@Input() titles: string[];
@Input() countryCode: string;
@Input() error: HttpError;

@Output() updateUserProfile = new EventEmitter<User>();
Expand All @@ -39,19 +34,11 @@ export class AccountProfileUserComponent implements OnInit {

titleOptions$: Observable<SelectOption[]>;

constructor(private appFacade: AppFacade, private translate: TranslateService) {}
constructor(private formsService: FormsService) {}

ngOnInit() {
// get localized option values for title select box
this.titleOptions$ = this.appFacade.currentLocale$.pipe(
whenTruthy(),
map(locale =>
determineSalutations(locale.lang?.slice(3)).map(title => ({
value: this.translate.instant(title),
label: title,
}))
)
);
this.titleOptions$ = this.formsService.getSalutationOptions();

this.model = pick(this.currentUser, 'title', 'firstName', 'lastName', 'phoneHome');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { findAllCustomElements, findAllDataTestingIDs } from 'ish-core/utils/dev
import { AddressComponent } from 'ish-shared/components/address/address/address.component';
import { FormlyCustomerAddressFormComponent } from 'ish-shared/formly-address-forms/components/formly-customer-address-form/formly-customer-address-form.component';
import { FormlyTestingModule } from 'ish-shared/formly/dev/testing/formly-testing.module';
import { FormsService } from 'ish-shared/forms/utils/forms.service';

import { BasketInvoiceAddressWidgetComponent } from './basket-invoice-address-widget.component';

Expand All @@ -23,6 +24,7 @@ describe('Basket Invoice Address Widget Component', () => {
let element: HTMLElement;
let checkoutFacade: CheckoutFacade;
let accountFacade: AccountFacade;
let formsService: FormsService;

beforeEach(async () => {
checkoutFacade = mock(CheckoutFacade);
Expand All @@ -32,6 +34,8 @@ describe('Basket Invoice Address Widget Component', () => {
accountFacade = mock(AccountFacade);
when(accountFacade.addresses$()).thenReturn(EMPTY);

formsService = mock(FormsService);

await TestBed.configureTestingModule({
imports: [FormlyTestingModule, TranslateModule.forRoot()],
declarations: [
Expand All @@ -44,6 +48,7 @@ describe('Basket Invoice Address Widget Component', () => {
providers: [
{ provide: CheckoutFacade, useFactory: () => instance(checkoutFacade) },
{ provide: AccountFacade, useFactory: () => instance(accountFacade) },
{ provide: FormsService, useFactory: () => instance(formsService) },
],
}).compileComponents();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { AccountFacade } from 'ish-core/facades/account.facade';
import { CheckoutFacade } from 'ish-core/facades/checkout.facade';
import { Address } from 'ish-core/models/address/address.model';
import { whenTruthy } from 'ish-core/utils/operators';
import { getAddressOptions } from 'ish-shared/forms/utils/form-utils';
import { FormsService } from 'ish-shared/forms/utils/forms.service';

/**
* Standalone widget component for selecting and setting the basket invoice address in the checkout.
Expand Down Expand Up @@ -40,7 +40,11 @@ export class BasketInvoiceAddressWidgetComponent implements OnInit, OnDestroy {

private destroy$ = new Subject();

constructor(private checkoutFacade: CheckoutFacade, private accountFacade: AccountFacade) {}
constructor(
private checkoutFacade: CheckoutFacade,
private accountFacade: AccountFacade,
private formsService: FormsService
) {}

ngOnInit() {
this.invoiceAddress$ = this.checkoutFacade.basketInvoiceAddress$;
Expand Down Expand Up @@ -73,12 +77,12 @@ export class BasketInvoiceAddressWidgetComponent implements OnInit, OnDestroy {
type: 'ish-select-field',
templateOptions: {
fieldClass: 'col-12',
options: getAddressOptions(this.addresses$),
options: this.formsService.getAddressOptions(this.addresses$),
placeholder: this.emptyOptionLabel,
},
hooks: {
onInit: () => {
this.form
onInit: field => {
field.form
.get('id')
.valueChanges.pipe(whenTruthy(), takeUntil(this.destroy$))
.subscribe(addressId => this.checkoutFacade.assignBasketAddress(addressId, 'invoice'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { AddressComponent } from 'ish-shared/components/address/address/address.
import { ModalDialogComponent } from 'ish-shared/components/common/modal-dialog/modal-dialog.component';
import { FormlyCustomerAddressFormComponent } from 'ish-shared/formly-address-forms/components/formly-customer-address-form/formly-customer-address-form.component';
import { FormlyTestingModule } from 'ish-shared/formly/dev/testing/formly-testing.module';
import { FormsService } from 'ish-shared/forms/utils/forms.service';

import { BasketShippingAddressWidgetComponent } from './basket-shipping-address-widget.component';

Expand All @@ -24,6 +25,7 @@ describe('Basket Shipping Address Widget Component', () => {
let element: HTMLElement;
let checkoutFacade: CheckoutFacade;
let accountFacade: AccountFacade;
let formsService: FormsService;

beforeEach(async () => {
checkoutFacade = mock(CheckoutFacade);
Expand All @@ -33,6 +35,8 @@ describe('Basket Shipping Address Widget Component', () => {
accountFacade = mock(AccountFacade);
when(accountFacade.addresses$()).thenReturn(EMPTY);

formsService = mock(FormsService);

await TestBed.configureTestingModule({
imports: [FormlyTestingModule, TranslateModule.forRoot()],
declarations: [
Expand All @@ -46,6 +50,7 @@ describe('Basket Shipping Address Widget Component', () => {
providers: [
{ provide: CheckoutFacade, useFactory: () => instance(checkoutFacade) },
{ provide: AccountFacade, useFactory: () => instance(accountFacade) },
{ provide: FormsService, useFactory: () => instance(formsService) },
],
}).compileComponents();
});
Expand Down
Loading

0 comments on commit 7fdd2fd

Please sign in to comment.