@use 'sass:map'; @use '../../density/private/all-density'; @use '../../color/all-color'; @use '../../typography/all-typography'; @use '../all-theme'; @use '../../typography/typography'; @use '../theming'; @use '../../m2/typography' as m2-typography; @use '../../m2/palette' as m2-palette; @use '../../m2/theming' as m2-theming; // Disable theme style duplication warnings. This test intentionally generates // the same themes multiple times. theming.$theme-ignore-duplication-warnings: true; // A new way to configure themes has been introduced. This Sass file ensures that the theming // API is backwards compatible, so that the old pattern for configuring themes can be still // used. The Sass compilation of this file will fail if one of the tests/assertions fails. $primary: m2-theming.define-palette(m2-palette.$blue-palette); $accent: m2-theming.define-palette(m2-palette.$grey-palette); $warn: m2-theming.define-palette(m2-palette.$indigo-palette); $default-warn: m2-theming.define-palette(m2-palette.$red-palette); // Asserts that a given value matches the expected value. If not, an error is // thrown with the given error message. @mixin assert($value, $expected, $error-msg) { @if $value != $expected { @error 'Expected "#{$value}" to be "#{$expected}". #{$error-msg}'; } } // Asserts that the specified color configuration is configured properly. @mixin assert-color-config($config, $primary, $accent, $warn, $is-dark) { $color: map.get($config, color); @include assert(map.get($color, primary), $primary, 'Primary palette does not match expected palette.'); @include assert(map.get($color, accent), $accent, 'Accent palette does not match expected palette.'); @include assert(map.get($color, warn), $warn, 'Warn palette does not match expected palette.'); @include assert(map.get($color, is-dark), $is-dark, 'Expected color config `is-dark` to be: #{$is-dark}'); } $legacy-light-theme: m2-theming.define-light-theme($primary, $accent, $warn); $legacy-dark-theme: m2-theming.define-dark-theme($primary, $accent, $warn); $legacy-light-theme-default-warn: m2-theming.define-light-theme($primary, $accent); $legacy-dark-theme-default-warn: m2-theming.define-dark-theme($primary, $accent); $new-api-light-theme: m2-theming.define-light-theme(( color: (primary: $primary, accent: $accent, warn: $warn) )); $new-api-dark-theme: m2-theming.define-dark-theme(( color: (primary: $primary, accent: $accent, warn: $warn) )); $new-api-light-theme-default-warn: m2-theming.define-light-theme(( color: (primary: $primary, accent: $accent) )); $new-api-dark-theme-default-warn: m2-theming.define-dark-theme(( color: (primary: $primary, accent: $accent) )); $light-theme-only-density: m2-theming.define-light-theme((density: -2)); $dark-theme-only-density: m2-theming.define-dark-theme((density: -2)); $typography-config: m2-typography.define-typography-config(); $light-theme-only-typography: m2-theming.define-light-theme((typography: $typography-config)); $dark-theme-only-typography: m2-theming.define-dark-theme((typography: $typography-config)); // Test which ensures that constructed themes by default do not set configurations // for the individual parts of the theming system (color, density, typography). @mixin test-default-theming-system-configs() { $themes: ($legacy-light-theme, $legacy-dark-theme, $new-api-light-theme, $new-api-dark-theme); @each $theme in $themes { @include assert(map.has-key($theme, color), true, 'Expected color to be explicitly configured.'); @include assert(map.has-key($theme, typography), false, 'Expected typography to be not explicitly configured.'); @include assert(map.has-key($theme, density), false, 'Expected density to be not explicitly configured.'); } @include assert(map.has-key($light-theme-only-density, color), false, 'Expected color to be not explicitly configured.'); @include assert(map.has-key($dark-theme-only-density, color), false, 'Expected color to be not explicitly configured.'); } // Test which ensures that constructed themes have the proper color configurations // as specified in the `mat-light-theme` and `mat-dark-theme` functions. @mixin test-create-color-config() { @include assert-color-config($legacy-light-theme, $primary, $accent, $warn, false); @include assert-color-config($legacy-dark-theme, $primary, $accent, $warn, true); @include assert-color-config($legacy-light-theme-default-warn, $primary, $accent, $default-warn, false); @include assert-color-config($legacy-dark-theme-default-warn, $primary, $accent, $default-warn, true); @include assert-color-config($new-api-light-theme, $primary, $accent, $warn, false); @include assert-color-config($new-api-dark-theme, $primary, $accent, $warn, true); @include assert-color-config($new-api-light-theme-default-warn, $primary, $accent, $default-warn, false); @include assert-color-config($new-api-dark-theme-default-warn, $primary, $accent, $default-warn, true); } // Test which ensures that constructed themes pass through the specified // density and typography configurations. @mixin test-density-typography-config-pass-through() { @include assert(map.get($light-theme-only-density, density), -2, 'Expected density config to be included in theme.'); @include assert(map.get($dark-theme-only-density, density), -2, 'Expected density config to be included in theme.'); @include assert(map.get($light-theme-only-typography, typography), $typography-config, 'Expected typography config to be included in theme.'); @include assert(map.get($dark-theme-only-typography, typography), $typography-config, 'Expected typography config to be included in theme.'); } // Test which ensures that color configurations can be properly read from // theme objects passed to individual component theme mixins. @mixin test-get-color-config() { $color-config: map.get($legacy-light-theme, color); $no-color-light-theme: m2-theming.define-light-theme((color: null)); $no-color-dark-theme: m2-theming.define-dark-theme((color: null)); @include assert(m2-theming.get-color-config($color-config), $color-config, 'Expected that passing a color config to a theme will work for backwards compatibility.'); // For legacy constructed themes, the color configuration is the actual `$theme` object. // This is done for backwards compatibility because developers could modify colors directly // by updating immediate properties on the `$theme` object. @include assert(m2-theming.get-color-config($legacy-light-theme), $legacy-light-theme, 'Expected that the theme object is used for the color configuration.'); @include assert(m2-theming.get-color-config($new-api-dark-theme), map.get($new-api-dark-theme, color), 'Expected that a color config can be read from a theme object.'); @include assert(m2-theming.get-color-config($light-theme-only-density), null, 'Expected that by default, no color configuration is used.'); @include assert(m2-theming.get-color-config($no-color-light-theme), null, 'Expected that no color configuration can be explicitly specified.'); @include assert(m2-theming.get-color-config($no-color-dark-theme), null, 'Expected that no color configuration can be explicitly specified.'); } // Test which ensures that density configurations can be properly read from // theme objects passed to individual component theme mixins. @mixin test-get-density-config() { $density-config: map.get($light-theme-only-density, density); $no-density-light-theme: m2-theming.define-light-theme((density: null)); $no-density-dark-theme: m2-theming.define-dark-theme((density: null)); @include assert(m2-theming.get-density-config($light-theme-only-density), -2, 'Expected that a density config can be read from a theme object.'); @include assert(m2-theming.get-density-config($light-theme-only-typography), 0, 'Expected that by default, the density system will be configured.'); @include assert(m2-theming.get-density-config($no-density-light-theme), null, 'Expected that no density configuration can be explicitly specified.'); @include assert(m2-theming.get-density-config($no-density-dark-theme), null, 'Expected that no density configuration can be explicitly specified.'); } // Test which ensures that typography configurations can be properly read from // theme objects passed to individual component theme mixins. @mixin test-get-typography-config() { $no-typography-light-theme: m2-theming.define-light-theme((density: null)); $no-typography-dark-theme: m2-theming.define-dark-theme((density: null)); @include assert(m2-theming.get-typography-config($light-theme-only-typography), $typography-config, 'Expected that a typography config can be read from a theme object.'); @include assert(m2-theming.get-typography-config($legacy-light-theme), null, 'Expected that by default, no typography configuration is used.'); @include assert(m2-theming.get-typography-config($no-typography-light-theme), null, 'Expected that no typography configuration can be explicitly specified.'); @include assert(m2-theming.get-typography-config($no-typography-dark-theme), null, 'Expected that no typography configuration can be explicitly specified.'); } // Test which ensures that all Angular Material theme mixins accept a theme // object without throwing any exception. @mixin test-theme-mixins-successful-compilation() { @include all-theme.all-component-themes($legacy-light-theme); @include all-theme.all-component-themes($legacy-light-theme-default-warn); @include all-theme.all-component-themes($legacy-dark-theme); @include all-theme.all-component-themes($legacy-dark-theme-default-warn); @include all-theme.all-component-themes($new-api-light-theme); @include all-theme.all-component-themes($new-api-light-theme-default-warn); @include all-theme.all-component-themes($new-api-dark-theme); @include all-theme.all-component-themes($new-api-dark-theme-default-warn); @include all-theme.all-component-themes($light-theme-only-density); @include all-theme.all-component-themes($dark-theme-only-density); @include all-theme.all-component-themes($light-theme-only-typography); @include all-theme.all-component-themes($dark-theme-only-typography); } // Custom theme mixin used by the custom theme backwards compatibility test. // This replicates a custom theme that expects legacy theme objects. @mixin _my-custom-theme-legacy($theme) { .demo-custom-comp { border-color: m2-theming.get-color-from-palette(map.get($theme, primary)); } } @mixin _my-custom-theme-new-api-color($config-or-theme) { $config: m2-theming.get-color-config($config-or-theme); .demo-custom-comp { border-color: m2-theming.get-color-from-palette(map.get($config, primary)); } } @mixin _my-custom-theme-new-api-density($config-or-theme) { $density-scale: m2-theming.get-density-config($config-or-theme); .demo-custom-comp { // Simulates logic for computing density according to the Material Design // specification. height: 48 - (4px * $density-scale); } } // Custom theme mixin used by the custom theme backwards compatibility test. @mixin _my-custom-theme-new-api($theme-or-color-config) { $theme: theming.private-legacy-get-theme($theme-or-color-config); $color: m2-theming.get-color-config($theme); $density: m2-theming.get-density-config($theme); @if $color != null { @include _my-custom-theme-new-api-color($color); } @if $density != null { @include _my-custom-theme-new-api-density($density); } } @mixin test-custom-theme-backwards-compatibility() { @include _my-custom-theme-legacy($legacy-light-theme); @include _my-custom-theme-legacy($legacy-dark-theme); @include _my-custom-theme-legacy($new-api-light-theme); @include _my-custom-theme-legacy($new-api-dark-theme); @include _my-custom-theme-new-api($legacy-light-theme); @include _my-custom-theme-new-api($legacy-dark-theme); @include _my-custom-theme-new-api($new-api-light-theme); @include _my-custom-theme-new-api($new-api-dark-theme); } // Test which ensures that either theme objects, or individual system configurations // can be passed to the all-density, all-typography or all-color mixins. @mixin test-all-theme-mixins-arguments() { $test-themes: ( $legacy-light-theme, $legacy-dark-theme, $new-api-light-theme, $new-api-dark-theme ); @each $theme in $test-themes { @include all-typography.all-component-typographies($theme); @include all-color.all-component-colors($theme); @include all-density.all-component-densities($theme); } @include all-typography.all-component-typographies( map.get($light-theme-only-typography, typography)); @include all-typography.all-component-typographies($light-theme-only-typography); @include all-density.all-component-densities(map.get($light-theme-only-density, density)); @include all-density.all-component-densities($light-theme-only-density); } @mixin test-individual-system-mixins-unwrap() { @include _my-custom-theme-new-api-color($new-api-dark-theme); @include _my-custom-theme-new-api-color(map.get($new-api-dark-theme, color)); @include _my-custom-theme-new-api($new-api-dark-theme); @include _my-custom-theme-new-api(map.get($new-api-dark-theme, color)); @include all-theme.all-component-themes($new-api-dark-theme); @include all-theme.all-component-themes(map.get($new-api-dark-theme, color)); } // Include all tests. Sass will throw if one of the tests fails. @include test-create-color-config(); @include test-default-theming-system-configs(); @include test-density-typography-config-pass-through(); @include test-theme-mixins-successful-compilation(); @include test-get-color-config(); @include test-get-density-config(); @include test-get-typography-config(); @include test-custom-theme-backwards-compatibility(); @include test-all-theme-mixins-arguments(); @include test-individual-system-mixins-unwrap();