Skip to content

Commit 78a3771

Browse files
fix(ref: no-ref): Ensure that "triggerOnMaskChange" and "shownMaskExpression" are received in "NgxMaskService" when provided through "provideNgxMask()"
fix(config): Ensure that "triggerOnMaskChange" and "shownMaskExpression" are received in "NgxMaskService" when provided through "provideNgxMask()".
2 parents dd9f592 + dfc172e commit 78a3771

File tree

5 files changed

+329
-6
lines changed

5 files changed

+329
-6
lines changed

projects/ngx-mask-lib/src/lib/ngx-mask-applier.service.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ export class NgxMaskApplierService {
5757

5858
public instantPrefix: NgxMaskConfig['instantPrefix'] = this._config.instantPrefix;
5959

60+
public triggerOnMaskChange: NgxMaskConfig['triggerOnMaskChange'] =
61+
this._config.triggerOnMaskChange;
62+
6063
private _shift = new Set<number>();
6164

6265
public plusOnePosition = false;
@@ -67,7 +70,8 @@ export class NgxMaskApplierService {
6770

6871
public showKeepCharacterExp = '';
6972

70-
public shownMaskExpression = '';
73+
public shownMaskExpression: NgxMaskConfig['shownMaskExpression'] =
74+
this._config.shownMaskExpression;
7175

7276
public deletedSpecialCharacter = false;
7377

projects/ngx-mask-lib/src/lib/ngx-mask.service.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ export class NgxMaskService extends NgxMaskApplierService {
1414
public selEnd: number | null = null;
1515
public maskChanged = false;
1616
public maskExpressionArray: string[] = [];
17-
public triggerOnMaskChange = false;
1817
public previousValue = '';
1918
public currentValue = '';
2019
/**

projects/ngx-mask-lib/src/test/default-config.spec.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { ReactiveFormsModule, FormControl } from '@angular/forms';
44
import { TestMaskComponent } from './utils/test-component.component';
55
import { provideEnvironmentNgxMask, NgxMaskDirective } from 'ngx-mask';
66
import type { NgxMaskOptions } from 'ngx-mask';
7+
import { By } from '@angular/platform-browser';
78

89
function createComponentWithDefaultConfig(
910
defaultConfig?: NgxMaskOptions
@@ -96,4 +97,52 @@ describe('Default config', () => {
9697
expect(fixture.nativeElement.querySelector('input').value).toBe('15 000,33 €');
9798
});
9899
});
100+
101+
it('default config - triggerOnMaskChange', async () => {
102+
const fixture = createComponentWithDefaultConfig({
103+
triggerOnMaskChange: true,
104+
});
105+
const component = fixture.componentInstance;
106+
component.mask.set('');
107+
fixture.detectChanges();
108+
109+
component.form.setValue('7912345678');
110+
fixture.detectChanges();
111+
await fixture.whenStable();
112+
let inputEl = fixture.debugElement.query(By.css('input'));
113+
expect(inputEl.nativeElement.value).toEqual('7912345678');
114+
expect(component.form.value).toEqual('7912345678');
115+
116+
component.mask.set('00 000 00 00');
117+
fixture.detectChanges();
118+
await fixture.whenStable();
119+
inputEl = fixture.debugElement.query(By.css('input'));
120+
expect(inputEl.nativeElement.value).toEqual('79 123 45 67');
121+
expect(component.form.value).toEqual('791234567');
122+
});
123+
124+
it('default config overridden - triggerOnMaskChange', async () => {
125+
const fixture = createComponentWithDefaultConfig({
126+
triggerOnMaskChange: false,
127+
});
128+
const component = fixture.componentInstance;
129+
// Override default triggerOnMaskChange
130+
component.triggerOnMaskChange.set(true);
131+
component.mask.set('');
132+
fixture.detectChanges();
133+
134+
component.form.setValue('7912345678');
135+
fixture.detectChanges();
136+
await fixture.whenStable();
137+
let inputEl = fixture.debugElement.query(By.css('input'));
138+
expect(inputEl.nativeElement.value).toEqual('7912345678');
139+
expect(component.form.value).toEqual('7912345678');
140+
141+
component.mask.set('00 000 00 00');
142+
fixture.detectChanges();
143+
await fixture.whenStable();
144+
inputEl = fixture.debugElement.query(By.css('input'));
145+
expect(inputEl.nativeElement.value).toEqual('79 123 45 67');
146+
expect(component.form.value).toEqual('791234567');
147+
});
99148
});
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
import type { ComponentFixture } from '@angular/core/testing';
2+
import { TestBed } from '@angular/core/testing';
3+
import { ReactiveFormsModule, FormControl } from '@angular/forms';
4+
import { TestMaskComponent } from './utils/test-component.component';
5+
import {
6+
provideEnvironmentNgxMask,
7+
NgxMaskDirective,
8+
NgxMaskService,
9+
NgxMaskConfig,
10+
} from 'ngx-mask';
11+
import type { NgxMaskOptions } from 'ngx-mask';
12+
import { Component, EventEmitter } from '@angular/core';
13+
14+
function createComponentWithDefaultConfigAndSimpleInputs(
15+
defaultConfig?: NgxMaskOptions
16+
): ComponentFixture<TestMaskSimpleInputsComponent> {
17+
TestBed.configureTestingModule({
18+
imports: [ReactiveFormsModule, NgxMaskDirective, TestMaskComponent],
19+
providers: [provideEnvironmentNgxMask(defaultConfig)],
20+
});
21+
return TestBed.createComponent(TestMaskSimpleInputsComponent);
22+
}
23+
24+
@Component({
25+
selector: 'jsdaddy-open-source-test',
26+
standalone: true,
27+
imports: [ReactiveFormsModule, NgxMaskDirective],
28+
template: `<input [mask]="mask" [formControl]="form" />`,
29+
})
30+
export class TestMaskSimpleInputsComponent {
31+
public form: FormControl = new FormControl();
32+
public mask?: string;
33+
}
34+
35+
describe('provideNgxMask', () => {
36+
it('config - suffix', async () => {
37+
createComponentWithDefaultConfigAndSimpleInputs({
38+
suffix: 'aaa',
39+
});
40+
const service = TestBed.inject(NgxMaskService);
41+
expect(service.suffix).toBe('aaa');
42+
});
43+
44+
it('config - prefix', async () => {
45+
createComponentWithDefaultConfigAndSimpleInputs({ prefix: 'bbb' });
46+
const service = TestBed.inject(NgxMaskService);
47+
expect(service.prefix).toBe('bbb');
48+
});
49+
50+
it('config - thousandSeparator', async () => {
51+
createComponentWithDefaultConfigAndSimpleInputs({ thousandSeparator: '-' });
52+
const service = TestBed.inject(NgxMaskService);
53+
expect(service.thousandSeparator).toBe('-');
54+
});
55+
56+
it('config - decimalMarker', async () => {
57+
createComponentWithDefaultConfigAndSimpleInputs({ decimalMarker: '.' });
58+
const service = TestBed.inject(NgxMaskService);
59+
expect(service.decimalMarker).toBe('.');
60+
});
61+
62+
it('config - clearIfNotMatch', async () => {
63+
createComponentWithDefaultConfigAndSimpleInputs({ clearIfNotMatch: true });
64+
const service = TestBed.inject(NgxMaskService);
65+
expect(service.clearIfNotMatch).toBeTrue();
66+
});
67+
68+
it('config - showMaskTyped', async () => {
69+
createComponentWithDefaultConfigAndSimpleInputs({ showMaskTyped: true });
70+
const service = TestBed.inject(NgxMaskService);
71+
expect(service.showMaskTyped).toBeTrue();
72+
});
73+
74+
it('config - placeHolderCharacter', async () => {
75+
createComponentWithDefaultConfigAndSimpleInputs({ placeHolderCharacter: 'ccc' });
76+
const service = TestBed.inject(NgxMaskService);
77+
expect(service.placeHolderCharacter).toBe('ccc');
78+
});
79+
80+
it('config - shownMaskExpression', async () => {
81+
createComponentWithDefaultConfigAndSimpleInputs({
82+
shownMaskExpression: 'ddd',
83+
});
84+
const service = TestBed.inject(NgxMaskService);
85+
expect(service.shownMaskExpression).toBe('ddd');
86+
});
87+
88+
it('config - specialCharacters', async () => {
89+
createComponentWithDefaultConfigAndSimpleInputs({ specialCharacters: ['a'] });
90+
const service = TestBed.inject(NgxMaskService);
91+
expect(service.specialCharacters).toEqual(['a']);
92+
});
93+
94+
it('config - dropSpecialCharacters', async () => {
95+
createComponentWithDefaultConfigAndSimpleInputs({ dropSpecialCharacters: ['a'] });
96+
const service = TestBed.inject(NgxMaskService);
97+
expect(service.dropSpecialCharacters).toEqual(['a']);
98+
});
99+
100+
it('config - hiddenInput', async () => {
101+
createComponentWithDefaultConfigAndSimpleInputs({ hiddenInput: true });
102+
const service = TestBed.inject(NgxMaskService);
103+
expect(service.hiddenInput).toBeTrue();
104+
});
105+
106+
it('config - validation', async () => {
107+
createComponentWithDefaultConfigAndSimpleInputs({ validation: true });
108+
const service = TestBed.inject(NgxMaskService);
109+
expect(service.validation).toBeTrue();
110+
});
111+
112+
it('config - instantPrefix', async () => {
113+
createComponentWithDefaultConfigAndSimpleInputs({ instantPrefix: true });
114+
const service = TestBed.inject(NgxMaskService);
115+
expect(service.instantPrefix).toBeTrue();
116+
});
117+
118+
it('config - separatorLimit', async () => {
119+
createComponentWithDefaultConfigAndSimpleInputs({ separatorLimit: 'a' });
120+
const service = TestBed.inject(NgxMaskService);
121+
expect(service.separatorLimit).toBe('a');
122+
});
123+
124+
it('config - apm', async () => {
125+
createComponentWithDefaultConfigAndSimpleInputs({ apm: true });
126+
const service = TestBed.inject(NgxMaskService);
127+
expect(service.apm).toBeTrue();
128+
});
129+
130+
it('config - allowNegativeNumbers', async () => {
131+
createComponentWithDefaultConfigAndSimpleInputs({ allowNegativeNumbers: true });
132+
const service = TestBed.inject(NgxMaskService);
133+
expect(service.allowNegativeNumbers).toBeTrue();
134+
});
135+
136+
it('config - leadZeroDateTime', async () => {
137+
createComponentWithDefaultConfigAndSimpleInputs({ leadZeroDateTime: true });
138+
const service = TestBed.inject(NgxMaskService);
139+
expect(service.leadZeroDateTime).toBeTrue();
140+
});
141+
142+
it('config - leadZero', async () => {
143+
createComponentWithDefaultConfigAndSimpleInputs({ leadZero: true });
144+
const service = TestBed.inject(NgxMaskService);
145+
expect(service.leadZero).toBeTrue();
146+
});
147+
148+
it('config - triggerOnMaskChange', async () => {
149+
createComponentWithDefaultConfigAndSimpleInputs({ triggerOnMaskChange: true });
150+
const service = TestBed.inject(NgxMaskService);
151+
expect(service.triggerOnMaskChange).toBeTrue();
152+
});
153+
154+
it('config - keepCharacterPositions', async () => {
155+
createComponentWithDefaultConfigAndSimpleInputs({ keepCharacterPositions: true });
156+
const service = TestBed.inject(NgxMaskService);
157+
expect(service.keepCharacterPositions).toBeTrue();
158+
});
159+
160+
it('config - inputTransformFn', async () => {
161+
const mockInputTransformFn = () => 'test';
162+
createComponentWithDefaultConfigAndSimpleInputs({
163+
inputTransformFn: mockInputTransformFn,
164+
});
165+
const service = TestBed.inject(NgxMaskService);
166+
expect(service.inputTransformFn).toBe(mockInputTransformFn);
167+
});
168+
169+
it('config - outputTransformFn', async () => {
170+
const mockOutputTransformFn = () => 'test';
171+
createComponentWithDefaultConfigAndSimpleInputs({
172+
outputTransformFn: mockOutputTransformFn,
173+
});
174+
const service = TestBed.inject(NgxMaskService);
175+
expect(service.outputTransformFn).toBe(mockOutputTransformFn);
176+
});
177+
178+
it('config - patterns', async () => {
179+
const mockPatterns = {
180+
'0': {
181+
pattern: new RegExp('[a-zA-Z]'),
182+
},
183+
};
184+
createComponentWithDefaultConfigAndSimpleInputs({
185+
patterns: mockPatterns,
186+
});
187+
const service = TestBed.inject(NgxMaskService);
188+
expect(service.patterns).toBe(mockPatterns);
189+
});
190+
191+
it('config - all values', async () => {
192+
const allConfigValues: NgxMaskConfig = {
193+
suffix: 'aaa',
194+
prefix: 'bbb',
195+
thousandSeparator: ',',
196+
decimalMarker: '.',
197+
clearIfNotMatch: true,
198+
showMaskTyped: true,
199+
placeHolderCharacter: '_',
200+
shownMaskExpression: 'c',
201+
specialCharacters: ['d'],
202+
dropSpecialCharacters: true,
203+
hiddenInput: true,
204+
validation: true,
205+
instantPrefix: true,
206+
separatorLimit: '1',
207+
apm: true,
208+
allowNegativeNumbers: true,
209+
leadZeroDateTime: true,
210+
leadZero: true,
211+
triggerOnMaskChange: true,
212+
keepCharacterPositions: true,
213+
inputTransformFn: () => 'e',
214+
outputTransformFn: () => 'f',
215+
maskFilled: new EventEmitter<void>(),
216+
patterns: {
217+
'0': {
218+
pattern: new RegExp('[a-zA-Z]'),
219+
},
220+
},
221+
};
222+
createComponentWithDefaultConfigAndSimpleInputs(allConfigValues);
223+
const service = TestBed.inject(NgxMaskService);
224+
225+
// Exclude the below config keys from the test which do not exist in the service or cannot be tested.
226+
const excludeConfig = ['maskFilled'];
227+
228+
// Ensure that all provided config values are passed through to the service.
229+
for (const key of Object.keys(allConfigValues)) {
230+
if (!excludeConfig.includes(key)) {
231+
expect((service as any)[key]).toEqual((allConfigValues as any)[key]);
232+
}
233+
}
234+
});
235+
});

projects/ngx-mask-lib/src/test/trigger-on-mask-change.spec.ts

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import type { ComponentFixture } from '@angular/core/testing';
22
import { TestBed } from '@angular/core/testing';
3-
43
import { By } from '@angular/platform-browser';
5-
import { ReactiveFormsModule } from '@angular/forms';
64
import { TestMaskComponent } from './utils/test-component.component';
5+
import { ReactiveFormsModule } from '@angular/forms';
76
import { NgxMaskDirective, provideNgxMask } from 'ngx-mask';
87
import type { DebugElement } from '@angular/core';
98
import { equal } from './utils/test-functions.component';
@@ -26,7 +25,7 @@ describe('Directive: Mask (Trigger on mask change)', () => {
2625
fixture.destroy();
2726
});
2827

29-
it('should trigger form value update if mask is changed', async () => {
28+
it('should trigger form value update if mask is changed when triggerOnMaskChange is true', async () => {
3029
component.mask.set('');
3130
component.triggerOnMaskChange.set(true);
3231
fixture.detectChanges();
@@ -46,7 +45,27 @@ describe('Directive: Mask (Trigger on mask change)', () => {
4645
expect(component.form.value).toEqual('791234567');
4746
});
4847

49-
it('should trigger form value update if mask is changed', async () => {
48+
it('should not trigger form value update if mask is changed when triggerOnMaskChange is false', async () => {
49+
component.mask.set('');
50+
component.triggerOnMaskChange.set(false);
51+
fixture.detectChanges();
52+
53+
component.form.setValue('7912345678');
54+
fixture.detectChanges();
55+
await fixture.whenStable();
56+
let inputEl = fixture.debugElement.query(By.css('input'));
57+
expect(inputEl.nativeElement.value).toEqual('7912345678');
58+
expect(component.form.value).toEqual('7912345678');
59+
60+
component.mask.set('00 000 00 00');
61+
fixture.detectChanges();
62+
await fixture.whenStable();
63+
inputEl = fixture.debugElement.query(By.css('input'));
64+
expect(inputEl.nativeElement.value).toEqual('79 123 45 67');
65+
expect(component.form.value).toEqual('7912345678');
66+
});
67+
68+
it('should trigger form value update if mask is changed when triggerOnMaskChange is true', async () => {
5069
component.mask.set('00000||00000-0000');
5170
component.triggerOnMaskChange.set(true);
5271
const debugElement: DebugElement = fixture.debugElement.query(By.css('input'));
@@ -62,4 +81,21 @@ describe('Directive: Mask (Trigger on mask change)', () => {
6281
equal(inputTarget.value, '', fixture, true);
6382
expect(component.form.value).toBe('');
6483
});
84+
85+
it('should not trigger form value update if mask is changed when triggerOnMaskChange is false', async () => {
86+
component.mask.set('00000||00000-0000');
87+
component.triggerOnMaskChange.set(false);
88+
const debugElement: DebugElement = fixture.debugElement.query(By.css('input'));
89+
const inputTarget: HTMLInputElement = debugElement.nativeElement as HTMLInputElement;
90+
spyOnProperty(document, 'activeElement').and.returnValue(inputTarget);
91+
fixture.detectChanges();
92+
93+
equal('1234', '1234', fixture);
94+
expect(inputTarget.value).toEqual('1234');
95+
expect(component.form.value).toBe('1234');
96+
97+
component.mask.set('S0S 0S0');
98+
equal(inputTarget.value, '', fixture, true);
99+
expect(component.form.value).toBe('1234');
100+
});
65101
});

0 commit comments

Comments
 (0)