Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions packages/design-system-twrnc-preset/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ module.exports = merge(baseConfig, {
// The display name when running multiple projects
displayName,

// TODO add tests to twrnc preset https://github.com/MetaMask/metamask-design-system/issues/90
// Pass with no tests if no test files are found
passWithNoTests: true,

// An object that configures minimum threshold enforcement for coverage results
coverageThreshold: {
global: {
Expand All @@ -38,4 +34,11 @@ module.exports = merge(baseConfig, {
moduleNameMapper: {
'\\.(css|less|scss)$': 'identity-obj-proxy',
},
// Exclude pure type files from coverage since they contain no executable code
// Also exclude enum files that Jest has difficulty tracking coverage for
coveragePathIgnorePatterns: [
'/node_modules/',
'typography\\.types\\.ts$',
'Theme\\.types\\.ts$',
],
});
1 change: 1 addition & 0 deletions packages/design-system-twrnc-preset/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
"jest": "^29.7.0",
"metro-react-native-babel-preset": "^0.77.0",
"react": "^18.2.0",
"react-native": "^0.72.15",
"react-test-renderer": "^18.3.1",
"ts-jest": "^29.2.5",
"typescript": "~5.2.2"
Expand Down
168 changes: 168 additions & 0 deletions packages/design-system-twrnc-preset/src/colors.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import { themeColors } from './colors';
import { Theme } from './Theme.types';

describe('colors', () => {
describe('themeColors', () => {
it('has colors for both light and dark themes', () => {
expect(themeColors).toHaveProperty(Theme.Light);
expect(themeColors).toHaveProperty(Theme.Dark);
expect(typeof themeColors[Theme.Light]).toBe('object');
expect(typeof themeColors[Theme.Dark]).toBe('object');
});

it('flattens nested color objects with kebab-case keys', () => {
const lightColors = themeColors[Theme.Light];

expect(lightColors).toHaveProperty('background-default');
expect(lightColors).toHaveProperty('background-alternative');
expect(lightColors).toHaveProperty('text-default');
expect(lightColors).toHaveProperty('primary-default');
expect(lightColors).toHaveProperty('error-default');
expect(lightColors).toHaveProperty('shadow-default');
});

it('contains expected color values for light theme', () => {
const lightColors = themeColors[Theme.Light];

expect(lightColors['background-default']).toBeDefined();
expect(lightColors['background-alternative']).toBeDefined();
expect(lightColors['text-default']).toBeDefined();
expect(lightColors['primary-default']).toBeDefined();
expect(lightColors['error-default']).toBeDefined();

expect(lightColors['background-default']).toMatch(
/^#[0-9A-F]{6}([0-9A-F]{2})?$/iu,
);
expect(lightColors['text-default']).toMatch(
/^#[0-9A-F]{6}([0-9A-F]{2})?$/iu,
);
expect(lightColors['primary-default']).toMatch(
/^#[0-9A-F]{6}([0-9A-F]{2})?$/iu,
);
expect(lightColors['error-default']).toMatch(
/^#[0-9A-F]{6}([0-9A-F]{2})?$/iu,
);
});

it('contains expected color values for dark theme', () => {
const darkColors = themeColors[Theme.Dark];

expect(darkColors['background-default']).toBeDefined();
expect(darkColors['background-alternative']).toBeDefined();
expect(darkColors['text-default']).toBeDefined();
expect(darkColors['primary-default']).toBeDefined();
expect(darkColors['error-default']).toBeDefined();

expect(darkColors['background-default']).toMatch(
/^#[0-9A-F]{6}([0-9A-F]{2})?$/iu,
);
expect(darkColors['text-default']).toMatch(
/^#[0-9A-F]{6}([0-9A-F]{2})?$/iu,
);
expect(darkColors['primary-default']).toMatch(
/^#[0-9A-F]{6}([0-9A-F]{2})?$/iu,
);
expect(darkColors['error-default']).toMatch(
/^#[0-9A-F]{6}([0-9A-F]{2})?$/iu,
);
});

it('has different colors between light and dark themes', () => {
const lightColors = themeColors[Theme.Light];
const darkColors = themeColors[Theme.Dark];

expect(lightColors['background-default']).not.toBe(
darkColors['background-default'],
);
expect(lightColors['text-default']).not.toBe(darkColors['text-default']);
expect(lightColors['primary-default']).not.toBe(
darkColors['primary-default'],
);
});

it('has consistent structure between themes', () => {
const lightColors = themeColors[Theme.Light];
const darkColors = themeColors[Theme.Dark];

const lightKeys = Object.keys(lightColors).sort();
const darkKeys = Object.keys(darkColors).sort();

expect(lightKeys).toStrictEqual(darkKeys);
expect(lightKeys.length).toBeGreaterThan(0);
});

it('converts camelCase to kebab-case in color keys', () => {
const lightColors = themeColors[Theme.Light];

expect(lightColors).toHaveProperty('background-alternative');
expect(lightColors).toHaveProperty('text-alternative');
expect(lightColors).toHaveProperty('primary-alternative');
expect(lightColors).toHaveProperty('error-alternative');

const keys = Object.keys(lightColors);
const hasCamelCase = keys.some((key) => /[A-Z]/u.test(key));
expect(hasCamelCase).toBe(false);
});

it('includes muted color variants', () => {
const lightColors = themeColors[Theme.Light];
const darkColors = themeColors[Theme.Dark];

expect(lightColors).toHaveProperty('background-muted');
expect(lightColors).toHaveProperty('text-muted');
expect(lightColors).toHaveProperty('primary-muted');
expect(lightColors).toHaveProperty('error-muted');

expect(darkColors).toHaveProperty('background-muted');
expect(darkColors).toHaveProperty('text-muted');
expect(darkColors).toHaveProperty('primary-muted');
expect(darkColors).toHaveProperty('error-muted');
});

it('includes shadow colors', () => {
const lightColors = themeColors[Theme.Light];
const darkColors = themeColors[Theme.Dark];

expect(lightColors).toHaveProperty('shadow-default');
expect(lightColors).toHaveProperty('shadow-primary');
expect(lightColors).toHaveProperty('shadow-error');

expect(darkColors).toHaveProperty('shadow-default');
expect(darkColors).toHaveProperty('shadow-primary');
expect(darkColors).toHaveProperty('shadow-error');
});

it('has all color values as strings', () => {
const lightColors = themeColors[Theme.Light];
const darkColors = themeColors[Theme.Dark];

Object.values(lightColors).forEach((color) => {
expect(typeof color).toBe('string');
expect(color).toMatch(/^#[0-9A-F]{6}([0-9A-F]{2})?$/iu);
});

Object.values(darkColors).forEach((color) => {
expect(typeof color).toBe('string');
expect(color).toMatch(/^#[0-9A-F]{6}([0-9A-F]{2})?$/iu);
});
});

it('filters out non-string and non-object values during flattening', () => {
const lightColors = themeColors[Theme.Light];
const darkColors = themeColors[Theme.Dark];

const lightKeys = Object.keys(lightColors);
const darkKeys = Object.keys(darkColors);

expect(lightKeys.length).toBeGreaterThan(10);
expect(darkKeys.length).toBeGreaterThan(10);

lightKeys.forEach((key) => {
expect(typeof lightColors[key]).toBe('string');
});
darkKeys.forEach((key) => {
expect(typeof darkColors[key]).toBe('string');
});
});
});
});
4 changes: 3 additions & 1 deletion packages/design-system-twrnc-preset/src/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ const flattenColors = (

if (typeof value === 'string') {
result[newKey] = value;
} else if (typeof value === 'object' && value !== null) {
}

if (typeof value === 'object' && value !== null) {
Object.assign(
result,
flattenColors(value as Record<string, unknown>, newKey),
Expand Down
Loading
Loading