summaryrefslogtreecommitdiffstats
path: root/scss/tests
diff options
context:
space:
mode:
Diffstat (limited to 'scss/tests')
-rw-r--r--scss/tests/jasmine.js16
-rw-r--r--scss/tests/mixins/_color-modes.test.scss69
-rw-r--r--scss/tests/mixins/_media-query-color-mode-full.test.scss8
-rw-r--r--scss/tests/mixins/_utilities.test.scss393
-rw-r--r--scss/tests/sass-true/register.js14
-rw-r--r--scss/tests/sass-true/runner.js17
-rw-r--r--scss/tests/utilities/_api.test.scss75
7 files changed, 592 insertions, 0 deletions
diff --git a/scss/tests/jasmine.js b/scss/tests/jasmine.js
new file mode 100644
index 0000000..25d838c
--- /dev/null
+++ b/scss/tests/jasmine.js
@@ -0,0 +1,16 @@
+/* eslint-disable camelcase */
+
+'use strict'
+
+const path = require('node:path')
+
+module.exports = {
+ spec_dir: 'scss',
+ // Make Jasmine look for `.test.scss` files
+ spec_files: ['**/*.{test,spec}.scss'],
+ // Compile them into JS scripts running `sass-true`
+ requires: [path.join(__dirname, 'sass-true/register')],
+ // Ensure we use `require` so that the require.extensions works
+ // as `import` completely bypasses it
+ jsLoader: 'require'
+}
diff --git a/scss/tests/mixins/_color-modes.test.scss b/scss/tests/mixins/_color-modes.test.scss
new file mode 100644
index 0000000..9ecc628
--- /dev/null
+++ b/scss/tests/mixins/_color-modes.test.scss
@@ -0,0 +1,69 @@
+// stylelint-disable selector-attribute-quotes
+
+@import "../../functions";
+@import "../../variables";
+@import "../../variables-dark";
+@import "../../maps";
+@import "../../mixins";
+
+@include describe("global $color-mode-type: data") {
+ @include it("generates data attribute selectors for dark mode") {
+ @include assert() {
+ @include output() {
+ @include color-mode(dark) {
+ .element {
+ color: var(--bs-primary-text-emphasis);
+ background-color: var(--bs-primary-bg-subtle);
+ }
+ }
+ @include color-mode(dark, true) {
+ --custom-color: #{mix($indigo, $blue, 50%)};
+ }
+ }
+ @include expect() {
+ [data-bs-theme=dark] .element {
+ color: var(--bs-primary-text-emphasis);
+ background-color: var(--bs-primary-bg-subtle);
+ }
+ [data-bs-theme=dark] {
+ --custom-color: #3a3ff8;
+ }
+ }
+ }
+ }
+}
+
+@include describe("global $color-mode-type: media-query") {
+ @include it("generates media queries for dark mode") {
+ $color-mode-type: media-query !global;
+
+ @include assert() {
+ @include output() {
+ @include color-mode(dark) {
+ .element {
+ color: var(--bs-primary-text-emphasis);
+ background-color: var(--bs-primary-bg-subtle);
+ }
+ }
+ @include color-mode(dark, true) {
+ --custom-color: #{mix($indigo, $blue, 50%)};
+ }
+ }
+ @include expect() {
+ @media (prefers-color-scheme: dark) {
+ .element {
+ color: var(--bs-primary-text-emphasis);
+ background-color: var(--bs-primary-bg-subtle);
+ }
+ }
+ @media (prefers-color-scheme: dark) {
+ :root {
+ --custom-color: #3a3ff8;
+ }
+ }
+ }
+ }
+
+ $color-mode-type: data !global;
+ }
+}
diff --git a/scss/tests/mixins/_media-query-color-mode-full.test.scss b/scss/tests/mixins/_media-query-color-mode-full.test.scss
new file mode 100644
index 0000000..00ed82d
--- /dev/null
+++ b/scss/tests/mixins/_media-query-color-mode-full.test.scss
@@ -0,0 +1,8 @@
+$color-mode-type: media-query;
+
+@import "../../bootstrap";
+
+@include describe("global $color-mode-type: media-query") {
+ @include it("compiles entirely Bootstrap CSS with media-query color mode") { // stylelint-disable-line block-no-empty
+ }
+}
diff --git a/scss/tests/mixins/_utilities.test.scss b/scss/tests/mixins/_utilities.test.scss
new file mode 100644
index 0000000..63fcae3
--- /dev/null
+++ b/scss/tests/mixins/_utilities.test.scss
@@ -0,0 +1,393 @@
+$prefix: bs-;
+$enable-important-utilities: false;
+
+// Important: Do not import rfs to check that the mixin just calls the appropriate functions from it
+@import "../../mixins/utilities";
+
+@mixin test-generate-utility($params...) {
+ @include assert() {
+ @include output() {
+ @include generate-utility($params...);
+ }
+
+ @include expect() {
+ @content;
+ }
+ }
+}
+
+@include describe(generate-utility) {
+ @include it("generates a utility class for each value") {
+ @include test-generate-utility(
+ (
+ property: "padding",
+ values: (small: .5rem, large: 2rem)
+ )
+ ) {
+ .padding-small {
+ padding: .5rem;
+ }
+
+ .padding-large {
+ padding: 2rem;
+ }
+ }
+ }
+
+ @include describe("global $enable-important-utilities: true") {
+ @include it("sets !important") {
+ $enable-important-utilities: true !global;
+
+ @include test-generate-utility(
+ (
+ property: "padding",
+ values: (small: .5rem, large: 2rem)
+ )
+ ) {
+ .padding-small {
+ padding: .5rem !important;
+ }
+
+ .padding-large {
+ padding: 2rem !important;
+ }
+ }
+
+ $enable-important-utilities: false !global;
+ }
+ }
+
+ @include describe("$utility") {
+ @include describe("values") {
+ @include it("supports null keys") {
+ @include test-generate-utility(
+ (
+ property: "padding",
+ values: (null: 1rem, small: .5rem, large: 2rem)
+ ),
+ ) {
+ .padding {
+ padding: 1rem;
+ }
+
+ .padding-small {
+ padding: .5rem;
+ }
+
+ .padding-large {
+ padding: 2rem;
+ }
+ }
+ }
+
+ @include it("ignores null values") {
+ @include test-generate-utility(
+ (
+ property: "padding",
+ values: (small: null, large: 2rem)
+ )
+ ) {
+ .padding-large {
+ padding: 2rem;
+ }
+ }
+ }
+
+ @include it("supports lists") {
+ @include test-generate-utility(
+ (
+ property: "padding",
+ values: 1rem 2rem
+ )
+ ) {
+ .padding-1rem {
+ padding: 1rem;
+ }
+
+ .padding-2rem {
+ padding: 2rem;
+ }
+ }
+ }
+
+ @include it("supports single values") {
+ @include test-generate-utility(
+ (
+ property: padding,
+ values: 1rem
+ )
+ ) {
+ .padding-1rem {
+ padding: 1rem;
+ }
+ }
+ }
+ }
+
+ @include describe("class & property") {
+ @include it("adds each property to the declaration") {
+ @include test-generate-utility(
+ (
+ class: padding-x,
+ property: padding-inline-start padding-inline-end,
+ values: 1rem
+ )
+ ) {
+ .padding-x-1rem {
+ padding-inline-start: 1rem;
+ padding-inline-end: 1rem;
+ }
+ }
+ }
+
+ @include it("uses the first property as class name") {
+ @include test-generate-utility(
+ (
+ property: padding-inline-start padding-inline-end,
+ values: 1rem
+ )
+ ) {
+ .padding-inline-start-1rem {
+ padding-inline-start: 1rem;
+ padding-inline-end: 1rem;
+ }
+ }
+ }
+
+ @include it("supports a null class to create classes straight from the values") {
+ @include test-generate-utility(
+ (
+ property: visibility,
+ class: null,
+ values: (
+ visible: visible,
+ invisible: hidden,
+ )
+ )
+ ) {
+ .visible {
+ visibility: visible;
+ }
+
+ .invisible {
+ visibility: hidden;
+ }
+ }
+ }
+ }
+
+ @include describe("state") {
+ @include it("Generates selectors for each states") {
+ @include test-generate-utility(
+ (
+ property: padding,
+ values: 1rem,
+ state: hover focus,
+ )
+ ) {
+ .padding-1rem {
+ padding: 1rem;
+ }
+
+ .padding-1rem-hover:hover {
+ padding: 1rem;
+ }
+
+ .padding-1rem-focus:focus {
+ padding: 1rem;
+ }
+ }
+ }
+ }
+
+ @include describe("css-var"){
+ @include it("sets a CSS variable instead of the property") {
+ @include test-generate-utility(
+ (
+ property: padding,
+ css-variable-name: padding,
+ css-var: true,
+ values: 1rem 2rem
+ )
+ ) {
+ .padding-1rem {
+ --bs-padding: 1rem;
+ }
+
+ .padding-2rem {
+ --bs-padding: 2rem;
+ }
+ }
+ }
+
+ @include it("defaults to class") {
+ @include test-generate-utility(
+ (
+ property: padding,
+ class: padding,
+ css-var: true,
+ values: 1rem 2rem
+ )
+ ) {
+ .padding-1rem {
+ --bs-padding: 1rem;
+ }
+
+ .padding-2rem {
+ --bs-padding: 2rem;
+ }
+ }
+ }
+ }
+
+ @include describe("local-vars") {
+ @include it("generates the listed variables") {
+ @include test-generate-utility(
+ (
+ property: color,
+ class: desaturated-color,
+ local-vars: (
+ color-opacity: 1,
+ color-saturation: .25
+ ),
+ values: (
+ blue: hsla(192deg, var(--bs-color-saturation), 0, var(--bs-color-opacity))
+ )
+ )
+ ) {
+ .desaturated-color-blue {
+ --bs-color-opacity: 1;
+ // Sass compilation will put a leading zero so we want to keep that one
+ // stylelint-disable-next-line stylistic/number-leading-zero
+ --bs-color-saturation: 0.25;
+ color: hsla(192deg, var(--bs-color-saturation), 0, var(--bs-color-opacity));
+ }
+ }
+ }
+ }
+
+ @include describe("css-var & state") {
+ @include it("Generates a rule with for each state with a CSS variable") {
+ @include test-generate-utility(
+ (
+ property: padding,
+ css-var: true,
+ css-variable-name: padding,
+ values: 1rem,
+ state: hover focus,
+ )
+ ) {
+ .padding-1rem {
+ --bs-padding: 1rem;
+ }
+
+ .padding-1rem-hover:hover {
+ --bs-padding: 1rem;
+ }
+
+ .padding-1rem-focus:focus {
+ --bs-padding: 1rem;
+ }
+ }
+ }
+ }
+
+ @include describe("rtl") {
+ @include it("sets up RTLCSS for removal when false") {
+ @include test-generate-utility(
+ (
+ property: padding,
+ values: 1rem,
+ rtl: false
+ )
+ ) {
+ /* rtl:begin:remove */
+
+ .padding-1rem {
+ padding: 1rem;
+ }
+
+ /* rtl:end:remove */
+
+ }
+ }
+ }
+
+ @include describe("rfs") {
+ @include it("sets the fluid value when not inside media query") {
+ @include test-generate-utility(
+ (
+ property: padding,
+ values: 1rem,
+ rfs: true
+ )
+ ) {
+ .padding-1rem {
+ padding: rfs-fluid-value(1rem);
+ }
+ }
+ }
+
+ @include it("sets the value when inside the media query") {
+ @include test-generate-utility(
+ (
+ property: padding,
+ values: 1rem,
+ rfs: true
+ ),
+ $is-rfs-media-query: true
+ ) {
+ .padding-1rem {
+ padding: rfs-value(1rem);
+ }
+ }
+ }
+ }
+ }
+
+ @include describe("$infix") {
+ @include it("inserts the given infix") {
+ @include test-generate-utility(
+ (
+ property: "padding",
+ values: (null: 1rem, small: .5rem, large: 2rem)
+ ),
+ $infix: -sm
+ ) {
+ .padding-sm {
+ padding: 1rem;
+ }
+
+ .padding-sm-small {
+ padding: .5rem;
+ }
+
+ .padding-sm-large {
+ padding: 2rem;
+ }
+ }
+ }
+
+ @include it("strips leading - if class is null") {
+ @include test-generate-utility(
+ (
+ property: visibility,
+ class: null,
+ values: (
+ visible: visible,
+ invisible: hidden,
+ )
+ ),
+ -sm
+ ) {
+ .sm-visible {
+ visibility: visible;
+ }
+
+ .sm-invisible {
+ visibility: hidden;
+ }
+ }
+ }
+ }
+}
diff --git a/scss/tests/sass-true/register.js b/scss/tests/sass-true/register.js
new file mode 100644
index 0000000..d93e414
--- /dev/null
+++ b/scss/tests/sass-true/register.js
@@ -0,0 +1,14 @@
+'use strict'
+
+const path = require('node:path')
+
+const runnerPath = path.join(__dirname, 'runner').replace(/\\/g, '/')
+
+require.extensions['.scss'] = (module, filename) => {
+ const normalizedFilename = filename.replace(/\\/g, '/')
+
+ return module._compile(`
+ const runner = require('${runnerPath}')
+ runner('${normalizedFilename}', { describe, it })
+ `, filename)
+}
diff --git a/scss/tests/sass-true/runner.js b/scss/tests/sass-true/runner.js
new file mode 100644
index 0000000..bef870a
--- /dev/null
+++ b/scss/tests/sass-true/runner.js
@@ -0,0 +1,17 @@
+'use strict'
+
+const fs = require('node:fs')
+const path = require('node:path')
+const { runSass } = require('sass-true')
+
+module.exports = (filename, { describe, it }) => {
+ const data = fs.readFileSync(filename, 'utf8')
+ const TRUE_SETUP = '$true-terminal-output: false; @import "true";'
+ const sassString = TRUE_SETUP + data
+
+ runSass(
+ { describe, it, sourceType: 'string' },
+ sassString,
+ { loadPaths: [path.dirname(filename)] }
+ )
+}
diff --git a/scss/tests/utilities/_api.test.scss b/scss/tests/utilities/_api.test.scss
new file mode 100644
index 0000000..304d8d1
--- /dev/null
+++ b/scss/tests/utilities/_api.test.scss
@@ -0,0 +1,75 @@
+@import "../../functions";
+@import "../../variables";
+@import "../../variables-dark";
+@import "../../maps";
+@import "../../mixins";
+
+$utilities: ();
+
+@include describe("utilities/api") {
+ @include it("generates utilities for each breakpoints") {
+ $utilities: (
+ margin: (
+ property: margin,
+ values: auto
+ ),
+ padding: (
+ property: padding,
+ responsive: true,
+ values: 1rem
+ ),
+ font-size: (
+ property: font-size,
+ values: (large: 1.25rem),
+ print: true
+ )
+ ) !global;
+
+ $grid-breakpoints: (
+ xs: 0,
+ sm: 333px,
+ md: 666px
+ ) !global;
+
+ @include assert() {
+ @include output() {
+ @import "../../utilities/api";
+ }
+
+ @include expect() {
+ // margin is not set to responsive
+ .margin-auto {
+ margin: auto !important;
+ }
+
+ // padding is, though
+ .padding-1rem {
+ padding: 1rem !important;
+ }
+
+ .font-size-large {
+ font-size: 1.25rem !important;
+ }
+
+ @media (min-width: 333px) {
+ .padding-sm-1rem {
+ padding: 1rem !important;
+ }
+ }
+
+ @media (min-width: 666px) {
+ .padding-md-1rem {
+ padding: 1rem !important;
+ }
+ }
+
+ @media print {
+ .font-size-print-large {
+ font-size: 1.25rem !important;
+ }
+ }
+ }
+
+ }
+ }
+}