Skip to content

Commit

Permalink
test: Add additional tests and validation for theme definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
mmalerba committed Aug 11, 2023
1 parent 2d69529 commit 74718a1
Show file tree
Hide file tree
Showing 6 changed files with 423 additions and 18 deletions.
120 changes: 103 additions & 17 deletions src/material-experimental/theming/_config-validation.scss
Original file line number Diff line number Diff line change
@@ -1,30 +1,80 @@
@use 'sass:list';
@use 'sass:map';
@use 'sass:meta';
@use 'sass:string';
@use '@angular/material' as mat;
@use './m3-palettes';

/// Updates an error message by finding `$config` and appending a suffix to it.
/// @param {List|String} $err The error message.
/// @param {String} $suffix The suffix to add.
/// @return {List|String} The updated error message.
@function _update-dollar-config($err, $suffix) {
@if meta.type-of($err) == 'list' {
@for $i from 1 through list.length($err) {
$err: list.set-nth($err, $i, _update-dollar-config(list.nth($err, $i), $suffix));
}
}
@else if meta.type-of($err) == 'string' {
$start: string.index($err, '$config');
@if $start {
$err: string.insert($err, $suffix, $start + 7);
}
}
@return $err;
}

/// Validates that the given object is an M3 palette.
/// @param {*} $palette The object to test
/// @return {Boolean|null} null if it is a valid M3 palette, else true.
@function _validate-palette($palette) {
@if not meta.type-of($palette) == 'map' {
@return true;
}
$keys: map.keys($palette);
$expected-keys: map.keys(m3-palettes.$red-palette);
@if mat.private-validate-allowed-values($keys, $expected-keys...) or
mat.private-validate-required-values($keys, $expected-keys...) {
@return true;
}
$nv-keys: map.keys(map.get($palette, neutral-variant));
$expected-nv-keys: map.keys(map.get(m3-palettes.$red-palette, neutral-variant));
@if mat.private-validate-allowed-values($nv-keys, $expected-nv-keys...) or
mat.private-validate-required-values($nv-keys, $expected-nv-keys...) {
@return true;
}
@return null;
}

