Skip to content

Commit 59b148e

Browse files
authored
AAE-37713 Amount locale display (#11285)
* [AAE-37713] amount widget formats value based on locale * [AAE-37713] added unit test with currency icon * [AAE-37713] provided amount widget config as observable * [AAE-37713] applied pr comments
1 parent 82b9b18 commit 59b148e

File tree

3 files changed

+418
-12
lines changed

3 files changed

+418
-12
lines changed

lib/core/src/lib/form/components/widgets/amount/amount.widget.html

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
<div class="adf-amount-widget-container">
1313
<mat-form-field class="adf-amount-widget__input adf-form-field-input" [floatLabel]="placeholder ? 'always' : null">
1414
@if ( (field.name || field?.required) && !field.leftLabels) { <mat-label class="adf-label" [attr.for]="field.id">{{field.name | translate }}</mat-label> }
15-
<span matTextPrefix class="adf-amount-widget__prefix-spacing">{{ currency }}&nbsp;</span>
15+
@if(!enableDisplayBasedOnLocale) {
16+
<span matTextPrefix class="adf-amount-widget__prefix-spacing">{{ currency }}&nbsp;</span>
17+
}
1618
<input
1719
matInput
1820
[title]="field.tooltip"
@@ -21,12 +23,13 @@
2123
[id]="field.id"
2224
[required]="field.required && field.isVisible"
2325
[placeholder]="placeholder"
24-
[value]="field.value"
25-
[(ngModel)]="field.value"
26-
(ngModelChange)="onFieldChanged(field)"
26+
[value]="amountWidgetValue"
27+
[(ngModel)]="amountWidgetValue"
28+
(ngModelChange)="onFieldChangedAmountWidget()"
2729
[disabled]="field.readOnly"
28-
(blur)="markAsTouched()"
29-
/>
30+
(focus)="amountWidgetOnFocus()"
31+
(blur)="amountWidgetOnBlur()"
32+
/>
3033
</mat-form-field>
3134
<div class="adf-error-messages-container">
3235
<error-widget [error]="field.validationSummary" />

lib/core/src/lib/form/components/widgets/amount/amount.widget.spec.ts

Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { FormModel } from '../core/form.model';
2323
import { HarnessLoader } from '@angular/cdk/testing';
2424
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
2525
import { UnitTestingUtils } from '../../../../testing/unit-testing-utils';
26+
import { of } from 'rxjs';
2627

2728
describe('AmountWidgetComponent', () => {
2829
let loader: HarnessLoader;
@@ -76,6 +77,137 @@ describe('AmountWidgetComponent', () => {
7677
expect(widget.placeholder).toBe('1234');
7778
});
7879

80+
it('it should return locale based on browser', () => {
81+
const returnedLanguages: string[] = ['en-GB', 'en-US', 'en', 'de-DE', 'pl'];
82+
const mockLanguages = spyOnProperty(window, 'navigator').and.returnValue({
83+
languages: returnedLanguages
84+
} as any);
85+
const locale = widget.getLocale();
86+
87+
expect(locale).toBe(returnedLanguages[0]);
88+
expect(mockLanguages).toHaveBeenCalled();
89+
});
90+
91+
it('it should return default locale if browser does not return valid value', () => {
92+
const defaultLocale = 'en-US';
93+
spyOnProperty(window, 'navigator').and.returnValue({
94+
languages: undefined
95+
} as any);
96+
const locale = widget.getLocale();
97+
98+
expect(locale).toBe(defaultLocale);
99+
});
100+
101+
it('should set initial values when enableDisplayBasedOnLocale is enabled', () => {
102+
const returnedLanguages: string[] = ['en-GB'];
103+
spyOnProperty(window, 'navigator').and.returnValue({
104+
languages: returnedLanguages
105+
} as any);
106+
widget.field = new FormFieldModel(null, { id: 1, name: 'test', value: 25, currency: 'USD' });
107+
widget.enableDisplayBasedOnLocale = true;
108+
widget.currency = 'USD';
109+
widget.setInitialValues();
110+
111+
expect(widget.amountWidgetValue).toBe('$25');
112+
expect(widget.decimalProperty).toBe('1.0-0');
113+
expect(widget.locale).toBe(returnedLanguages[0]);
114+
expect(widget.valueAsNumber).toBe(25);
115+
});
116+
117+
it('should set initial values with correct currency', () => {
118+
const returnedLanguages: string[] = ['en-GB'];
119+
spyOnProperty(window, 'navigator').and.returnValue({
120+
languages: returnedLanguages
121+
} as any);
122+
widget.field = new FormFieldModel(null, { id: 2, name: 'test', value: 25, currency: 'GBP' });
123+
widget.enableDisplayBasedOnLocale = true;
124+
widget.currency = 'GBP';
125+
widget.setInitialValues();
126+
127+
expect(widget.amountWidgetValue).toBe('£25');
128+
expect(widget.decimalProperty).toBe('1.0-0');
129+
});
130+
131+
it('should set initial values with correct currency icon', () => {
132+
const returnedLanguages: string[] = ['en-GB'];
133+
spyOnProperty(window, 'navigator').and.returnValue({
134+
languages: returnedLanguages
135+
} as any);
136+
widget.field = new FormFieldModel(null, { id: 2, name: 'test', value: 25, currency: '¥' });
137+
widget.enableDisplayBasedOnLocale = true;
138+
widget.currency = '¥';
139+
widget.setInitialValues();
140+
141+
expect(widget.amountWidgetValue).toBe('¥25');
142+
expect(widget.decimalProperty).toBe('1.0-0');
143+
});
144+
145+
it('should set initial values without currency', () => {
146+
const returnedLanguages: string[] = ['en-GB'];
147+
spyOnProperty(window, 'navigator').and.returnValue({
148+
languages: returnedLanguages
149+
} as any);
150+
widget.field = new FormFieldModel(null, { id: 3, name: 'test', value: 25, currency: '' });
151+
widget.enableDisplayBasedOnLocale = true;
152+
widget.currency = '';
153+
widget.currencyDisplay = '';
154+
widget.setInitialValues();
155+
156+
expect(widget.amountWidgetValue).toBe('25');
157+
expect(widget.decimalProperty).toBe('1.0-0');
158+
});
159+
160+
it('should set initial values when enableDisplayBasedOnLocale is disabled', () => {
161+
widget.field = new FormFieldModel(null, { id: 4, name: 'test', value: 25, enableFractions: false, className: '' });
162+
widget.enableDisplayBasedOnLocale = false;
163+
widget.setInitialValues();
164+
165+
expect(widget.amountWidgetValue.toString()).toBe('25');
166+
});
167+
168+
it('should transform value from number to string', () => {
169+
widget.enableDisplayBasedOnLocale = true;
170+
widget.valueAsNumber = 123456;
171+
widget.amountWidgetOnFocus();
172+
expect(widget.amountWidgetValue).toBe('123456');
173+
174+
widget.valueAsNumber = 123456.11;
175+
widget.amountWidgetOnFocus();
176+
expect(widget.amountWidgetValue).toBe('123456.11');
177+
178+
widget.valueAsNumber = 0;
179+
widget.amountWidgetOnFocus();
180+
expect(widget.amountWidgetValue).toBe('0');
181+
182+
widget.valueAsNumber = undefined;
183+
widget.amountWidgetOnFocus();
184+
expect(widget.amountWidgetValue).toBe(null);
185+
});
186+
187+
it('should update field.value on change', () => {
188+
widget.field = new FormFieldModel(null, { id: 5, name: 'test', value: 25 });
189+
const mockValue = '1234.12';
190+
widget.amountWidgetValue = mockValue;
191+
widget.onFieldChangedAmountWidget();
192+
193+
expect(widget.field.value).toBe(mockValue);
194+
});
195+
196+
it('should transform values on blur', () => {
197+
widget.enableDisplayBasedOnLocale = true;
198+
widget.amountWidgetValue = '1234.56';
199+
widget.amountWidgetOnBlur();
200+
201+
expect(widget.valueAsNumber).toBe(1234.56);
202+
expect(widget.amountWidgetValue).toBe('$1,234.56');
203+
204+
widget.amountWidgetValue = '';
205+
widget.amountWidgetOnBlur();
206+
207+
expect(widget.valueAsNumber).toBe(null);
208+
expect(widget.amountWidgetValue).toBe(null);
209+
});
210+
79211
describe('when tooltip is set', () => {
80212
beforeEach(() => {
81213
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }), {
@@ -327,6 +459,189 @@ describe('AmountWidgetComponent - rendering', () => {
327459
expect(asterisk.textContent).toEqual('*');
328460
});
329461
});
462+
463+
describe('Test widget with different setting for enableDisplayBasedOnLocale', () => {
464+
beforeEach(() => {
465+
TestBed.resetTestingModule();
466+
});
467+
468+
describe('set module for enableDisplayBasedOnLocale = true', () => {
469+
const mockField = new FormFieldModel(new FormModel(), {
470+
id: 'TestAmount1',
471+
name: 'Test Amount',
472+
type: 'amount',
473+
currency: 'USD',
474+
enableFractions: true,
475+
value: '1234.55'
476+
});
477+
beforeEach(async () => {
478+
TestBed.configureTestingModule({
479+
imports: [AmountWidgetComponent],
480+
providers: [{ provide: ADF_AMOUNT_SETTINGS, useValue: { enableDisplayBasedOnLocale: true } }]
481+
});
482+
fixture = TestBed.createComponent(AmountWidgetComponent);
483+
widget = fixture.componentInstance;
484+
485+
fixture.componentRef.setInput('field', mockField);
486+
loader = TestbedHarnessEnvironment.loader(fixture);
487+
testingUtils = new UnitTestingUtils(fixture.debugElement, loader);
488+
fixture.detectChanges();
489+
});
490+
491+
it('should not display prefix with currency when enableDisplayBasedOnLocale = true', async () => {
492+
const field = await testingUtils.getMatFormField();
493+
expect(await field.getPrefixText()).toBe('');
494+
});
495+
496+
it('should call method on focus and change input value', async () => {
497+
const focusSpy = spyOn(widget, 'amountWidgetOnFocus').and.callThrough();
498+
fixture.detectChanges();
499+
500+
const field = await testingUtils.getMatInput();
501+
const fieldValueBeforeFocus = await field.getValue();
502+
await field.focus();
503+
const fieldValue = await field.getValue();
504+
505+
expect(field).toBeDefined();
506+
expect(widget.field.value).toBe('1234.55');
507+
expect(fieldValueBeforeFocus).toBe('$1,234.55');
508+
expect(focusSpy).toHaveBeenCalled();
509+
expect(fieldValue).toBe('1234.55');
510+
});
511+
512+
it('should transform value on blur', async () => {
513+
const newValue = '456789';
514+
const blurSpy = spyOn(widget, 'amountWidgetOnBlur').and.callThrough();
515+
fixture.detectChanges();
516+
517+
const field = await testingUtils.getMatInput();
518+
const fieldValueBeforeBlur = await field.getValue();
519+
await field.setValue(newValue);
520+
await field.blur();
521+
const fieldValue = await field.getValue();
522+
523+
expect(field).toBeDefined();
524+
expect(widget.field.value).toBe(newValue);
525+
expect(fieldValueBeforeBlur).toBe('$1,234.55');
526+
expect(blurSpy).toHaveBeenCalled();
527+
expect(widget.valueAsNumber).toBe(parseFloat(newValue));
528+
expect(widget.amountWidgetValue).toBe('$456,789.00');
529+
expect(fieldValue).toBe('$456,789.00');
530+
});
531+
});
532+
describe('set module for enableDisplayBasedOnLocale = false', () => {
533+
const mockField = new FormFieldModel(new FormModel(), {
534+
id: 'TestAmount1',
535+
name: 'Test Amount',
536+
type: 'amount',
537+
currency: 'USD',
538+
enableFractions: true,
539+
value: '1234.55'
540+
});
541+
beforeEach(async () => {
542+
TestBed.configureTestingModule({
543+
imports: [AmountWidgetComponent],
544+
providers: [{ provide: ADF_AMOUNT_SETTINGS, useValue: { enableDisplayBasedOnLocale: false } }]
545+
});
546+
fixture = TestBed.createComponent(AmountWidgetComponent);
547+
widget = fixture.componentInstance;
548+
549+
fixture.componentRef.setInput('field', mockField);
550+
loader = TestbedHarnessEnvironment.loader(fixture);
551+
testingUtils = new UnitTestingUtils(fixture.debugElement, loader);
552+
fixture.detectChanges();
553+
});
554+
555+
it('should display prefix with currency when enableDisplayBasedOnLocale = true', async () => {
556+
const field = await testingUtils.getMatFormField();
557+
expect(await field.getPrefixText()).toBe('USD');
558+
});
559+
560+
it('should call method on focus and not change input value', async () => {
561+
const focusSpy = spyOn(widget, 'amountWidgetOnFocus').and.callThrough();
562+
fixture.detectChanges();
563+
564+
const field = await testingUtils.getMatInput();
565+
const fieldValueBeforeFocus = await field.getValue();
566+
await field.focus();
567+
const fieldValue = await field.getValue();
568+
569+
expect(field).toBeDefined();
570+
expect(widget.field.value).toBe('1234.55');
571+
expect(widget.valueAsNumber).toBeUndefined();
572+
expect(fieldValueBeforeFocus).toBe('1234.55');
573+
expect(focusSpy).toHaveBeenCalled();
574+
expect(fieldValue).toBe('1234.55');
575+
});
576+
577+
it('should call method on blur and not change input value', async () => {
578+
const newValue = '456789';
579+
const blurSpy = spyOn(widget, 'amountWidgetOnBlur').and.callThrough();
580+
fixture.detectChanges();
581+
582+
const field = await testingUtils.getMatInput();
583+
const fieldValueBeforeBlur = await field.getValue();
584+
await field.setValue(newValue);
585+
await field.blur();
586+
const fieldValue = await field.getValue();
587+
588+
expect(field).toBeDefined();
589+
expect(widget.field.value).toBe(newValue);
590+
expect(widget.valueAsNumber).toBeUndefined();
591+
expect(fieldValueBeforeBlur).toBe('1234.55');
592+
expect(blurSpy).toHaveBeenCalled();
593+
expect(widget.valueAsNumber).toBeUndefined();
594+
expect(widget.amountWidgetValue).toBe('456789');
595+
expect(fieldValue).toBe('456789');
596+
});
597+
});
598+
});
599+
600+
describe('Test widget with ADF_AMOUNT_SETTINGS as observable', () => {
601+
beforeEach(() => {
602+
TestBed.resetTestingModule();
603+
});
604+
605+
describe('set module for enableDisplayBasedOnLocale = true', () => {
606+
const mockField = new FormFieldModel(new FormModel(), {
607+
id: 'TestAmount1',
608+
name: 'Test Amount',
609+
type: 'amount',
610+
currency: 'USD',
611+
enableFractions: true,
612+
value: '1234.55'
613+
});
614+
beforeEach(async () => {
615+
TestBed.configureTestingModule({
616+
imports: [AmountWidgetComponent],
617+
providers: [{ provide: ADF_AMOUNT_SETTINGS, useValue: of({ enableDisplayBasedOnLocale: true }) }]
618+
});
619+
fixture = TestBed.createComponent(AmountWidgetComponent);
620+
widget = fixture.componentInstance;
621+
const returnedLanguages: string[] = ['en-GB', 'en-US', 'en', 'de-DE', 'pl'];
622+
spyOnProperty(window, 'navigator').and.returnValue({
623+
languages: returnedLanguages
624+
} as any);
625+
fixture.componentRef.setInput('field', mockField);
626+
loader = TestbedHarnessEnvironment.loader(fixture);
627+
testingUtils = new UnitTestingUtils(fixture.debugElement, loader);
628+
fixture.detectChanges();
629+
});
630+
631+
it('should set enableDisplayBasedOnLocale to true', () => {
632+
expect(widget.enableDisplayBasedOnLocale).toBeTrue();
633+
expect(widget.decimalProperty).toBe('1.2-2');
634+
expect(widget.locale).toBe('en-GB');
635+
expect(widget.valueAsNumber).toBe('1234.55');
636+
expect(widget.amountWidgetValue).toBe('$1,234.55');
637+
});
638+
639+
it('should not display prefix with currency when enableDisplayBasedOnLocale = true', async () => {
640+
const field = await testingUtils.getMatFormField();
641+
expect(await field.getPrefixText()).toBe('');
642+
});
643+
});
644+
});
330645
});
331646

332647
describe('AmountWidgetComponent settings', () => {

0 commit comments

Comments
 (0)