JavaScript function to convert underscore-case to camel-case (and vice-versa) Actually I needed a function which converts underscore to camel-case. 
But then I've had the idea: Why not extend the function so, that is works the other way around?

Finally I recalled that there is a third case which programmers use: Pascal-Case. So I included that too.

The function doesn't work perfect but as long as the different cases are used as expected it works alright.

Any hints and suggestions concerning improvements are welcomed.



/**
* Converts a string to either underscore-case or camel-case or
*   to pascal-case. 
* @param {string} toChange
* @param {string} [toCase='toUnderscoreCase'] - Options: 
*   'toUnderscoreCase' | 'toCamelCase' | 'toPascalCase'  
* @returns {string} according toCase-param.
*   Returns an empty string in case of error.
*/

function changeCase(toChange, toCase) {
  var needle = null;
  var funct = null;
  var needleChangingUpperLower = /[a-z0-9]_[a-z0-9]/g;
  var needleToUnderscore = /(([a-zA-Z0-9]*?)(([a-z0-9][A-Z]))|([a-zA-Z0-9]*)$)/g;  

  toCase = toCase || 'toUnderscoreCase'

  if ( !toChange || 
      typeof toChange !== 'string' || 
      toChange.length &lt; 2 ) {
    return '';
  }

  if (toChange.search(/[^\w]/g) &gt; -1) {
    return '';
  }

  function toChangingUpperLower(match) {
    var chars = match.split('_');

    return chars[0] + chars[1].toUpperCase();
  }

  function toUnderscore(match, wordComplete, wordTruncated, wordChange) {
    var ret = '';

    if (wordChange) {

      var chars = wordChange.split('');

      ret += wordTruncated.toLowerCase() + chars[0] + '_' + chars[1].toLowerCase();
    } else {
      ret = wordComplete.toLowerCase();
    }

    return ret;
  }

  switch (toCase) {
    case 'toCamelCase':
      needle = needleChangingUpperLower;

      toChange = toChange.slice(0, 1).toLowerCase() + toChange.slice(1);

      funct = toChangingUpperLower;

      break;
    case 'toPascalCase':
      needle = needleChangingUpperLower;

      toChange = toChange.slice(0, 1).toUpperCase() + toChange.slice(1);

      funct = toChangingUpperLower;

      break;
    case 'toUnderscoreCase':
      needle = needleToUnderscore;

      funct = toUnderscore;

      break;
    default:
      return '';
  }

  return toChange.replace(needle, funct);
}

// --- Usage-examples and test-cases -------- 
var tests = [ {
  toChange: 'get_amount_of_taxes',
  toCase: ''
},
             
{
  toChange: 'ThisIsTheSoCalledPascalCase',
  toCase: 'toCamelCase'
},
{
  toChange: 'thisIsTheSoCalledCamelCase',
  toCase: 'toPascalCase'
},
{
  toChange: 'set_sum_of_articles',
  toCase: 'toCamelCase'
},
{
  toChange: 'getAmountOfTaxes',
  toCase: 'toUnderscoreCase'
},
{
  toChange: 'XMLHttpRequest',
  toCase: 'toUnderscoreCase'
},
{
  toChange: 'theXMLconnector1ForABC',
  toCase: 'toUnderscoreCase'
},
{
  toChange: 'aB',
  toCase: 'toUnderscoreCase'
},
{
  toChange: 'c',
  toCase: 'toUnderscoreCase'
},
{
  toChange: [2, 3],
  toCase: 'toUnderscoreCase'
},
{
  toChange: 'abc#123Spec',
  toCase: 'toUnderscoreCase'
},
{
  toChange: 'abc_890-spec',
  toCase: 'toCamelCase'
},
{
  toChange: 'get_amount_of_taxes',
  toCase: 'abc123'
} ];

tests.forEach(function(test) {
  var result = changeCase(test.toChange, test.toCase);
  var log = console.log;
  var err = console.error;

  !result
  ? err( '%s\n%s', 
        'Something has gone wrong.', 
        JSON.stringify(test, null, 2)) 
  : log( '%s - %s', 
        result,
        JSON.stringify(test, null, 2));
});
Tests

Your test code isn't the clearest. Assuming the rest of the code works as it should, then you should look into making your tests clearer and more reliable.

As it stands, you don't give any expected value for the test results. Having that would enable you to throw an error if the result is wrong as well as if the method throws. Consider something like this:

var tests = [
    {
        'toChange': 'ThisIsPascalCase',
        'toCase': 'toUnderscoreCase',
        'expected': 'this_is_pascal_case'
    }
];

tests.forEach(function(test) {
    var result = changeCase(test.toChange, test.toCase);
    if(!result) {
        console.error("Something has gone wrong!");
        // log extra error details if you want them
    }
    else if(result !== test.expected) {
        console.error("Result doesn't match expected result!");
        // log extra error and environment/stack details
    }
    else {
        console.log("Test passed successfully.");
    }
});


That makes your test code clearer, and provides you with accuracy checking.