Skip to content

Commit 29d611b

Browse files
committed
Rebase and improve type checking by ensuring comparator is a function
1 parent 99b09ad commit 29d611b

File tree

2 files changed

+40
-39
lines changed

2 files changed

+40
-39
lines changed

src/lib/select/select.spec.ts

Lines changed: 35 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2168,34 +2168,27 @@ describe('MdSelect', () => {
21682168
beforeEach(async(() => {
21692169
fixture = TestBed.createComponent(NgModelCompareWithSelect);
21702170
instance = fixture.componentInstance;
2171-
spyOn(instance, 'compareByReference').and.callThrough();
21722171
fixture.detectChanges();
21732172
}));
21742173

2175-
const testCompareByReferenceBehavior = () => {
2176-
it('should initialize with no selection despite having a value', () => {
2177-
expect(instance.selectedFood.value).toBe('pizza-1');
2178-
expect(instance.select.selected).toBeUndefined();
2179-
});
2180-
2181-
it('should not update the selection when changing the value', async(() => {
2182-
instance.options.first._selectViaInteraction();
2183-
fixture.detectChanges();
2184-
fixture.whenStable().then(() => {
2185-
expect(instance.selectedFood.value).toEqual('steak-0');
2186-
expect(instance.select.selected).toBeUndefined();
2187-
});
2188-
}));
2189-
};
2190-
2191-
it('should not use the comparator', () => {
2192-
expect(instance.compareByReference).not.toHaveBeenCalled();
2174+
it('should have a selection', () => {
2175+
const selectedOption = instance.select.selected as MdOption;
2176+
expect(selectedOption.value.value).toEqual('pizza-1');
21932177
});
21942178

2195-
testCompareByReferenceBehavior();
2179+
it('should update when making a new selection', async(() => {
2180+
instance.options.last._selectViaInteraction();
2181+
fixture.detectChanges();
2182+
fixture.whenStable().then(() => {
2183+
const selectedOption = instance.select.selected as MdOption;
2184+
expect(instance.selectedFood.value).toEqual('tacos-2');
2185+
expect(selectedOption.value.value).toEqual('tacos-2');
2186+
});
2187+
}));
21962188

21972189
describe('when comparing by reference', () => {
21982190
beforeEach(async(() => {
2191+
spyOn(instance, 'compareByReference').and.callThrough();
21992192
instance.useCompareByReference();
22002193
fixture.detectChanges();
22012194
}));
@@ -2204,30 +2197,32 @@ describe('MdSelect', () => {
22042197
expect(instance.compareByReference).toHaveBeenCalled();
22052198
});
22062199

2207-
testCompareByReferenceBehavior();
2208-
});
2209-
2210-
describe('when comparing by value', () => {
2211-
beforeEach(async(() => {
2212-
instance.useCompareByValue();
2213-
fixture.detectChanges();
2214-
}));
2215-
2216-
it('should have a selection', () => {
2217-
const selectedOption = instance.select.selected as MdOption;
2218-
expect(selectedOption.value.value).toEqual('pizza-1');
2200+
it('should initialize with no selection despite having a value', () => {
2201+
expect(instance.selectedFood.value).toBe('pizza-1');
2202+
expect(instance.select.selected).toBeUndefined();
22192203
});
22202204

2221-
it('should update when making a new selection', async(() => {
2222-
instance.options.last._selectViaInteraction();
2205+
it('should not update the selection when changing the value', async(() => {
2206+
instance.options.first._selectViaInteraction();
22232207
fixture.detectChanges();
22242208
fixture.whenStable().then(() => {
2225-
const selectedOption = instance.select.selected as MdOption;
2226-
expect(instance.selectedFood.value).toEqual('tacos-2');
2227-
expect(selectedOption.value.value).toEqual('tacos-2');
2209+
expect(instance.selectedFood.value).toEqual('steak-0');
2210+
expect(instance.select.selected).toBeUndefined();
22282211
});
22292212
}));
22302213
});
2214+
2215+
describe('when using a non-function comparator', () => {
2216+
beforeEach(() => {
2217+
instance.useNullComparator();
2218+
});
2219+
2220+
it('should throw an error', () => {
2221+
expect(() => {
2222+
fixture.detectChanges();
2223+
}).toThrowError('compareWith must be a function, but received null');
2224+
});
2225+
});
22312226
});
22322227
});
22332228

@@ -2636,7 +2631,7 @@ class NgModelCompareWithSelect {
26362631
{ value: 'tacos-2', viewValue: 'Tacos' },
26372632
];
26382633
selectedFood: {value: string, viewValue: string} = { value: 'pizza-1', viewValue: 'Pizza' };
2639-
comparator: (f1: any, f2: any) => boolean;
2634+
comparator: ((f1: any, f2: any) => boolean)|null = this.compareByValue;
26402635

26412636
@ViewChild(MdSelect) select: MdSelect;
26422637
@ViewChildren(MdOption) options: QueryList<MdOption>;
@@ -2645,6 +2640,8 @@ class NgModelCompareWithSelect {
26452640

26462641
useCompareByReference() { this.comparator = this.compareByReference; }
26472642

2643+
useNullComparator() { this.comparator = null; }
2644+
26482645
compareByValue(f1: any, f2: any) { return f1 && f2 && f1.value === f2.value; }
26492646

26502647
compareByReference(f1: any, f2: any) { return f1 === f2; }

src/lib/select/select.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,11 +277,15 @@ export class MdSelect implements AfterContentInit, OnDestroy, OnInit, ControlVal
277277
@Input()
278278
get compareWith() { return this._compareWith; }
279279
set compareWith(fn: (o1: any, o2: any) => boolean) {
280+
if (typeof fn !== 'function') {
281+
throw new TypeError(
282+
`compareWith must be a function, but received ${JSON.stringify(fn)}`);
283+
}
284+
this._compareWith = fn;
280285
if (this._selectionModel) {
281286
// A different comparator means the selection could change.
282287
this._initializeSelection();
283288
}
284-
this._compareWith = fn;
285289
}
286290

287291
/** Whether to float the placeholder text. */

0 commit comments

Comments
 (0)