Skip to content

Commit b6e50c6

Browse files
committed
test: Add additional tests and validation for theme definitions
1 parent 8b4b58b commit b6e50c6

File tree

6 files changed

+423
-18
lines changed

6 files changed

+423
-18
lines changed
Lines changed: 103 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,80 @@
11
@use 'sass:list';
22
@use 'sass:map';
3+
@use 'sass:meta';
4+
@use 'sass:string';
35
@use '@angular/material' as mat;
6+
@use './m3-palettes';
7+
8+
/// Updates an error message by finding `$config` and appending a suffix to it.
9+
/// @param {List|String} $err The error message.
10+
/// @param {String} $suffix The suffix to add.
11+
/// @return {List|String} The updated error message.
12+
@function _update-dollar-config($err, $suffix) {
13+
@if meta.type-of($err) == 'list' {
14+
@for $i from 1 through list.length($err) {
15+
$err: list.set-nth($err, $i, _update-dollar-config(list.nth($err, $i), $suffix));
16+
}
17+
}
18+
@else if meta.type-of($err) == 'string' {
19+
$start: string.index($err, '$config');
20+
@if $start {
21+
$err: string.insert($err, $suffix, $start + 7);
22+
}
23+
}
24+
@return $err;
25+
}
26+
27+
/// Validates that the given object is an M3 palette.
28+
/// @param {*} $palette The object to test
29+
/// @return {Boolean|null} null if it is a valid M3 palette, else true.
30+
@function _validate-palette($palette) {
31+
@if not meta.type-of($palette) == 'map' {
32+
@return true;
33+
}
34+
$keys: map.keys($palette);
35+
$expected-keys: map.keys(m3-palettes.$red-palette);
36+
@if mat.private-validate-allowed-values($keys, $expected-keys...) or
37+
mat.private-validate-required-values($keys, $expected-keys...) {
38+
@return true;
39+
}
40+
$nv-keys: map.keys(map.get($palette, neutral-variant));
41+
$expected-nv-keys: map.keys(map.get(m3-palettes.$red-palette, neutral-variant));
42+
@if mat.private-validate-allowed-values($nv-keys, $expected-nv-keys...) or
43+
mat.private-validate-required-values($nv-keys, $expected-nv-keys...) {
44+
@return true;
45+
}
46+
@return null;
47+
}
448

