Skip to content

Commit

Permalink
Merge pull request #2013 from sass/feature.color-4
Browse files Browse the repository at this point in the history
Merge feature.color-4 into main
  • Loading branch information
nex3 committed Sep 13, 2024
2 parents 3d10521 + 80b5428 commit e83abf6
Show file tree
Hide file tree
Showing 626 changed files with 61,244 additions and 5,132 deletions.
128 changes: 128 additions & 0 deletions js-api-spec/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,29 @@ declare global {
*/
toEqualWithHash(value: immutable.ValueObject): T;

/**
* Matches a number that is equal to `value` using `SassNumber.equals()`.
*/
toFuzzyEqual(value: number): T;

/**
* Matches a number that is equal to `value` to 5 decimal places.
*/
toLooselyEqual(value: number): T;

/**
* Matches a SassColor where each channel in `value` is equal to 5 decimal
* places.
*/
toLooselyEqualColor(value: sass.SassColor): T;

/**
* Matches an array against an Immutable List. Non-numeric values are
* exactly matched, and numbers are fuzzy matched using
* `SassNumber.equals()`.
*/
toFuzzyEqualList(value: unknown[]): T;

/**
* Matches a value that's `null` or `undefined`.
*/
Expand Down Expand Up @@ -312,6 +335,99 @@ const toEqualIgnoringWhitespace = (received: unknown, actual: string) => {
};
};

const toFuzzyEqual = (received: unknown, actual: number) => {
if (typeof received !== 'number') {
throw new Error('Received value must be a number');
}
return {
message: `expected ${received} to fuzzy equal ${actual}`,
pass: new sass.SassNumber(received).equals(new sass.SassNumber(actual)),
};
};

const toLooselyEqual = (received: unknown, actual: number) => {
if (typeof received !== 'number') {
throw new Error('Received value must be a number');
}
return {
message: `expected ${received} to loosely equal ${actual} to 5 decimal places`,
pass: Math.round((received * 10) ^ 5) === Math.round((actual * 10) ^ 5),
};
};

// The max distance two Sass numbers can be from each another before they're
// considered different (2 decimals).
//
// Uses ** instead of Math.pow() for constant folding.
// TODO: Ideally this should be more precise, but ColorJS does not always match.
const epsilon = 10 ** -2;

const toLooselyEqualColor = (received: unknown, actual: sass.SassColor) => {
function isSassColor(item: unknown): item is sass.SassColor {
return !!(item as sass.SassColor).assertColor();
}
if (!isSassColor(received)) {
throw new Error('Received value must be a SassColor');
}
const unequalIndices: number[] = [];
received.channelsOrNull.forEach((channel: number | null, index: number) => {
const actualChannel = actual.channelsOrNull.get(index);
if (channel === null) {
if (actualChannel !== null) unequalIndices.push(index);
} else if (
actualChannel === null ||
Math.abs(channel - actualChannel) > epsilon
) {
unequalIndices.push(index);
}
});
const plural = unequalIndices.length !== 1;
const indexMessage = `${plural ? 'indices' : 'index'} ${unequalIndices.join(
','
)}`;
return {
message: `expected ${received} to loosely equal ${actual}, but channels at ${indexMessage} differ`,
pass: unequalIndices.length === 0,
};
};

const toFuzzyEqualList = (received: unknown, actual: unknown[]) => {
if (!immutable.List.isList(received)) {
throw new Error('Received value must be an Immutuable List');
}
if (received.count() !== actual.length) {
return {
pass: false,
message: `expected List to have length ${
actual.length
}, received ${received.count()}`,
};
}
let pass = true;
let message = '';
received.forEach((receivedItem, index) => {
const actualItem = actual[index];
if (!pass) return;
if (typeof receivedItem !== typeof actualItem) {
pass = false;
message = `expected ${receivedItem} to be the same type as ${actual[index]} at index ${index}`;
}
if (typeof receivedItem === 'number' && typeof actualItem === 'number') {
pass = new sass.SassNumber(receivedItem).equals(
new sass.SassNumber(actualItem)
);
message = `expected ${receivedItem} to fuzzy equal ${actual[index]} at index ${index}`;
} else {
pass = receivedItem === actualItem;
message = `expected non-numeric ${receivedItem} to exactly equal ${actual[index]} at index ${index}`;
}
});
return {
message,
pass,
};
};

// Add custom matchers to Jasmine
beforeAll(() => {
jasmine.addMatchers({
Expand All @@ -330,6 +446,18 @@ beforeAll(() => {
toEqualIgnoringWhitespace: () => ({
compare: toEqualIgnoringWhitespace,
}),
toFuzzyEqual: () => ({
compare: toFuzzyEqual,
}),
toLooselyEqual: () => ({
compare: toLooselyEqual,
}),
toLooselyEqualColor: () => ({
compare: toLooselyEqualColor,
}),
toFuzzyEqualList: () => ({
compare: toFuzzyEqualList,
}),
});
jasmine.addAsyncMatchers({
toThrowSassException: () => ({
Expand Down
Loading

0 comments on commit e83abf6

Please sign in to comment.