apphouse
Version:
Component library for React that uses observable state management and theme-able components.
576 lines (510 loc) • 17.6 kB
text/typescript
import { ApphouseThemeTokens } from '../../styles/defaults/app.token.values';
import {
hasFontSizeUnit,
isValidFontSizeUnit
} from '../../utils/units/isValidFontSizeUnit';
import { toPt } from '../../utils/units/toPt';
import { toRems } from '../../utils/units/toRems';
import { toSp } from '../../utils/units/toSp';
import { Token } from '../Token';
import { THEMES } from '../presets';
import { commonColors } from '../presets/commonColors';
import { COLOR, TOKEN } from '../style.interface';
import { SampleTestTheme } from './theme.utils.test';
import {
getColorTokensLookupReferenceFromPalettes,
getLookupTable,
getReferenceTokenFromObject,
getStyleTokenReferenceType,
getTokenListId,
getValueReferenceStringFromObject,
hasColorReference,
toTokensObject
} from './tokens.utils';
describe('objectify tokens', () => {
test('getTokenListId', () => {
let tokenId = getTokenListId({ key: 'small', type: 'spacing' });
expect(tokenId).toBe('spacing.small');
tokenId = getTokenListId({});
expect(tokenId).toBe('unknownTokenId');
tokenId = getTokenListId(undefined);
expect(tokenId).toBe('unknownTokenId');
tokenId = getTokenListId({ key: 'small' });
expect(tokenId).toBe('unknownTokenId');
tokenId = getTokenListId(5);
expect(tokenId).toBe('unknownTokenId');
tokenId = getTokenListId('oueoujqowdjoa');
expect(tokenId).toBe('unknownTokenId');
});
test('objectifyToken dark theme', () => {
const tokens: Record<string, Token> = {
'fontSize.small': new Token({
key: 'small',
value: '11px',
type: 'fontSize'
}),
'fontSize.standard': new Token({
key: 'standard',
value: '15px',
type: 'fontSize'
}),
'fontWeight.bold': new Token({
key: 'bold',
value: '700',
type: 'fontWeight'
})
};
const objToken = toTokensObject(tokens);
expect(objToken).toEqual({
fontSize: {
small: '11px',
standard: '15px'
},
fontWeight: {
bold: '700'
}
});
});
test('getTokenReferenceType', () => {
let type = getStyleTokenReferenceType('backgroundColor');
expect(type).toEqual(COLOR);
type = getStyleTokenReferenceType('color');
expect(type).toEqual(COLOR);
type = getStyleTokenReferenceType('spacings');
expect(type).toEqual(TOKEN);
});
test('hasColorReference', () => {
let ref = hasColorReference('backgroundColor');
expect(ref).toEqual(true);
ref = hasColorReference('color');
expect(ref).toEqual(true);
ref = hasColorReference('spacings');
expect(ref).toEqual(false);
});
test('getReferenceTokenFromObject', () => {
const colors = {
WHITE: '#FFF',
BLACK: '#000'
};
const obj = {
backgroundColor: colors.WHITE
};
let referenceObject = getReferenceTokenFromObject(obj);
expect(referenceObject).toEqual({
key: 'backgroundColor',
type: 'color',
value: '#FFF'
});
referenceObject = getReferenceTokenFromObject(obj, 'button.primary');
expect(referenceObject).toEqual({
key: 'button.primary.backgroundColor',
type: 'color',
value: '#FFF'
});
});
test('getReferenceTokenFromObject when there are nested selectors', () => {
const primaryButtonStyles = THEMES.APPHOUSE_DARK.styles.button.primary;
let referenceObject = getReferenceTokenFromObject(primaryButtonStyles);
expect(referenceObject).toEqual({
key: 'backgroundColor',
type: 'color',
value: '#FFF'
});
referenceObject = getReferenceTokenFromObject(
primaryButtonStyles,
'button.primary'
);
expect(referenceObject).toEqual({
key: 'button.primary.backgroundColor',
type: 'color',
value: '#FFF'
});
});
test('getLookupTable', () => {
const colors = {
WHITE: '#FFF',
BLACK: '#000'
};
const colorsHash = getLookupTable(colors, {}, 'base');
expect(colorsHash).toEqual({
'base.WHITE': '#FFF',
'base.BLACK': '#000'
});
const spacings = {
borders: {
medium: '2px',
large: '3px',
small: '2px'
},
margins: {
medium: '5px',
a: {
b: {
c: '6px'
}
}
}
};
const spacingsHash = getLookupTable(spacings, {}, 'spacings');
expect(spacingsHash).toEqual({
'spacings.borders.small': '2px',
'spacings.borders.medium': '2px', //this will not be part of it because it is a duplicate value
'spacings.borders.large': '3px',
'spacings.margins.medium': '5px',
'spacings.margins.a.b.c': '6px'
});
});
test('getValueReferenceStringFromObject', () => {
const colors = {
WHITE: '#FFF',
BLACK: '#000'
};
let colorsHash = getLookupTable(colors, {}, 'base');
let refString = getValueReferenceStringFromObject('#FFF', colorsHash);
expect(refString).toEqual('base.WHITE');
colorsHash = getLookupTable(colors, {});
refString = getValueReferenceStringFromObject('#FFF', colorsHash);
expect(refString).toEqual('WHITE');
colorsHash = getLookupTable(colors, {}, 'colors');
refString = getValueReferenceStringFromObject('#000', colorsHash);
expect(refString).toEqual('colors.BLACK');
});
test('getValueReferenceStringFromObject using namespace', () => {
const spacings = {
borders: {
medium: '2px',
large: '3px'
},
padding: {
small: '2px'
},
margins: {
medium: '5px',
a: {
b: {
c: '6px'
}
}
}
};
const colorsHash = getLookupTable(spacings, {}, 'spacings');
let refString = getValueReferenceStringFromObject(
'#FFF',
colorsHash,
'padding'
);
expect(refString).toEqual('#FFF');
refString = getValueReferenceStringFromObject('2px', colorsHash, 'padding');
expect(refString).toEqual('spacings.padding.small');
});
test('correctly create lookup table for base colors', () => {
const colorsHash = getLookupTable(commonColors, {}, 'base');
expect(colorsHash).toEqual({
'base.border': '#4B4A4A',
'base.brand': 'rgb(0, 113, 227)',
'base.brandAlt': 'rgb(0, 113, 227)',
'base.error': '#FF0000',
'base.info': 'rgb(0, 113, 227)',
'base.onBrand': '#ececec',
'base.onError': '#ececec',
'base.onInfo': '#ececec',
'base.onSuccess': '#1F1F1F',
'base.onWarning': '#1F1F1F',
'base.required': '#FF0000',
'base.success': '#00B324',
'base.toggleOn': 'rgb(0, 113, 227)',
'base.warning': '#ffa500'
});
});
test('correctly create lookup table for app tokens', () => {
const tokens = getLookupTable(ApphouseThemeTokens);
expect(tokens).toEqual({
'borderWidth.default': '2px',
'borderWidth.none': 0,
'borderWidth.thin': '1px',
'fontFamily.default':
'-apple-system,BlinkMacSystemFont, Roboto, Oxygen, Ubuntu, Cantarell, Open Sans, Helvetica, sans-serif',
'fontFamily.heading':
'-apple-system,BlinkMacSystemFont, Roboto, Oxygen, Ubuntu, Cantarell, Open Sans, Helvetica, sans-serif',
'fontFamily.monospace': 'monospace',
'fontFamily.text':
'-apple-system,BlinkMacSystemFont, Roboto, Oxygen, Ubuntu, Cantarell, Open Sans, Helvetica, sans-serif',
'fontSize.caption': '10px',
'fontSize.header': '42px',
'fontSize.standard': '13px',
'fontSize.standardLarge': '15px',
'fontSize.standardSmall': '11px',
'fontSize.subheader': '26px',
'fontSize.subtitle': '16px',
'fontSize.title': '18px',
'fontWeight.bold': 600,
'fontWeight.bolder': 700,
'fontWeight.light': 300,
'fontWeight.standard': 500,
'iconSize.l': 30,
'iconSize.m': 24,
'iconSize.s': 12,
'iconSize.standard': 16,
'mediaQuery.l':
'@media only screen and (min-width: 1280px) and (max-width: 1919px)',
'mediaQuery.m':
'@media only screen and (min-width: 960px) and (max-width: 1279px)',
'mediaQuery.s':
'@media only screen and (min-width: 600px) and (max-width: 959px)',
'mediaQuery.xl': '@media only screen and (min-width: 1920px)',
'mediaQuery.xs': '@media only screen and (max-width: 599px)',
'radius.circle': '50%',
'radius.default': '6px',
'radius.l': '12px',
'radius.m': '8px',
'radius.s': '4px',
'spacings.default': 8,
'spacings.l': 20,
'spacings.m': 14,
'spacings.r': 10,
'spacings.s': 4,
'spacings.xl': 30,
'spacings.xs': 2,
'zIndex.default': 1,
'zIndex.menu': 400,
'zIndex.overlay': 1000,
'zIndex.panel': 0,
'zIndex.popup': 5000,
'zIndex.toast': 300
});
});
test('correctly creates lookup table for dark themed colors', () => {
const darkColorsLookup = getLookupTable(
THEMES.APPHOUSE_DARK.colors,
{},
'theme'
);
expect(darkColorsLookup).toEqual({
'theme.primary': '#1F1F1F',
'theme.primaryInverse': '#ececec',
'theme.selection': '#39393B',
'theme.surface': '#252526',
'theme.surface10': '#2d2d2d',
'theme.backgroundFocus': undefined,
'theme.backgroundHover': undefined,
'theme.border': '#4B4A4A',
'theme.brand': 'rgb(0, 113, 227)',
'theme.brandAlt': 'rgb(0, 113, 227)',
'theme.error': '#FF0000',
'theme.info': 'rgb(0, 113, 227)',
'theme.onBrand': '#ececec',
'theme.onError': '#ececec',
'theme.onInfo': '#ececec',
'theme.onSuccess': '#1F1F1F',
'theme.onWarning': '#1F1F1F',
'theme.required': '#FF0000',
'theme.success': '#00B324',
'theme.toggleOn': 'rgb(0, 113, 227)',
'theme.warning': '#ffa500',
'theme.borderOnPrimary': '#4B4A4A',
'theme.borderOnPrimaryInverse': '#4B4A4A',
'theme.borderOnSurface': '#4B4A4A',
'theme.borderOnSurface10': '#4B4A4A',
'theme.focusRing.inset': '#000000',
'theme.focusRing.outline': '#FFFFFF',
'theme.onPrimary': '#ececec',
'theme.onPrimaryInverse': '#1F1F1F',
'theme.onSelection': '#ececec',
'theme.onSurface': '#ececec',
'theme.onSurface10': '#ececec'
});
});
test('correctly create lookup table for palette base colors', () => {
const lookup = getColorTokensLookupReferenceFromPalettes(
SampleTestTheme.palette,
'base'
);
expect(lookup).toEqual({
'base.BLACK': 'rgba(31, 31, 31, 1)',
'base.GREEN': 'rgba(0, 179, 36, 1)',
'base.GREY': 'rgba(75, 74, 74, 1)',
'base.GREY_ALT': 'rgba(198, 198, 198, 1)',
'base.GREY_ALT_50': 'rgba(45, 45, 45, 1)',
'base.LIGHT_BLUE': 'rgba(0, 113, 227, 1)',
'base.LIGHT_GRAY': 'rgba(211, 211, 211, 1)',
'base.MONTANA': 'rgba(57, 57, 59, 1)',
'base.NERO': 'rgba(37, 37, 38, 1)',
'base.PURE_BLACK': 'rgba(0, 0, 0, 1)',
'base.PURE_WHITE': 'rgba(255, 255, 255, 1)',
'base.RED': 'rgba(255, 0, 0, 1)',
'base.WHITE': 'rgba(236, 236, 236, 1)',
'base.WHITEISH': 'rgba(221, 221, 221, 1)',
'base.YELLOW': 'rgba(255, 165, 0, 1)'
});
});
test('correctly create lookup table for palette dark colors', () => {
const lookup = getColorTokensLookupReferenceFromPalettes(
SampleTestTheme.palette,
'base',
'dark'
);
expect(lookup).toEqual({
'theme.border': 'rgba(75, 74, 74, 1)',
'theme.brand': 'rgba(0, 113, 227, 1)',
'theme.brandAlt': 'rgba(0, 113, 227, 1)',
'theme.error': 'rgba(255, 0, 0, 1)',
'theme.info': 'rgba(0, 113, 227, 1)',
'theme.inset': 'rgba(0, 0, 0, 1)',
'theme.onBrand': 'rgba(236, 236, 236, 1)',
'theme.onError': 'rgba(236, 236, 236, 1)',
'theme.onInfo': 'rgba(236, 236, 236, 1)',
'theme.onPrimary': 'rgba(75, 74, 74, 1)',
'theme.onPrimaryInverse': 'rgba(75, 74, 74, 1)',
'theme.onSuccess': 'rgba(31, 31, 31, 1)',
'theme.onSurface': 'rgba(75, 74, 74, 1)',
'theme.onSurface10': 'rgba(75, 74, 74, 1)',
'theme.onWarning': 'rgba(31, 31, 31, 1)',
'theme.outline': 'rgba(255, 255, 255, 1)',
'theme.primary': 'rgba(236, 236, 236, 1)',
'theme.primaryInverse': 'rgba(31, 31, 31, 1)',
'theme.required': 'rgba(255, 0, 0, 1)',
'theme.selection': 'rgba(236, 236, 236, 1)',
'theme.success': 'rgba(0, 179, 36, 1)',
'theme.surface': 'rgba(236, 236, 236, 1)',
'theme.surface10': 'rgba(236, 236, 236, 1)',
'theme.toggleOn': 'rgba(0, 113, 227, 1)',
'theme.warning': 'rgba(255, 165, 0, 1)'
});
});
test('correctly create lookup table for palette light colors', () => {
const lookup = getColorTokensLookupReferenceFromPalettes(
SampleTestTheme.palette,
'base',
'light'
);
expect(lookup).toEqual({
'theme.border': 'rgba(75, 74, 74, 1)',
'theme.brand': 'rgba(0, 113, 227, 1)',
'theme.brandAlt': 'rgba(0, 113, 227, 1)',
'theme.error': 'rgba(255, 0, 0, 1)',
'theme.info': 'rgba(0, 113, 227, 1)',
'theme.inset': 'rgba(255, 255, 255, 1)',
'theme.onBrand': 'rgba(236, 236, 236, 1)',
'theme.onError': 'rgba(236, 236, 236, 1)',
'theme.onInfo': 'rgba(236, 236, 236, 1)',
'theme.onPrimary': 'rgba(198, 198, 198, 1)',
'theme.onPrimaryInverse': 'rgba(198, 198, 198, 1)',
'theme.onSuccess': 'rgba(31, 31, 31, 1)',
'theme.onSurface': 'rgba(198, 198, 198, 1)',
'theme.onSurface10': 'rgba(198, 198, 198, 1)',
'theme.onWarning': 'rgba(31, 31, 31, 1)',
'theme.outline': 'rgba(0, 0, 0, 1)',
'theme.primary': 'rgba(31, 31, 31, 1)',
'theme.primaryInverse': 'rgba(236, 236, 236, 1)',
'theme.required': 'rgba(255, 0, 0, 1)',
'theme.selection': 'rgba(31, 31, 31, 1)',
'theme.success': 'rgba(0, 179, 36, 1)',
'theme.surface': 'rgba(31, 31, 31, 1)',
'theme.surface10': 'rgba(31, 31, 31, 1)',
'theme.toggleOn': 'rgba(0, 113, 227, 1)',
'theme.warning': 'rgba(255, 165, 0, 1)'
});
});
});
describe('Token unit conversion', () => {
describe('toRems', () => {
test('converts raw number to rems', () => {
let fontSize = toRems(1);
expect(fontSize).toEqual('0.0625rem');
});
test('converts string number to rems', () => {
let fontSize = toRems('1');
expect(fontSize).toEqual('0.0625rem');
});
test('converts string with px unit to rems', () => {
let fontSize = toRems('1px');
expect(fontSize).toEqual('0.0625rem');
});
test('converts string with rem unit to rems', () => {
let fontSize = toRems('1rem');
expect(fontSize).toEqual('1rem');
});
test('converts string with rem unit without any numbers to rems', () => {
let fontSize = toRems('rem');
expect(fontSize).toEqual('0rem');
});
test('converts garbage input to 0rem', () => {
let fontSize = toRems('adadqweqweq');
expect(fontSize).toEqual('0rem');
});
});
test('toSp', () => {
let fontSize = toSp(1);
expect(fontSize).toEqual('1sp');
fontSize = toSp('1');
expect(fontSize).toEqual('1sp');
fontSize = toSp('1px');
expect(fontSize).toEqual('1sp');
fontSize = toSp('1rem');
expect(fontSize).toEqual('16sp');
fontSize = toSp('1xp');
expect(fontSize).toEqual('1sp');
fontSize = toSp('aldkjalskdj');
expect(fontSize).toEqual('1sp');
});
test('toPt', () => {
let fontSize = toPt(1);
expect(fontSize).toEqual('1pt');
fontSize = toPt('1');
expect(fontSize).toEqual('1pt');
fontSize = toPt('1px');
expect(fontSize).toEqual('1pt');
fontSize = toPt('1rem');
expect(fontSize).toEqual('16pt');
fontSize = toPt('1xp');
expect(fontSize).toEqual('1pt');
});
});
describe('Font Units Validation', () => {
test('hasFontSizeUnit', () => {
let fontSize = hasFontSizeUnit(1);
expect(fontSize).toEqual(false);
fontSize = hasFontSizeUnit('1px');
expect(fontSize).toEqual(true);
fontSize = hasFontSizeUnit('1sp');
expect(fontSize).toEqual(true);
fontSize = hasFontSizeUnit('1rem');
expect(fontSize).toEqual(true);
fontSize = hasFontSizeUnit('1ps');
expect(fontSize).toEqual(false);
fontSize = hasFontSizeUnit('1psx');
expect(fontSize).toEqual(false);
//@ts-ignore
fontSize = hasFontSizeUnit(undefined);
expect(fontSize).toEqual(false);
//@ts-ignore
fontSize = hasFontSizeUnit({});
expect(fontSize).toEqual(false);
});
test('isValidFontSizeUnit', () => {
let fontSize = isValidFontSizeUnit(1);
expect(fontSize).toEqual(false);
fontSize = isValidFontSizeUnit('1px');
expect(fontSize).toEqual(true);
fontSize = isValidFontSizeUnit('1sp');
expect(fontSize).toEqual(true);
fontSize = isValidFontSizeUnit('1rem');
expect(fontSize).toEqual(true);
fontSize = isValidFontSizeUnit('1remremrem');
expect(fontSize).toEqual(false);
fontSize = isValidFontSizeUnit('1rempx');
expect(fontSize).toEqual(false);
fontSize = isValidFontSizeUnit('1pxpt');
expect(fontSize).toEqual(false);
fontSize = isValidFontSizeUnit('1ps');
expect(fontSize).toEqual(false);
fontSize = isValidFontSizeUnit('1psx');
expect(fontSize).toEqual(false);
//@ts-ignore
fontSize = isValidFontSizeUnit(undefined);
expect(fontSize).toEqual(false);
//@ts-ignore
fontSize = isValidFontSizeUnit({});
expect(fontSize).toEqual(false);
});
});