diff --git a/lib/constants.js b/lib/constants.js
index 1b58869..8f7f6c8 100644
--- a/lib/constants.js
+++ b/lib/constants.js
@@ -4,3 +4,13 @@ module.exports.POSITION_AT_SHORTHAND = {
   first: 0,
   second: 1,
 };
+
+// CSS global values
+// see https://drafts.csswg.org/css-cascade-5/#defaulting-keywords
+module.exports.GLOBAL_VALUES = Object.freeze([
+  'initial',
+  'inherit',
+  'unset',
+  'revert',
+  'revert-layer',
+]);
diff --git a/lib/parsers.js b/lib/parsers.js
index bcf4e7c..6823ccc 100644
--- a/lib/parsers.js
+++ b/lib/parsers.js
@@ -4,43 +4,45 @@
  ********************************************************************/
 'use strict';
 
+// FIXME: should move shorthandGetter(), shorthandSetter(), implicitSetter() and
+// subImplicitSetter() to CSSStyleDeclaration()
+
 const { resolve: resolveColor, utils } = require('@asamuzakjp/css-color');
+const { GLOBAL_VALUES } = require('./constants');
+
 const { cssCalc, isColor, isGradient, splitValue } = utils;
 
 exports.TYPES = {
-  INTEGER: 1,
-  NUMBER: 2,
-  LENGTH: 3,
-  PERCENT: 4,
-  URL: 5,
-  COLOR: 6,
-  STRING: 7,
-  ANGLE: 8,
-  KEYWORD: 9,
-  NULL_OR_EMPTY_STR: 10,
-  CALC: 11,
-  VAR: 12,
-  GRADIENT: 13,
+  UNDEFINED: 0,
+  NULL_OR_EMPTY_STR: 1,
+  VAR: 2,
+  NUMBER: 4,
+  PERCENT: 8,
+  LENGTH: 0x10,
+  ANGLE: 0x20,
+  CALC: 0x40,
+  COLOR: 0x80,
+  STRING: 0x100,
+  KEYWORD: 0x200,
+  UNIDENT: 0x8000,
 };
 
 // regular expressions
 var DIGIT = '(?:0|[1-9]\\d*)';
 var NUMBER = `[+-]?(?:${DIGIT}(?:\\.\\d*)?|\\.\\d+)(?:e-?${DIGIT})?`;
-var integerRegEx = new RegExp(`^[+-]?${DIGIT}$`);
-var numberRegEx = new RegExp(`^${NUMBER}$`);
-var lengthRegEx = new RegExp(
-  `^${NUMBER}(?:[cm]m|[dls]?v(?:[bhiw]|max|min)|in|p[ctx]|q|r?(?:[cl]h|cap|e[mx]|ic))$`
-);
-var percentRegEx = new RegExp(`^${NUMBER}%$`);
+var unitRegEx = new RegExp(`^(${NUMBER})([a-z]+|%)?$`);
 var angleRegEx = new RegExp(`^${NUMBER}(?:deg|g?rad|turn)$`);
 var urlRegEx = /^url\(\s*((?:[^)]|\\\))*)\s*\)$/;
+var keywordRegEx = /^[a-z]+(?:\-[a-z]+)*$/i;
 var stringRegEx = /^("[^"]*"|'[^']*')$/;