/// Validates a theme config.
/// @param {Map} $config The config to test.
/// @return {List} null if no error, else the error message
@function validate-theme-config($config) {
$err: mat.private-validate-type($config, 'map', 'null');
@if $err {
@return (#{'$config'} #{'should be a color configuration object. Got:'} $config);
@return (#{'$config should be a configuration object. Got:'} $config);
}
$err: mat.private-validate-allowed-values(map.keys($config or ()), color, typography, density);
$allowed: (color, typography, density);
$err: mat.private-validate-allowed-values(map.keys($config or ()), $allowed...);
@if $err {
@return (#{'$config'} #{'has unexpected properties:'} $err);
@return (
#{'$config has unexpected properties. Valid properties are'}
#{'#{$allowed}.'}
#{'Found:'}
$err
);
}
$err: validate-color-config(map.get($config, color));
@if $err {
@return list.set-nth($err, 1, #{'#{list.nth($err, 1)}.color'});
@return _update-dollar-config($err, '.color');
}
$err: validate-typography-config(map.get($config, typography));
@if $err {
@return list.set-nth($err, 1, #{'#{list.nth($err, 1)}.typography'});
@return _update-dollar-config($err, '.typography');
}
$err: validate-density-config(map.get($config, density));
@if $err {
@return list.set-nth($err, 1, #{'#{list.nth($err, 1)}.density'});
@return _update-dollar-config($err, '.density');
}
@return null;
}
Expand All @@ -35,12 +85,35 @@
@function validate-color-config($config) {
$err: mat.private-validate-type($config, 'map', 'null');
@if $err {
@return (#{'$config'} #{'should be a color configuration object. Got:'} $config);
@return (#{'$config should be a color configuration object. Got:'} $config);
}
$err: mat.private-validate-allowed-values(
map.keys($config or ()), theme-type, primary, secondary, tertiary);
$allowed: (theme-type, primary, secondary, tertiary);
$err: mat.private-validate-allowed-values(map.keys($config or ()), $allowed...);
@if $err {
@return (#{'$config'} #{'has unexpected properties:'} $err);
@return (
#{'$config has unexpected properties. Valid properties are'}
#{'#{$allowed}.'}
#{'Found:'}
$err
);
}
@if $config and map.has-key($config, theme-type) and
not list.index((light, dark), map.get($config, theme-type)) {
@return (
#{'Expected $config.theme-type to be one of: light, dark. Got:'}
map.get($config, theme-type)
);
}
@each $palette in (primary, secondary, tertiary) {
@if $config and map.has-key($config, $palette) {
$err: _validate-palette(map.get($config, $palette));
@if $err {
@return (
#{'Expected $config.#{$palette} to be a valid M3 palette. Got:'}
map.get($config, $palette)
);
}
}
}
@return null;
}
Expand All @@ -51,13 +124,17 @@
@function validate-typography-config($config) {
$err: mat.private-validate-type($config, 'map', 'null');
@if $err {
@return (#{'$config'} #{'should be a typography configuration object. Got:'} $config);
@return (#{'$config should be a typography configuration object. Got:'} $config);
}
$err: mat.private-validate-allowed-values(
map.keys($config or ()), brand-family, plain-family, bold-weight, medium-weight,
regular-weight);
$allowed: (brand-family, plain-family, bold-weight, medium-weight, regular-weight);
$err: mat.private-validate-allowed-values(map.keys($config or ()), $allowed...);
@if $err {
@return (#{'$config'} #{'has unexpected properties:'} $err);
@return (
#{'$config has unexpected properties. Valid properties are'}
#{'#{$allowed}.'}
#{'Found:'}
$err
);
}
@return null;
}
Expand All @@ -68,11 +145,20 @@
@function validate-density-config($config) {
$err: mat.private-validate-type($config, 'map', 'null');
@if $err {
@return (#{'$config'} #{'should be a density configuration object. Got:'} $config);
@return (#{'$config should be a density configuration object. Got:'} $config);
}
$err: mat.private-validate-allowed-values(map.keys($config or ()), scale);
@if $err {
@return (#{'$config'} #{'has unexpected properties:'} $err);
@return (#{'$config has unexpected properties. Valid properties are: scale. Found:'} $err);
}
@if $config and map.has-key($config, scale) {
$allowed-scales: (0, -1, -2, -3, -4 -5, minimum, maximum);
@if mat.private-validate-allowed-values(map.get($config, scale), $allowed-scales...) {
@return (
#{'Expected $config.scale to be one of: #{$allowed-scales}. Got:'}
map.get($config, scale)
);
}
}
@return null;
}
2 changes: 1 addition & 1 deletion src/material-experimental/theming/_definition.scss
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ $theme-version: 1;
@error $err;
}

$plain: map.get($config, plain-family) or Roboto, sans-serif;
$plain: map.get($config, plain-family) or (Roboto, sans-serif);
$brand: map.get($config, brand-family) or $plain;
$bold: map.get($config, bold-weight) or 700;
$medium: map.get($config, medium-weight) or 500;
Expand Down
1 change: 1 addition & 0 deletions src/material-experimental/theming/_m3-palettes.scss
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ $yellow-palette: (
90: #e6e3d1,
95: #f4f1df,
99: #fffbff,
100: #fff,
),
);

Expand Down
14 changes: 14 additions & 0 deletions src/material/core/style/_validation.scss
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,17 @@
}
@return if(list.length($invalid) > 0, $invalid, null);
}

/// Validates that a list contains all values from the required list of values.
/// @param {List} $list The list to test
/// @param {List} $required The required values
/// @return {List} null if no error, else the list of missing values.
@function validate-required-values($list, $required...) {
$invalid: ();
@each $element in $required {
@if not list.index($list, $element) {
$invalid: list.append($invalid, $element);
}
}
@return if(list.length($invalid) > 0, $invalid, null);
}
1 change: 1 addition & 0 deletions src/material/core/theming/tests/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ ts_library(
name = "unit_test_lib",
testonly = True,
srcs = [
"theming-definition-api.spec.ts",
"theming-inspection-api.spec.ts",
"theming-mixin-api.spec.ts",
],
Expand Down
Loading

0 comments on commit 74718a1

Please sign in to comment.