From 326fc3b4ce10962cf70517ff27d5bc5a9f77e049 Mon Sep 17 00:00:00 2001 From: Johannes Odland Date: Tue, 27 Feb 2024 19:32:42 +0100 Subject: [PATCH] Test both upper and lower case units when testing CSSUnitValue().type() --- src/numeric-values.js | 24 ++++++++------- src/proxy-cssom.js | 10 +++++-- .../unit/cssom/css-numeric-value-type.test.js | 29 ++++++++++++++----- 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/numeric-values.js b/src/numeric-values.js index 0b3965a..16af704 100644 --- a/src/numeric-values.js +++ b/src/numeric-values.js @@ -158,28 +158,30 @@ export function rectifyType(type) { * Implementation of `create a type` from css-typed-om-1: * https://www.w3.org/TR/css-typed-om-1/#create-a-type * - * @param {string} input + * @param {string} unit * @return {CSSNumericType|Failure} */ -export function createAType(input) { - const unit = input.toLowerCase(); +export function createAType(unit) { + const unitLowerCase = unit.toLowerCase(); + // Number and percent unit is specced to be lower case. + // https://drafts.css-houdini.org/css-typed-om-1/#cssnumericvalue-create-a-type if (unit === "number") { return {}; } else if (unit === "percent") { return {"percent": 1}; - } else if (unitGroups.absoluteLengths.units.has(unit) || - unitGroups.fontRelativeLengths.units.has(unit) || - unitGroups.viewportRelativeLengths.units.has(unit)) { + } else if (unitGroups.absoluteLengths.units.has(unitLowerCase) || + unitGroups.fontRelativeLengths.units.has(unitLowerCase) || + unitGroups.viewportRelativeLengths.units.has(unitLowerCase)) { return {"length": 1}; - } else if (unitGroups.angle.units.has(unit)) { + } else if (unitGroups.angle.units.has(unitLowerCase)) { return {"angle": 1}; - } else if (unitGroups.time.units.has(unit)) { + } else if (unitGroups.time.units.has(unitLowerCase)) { return {"time": 1}; - } else if (unitGroups.frequency.units.has(unit)) { + } else if (unitGroups.frequency.units.has(unitLowerCase)) { return {"frequency": 1}; - } else if (unitGroups.resolution.units.has(unit)) { + } else if (unitGroups.resolution.units.has(unitLowerCase)) { return {"resolution": 1}; - } else if (unit === "fr") { + } else if (unitLowerCase === "fr") { return {"flex": 1}; } else { return failure; diff --git a/src/proxy-cssom.js b/src/proxy-cssom.js index ed4857d..fc0bb15 100644 --- a/src/proxy-cssom.js +++ b/src/proxy-cssom.js @@ -97,9 +97,13 @@ export function installCSSOM() { 'CSSUnitValue': class extends CSSNumericValue { constructor(value, unit) { super(); + const type = createAType(unit); + if (type === null) { + throw new TypeError('Type error'); + } privateDetails.set(this, { value: value, - unit: unit + unit: unit.toLowerCase() }); } @@ -150,7 +154,7 @@ export function installCSSOM() { super(values, 'sum', 'calc', ' + '); const type = values.map(v => v.type()).reduce(addTypes); if (type === null) { - throw new TypeError(); + throw new TypeError('Type error'); } } @@ -167,7 +171,7 @@ export function installCSSOM() { super(values, 'product', 'calc', ' * '); const type = values.map(v => v.type()).reduce(multiplyTypes); if (type === null) { - throw new TypeError(); + throw new TypeError('Type error'); } } diff --git a/test/unit/cssom/css-numeric-value-type.test.js b/test/unit/cssom/css-numeric-value-type.test.js index 860a09c..c2277e6 100644 --- a/test/unit/cssom/css-numeric-value-type.test.js +++ b/test/unit/cssom/css-numeric-value-type.test.js @@ -9,54 +9,67 @@ describe('CSSNumericValue.type()', () => { describe('CSSUnitValue.type()', () => { + function testUnitIsType(unit, type) { + expect(new CSSUnitValue(10, unit).type()).toEqual(type); + expect(new CSSUnitValue(10, unit.toUpperCase()).type()).toEqual(type); + } + const lengthUnits = ['em', 'rem', 'ex', 'rex', 'cap', 'rcap', 'ch', 'rch', 'ic', 'ric', 'lh', 'rlh', 'vw', 'lvw', 'svw', 'dvw', 'vh', 'lvh', 'svh', 'dvh', 'vi', 'lvi', 'svi', 'dvi', 'vb', 'lvb', 'svb', 'dvb', 'vmin', 'lvmin', - 'svmin', 'dvmin', 'vmax', 'lvmax', 'svmax', 'dvmax', 'cm', 'mm', 'Q', 'in', 'pt', 'pc', 'px']; + 'svmin', 'dvmin', 'vmax', 'lvmax', 'svmax', 'dvmax', 'cm', 'mm', 'q', 'in', 'pt', 'pc', 'px']; for (const unit of lengthUnits) { test(`Type of '${unit}' is length`, () => { - expect(new CSSUnitValue(10, unit).type()).toEqual({length: 1}); + testUnitIsType(unit, {length: 1}); }); } const angleUnits = ['deg', 'grad', 'rad', 'turn']; for (const unit of angleUnits) { test(`Type of '${unit}' is angle`, () => { - expect(new CSSUnitValue(10, unit).type()).toEqual({angle: 1}); + testUnitIsType(unit, {angle: 1}); }); } const timeUnits = ['s', 'ms']; for (const unit of timeUnits) { test(`Type of '${unit}' is time`, () => { - expect(new CSSUnitValue(10, unit).type()).toEqual({time: 1}); + testUnitIsType(unit, {time: 1}); }); } - const frequencyUnits = ['Hz', 'kHz']; + const frequencyUnits = ['hz', 'khz']; for (const unit of frequencyUnits) { test(`Type of '${unit}' is frequency`, () => { - expect(new CSSUnitValue(10, unit).type()).toEqual({frequency: 1}); + testUnitIsType(unit, {frequency: 1}); }); } const resolutionUnits = ['dpi', 'dpcm', 'dppx']; for (const unit of resolutionUnits) { test(`Type of '${unit}' is resolution`, () => { - expect(new CSSUnitValue(10, unit).type()).toEqual({resolution: 1}); + testUnitIsType(unit, {resolution: 1}); }); } test(`Type of 'fr' is flex`, () => { - expect(new CSSUnitValue(10, 'fr').type()).toEqual({flex: 1}); + testUnitIsType('fr', {flex: 1}); }); test(`Type of 'percent' is percent`, () => { + // Percent unit is specced to be lower case. + // https://drafts.css-houdini.org/css-typed-om-1/#cssnumericvalue-create-a-type + expect(new CSSUnitValue(10, 'percent').type()).toEqual({percent: 1}); + expect(() => new CSSUnitValue(10, 'PERCENT').type()).toThrowError(TypeError); }); test(`Type of number is number`, () => { + // Number unit is specced to be lower case. + // https://drafts.css-houdini.org/css-typed-om-1/#cssnumericvalue-create-a-type + expect(new CSSUnitValue(10, 'number').type()).toEqual({}); + expect(() => new CSSUnitValue(10, 'NUMBER').type()).toThrowError(TypeError); }); });