549
/// Validates a theme config.
650
/// @param {Map} $config The config to test.
751
/// @return {List} null if no error, else the error message
852
@function validate-theme-config($config) {
953
$err: mat.private-validate-type($config, 'map', 'null');
1054
@if $err {
11-
@return (#{'$config'} #{'should be a color configuration object. Got:'} $config);
55+
@return (#{'$config should be a configuration object. Got:'} $config);
1256
}
13-
$err: mat.private-validate-allowed-values(map.keys($config or ()), color, typography, density);
57+
$allowed: (color, typography, density);
58+
$err: mat.private-validate-allowed-values(map.keys($config or ()), $allowed...);
1459
@if $err {
15-
@return (#{'$config'} #{'has unexpected properties:'} $err);
60+
@return (
61+
#{'$config has unexpected properties. Valid properties are'}
62+
#{'#{$allowed}.'}
63+
#{'Found:'}
64+
$err
65+
);
1666
}
1767
$err: validate-color-config(map.get($config, color));
1868
@if $err {
19-
@return list.set-nth($err, 1, #{'#{list.nth($err, 1)}.color'});
69+
@return _update-dollar-config($err, '.color');
2070
}
2171
$err: validate-typography-config(map.get($config, typography));
2272
@if $err {
23-
@return list.set-nth($err, 1, #{'#{list.nth($err, 1)}.typography'});
73+
@return _update-dollar-config($err, '.typography');
2474
}
2575
$err: validate-density-config(map.get($config, density));
2676
@if $err {
27-
@return list.set-nth($err, 1, #{'#{list.nth($err, 1)}.density'});
77+
@return _update-dollar-config($err, '.density');
2878
}
2979
@return null;
3080
}
@@ -35,12 +85,35 @@
3585
@function validate-color-config($config) {
3686
$err: mat.private-validate-type($config, 'map', 'null');
3787
@if $err {
38-
@return (#{'$config'} #{'should be a color configuration object. Got:'} $config);
88+
@return (#{'$config should be a color configuration object. Got:'} $config);
3989
}
40-
$err: mat.private-validate-allowed-values(
41-
map.keys($config or ()), theme-type, primary, secondary, tertiary);
90+
$allowed: (theme-type, primary, secondary, tertiary);
91+
$err: mat.private-validate-allowed-values(map.keys($config or ()), $allowed...);
4292
@if $err {
43-
@return (#{'$config'} #{'has unexpected properties:'} $err);
93+
@return (
94+
#{'$config has unexpected properties. Valid properties are'}
95+
#{'#{$allowed}.'}
96+
#{'Found:'}
97+
$err
98+
);
99+
}
100+
@if $config and map.has-key($config, theme-type) and
101+
not list.index((light, dark), map.get($config, theme-type)) {
102+
@return (
103+
#{'Expected $config.theme-type to be one of: light, dark. Got:'}
104+
map.get($config, theme-type)
105+
);
106+
}
107+
@each $palette in (primary, secondary, tertiary) {
108+
@if $config and map.has-key($config, $palette) {
109+
$err: _validate-palette(map.get($config, $palette));
110+
@if $err {
111+
@return (
112+
#{'Expected $config.#{$palette} to be a valid M3 palette. Got:'}
113+
map.get($config, $palette)
114+
);
115+
}
116+
}
44117
}
45118
@return null;
46119
}
@@ -51,13 +124,17 @@
51124
@function validate-typography-config($config) {
52125
$err: mat.private-validate-type($config, 'map', 'null');
53126
@if $err {
54-
@return (#{'$config'} #{'should be a typography configuration object. Got:'} $config);
127+
@return (#{'$config should be a typography configuration object. Got:'} $config);
55128
}
56-
$err: mat.private-validate-allowed-values(
57-
map.keys($config or ()), brand-family, plain-family, bold-weight, medium-weight,
58-
regular-weight);
129+
$allowed: (brand-family, plain-family, bold-weight, medium-weight, regular-weight);
130+
$err: mat.private-validate-allowed-values(map.keys($config or ()), $allowed...);
59131
@if $err {
60-
@return (#{'$config'} #{'has unexpected properties:'} $err);
132+
@return (
133+
#{'$config has unexpected properties. Valid properties are'}
134+
#{'#{$allowed}.'}
135+
#{'Found:'}
136+
$err
137+
);
61138
}
62139
@return null;
63140
}
@@ -68,11 +145,20 @@
68145
@function validate-density-config($config) {
69146
$err: mat.private-validate-type($config, 'map', 'null');
70147
@if $err {
71-
@return (#{'$config'} #{'should be a density configuration object. Got:'} $config);
148+
@return (#{'$config should be a density configuration object. Got:'} $config);
72149
}
73150
$err: mat.private-validate-allowed-values(map.keys($config or ()), scale);
74151
@if $err {
75-
@return (#{'$config'} #{'has unexpected properties:'} $err);
152+
@return (#{'$config has unexpected properties. Valid properties are: scale. Found:'} $err);
153+
}
154+
@if $config and map.has-key($config, scale) {
155+
$allowed-scales: (0, -1, -2, -3, -4 -5, minimum, maximum);
156+
@if mat.private-validate-allowed-values(map.get($config, scale), $allowed-scales...) {
157+
@return (
158+
#{'Expected $config.scale to be one of: #{$allowed-scales}. Got:'}
159+
map.get($config, scale)
160+
);
161+
}
76162
}
77163
@return null;
78164
}

src/material-experimental/theming/_definition.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ $theme-version: 1;
6969
@error $err;
7070
}
7171

72-
$plain: map.get($config, plain-family) or Roboto, sans-serif;
72+
$plain: map.get($config, plain-family) or (Roboto, sans-serif);
7373
$brand: map.get($config, brand-family) or $plain;
7474
$bold: map.get($config, bold-weight) or 700;
7575
$medium: map.get($config, medium-weight) or 500;

src/material-experimental/theming/_m3-palettes.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ $yellow-palette: (
9090
90: #e6e3d1,
9191
95: #f4f1df,
9292
99: #fffbff,
93+
100: #fff,
9394
),
9495
);
9596

src/material/core/style/_validation.scss

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,17 @@
2727
}
2828
@return if(list.length($invalid) > 0, $invalid, null);
2929
}
30+
31+
/// Validates that a list contains all values from the required list of values.
32+
/// @param {List} $list The list to test
33+
/// @param {List} $required The required values
34+
/// @return {List} null if no error, else the list of missing values.
35+
@function validate-required-values($list, $required...) {
36+
$invalid: ();
37+
@each $element in $required {
38+
@if not list.index($list, $element) {
39+
$invalid: list.append($invalid, $element);
40+
}
41+
}
42+
@return if(list.length($invalid) > 0, $invalid, null);
43+
}

src/material/core/theming/tests/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ ts_library(
5656
name = "unit_test_lib",
5757
testonly = True,
5858
srcs = [
59+
"theming-definition-api.spec.ts",
5960
"theming-inspection-api.spec.ts",
6061
"theming-mixin-api.spec.ts",
6162
],

0 commit comments

Comments
 (0)