Skip to content

Commit

Permalink
fix(ObservableMedia): properly announce 'xs' activation at startup (#396
Browse files Browse the repository at this point in the history
)

MatchMedia was not properly announcing XS activations for applications with startup viewports < 600px.
Improve the specificity of the 'xs' media query enables proper MatchMedia notifications at startup.

Fixes #388.
  • Loading branch information
ThomasBurleson authored and tinayuangao committed Sep 7, 2017
1 parent 7a48c25 commit 66f3717
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 47 deletions.
7 changes: 3 additions & 4 deletions src/lib/api/core/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,8 @@ export abstract class BaseFxDirective implements OnDestroy, OnChanges {
* Note: this allows use to preserve the original style
* and optional restore it when the mediaQueries deactivate
*/
protected _getDisplayStyle(source?: HTMLElement): string {
let element: HTMLElement = source || this.nativeElement;
return lookupStyle(element, 'display');
protected _getDisplayStyle(source: HTMLElement = this.nativeElement): string {
return lookupStyle(source || this.nativeElement, 'display');
}

/**
Expand Down Expand Up @@ -164,7 +163,7 @@ export abstract class BaseFxDirective implements OnDestroy, OnChanges {
*/
protected _applyStyleToElement(style: StyleDefinition,
value?: string | number,
nativeElement?: any) {
nativeElement: any = this.nativeElement) {
let element = nativeElement || this.nativeElement;
applyStyleToElement(this._renderer, element, style, value);
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/media-query/breakpoints/data/break-points.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const RESPONSIVE_ALIASES = [
export const DEFAULT_BREAKPOINTS: BreakPoint[] = [
{
alias: 'xs',
mediaQuery: '(max-width: 599px)'
mediaQuery: '(min-width: 0px) and (max-width: 599px)'
},
{
alias: 'gt-xs',
Expand Down
17 changes: 17 additions & 0 deletions src/lib/media-query/mock/mock-match-media.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,4 +237,21 @@ describe('mock-match-media', () => {

subscription.unsubscribe();
});

it('can observe a startup activation of XS', () => {
let current: MediaChange,
bpXS = breakPoints.findByAlias('xs');

matchMedia.activate(bpXS.mediaQuery);
let subscription = matchMedia.observe(bpXS.mediaQuery)
.subscribe((change: MediaChange) => {
current = change;
});

expect(current).toBeTruthy();
expect(current.mediaQuery).toEqual(bpXS.mediaQuery);
expect(matchMedia.isActive(bpXS.mediaQuery)).toBeTruthy();

subscription.unsubscribe();
});
});
96 changes: 58 additions & 38 deletions src/lib/media-query/observable-media.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,26 +139,46 @@ describe('observable-media', () => {
}));

it('can `.unsubscribe()` properly', async(inject(
[ObservableMedia, MatchMedia],
(media, matchMedia) => {
let current: MediaChange;
let subscription = media.subscribe((change: MediaChange) => {
current = change;
});

// Activate mediaQuery associated with 'md' alias
matchMedia.activate('md');
expect(current.mediaQuery).toEqual(findMediaQuery('md'));

// Un-subscribe
subscription.unsubscribe();

matchMedia.activate('lg');
expect(current.mqAlias).toBe('md');

matchMedia.activate('xs');
expect(current.mqAlias).toBe('md');
})));
[ObservableMedia, MatchMedia],
(media, matchMedia) => {
let current: MediaChange;
let subscription = media.subscribe((change: MediaChange) => {
current = change;
});

// Activate mediaQuery associated with 'md' alias
matchMedia.activate('md');
expect(current.mediaQuery).toEqual(findMediaQuery('md'));

// Un-subscribe
subscription.unsubscribe();

matchMedia.activate('lg');
expect(current.mqAlias).toBe('md');

matchMedia.activate('xs');
expect(current.mqAlias).toBe('md');
})));

it('can observe a startup activation of XS', async(inject(
[ObservableMedia, MatchMedia],
(media, matchMedia) => {
let current: MediaChange;
let subscription = media.subscribe((change: MediaChange) => {
current = change;
});

// Activate mediaQuery associated with 'md' alias
matchMedia.activate('xs');
expect(current.mediaQuery).toEqual(findMediaQuery('xs'));

// Un-subscribe
subscription.unsubscribe();

matchMedia.activate('lg');
expect(current.mqAlias).toBe('xs');

})));
});

describe('with custom BreakPoints', () => {
Expand All @@ -176,30 +196,30 @@ describe('observable-media', () => {
providers: [
BreakPointRegistry, // Registry of known/used BreakPoint(s)
MockMatchMediaProvider,
CUSTOM_BREAKPOINTS_PROVIDER_FACTORY(CUSTOM_BREAKPOINTS, {defaults: excludeDefaults} ),
CUSTOM_BREAKPOINTS_PROVIDER_FACTORY(CUSTOM_BREAKPOINTS, {defaults: excludeDefaults}),
OBSERVABLE_MEDIA_PROVIDER,
]
});
});

it('can activate custom alias with custom mediaQueries', async(inject(
[ObservableMedia, MatchMedia],
(media, matchMedia) => {
let current: MediaChange;
let subscription = media.subscribe((change: MediaChange) => {
current = change;
});

// Activate mediaQuery associated with 'md' alias
matchMedia.activate('print.md');
expect(current.mediaQuery).toEqual(mdMediaQuery);

matchMedia.activate('tablet-gt-xs');
expect(current.mqAlias).toBe('tablet-gt-xs');
expect(current.mediaQuery).toBe(gtXsMediaQuery);

subscription.unsubscribe();
})));
[ObservableMedia, MatchMedia],
(media, matchMedia) => {
let current: MediaChange;
let subscription = media.subscribe((change: MediaChange) => {
current = change;
});

// Activate mediaQuery associated with 'md' alias
matchMedia.activate('print.md');
expect(current.mediaQuery).toEqual(mdMediaQuery);

matchMedia.activate('tablet-gt-xs');
expect(current.mqAlias).toBe('tablet-gt-xs');
expect(current.mediaQuery).toBe(gtXsMediaQuery);

subscription.unsubscribe();
})));

});

Expand Down
9 changes: 5 additions & 4 deletions src/lib/utils/testing/custom-matchers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,12 +224,13 @@ function buildCompareStyleFunction(inlineOnly = true) {
return {
pass: allPassed,
get message() {
const expectedValueStr = (typeof styles === 'string') ? styles : JSON.stringify(styles);
const expectedValueStr = (typeof styles === 'string') ? styles :
JSON.stringify(styles, null, 2);
const foundValueStr = inlineOnly ? actual.outerHTML : JSON.stringify(found);
return `
Expected ${foundValueStr} ${!allPassed ? ' ' : 'not '} to contain the
CSS ${typeof styles === 'string' ? 'property' : 'styles'} '${expectedValueStr}'
`;
Expected ${foundValueStr} ${!allPassed ? ' ' : 'not '} to contain the
CSS ${typeof styles === 'string' ? 'property' : 'styles'} '${expectedValueStr}'
`;
}
};
};
Expand Down

0 comments on commit 66f3717

Please sign in to comment.