-var varRegEx = /^var\(|(?<=[*/\s(])var\(/;
+var varRegEx = /^var\(/;
+var varContainedRegEx = /(?<=[*/\s(])var\(/;
 var calcRegEx =
   /^(?:a?(?:cos|sin|tan)|abs|atan2|calc|clamp|exp|hypot|log|max|min|mod|pow|rem|round|sign|sqrt)\(/;
 
 // This will return one of the above types based on the passed in string
 exports.valueType = function valueType(val) {
+  // see https://webidl.spec.whatwg.org/#LegacyNullToEmptyString
   if (val === '' || val === null) {
     return exports.TYPES.NULL_OR_EMPTY_STR;
   }
@@ -48,25 +50,7 @@ exports.valueType = function valueType(val) {
     val = val.toString();
   }
   if (typeof val !== 'string') {
-    return undefined;
-  }
-  if (integerRegEx.test(val)) {
-    return exports.TYPES.INTEGER;
-  }
-  if (numberRegEx.test(val)) {
-    return exports.TYPES.NUMBER;
-  }
-  if (lengthRegEx.test(val)) {
-    return exports.TYPES.LENGTH;
-  }
-  if (percentRegEx.test(val)) {
-    return exports.TYPES.PERCENT;
-  }
-  if (val.startsWith('url(') && val.endsWith(')')) {
-    if (urlRegEx.test(val)) {
-      return exports.TYPES.URL;
-    }
-    return undefined;
+    return exports.TYPES.UNDEFINED;
   }
   if (varRegEx.test(val)) {
     return exports.TYPES.VAR;
@@ -74,20 +58,47 @@ exports.valueType = function valueType(val) {
   if (calcRegEx.test(val)) {
     return exports.TYPES.CALC;
   }
-  if (stringRegEx.test(val)) {
-    return exports.TYPES.STRING;
-  }
-  if (angleRegEx.test(val)) {
-    return exports.TYPES.ANGLE;
+  if (unitRegEx.test(val)) {
+    var [, , unit] = unitRegEx.exec(val);
+    if (!unit) {
+      return exports.TYPES.NUMBER;
+    }
+    if (unit === '%') {
+      return exports.TYPES.PERCENT;
+    }
+    if (/^(?:[cm]m|[dls]?v(?:[bhiw]|max|min)|in|p[ctx]|q|r?(?:[cl]h|cap|e[mx]|ic))$/.test(unit)) {
+      return exports.TYPES.LENGTH;
+    }
+    if (/^(?:deg|g?rad|turn)$/.test(unit)) {
+      return exports.TYPES.ANGLE;
+    }
   }
   if (isColor(val)) {
     return exports.TYPES.COLOR;
   }
-  if (isGradient(val)) {
-    return exports.TYPES.GRADIENT;
+  if (stringRegEx.test(val)) {
+    return exports.TYPES.STRING;
   }
 
   switch (val.toLowerCase()) {
+    // system color keywords
+    case 'accentcolor':
+    case 'accentcolortext':
+    case 'activetext':
+    case 'buttonborder':
+    case 'buttonface':
+    case 'buttontext':
+    case 'canvas':
+    case 'canvastext':
+    case 'field':
+    case 'fieldtext':
+    case 'graytext':
+    case 'highlight':
+    case 'highlighttext':
+    case 'linktext':
+    case 'mark':
+    case 'marktext':
+    case 'visitedtext':
     // the following are deprecated in CSS3
     case 'activeborder':
     case 'activecaption':
@@ -119,93 +130,121 @@ exports.valueType = function valueType(val) {
     case 'windowtext':
       return exports.TYPES.COLOR;
     default:
-      return exports.TYPES.KEYWORD;
-  }
-};
-
-exports.parseInteger = function parseInteger(val) {
-  var type = exports.valueType(val);
-  if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
-    return val;
-  }
-  if (type !== exports.TYPES.INTEGER) {
-    return undefined;
+      if (keywordRegEx.test(val)) {
+        return exports.TYPES.KEYWORD;
+      }
+      return exports.TYPES.UNIDENT;
   }
-  return String(parseInt(val, 10));
 };
 
 exports.parseNumber = function parseNumber(val) {
   var type = exports.valueType(val);
-  if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
-    return val;
-  }
-  if (type !== exports.TYPES.NUMBER && type !== exports.TYPES.INTEGER) {
-    return undefined;
+  switch (type) {
+    case exports.TYPES.NULL_OR_EMPTY_STR:
+    case exports.TYPES.VAR:
+      return val;
+    case exports.TYPES.NUMBER:
+      return `${parseFloat(val)}`;
+    case exports.TYPES.CALC:
+      return cssCalc(val, {
+        format: 'specifiedValue',
+      });
+    default:
+      if (varContainedRegEx.test(val)) {
+        return val;
+      }
+      return undefined;
   }
-  return String(parseFloat(val));
 };
 
 exports.parseLength = function parseLength(val) {
-  if (val === 0 || val === '0') {
-    return '0px';
-  }
   var type = exports.valueType(val);
-  if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
-    return val;
-  }
-  if (type !== exports.TYPES.LENGTH) {
-    return undefined;
+  switch (type) {
+    case exports.TYPES.NULL_OR_EMPTY_STR:
+    case exports.TYPES.VAR:
+      return val;
+    case exports.TYPES.CALC:
+      return cssCalc(val, {
+        format: 'specifiedValue',
+      });
+    case exports.TYPES.LENGTH: {
+      var [, numVal, unit] = unitRegEx.exec(val);
+      return `${parseFloat(numVal)}${unit}`;
+    }
+    default:
+      if (varContainedRegEx.test(val)) {
+        return val;
+      }
+      if (type === exports.TYPES.NUMBER && parseFloat(val) === 0) {
+        return '0px';
+      }
+      return undefined;
   }
-  return val;
 };
 
 exports.parsePercent = function parsePercent(val) {
-  if (val === 0 || val === '0') {
-    return '0%';
-  }
   var type = exports.valueType(val);
-  if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
-    return val;
-  }
-  if (type !== exports.TYPES.PERCENT) {
-    return undefined;
+  switch (type) {
+    case exports.TYPES.NULL_OR_EMPTY_STR:
+    case exports.TYPES.VAR:
+      return val;
+    case exports.TYPES.CALC:
+      return cssCalc(val, {
+        format: 'specifiedValue',
+      });
+    case exports.TYPES.PERCENT: {
+      var [, numVal, unit] = unitRegEx.exec(val);
+      return `${parseFloat(numVal)}${unit}`;
+    }
+    default:
+      if (varContainedRegEx.test(val)) {
+        return val;
+      }
+      if (type === exports.TYPES.NUMBER && parseFloat(val) === 0) {
+        return '0%';
+      }
+      return undefined;
   }
-  return val;
 };
 
 // either a length or a percent
 exports.parseMeasurement = function parseMeasurement(val) {
   var type = exports.valueType(val);
-  if (type === exports.TYPES.VAR) {
-    return val;
-  }
-  if (type === exports.TYPES.CALC) {
-    return cssCalc(val, {
-      format: 'specifiedValue',
-    });
-  }
-
-  var length = exports.parseLength(val);
-  if (length !== undefined) {
-    return length;
+  switch (type) {
+    case exports.TYPES.NULL_OR_EMPTY_STR:
+    case exports.TYPES.VAR:
+      return val;
+    case exports.TYPES.CALC:
+      return cssCalc(val, {
+        format: 'specifiedValue',
+      });
+    case exports.TYPES.LENGTH:
+    case exports.TYPES.PERCENT: {
+      var [, numVal, unit] = unitRegEx.exec(val);
+      return `${parseFloat(numVal)}${unit}`;
+    }
+    default:
+      if (varContainedRegEx.test(val)) {
+        return val;
+      }
+      if (type === exports.TYPES.NUMBER && parseFloat(val) === 0) {
+        return '0px';
+      }
+      return undefined;
   }
-  return exports.parsePercent(val);
 };
 
-exports.parseInheritingMeasurement = function parseInheritingMeasurement(v) {
-  if (String(v).toLowerCase() === 'auto') {
-    return 'auto';
-  }
-  if (String(v).toLowerCase() === 'inherit') {
-    return 'inherit';
+exports.parseInheritingMeasurement = function parseInheritingMeasurement(val) {
+  if (/^(?:auto|inherit)$/i.test(val)) {
+    return val.toLowerCase();
   }
-  return exports.parseMeasurement(v);
+  return exports.parseMeasurement(val);
 };
 
 exports.parseUrl = function parseUrl(val) {
   var type = exports.valueType(val);
   if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
-    return val;
+    return '';
   }
   var res = urlRegEx.exec(val);
   // does it match the regex?
@@ -262,10 +301,11 @@ exports.parseUrl = function parseUrl(val) {
   return 'url("' + urlstr + '")';
 };
 
+// NOTE: seems not in use?
 exports.parseString = function parseString(val) {
   var type = exports.valueType(val);
   if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
-    return val;
+    return '';
   }
   if (type !== exports.TYPES.STRING) {
     return undefined;
@@ -289,11 +329,38 @@ exports.parseString = function parseString(val) {
   return val;
 };
 
+exports.parseKeyword = function parseKeyword(val, validKeywords = []) {
+  var type = exports.valueType(val);
+  if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
+    return '';
+  }
+  if (type === exports.TYPES.VAR) {
+    return val;
+  }
+  if (type !== exports.TYPES.KEYWORD) {
+    return undefined;
+  }
+  val = val.toString().toLowerCase();
+  if (validKeywords.includes(val) || GLOBAL_VALUES.includes(val)) {
+    return val;
+  }
+  return undefined;
+};
+
 exports.parseColor = function parseColor(val) {
   var type = exports.valueType(val);
   if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
+    return '';
+  }
+  if (type === exports.TYPES.UNDEFINED) {
+    return undefined;
+  }
+  if (type === exports.TYPES.VAR) {
     return val;
   }
+  if (type === exports.TYPES.KEYWORD) {
+    return exports.parseKeyword(val);
+  }
   if (/^[a-z]+$/i.test(val) && type === exports.TYPES.COLOR) {
     return val;
   }
@@ -306,10 +373,13 @@ exports.parseColor = function parseColor(val) {
   return undefined;
 };
 
+// FIXME:
+// This function seems to be incorrect.
+// However, this has no impact so far, as this function is only used by the deprecated `azimuth` property.
 exports.parseAngle = function parseAngle(val) {
   var type = exports.valueType(val);
   if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
-    return val;
+    return '';
   }
   if (type !== exports.TYPES.ANGLE) {
     return undefined;
@@ -331,46 +401,36 @@ exports.parseAngle = function parseAngle(val) {
   return flt + 'deg';
 };
 
-exports.parseKeyword = function parseKeyword(val, valid_keywords) {
+exports.parseImage = function parseImage(val) {
   var type = exports.valueType(val);
   if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
-    return val;
+    return '';
   }
-  if (type !== exports.TYPES.KEYWORD) {
+  if (type === exports.TYPES.UNDEFINED) {
     return undefined;
   }
-  val = val.toString().toLowerCase();
-  var i;
-  for (i = 0; i < valid_keywords.length; i++) {
-    if (valid_keywords[i].toLowerCase() === val) {
-      return valid_keywords[i];
-    }
-  }
-  return undefined;
-};
-
-exports.parseImage = function parseImage(val) {
-  if (/^(?:none|inherit)$/i.test(val)) {
+  if (type === exports.TYPES.VAR) {
     return val;
   }
-  var type = exports.valueType(val);
-  if (type === exports.TYPES.NULL_OR_EMPTY_STR || type === exports.TYPES.VAR) {
-    return val;
+  if (type === exports.TYPES.KEYWORD) {
+    return exports.parseKeyword(val, ['none']);
   }
-  var values = splitValue(val, ',');
+  var values = splitValue(val, {
+    delimiter: ',',
+    preserveComment: varContainedRegEx.test(val),
+  });
   var isImage = !!values.length;
   var i;
   for (i = 0; i < values.length; i++) {
     var image = values[i];
-    var t = exports.valueType(image);
-    if (t === exports.TYPES.NULL_OR_EMPTY_STR) {
+    if (exports.valueType(image) === exports.TYPES.NULL_OR_EMPTY_STR) {
       return image;
     }
-    if (t === exports.TYPES.GRADIENT || /^(?:none|inherit)$/i.test(image)) {
+    if (isGradient(image) || /^(?:none|inherit)$/i.test(image)) {
       continue;
     }
     var imageUrl = exports.parseUrl(image);
-    if (exports.valueType(imageUrl) === exports.TYPES.URL) {
+    if (imageUrl) {
       values[i] = imageUrl;
     } else {
       isImage = false;
@@ -384,11 +444,15 @@ exports.parseImage = function parseImage(val) {
 };
 
 // utility to translate from border-width to borderWidth
-var dashedToCamelCase = function (dashed) {
-  var i;
+exports.dashedToCamelCase = function (dashed) {
+  if (dashed.startsWith('--')) {
+    return dashed;
+  }
+  // skip leading hyphen in vendor prefixed value, e.g. -webkit-foo
+  var i = /^\-webkit/.test(dashed) ? 1 : 0;
   var camel = '';
   var nextCap = false;
-  for (i = 0; i < dashed.length; i++) {
+  for (; i < dashed.length; i++) {
     if (dashed[i] !== '-') {
       camel += nextCap ? dashed[i].toUpperCase() : dashed[i];
       nextCap = false;
@@ -398,93 +462,57 @@ var dashedToCamelCase = function (dashed) {
   }
   return camel;
 };
-exports.dashedToCamelCase = dashedToCamelCase;
-
-var is_space = /\s/;
-var opening_deliminators = ['"', "'", '('];
-var closing_deliminators = ['"', "'", ')'];
-// this splits on whitespace, but keeps quoted and parened parts together
-var getParts = function (str) {
-  var deliminator_stack = [];
-  var length = str.length;
-  var i;
-  var parts = [];
-  var current_part = '';
-  var opening_index;
-  var closing_index;
-  for (i = 0; i < length; i++) {
-    opening_index = opening_deliminators.indexOf(str[i]);
-    closing_index = closing_deliminators.indexOf(str[i]);
-    if (is_space.test(str[i])) {
-      if (deliminator_stack.length === 0) {
-        if (current_part !== '') {
-          parts.push(current_part);
-        }
-        current_part = '';
-      } else {
-        current_part += str[i];
-      }
-    } else {
-      if (str[i] === '\\') {
-        i++;
-        current_part += str[i];
-      } else {
-        current_part += str[i];
-        if (
-          closing_index !== -1 &&
-          closing_index === deliminator_stack[deliminator_stack.length - 1]
-        ) {
-          deliminator_stack.pop();
-        } else if (opening_index !== -1) {
-          deliminator_stack.push(opening_index);
-        }
-      }
-    }
-  }
-  if (current_part !== '') {
-    parts.push(current_part);
+
+exports.camelToDashed = function (camelCase) {
+  var dashed = camelCase.replace(/(?<=[a-z])[A-Z]/g, '-$&').toLowerCase();
+  var match = dashed.match(/^webkit\-/);
+  if (match) {
+    dashed = '-' + dashed;
   }
-  return parts;
+  return dashed;
 };
 
-/*
- * this either returns undefined meaning that it isn't valid
- * or returns an object where the keys are dashed short
- * hand properties and the values are the values to set
- * on them
- */
-exports.shorthandParser = function parse(v, shorthand_for) {
+// this either returns undefined meaning that it isn't valid
+// or returns an object where the keys are dashed short
+// hand properties and the values are the values to set
+// on them
+// FIXME: need additional argument which indicates syntax
+// and/or use Map() for shorthandFor to ensure order of the longhand properties.
+// Note that there is `constants.js` that is presumably for this purpose?
+exports.shorthandParser = function parse(v, shorthandFor) {
   var obj = {};
   var type = exports.valueType(v);
   if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
-    Object.keys(shorthand_for).forEach(function (property) {
+    Object.keys(shorthandFor).forEach(function (property) {
       obj[property] = '';
     });
     return obj;
   }
-
+  if (type === exports.TYPES.UNDEFINED) {
+    return undefined;
+  }
   if (typeof v === 'number') {
     v = v.toString();
   }
-
   if (typeof v !== 'string') {
     return undefined;
   }
-
   if (v.toLowerCase() === 'inherit') {
     return {};
   }
-  var parts = getParts(v);
+  var parts = splitValue(v);
   var valid = true;
   parts.forEach(function (part, i) {
-    var part_valid = false;
-    Object.keys(shorthand_for).forEach(function (property) {
-      if (shorthand_for[property].isValid(part, i)) {
-        part_valid = true;
+    var partValid = false;
+    Object.keys(shorthandFor).forEach(function (property) {
+      if (shorthandFor[property].isValid(part, i)) {
+        partValid = true;
         obj[property] = part;
       }
     });
-    valid = valid && part_valid;
+    if (valid) {
+      valid = partValid;
+    }
   });
   if (!valid) {
     return undefined;
@@ -492,17 +520,23 @@ exports.shorthandParser = function parse(v, shorthand_for) {
   return obj;
 };
 
-exports.shorthandSetter = function (property, shorthand_for) {
+// FIXME: check against shorthandParser and reduce Object.keys().forEach() loops
+exports.shorthandSetter = function (property, shorthandFor) {
   return function (v) {
-    var obj = exports.shorthandParser(v, shorthand_for);
+    if (v === undefined) {
+      return;
+    }
+    if (v === null) {
+      v = '';
+    }
+    var obj = exports.shorthandParser(v, shorthandFor);
     if (obj === undefined) {
       return;
     }
-    //console.log('shorthandSetter for:', property, 'obj:', obj);
     Object.keys(obj).forEach(function (subprop) {
       // in case subprop is an implicit property, this will clear
       // *its* subpropertiesX
-      var camel = dashedToCamelCase(subprop);
+      var camel = exports.dashedToCamelCase(subprop);
       this[camel] = obj[subprop];
       // in case it gets translated into something else (0 -> 0px)
       obj[subprop] = this[camel];
@@ -512,7 +546,7 @@ exports.shorthandSetter = function (property, shorthand_for) {
         this._values[subprop] = obj[subprop];
       }
     }, this);
-    Object.keys(shorthand_for).forEach(function (subprop) {
+    Object.keys(shorthandFor).forEach(function (subprop) {
       if (!obj.hasOwnProperty(subprop)) {
         this.removeProperty(subprop);
         delete this._values[subprop];
@@ -523,19 +557,19 @@ exports.shorthandSetter = function (property, shorthand_for) {
     // if it already exists, then call the shorthandGetter, if it's an empty
     // string, don't set the property
     this.removeProperty(property);
-    var calculated = exports.shorthandGetter(property, shorthand_for).call(this);
+    var calculated = exports.shorthandGetter(property, shorthandFor).call(this);
     if (calculated !== '') {
       this._setProperty(property, calculated);
     }
   };
 };
 
-exports.shorthandGetter = function (property, shorthand_for) {
+exports.shorthandGetter = function (property, shorthandFor) {
   return function () {
     if (this._values[property] !== undefined) {
       return this.getPropertyValue(property);
     }
-    return Object.keys(shorthand_for)
+    return Object.keys(shorthandFor)
       .map(function (subprop) {
         return this.getPropertyValue(subprop);
       }, this)
@@ -551,12 +585,12 @@ exports.shorthandGetter = function (property, shorthand_for) {
 // if two, the first applies to the top and bottom, and the second to left and right
 // if three, the first applies to the top, the second to left and right, the third bottom
 // if four, top, right, bottom, left
-exports.implicitSetter = function (property_before, property_after, isValid, parser) {
-  property_after = property_after || '';
-  if (property_after !== '') {
-    property_after = '-' + property_after;
+exports.implicitSetter = function (propertyBefore, propertyAfter, isValid, parser) {
+  propertyAfter = propertyAfter || '';
+  if (propertyAfter !== '') {
+    propertyAfter = '-' + propertyAfter;
   }
-  var part_names = ['top', 'right', 'bottom', 'left'];
+  var partNames = ['top', 'right', 'bottom', 'left'];
 
   return function (v) {
     if (typeof v === 'number') {
@@ -569,7 +603,7 @@ exports.implicitSetter = function (property_before, property_after, isValid, par
     if (v.toLowerCase() === 'inherit' || v === '') {
       parts = [v];
     } else {
-      parts = getParts(v);
+      parts = splitValue(v);
     }
     if (parts.length < 1 || parts.length > 4) {
       return undefined;
@@ -582,7 +616,7 @@ exports.implicitSetter = function (property_before, property_after, isValid, par
     parts = parts.map(function (part) {
       return parser(part);
     });
-    this._setProperty(property_before + property_after, parts.join(' '));
+    this._setProperty(propertyBefore + propertyAfter, parts.join(' '));
     if (parts.length === 1) {
       parts[1] = parts[0];
     }
@@ -594,7 +628,7 @@ exports.implicitSetter = function (property_before, property_after, isValid, par
     }
 
     for (var i = 0; i < 4; i++) {
-      var property = property_before + '-' + part_names[i] + property_after;
+      var property = propertyBefore + '-' + partNames[i] + propertyAfter;
       this.removeProperty(property);
       if (parts[i] !== '') {
         this._values[property] = parts[i];
@@ -604,12 +638,10 @@ exports.implicitSetter = function (property_before, property_after, isValid, par
   };
 };
 
-//
 //  Companion to implicitSetter, but for the individual parts.
 //  This sets the individual value, and checks to see if all four
 //  sub-parts are set.  If so, it sets the shorthand version and removes
 //  the individual parts from the cssText.
-//
 exports.subImplicitSetter = function (prefix, part, isValid, parser) {
   var property = prefix + '-' + part;
   var subparts = [prefix + '-top', prefix + '-right', prefix + '-bottom', prefix + '-left'];
@@ -655,16 +687,3 @@ exports.subImplicitSetter = function (prefix, part, isValid, parser) {
     return v;
   };
 };
-
-var camel_to_dashed = /[A-Z]/g;
-var first_segment = /^\([^-]\)-/;
-var vendor_prefixes = ['o', 'moz', 'ms', 'webkit'];
-exports.camelToDashed = function (camel_case) {
-  var match;
-  var dashed = camel_case.replace(camel_to_dashed, '-$&').toLowerCase();
-  match = dashed.match(first_segment);
-  if (match && vendor_prefixes.indexOf(match[1]) !== -1) {
-    dashed = '-' + dashed;
-  }
-  return dashed;
-};
diff --git a/lib/properties/margin.js b/lib/properties/margin.js
index fc6f031..339d65b 100644
--- a/lib/properties/margin.js
+++ b/lib/properties/margin.js
@@ -13,7 +13,7 @@ var isValid = function (v) {
     type === TYPES.LENGTH ||
     type === TYPES.PERCENT ||
     type === TYPES.CALC ||
-    (type === TYPES.INTEGER && (v === '0' || v === 0))
+    (type === TYPES.NUMBER && parseFloat(v) === 0)
   );
 };
 
diff --git a/lib/properties/padding.js b/lib/properties/padding.js
index a82900b..792f65f 100644
--- a/lib/properties/padding.js
+++ b/lib/properties/padding.js
@@ -10,7 +10,7 @@ var isValid = function (v) {
     type === TYPES.LENGTH ||
     type === TYPES.PERCENT ||
     type === TYPES.CALC ||
-    (type === TYPES.INTEGER && (v === '0' || v === 0))
+    (type === TYPES.NUMBER && parseFloat(v) === 0)
   );
 };
 
diff --git a/package-lock.json b/package-lock.json
index dc40f2a..ba94145 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,7 +9,7 @@
       "version": "4.3.1",
       "license": "MIT",
       "dependencies": {
-        "@asamuzakjp/css-color": "^3.1.3",
+        "@asamuzakjp/css-color": "^3.1.7",
         "rrweb-cssom": "^0.8.0"
       },
       "devDependencies": {
@@ -30,9 +30,9 @@
       }
     },
     "node_modules/@asamuzakjp/css-color": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.1.3.tgz",
-      "integrity": "sha512-u25AyjuNrRFGb1O7KmWEu0ExN6iJMlUmDSlOPW/11JF8khOrIGG6oCoYpC+4mZlthNVhFUahk68lNrNI91f6Yg==",
+      "version": "3.1.7",
+      "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.1.7.tgz",
+      "integrity": "sha512-Ok5fYhtwdyJQmU1PpEv6Si7Y+A4cYb8yNM9oiIJC9TzXPMuN9fvdonKJqcnz9TbFqV6bQ8z0giRq0iaOpGZV2g==",
       "license": "MIT",
       "dependencies": {
         "@csstools/css-calc": "^2.1.3",
diff --git a/package.json b/package.json
index 05b41e2..bf4b322 100644
--- a/package.json
+++ b/package.json
@@ -37,7 +37,7 @@
   ],
   "main": "./lib/CSSStyleDeclaration.js",
   "dependencies": {
-    "@asamuzakjp/css-color": "^3.1.3",
+    "@asamuzakjp/css-color": "^3.1.7",
     "rrweb-cssom": "^0.8.0"
   },
   "devDependencies": {
diff --git a/test/parsers.js b/test/parsers.js
index de16abd..7a061e8 100644
--- a/test/parsers.js
+++ b/test/parsers.js
@@ -23,14 +23,14 @@ describe('valueType', () => {
     let input = undefined;
     let output = parsers.valueType(input);
 
-    assert.strictEqual(output, undefined);
+    assert.strictEqual(output, parsers.TYPES.UNDEFINED);
   });
 
-  it('returns integer for 1', () => {
+  it('returns number for 1', () => {
     let input = 1;
     let output = parsers.valueType(input);
 
-    assert.strictEqual(output, parsers.TYPES.INTEGER);
+    assert.strictEqual(output, parsers.TYPES.NUMBER);
   });
 
   it('returns number for 1.1', () => {
@@ -40,6 +40,13 @@ describe('valueType', () => {
     assert.strictEqual(output, parsers.TYPES.NUMBER);
   });
 
+  it('returns number for ".1"', () => {
+    let input = '.1';
+    let output = parsers.valueType(input);
+
+    assert.strictEqual(output, parsers.TYPES.NUMBER);
+  });
+
   it('returns length for 100ch', () => {
     let input = '100ch';
     let output = parsers.valueType(input);
@@ -54,46 +61,46 @@ describe('valueType', () => {
     assert.strictEqual(output, parsers.TYPES.PERCENT);
   });
 
-  it('returns url for url(https://example.com)', () => {
+  it('returns unidentified for url(https://example.com)', () => {
     let input = 'url(https://example.com)';
     let output = parsers.valueType(input);
 
-    assert.strictEqual(output, parsers.TYPES.URL);
+    assert.strictEqual(output, parsers.TYPES.UNIDENT);
   });
 
-  it('returns url for url("https://example.com")', () => {
+  it('returns unidentified for url("https://example.com")', () => {
     let input = 'url("https://example.com")';
     let output = parsers.valueType(input);
 
-    assert.strictEqual(output, parsers.TYPES.URL);
+    assert.strictEqual(output, parsers.TYPES.UNIDENT);
   });
 
-  it('returns url for url(foo.png)', () => {
+  it('returns unidentified for url(foo.png)', () => {
     let input = 'url(foo.png)';
     let output = parsers.valueType(input);
 
-    assert.strictEqual(output, parsers.TYPES.URL);
+    assert.strictEqual(output, parsers.TYPES.UNIDENT);
   });
 
-  it('returns url for url("foo.png")', () => {
+  it('returns unidentified for url("foo.png")', () => {
     let input = 'url("foo.png")';
     let output = parsers.valueType(input);
 
-    assert.strictEqual(output, parsers.TYPES.URL);
+    assert.strictEqual(output, parsers.TYPES.UNIDENT);
   });
 
-  it('returns undefined for url(var(--foo))', () => {
+  it('returns unidentified for url(var(--foo))', () => {
     let input = 'url(var(--foo))';
     let output = parsers.valueType(input);
 
-    assert.strictEqual(output, undefined);
+    assert.strictEqual(output, parsers.TYPES.UNIDENT);
   });
 
-  it('returns var from calc(100px *  var(--foo))', () => {
+  it('returns calc from calc(100px *  var(--foo))', () => {
     let input = 'calc(100px *  var(--foo))';
     let output = parsers.valueType(input);
 
-    assert.strictEqual(output, parsers.TYPES.VAR);
+    assert.strictEqual(output, parsers.TYPES.CALC);
   });
 
   it('returns var from var(--foo)', () => {
@@ -215,11 +222,18 @@ describe('valueType', () => {
     assert.strictEqual(output, parsers.TYPES.COLOR);
   });
 
-  it('returns gradient for linear-gradient(red, blue)', () => {
+  it('returns unidentified for linear-gradient(red, blue)', () => {
     let input = 'linear-gradient(red, blue)';
     let output = parsers.valueType(input);
 
-    assert.strictEqual(output, parsers.TYPES.GRADIENT);
+    assert.strictEqual(output, parsers.TYPES.UNIDENT);
+  });
+
+  it('returns color for accentcolor', () => {
+    let input = 'AccentColor';
+    let output = parsers.valueType(input);
+
+    assert.strictEqual(output, parsers.TYPES.COLOR);
   });
 
   it('returns color for legacy activeborder', () => {
@@ -229,27 +243,196 @@ describe('valueType', () => {
     assert.strictEqual(output, parsers.TYPES.COLOR);
   });
 
-  it('returns keyword for else', () => {
+  it('returns keyword for foo', () => {
     let input = 'foo';
     let output = parsers.valueType(input);
 
     assert.strictEqual(output, parsers.TYPES.KEYWORD);
   });
-});
 
-describe('parseInteger', () => {
-  it.todo('test');
+  it('returns keyword for foo-bar', () => {
+    let input = 'foo-bar';
+    let output = parsers.valueType(input);
+
+    assert.strictEqual(output, parsers.TYPES.KEYWORD);
+  });
+
+  it('returns unidentified for foo(bar)', () => {
+    let input = 'foo(bar)';
+    let output = parsers.valueType(input);
+
+    assert.strictEqual(output, parsers.TYPES.UNIDENT);
+  });
 });
+
 describe('parseNumber', () => {
-  it.todo('test');
+  it('should return null', () => {
+    let input = null;
+    let output = parsers.parseNumber(input);
+
+    assert.strictEqual(output, null);
+  });
+
+  it('should return empty string', () => {
+    let input = '';
+    let output = parsers.parseNumber(input);
+
+    assert.strictEqual(output, '');
+  });
+
+  it('should return undefined', () => {
+    let input = 'foo';
+    let output = parsers.parseNumber(input);
+
+    assert.strictEqual(output, undefined);
+  });
+
+  it('should return undefined', () => {
+    let input = undefined;
+    let output = parsers.parseNumber(input);
+
+    assert.strictEqual(output, undefined);
+  });
+
+  it('should return "1"', () => {
+    let input = 1;
+    let output = parsers.parseNumber(input);
+
+    assert.strictEqual(output, '1');
+  });
+
+  it('should return "1"', () => {
+    let input = '1';
+    let output = parsers.parseNumber(input);
+
+    assert.strictEqual(output, '1');
+  });
+
+  it('should return "0.5"', () => {
+    let input = 0.5;
+    let output = parsers.parseNumber(input);
+
+    assert.strictEqual(output, '0.5');
+  });
+
+  it('should return "0.5"', () => {
+    let input = '0.5';
+    let output = parsers.parseNumber(input);
+
+    assert.strictEqual(output, '0.5');
+  });
+
+  it('should return "0.5"', () => {
+    let input = '.5';
+    let output = parsers.parseNumber(input);
+
+    assert.strictEqual(output, '0.5');
+  });
+
+  it('should return calculated value', () => {
+    let input = 'calc(2 / 3)';
+    let output = parsers.parseLength(input);
+
+    assert.strictEqual(output, 'calc(0.666667)');
+  });
 });
+
 describe('parseLength', () => {
-  it.todo('test');
+  it('should return null', () => {
+    let input = null;
+    let output = parsers.parseLength(input);
+
+    assert.strictEqual(output, null);
+  });
+
+  it('should return empty string', () => {
+    let input = '';
+    let output = parsers.parseLength(input);
+
+    assert.strictEqual(output, '');
+  });
+
+  it('should return value as is', () => {
+    let input = 'var(/* comment */ --foo)';
+    let output = parsers.parseLength(input);
+
+    assert.strictEqual(output, 'var(/* comment */ --foo)');
+  });
+
+  it('should return calculated value', () => {
+    let input = 'calc(2em / 3)';
+    let output = parsers.parseLength(input);
+
+    assert.strictEqual(output, 'calc(0.666667em)');
+  });
+
+  it('should return serialized value', () => {
+    let input = 'calc(10px + 20%)';
+    let output = parsers.parseLength(input);
+
+    assert.strictEqual(output, 'calc(20% + 10px)');
+  });
+
+  it('should return serialized value', () => {
+    let input = 'calc(100vh + 10px)';
+    let output = parsers.parseLength(input);
+
+    assert.strictEqual(output, 'calc(10px + 100vh)');
+  });
 });
+
 describe('parsePercent', () => {
-  it.todo('test');
+  it('should return null', () => {
+    let input = null;
+    let output = parsers.parsePercent(input);
+
+    assert.strictEqual(output, null);
+  });
+
+  it('should return empty string', () => {
+    let input = '';
+    let output = parsers.parsePercent(input);
+
+    assert.strictEqual(output, '');
+  });
+
+  it('should return value as is', () => {
+    let input = 'var(/* comment */ --foo)';
+    let output = parsers.parsePercent(input);
+
+    assert.strictEqual(output, 'var(/* comment */ --foo)');
+  });
+
+  it('should return calculated value', () => {
+    let input = 'calc(100% / 3)';
+    let output = parsers.parsePercent(input);
+
+    assert.strictEqual(output, 'calc(33.3333%)');
+  });
+
+  it('should return serialized value', () => {
+    let input = 'calc(10px + 20%)';
+    let output = parsers.parsePercent(input);
+
+    assert.strictEqual(output, 'calc(20% + 10px)');
+  });
 });
+
 describe('parseMeasurement', () => {
+  it('should return null', () => {
+    let input = null;
+    let output = parsers.parseMeasurement(input);
+
+    assert.strictEqual(output, null);
+  });
+
+  it('should return empty string', () => {
+    let input = '';
+    let output = parsers.parseMeasurement(input);
+
+    assert.strictEqual(output, '');
+  });
+
   it('should return value with em unit', () => {
     let input = '1em';
     let output = parsers.parseMeasurement(input);
@@ -293,15 +476,86 @@ describe('parseMeasurement', () => {
   });
 
   it('should return serialized value', () => {
-    let input = 'calc(10px + 100vh)';
+    let input = 'calc(100vh + 10px)';
     let output = parsers.parseMeasurement(input);
 
     assert.strictEqual(output, 'calc(10px + 100vh)');
   });
 
-  it.todo('test');
+  it('should return 0px for 0', () => {
+    let input = 0;
+    let output = parsers.parseMeasurement(input);
+
+    assert.strictEqual(output, '0px');
+  });
+
+  it('should return 0px for "0"', () => {
+    let input = '0';
+    let output = parsers.parseMeasurement(input);
+
+    assert.strictEqual(output, '0px');
+  });
+});
+
+describe('parseInheritingMeasurement', () => {
+  it('should return auto', () => {
+    let input = 'auto';
+    let output = parsers.parseInheritingMeasurement(input);
+
+    assert.strictEqual(output, 'auto');
+  });
+
+  it('should return auto', () => {
+    let input = 'AUTO';
+    let output = parsers.parseInheritingMeasurement(input);
+
+    assert.strictEqual(output, 'auto');
+  });
+
+  it('should return inherit', () => {
+    let input = 'inherit';
+    let output = parsers.parseInheritingMeasurement(input);
+
+    assert.strictEqual(output, 'inherit');
+  });
+
+  it('should return inherit', () => {
+    let input = 'INHERIT';
+    let output = parsers.parseInheritingMeasurement(input);
+
+    assert.strictEqual(output, 'inherit');
+  });
+
+  it('should return value with em unit', () => {
+    let input = '1em';
+    let output = parsers.parseInheritingMeasurement(input);
+
+    assert.strictEqual(output, '1em');
+  });
+
+  it('should return value with percent', () => {
+    let input = '100%';
+    let output = parsers.parseInheritingMeasurement(input);
+
+    assert.strictEqual(output, '100%');
+  });
 });
+
 describe('parseUrl', () => {
+  it('should return empty string', () => {
+    let input = null;
+    let output = parsers.parseUrl(input);
+
+    assert.strictEqual(output, '');
+  });
+
+  it('should return empty string', () => {
+    let input = '';
+    let output = parsers.parseUrl(input);
+
+    assert.strictEqual(output, '');
+  });
+
   it('should return undefined', () => {
     let input = 'url(var(--foo))';
     let output = parsers.parseUrl(input);
@@ -309,6 +563,13 @@ describe('parseUrl', () => {
     assert.strictEqual(output, undefined);
   });
 
+  it('should return undefined', () => {
+    let input = undefined;
+    let output = parsers.parseUrl(input);
+
+    assert.strictEqual(output, undefined);
+  });
+
   it('should return quoted url string', () => {
     let input = 'url(sample.png)';
     let output = parsers.parseUrl(input);
@@ -428,13 +689,41 @@ describe('parseUrl', () => {
 
     assert.strictEqual(output, 'url("")');
   });
-
-  it.todo('test');
 });
+
 describe('parseString', () => {
   it.todo('test');
 });
+
 describe('parseColor', () => {
+  it('should return empty string', () => {
+    let input = null;
+    let output = parsers.parseColor(input);
+
+    assert.strictEqual(output, '');
+  });
+
+  it('should return empty string', () => {
+    let input = '';
+    let output = parsers.parseColor(input);
+
+    assert.strictEqual(output, '');
+  });
+
+  it('should return undefined', () => {
+    let input = undefined;
+    let output = parsers.parseColor(input);
+
+    assert.strictEqual(output, undefined);
+  });
+
+  it('should return inherit', () => {
+    let input = 'inherit';
+    let output = parsers.parseColor(input);
+
+    assert.strictEqual(output, 'inherit');
+  });
+
   it('should convert hsl to rgb values', () => {
     let input = 'hsla(0, 1%, 2%)';
     let output = parsers.parseColor(input);
@@ -519,27 +808,61 @@ describe('parseColor', () => {
     assert.strictEqual(output, 'transparent');
   });
 
-  it.todo('Add more tests');
+  it('should return value as is with var()', () => {
+    let input = 'rgb(var(--my-var, 0, 0, 0))';
+    let output = parsers.parseColor(input);
+
+    assert.strictEqual(output, 'rgb(var(--my-var, 0, 0, 0))');
+  });
 });
+
 describe('parseAngle', () => {
   it.todo('test');
 });
+
 describe('parseKeyword', () => {
-  it.todo('test');
+  it('should return value', () => {
+    let input = 'inherit';
+    let output = parsers.parseKeyword(input);
+
+    assert.strictEqual(output, 'inherit');
+  });
+
+  it('should return value', () => {
+    let input = 'foo';
+    let output = parsers.parseKeyword(input, ['foo', 'bar']);
+
+    assert.strictEqual(output, 'foo');
+  });
+
+  it('should return value', () => {
+    let input = 'Bar';
+    let output = parsers.parseKeyword(input, ['foo', 'bar']);
+
+    assert.strictEqual(output, 'bar');
+  });
+
+  it('should return undefined', () => {
+    let input = 'baz';
+    let output = parsers.parseKeyword(input, ['foo', 'bar']);
+
+    assert.strictEqual(output, undefined);
+  });
 });
+
 describe('parseImage', () => {
-  it('should return value', () => {
-    let input = 'none';
+  it('should return empty string', () => {
+    let input = '';
     let output = parsers.parseImage(input);
 
-    assert.strictEqual(output, 'none');
+    assert.strictEqual(output, '');
   });
 
-  it('should return value', () => {
-    let input = 'inherit';
+  it('should return empty string', () => {
+    let input = null;
     let output = parsers.parseImage(input);
 
-    assert.strictEqual(output, 'inherit');
+    assert.strictEqual(output, '');
   });
 
   it('should return undefined', () => {
@@ -549,18 +872,25 @@ describe('parseImage', () => {
     assert.strictEqual(output, undefined);
   });
 
-  it('should return undefined for negative radii', () => {
-    let input = 'radial-gradient(circle -10px at center, red, blue)';
+  it('should return none', () => {
+    let input = 'none';
     let output = parsers.parseImage(input);
 
-    assert.strictEqual(output, undefined);
+    assert.strictEqual(output, 'none');
   });
 
-  it('should return empty string', () => {
-    let input = '';
+  it('should return inherit', () => {
+    let input = 'inherit';
     let output = parsers.parseImage(input);
 
-    assert.strictEqual(output, '');
+    assert.strictEqual(output, 'inherit');
+  });
+
+  it('should return undefined for negative radii', () => {
+    let input = 'radial-gradient(circle -10px at center, red, blue)';
+    let output = parsers.parseImage(input);
+
+    assert.strictEqual(output, undefined);
   });
 
   it('should return value', () => {
@@ -597,25 +927,143 @@ describe('parseImage', () => {
 
     assert.strictEqual(
       output,
-      'radial-gradient(transparent, /* comment */ var(--custom-color)), url(example.png)'
+      'radial-gradient(transparent, /* comment */ var(--custom-color)), url("example.png")'
     );
   });
 
-  it('should return value as is if var() is included and even if invalid image type is included', () => {
+  it('should return undefined if invalid image type is included', () => {
     let input = 'radial-gradient(transparent, var(--custom-color)), red';
     let output = parsers.parseImage(input);
 
-    assert.strictEqual(output, 'radial-gradient(transparent, var(--custom-color)), red');
+    assert.strictEqual(output, undefined);
   });
 
-  it.todo('test');
+  it('should return undefined if value is not image type', () => {
+    let input = 'rgb(var(--my-var, 0, 0, 0))';
+    let output = parsers.parseImage(input);
+
+    assert.strictEqual(output, undefined);
+  });
 });
+
 describe('dashedToCamelCase', () => {
-  it.todo('test');
+  it('should not camelize custom property', () => {
+    let input = '--foo-bar-baz';
+    let output = parsers.dashedToCamelCase(input);
+
+    assert.strictEqual(output, '--foo-bar-baz');
+  });
+
+  it('should camelize value', () => {
+    let input = 'foo-bar-baz';
+    let output = parsers.dashedToCamelCase(input);
+
+    assert.strictEqual(output, 'fooBarBaz');
+  });
+
+  it('should camelize vendor prefixed value', () => {
+    let input = '-webkit-foo';
+    let output = parsers.dashedToCamelCase(input);
+
+    assert.strictEqual(output, 'webkitFoo');
+  });
+
+  it('should not camelize snake cased value', () => {
+    let input = 'foo_bar_baz';
+    let output = parsers.dashedToCamelCase(input);
+
+    assert.strictEqual(output, 'foo_bar_baz');
+  });
 });
+
 describe('shorthandParser', () => {
+  const flexGrow = require('../lib/properties/flexGrow');
+  const flexShrink = require('../lib/properties/flexShrink');
+  const flexBasis = require('../lib/properties/flexBasis');
+  const shorthandFor = {
+    'flex-grow': flexGrow,
+    'flex-shrink': flexShrink,
+    'flex-basis': flexBasis,
+  };
+
+  it('should return undefined for keyword', () => {
+    let input = 'none';
+    let output = parsers.shorthandParser(input, shorthandFor);
+
+    assert.strictEqual(output, undefined);
+  });
+
+  it('should return object', () => {
+    let input = '0 0 auto';
+    let output = parsers.shorthandParser(input, shorthandFor);
+
+    assert.deepEqual(output, {
+      'flex-grow': '0',
+      'flex-shrink': '0',
+      'flex-basis': 'auto',
+    });
+  });
+
+  it('should return object', () => {
+    let input = '0 1 auto';
+    let output = parsers.shorthandParser(input, shorthandFor);
+
+    assert.deepEqual(output, {
+      'flex-grow': '0',
+      'flex-shrink': '1',
+      'flex-basis': 'auto',
+    });
+  });
+
+  it('should return object', () => {
+    let input = '2';
+    let output = parsers.shorthandParser(input, shorthandFor);
+
+    assert.deepEqual(output, {
+      'flex-grow': '2',
+    });
+  });
+
+  it('should return object', () => {
+    let input = '2 1';
+    let output = parsers.shorthandParser(input, shorthandFor);
+
+    assert.deepEqual(output, {
+      'flex-grow': '2',
+      'flex-shrink': '1',
+    });
+  });
+
+  it('should return object', () => {
+    let input = '10px';
+    let output = parsers.shorthandParser(input, shorthandFor);
+
+    assert.deepEqual(output, {
+      'flex-basis': '10px',
+    });
+  });
+
+  it('should return object', () => {
+    let input = '2 10px';
+    let output = parsers.shorthandParser(input, shorthandFor);
+
+    assert.deepEqual(output, {
+      'flex-grow': '2',
+      'flex-basis': '10px',
+    });
+  });
+
+  // FIXME:
+  it.skip('should return undefined', () => {
+    let input = '2 10px 20px';
+    let output = parsers.shorthandParser(input, shorthandFor);
+
+    assert.deepEqual(output, undefined);
+  });
+
   it.todo('test');
 });
+
 describe('shorthandSetter', () => {
   it.todo('test');
 });
@@ -628,6 +1076,33 @@ describe('implicitSetter', () => {
 describe('subImplicitSetter', () => {
   it.todo('test');
 });
+
 describe('camelToDashed', () => {
-  it.todo('test');
+  it('should return dashed value', () => {
+    let input = 'fooBarBaz';
+    let output = parsers.camelToDashed(input);
+
+    assert.strictEqual(output, 'foo-bar-baz');
+  });
+
+  it('should return dashed value', () => {
+    let input = 'FooBarBaz';
+    let output = parsers.camelToDashed(input);
+
+    assert.strictEqual(output, 'foo-bar-baz');
+  });
+
+  it('should return dashed value', () => {
+    let input = 'webkitFooBar';
+    let output = parsers.camelToDashed(input);
+
+    assert.strictEqual(output, '-webkit-foo-bar');
+  });
+
+  it('should return dashed value', () => {
+    let input = 'WebkitFooBar';
+    let output = parsers.camelToDashed(input);
+
+    assert.strictEqual(output, '-webkit-foo-bar');
+  });
 });