diff options
author | Trent Richardson <trentdrichardson@gmail.com> | 2013-07-15 05:04:36 -0700 |
---|---|---|
committer | Trent Richardson <trentdrichardson@gmail.com> | 2013-07-15 05:04:36 -0700 |
commit | a1e67c52f3689a0618285048befaacdd6c776c4a (patch) | |
tree | 8f94c93c9f52fdc0bd9ee7b1642ee58859f730a2 | |
parent | af2f050bf8c983003a6812fb45b73cf8182e4547 (diff) | |
parent | 032adf1ed6eff592955cfd56981bc14c776d2ae7 (diff) | |
download | jQuery-Timepicker-Addon-a1e67c52f3689a0618285048befaacdd6c776c4a.zip jQuery-Timepicker-Addon-a1e67c52f3689a0618285048befaacdd6c776c4a.tar.gz jQuery-Timepicker-Addon-a1e67c52f3689a0618285048befaacdd6c776c4a.tar.bz2 |
Merge pull request #606 from srvance/dev
More tests added, cleanup
-rw-r--r-- | jquery-ui-timepicker-addon.js | 134 | ||||
-rw-r--r-- | test/jquery-ui-timepicker-addon_spec.js | 265 |
2 files changed, 328 insertions, 71 deletions
diff --git a/jquery-ui-timepicker-addon.js b/jquery-ui-timepicker-addon.js index 8dbf0d2..50d6da3 100644 --- a/jquery-ui-timepicker-addon.js +++ b/jquery-ui-timepicker-addon.js @@ -152,8 +152,8 @@ /* * Override the default settings for all instances of the time picker. - * @param settings object - the new settings to use as defaults (anonymous object) - * @return the manager object + * @param {Object} settings object - the new settings to use as defaults (anonymous object) + * @return {Object} the manager object */ setDefaults: function(settings) { extendRemove(this._defaults, settings || {}); @@ -1823,51 +1823,36 @@ return String(hour); }; + var computeEffectiveSetting = function (settings, property) { + return settings && settings[property] ? settings[property] : $.timepicker._defaults[property]; + }; + /* * Splits datetime string into date and time substrings. * Throws exception when date can't be parsed - * Returns [dateString, timeString] + * Returns {dateString: dateString, timeString: timeString} */ - var splitDateTime = function(dateFormat, dateTimeString, dateSettings, timeSettings) { - try { - // The idea is to get the number separator occurrences in datetime and the time format requested (since time has - // fewer unknowns, mostly numbers and am/pm). We will use the time pattern to split. - var separator = timeSettings && timeSettings.separator ? timeSettings.separator : $.timepicker._defaults.separator, - format = timeSettings && timeSettings.timeFormat ? timeSettings.timeFormat : $.timepicker._defaults.timeFormat, - timeParts = format.split(separator), // how many occurrences of separator may be in our format? - timePartsLen = timeParts.length, - allParts = dateTimeString.split(separator), - allPartsLen = allParts.length; - - if (allPartsLen > 1) { - return [ - allParts.splice(0,allPartsLen-timePartsLen).join(separator), - allParts.splice(0,timePartsLen).join(separator) - ]; - } - - } catch (err) { - $.timepicker.log('Could not split the date from the time. Please check the following datetimepicker options' + - "\nthrown error: " + err + - "\ndateTimeString" + dateTimeString + - "\ndateFormat = " + dateFormat + - "\nseparator = " + timeSettings.separator + - "\ntimeFormat = " + timeSettings.timeFormat); - - if (err.indexOf(":") >= 0) { - // Hack! The error message ends with a colon, a space, and - // the "extra" characters. We rely on that instead of - // attempting to perfectly reproduce the parsing algorithm. - var dateStringLength = dateTimeString.length - (err.length - err.indexOf(':') - 2), - timeString = dateTimeString.substring(dateStringLength); - - return [$.trim(dateTimeString.substring(0, dateStringLength)), $.trim(dateTimeString.substring(dateStringLength))]; - - } else { - throw err; - } + var splitDateTime = function(dateTimeString, timeSettings) { + // The idea is to get the number separator occurrences in datetime and the time format requested (since time has + // fewer unknowns, mostly numbers and am/pm). We will use the time pattern to split. + var separator = computeEffectiveSetting(timeSettings, 'separator'), + format = computeEffectiveSetting(timeSettings, 'timeFormat'), + timeParts = format.split(separator), // how many occurrences of separator may be in our format? + timePartsLen = timeParts.length, + allParts = dateTimeString.split(separator), + allPartsLen = allParts.length; + + if (allPartsLen > 1) { + return { + dateString: allParts.splice(0,allPartsLen-timePartsLen).join(separator), + timeString: allParts.splice(0,timePartsLen).join(separator) + }; } - return [dateTimeString, '']; + + return { + dateString: dateTimeString, + timeString: '' + }; }; /* @@ -1877,25 +1862,29 @@ * timeObj = {hour: , minute: , second: , millisec: , microsec: } - parsed time. Optional */ var parseDateTimeInternal = function(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) { - var date; - var splitRes = splitDateTime(dateFormat, dateTimeString, dateSettings, timeSettings); - date = $.datepicker._base_parseDate(dateFormat, splitRes[0], dateSettings); - if (splitRes[1] !== '') { - var timeString = splitRes[1], - parsedTime = $.datepicker.parseTime(timeFormat, timeString, timeSettings); - - if (parsedTime === null) { - throw 'Wrong time format'; - } - return { - date: date, - timeObj: parsedTime - }; - } else { + var date, + parts, + parsedTime; + + parts = splitDateTime(dateTimeString, timeSettings); + date = $.datepicker._base_parseDate(dateFormat, parts.dateString, dateSettings); + + if (parts.timeString === '') { return { date: date }; } + + parsedTime = $.datepicker.parseTime(timeFormat, parts.timeString, timeSettings); + + if (!parsedTime) { + throw 'Wrong time format'; + } + + return { + date: date, + timeObj: parsedTime + }; }; /* @@ -1915,12 +1904,12 @@ /** * Get the timezone offset as string from a date object (eg '+0530' for UTC+5.5) - * @param {number} tzMinutes if not a number this value is returned + * @param {number} tzMinutes if not a number, less than -720 (-1200), or greater than 840 (+1400) this value is returned * @param {boolean} iso8601 if true formats in accordance to iso8601 "+12:45" * @return {string} */ $.timepicker.timezoneOffsetString = function(tzMinutes, iso8601) { - if(isNaN(tzMinutes) || tzMinutes > 840){ + if(isNaN(tzMinutes) || tzMinutes > 840 || tzMinutes < -720){ return tzMinutes; } @@ -1928,7 +1917,7 @@ minutes = off % 60, hours = (off - minutes) / 60, iso = iso8601? ':':'', - tz = (off >= 0 ? '+' : '-') + ('0' + (hours * 101).toString()).slice(-2) + iso + ('0' + (minutes * 101).toString()).slice(-2); + tz = (off >= 0 ? '+' : '-') + ('0' + Math.abs(hours)).slice(-2) + iso + ('0' + Math.abs(minutes)).slice(-2); if(tz == '+00:00'){ return 'Z'; @@ -1938,23 +1927,23 @@ /** * Get the number in minutes that represents a timezone string - * @param {string} tzString formatted like "+0500", "-1245" - * @return {number} + * @param {string} tzString formatted like "+0500", "-1245", "Z" + * @return {number} the offset minutes or the original string if it doesn't match expectations */ $.timepicker.timezoneOffsetNumber = function(tzString) { - tzString = tzString.toString().replace(':',''); // excuse any iso8601, end up with "+1245" + var normalized = tzString.toString().replace(':',''); // excuse any iso8601, end up with "+1245" - if(tzString.toUpperCase() === 'Z'){ // if iso8601 with Z, its 0 minute offset + if(normalized.toUpperCase() === 'Z'){ // if iso8601 with Z, its 0 minute offset return 0; } - if(!/^(\-|\+)\d{4}$/.test(tzString)){ // possibly a user defined tz, so just give it back + if(!/^(\-|\+)\d{4}$/.test(normalized)){ // possibly a user defined tz, so just give it back return tzString; } - return ((tzString.substr(0,1) =='-'? -1 : 1) * // plus or minus - ((parseInt(tzString.substr(1,2),10)*60) + // hours (converted to minutes) - parseInt(tzString.substr(3,2),10))); // minutes + return ((normalized.substr(0,1) =='-'? -1 : 1) * // plus or minus + ((parseInt(normalized.substr(1,2),10)*60) + // hours (converted to minutes) + parseInt(normalized.substr(3,2),10))); // minutes }; /** @@ -1966,7 +1955,7 @@ $.timepicker.timezoneAdjust = function(date, toTimezone) { var toTz = $.timepicker.timezoneOffsetNumber(toTimezone); if(!isNaN(toTz)){ - date.setMinutes(date.getMinutes()*1 + (date.getTimezoneOffset()*-1 - toTz*1) ); + date.setMinutes(date.getMinutes() + -date.getTimezoneOffset() - toTz); } return date; }; @@ -1999,7 +1988,7 @@ }; /** - * Calls `method` on the `startTime` and `endTime` elements, and configures them to + * Calls `datepicker` on the `startTime` and `endTime` elements, and configures them to * enforce date range limits. * @param {Element} startTime * @param {Element} endTime @@ -2113,7 +2102,10 @@ _isEmptyObject: isEmptyObject, _convert24to12: convert24to12, _detectSupport: detectSupport, - _selectLocalTimezone: selectLocalTimezone + _selectLocalTimezone: selectLocalTimezone, + _computeEffectiveSetting: computeEffectiveSetting, + _splitDateTime: splitDateTime, + _parseDateTimeInternal: parseDateTimeInternal }; /* diff --git a/test/jquery-ui-timepicker-addon_spec.js b/test/jquery-ui-timepicker-addon_spec.js index 70f44b2..4676c25 100644 --- a/test/jquery-ui-timepicker-addon_spec.js +++ b/test/jquery-ui-timepicker-addon_spec.js @@ -195,5 +195,270 @@ describe('datetimepicker', function() { expect(timepicker.timezone_select.val()).toBe(timezoneOffset); }); }); + + describe('computeEffectiveSetting', function() { + it('pulls the setting from the passed settings object if it is there', function() { + var expectedUniqueValue = 'This is very unique', + settings = { + property: expectedUniqueValue + }; + + expect(util._computeEffectiveSetting(settings, 'property')).toBe(expectedUniqueValue); + }); + + it('pulls the setting from the timepicker defaults if there are no passed settings', function() { + var expectedValue = $.timepicker._defaults.separator; + expect(expectedValue).toBeDefined(); + + expect(util._computeEffectiveSetting(undefined, 'separator')).toBe(expectedValue); + }); + + it('pulls the setting from the timepicker defaults if not present in the passed settings', function() { + var expectedValue = $.timepicker._defaults.separator, + settings = {}; + expect(expectedValue).toBeDefined(); + + expect(util._computeEffectiveSetting(settings, 'separator')).toBe(expectedValue); + }); + }); + + describe('splitDateTime', function() { + var expectedDateString = '3/6/1967', + expectedTimeString = '07:32'; + + it('splits a date and time into its parts using the default separator', function() { + var inputDateTimeString = expectedDateString + $.timepicker._defaults.separator + expectedTimeString, + result; + + result = $.timepicker._util._splitDateTime(inputDateTimeString, {}); + + expect(result).toEqual({dateString: expectedDateString, timeString: expectedTimeString}); + }); + + it('splits a date and time into its parts using a supplied separator', function() { + var separator = '-', + inputDateTimeString = expectedDateString + separator + expectedTimeString, + result; + + result = $.timepicker._util._splitDateTime(inputDateTimeString, {separator: separator}); + + expect(result).toEqual({dateString: expectedDateString, timeString: expectedTimeString}); + }); + + it('splits a date and time into its parts when there are multiple separators in the time format', function() { + var timeFormat = 'hh mm tt', + separator = ' ', + alternateTimeString = '07 32 am', + inputDateTimeString = expectedDateString + separator + alternateTimeString, + timeSettings = {separator: separator, timeFormat: timeFormat}, + result; + + result = $.timepicker._util._splitDateTime(inputDateTimeString, timeSettings); + + expect(result).toEqual({dateString: expectedDateString, timeString: alternateTimeString}); + }); + + it('splits only a date into itself', function() { + var result = $.timepicker._util._splitDateTime(expectedDateString, {}); + + expect(result).toEqual({dateString: expectedDateString, timeString: ''}); + }); + }); + + describe('parseDateTimeInternal', function() { + var dateFormat = 'mm/dd/yy'; + + it('should return only a date if there is no time component', function() { + var inputDateString = '9/11/2001', + expectedDate = new Date(inputDateString), + result; + + result = util._parseDateTimeInternal(dateFormat, undefined, inputDateString, undefined, undefined); + + expect(result.date).toEqual(expectedDate); + expect(result.timeObj).toBeUndefined(); + }); + + it('should return a date and a parsed time if a time is included', function() { + var expectedDateString = '7/4/1976', + expectedParsedTime = { + hour: 1, + minute: 23, + second: 45, + millisec: 678, + microsec: 0 + }, + inputDateTimeString = expectedDateString + ' ' + + expectedParsedTime.hour + ':' + + expectedParsedTime.minute + ':' + + expectedParsedTime.second + '.' + + expectedParsedTime.millisec, + expectedDate = new Date(expectedDateString), + result; + + result = util._parseDateTimeInternal(dateFormat, 'H:m:s.l', inputDateTimeString, undefined, undefined); + + expect(result.date).toEqual(expectedDate); + expect(result.timeObj).toEqual(expectedParsedTime); + }); + + it('should throw an exception if it cannot parse the time', function() { + var inputDateString = '4/17/2008 11:22:33'; + + expect(function() { + util._parseDateTimeInternal(dateFormat, 'q', inputDateString, undefined, undefined); + }).toThrow('Wrong time format'); + }); + }); + }); + + describe('timepicker functions', function() { + describe('timezoneOffsetNumber', function() { + it('returns 0 if the time zone string is iso8601 Zulu', function() { + expect($.timepicker.timezoneOffsetNumber('Z')).toBe(0); + expect($.timepicker.timezoneOffsetNumber('z')).toBe(0); + expect($.timepicker.timezoneOffsetNumber(':Z')).toBe(0); + }); + + it('returns a string that does not match the expected representations', function() { + expect($.timepicker.timezoneOffsetNumber('EDT')).toBe('EDT'); + expect($.timepicker.timezoneOffsetNumber('1234')).toBe('1234'); + expect($.timepicker.timezoneOffsetNumber('+123')).toBe('+123'); + expect($.timepicker.timezoneOffsetNumber('-123')).toBe('-123'); + expect($.timepicker.timezoneOffsetNumber('abc:def')).toBe('abc:def'); + }); + + it('returns the minute offset from a time zone offset string', function() { + expect($.timepicker.timezoneOffsetNumber('-0000')).toBe(0); + expect($.timepicker.timezoneOffsetNumber('+0000')).toBe(0); + expect($.timepicker.timezoneOffsetNumber('-0400')).toBe(-240); + expect($.timepicker.timezoneOffsetNumber('+0400')).toBe(240); + }); + }); + + describe('timezoneOffsetString', function() { + it('returns NaN if the input is NaN', function() { + expect($.timepicker.timezoneOffsetString(NaN)).toBeNaN(); + }); + + it('returns the input if the input is greater than 840 (+14:00)', function() { + var expectedMinutes = 850; + + var actualMinutes = $.timepicker.timezoneOffsetString(expectedMinutes); + + expect(actualMinutes).toBe(expectedMinutes); + }); + + it('returns the input if the input is less than -720 (-12:00)', function() { + var expectedMinutes = -730; + + var actualMinutes = $.timepicker.timezoneOffsetString(expectedMinutes); + + expect(actualMinutes).toBe(expectedMinutes); + }); + + it('returns "Z" if the offset is 0 and iso8601 is true', function() { + expect($.timepicker.timezoneOffsetString(0, true)).toBe('Z'); + }); + + it('returns the expected offset string for non-iso8601 values', function() { + expect($.timepicker.timezoneOffsetString(0, false)).toBe('+0000'); + expect($.timepicker.timezoneOffsetString(60, false)).toBe('+0100'); + expect($.timepicker.timezoneOffsetString(480, false)).toBe('+0800'); + expect($.timepicker.timezoneOffsetString(-60, false)).toBe('-0100'); + expect($.timepicker.timezoneOffsetString(-480, false)).toBe('-0800'); + expect($.timepicker.timezoneOffsetString(-720, false)).toBe('-1200'); + expect($.timepicker.timezoneOffsetString(840, false)).toBe('+1400'); + }); + + it('returns the expected offset string for iso8601 values', function() { + expect($.timepicker.timezoneOffsetString(60, true)).toBe('+01:00'); + expect($.timepicker.timezoneOffsetString(480, true)).toBe('+08:00'); + expect($.timepicker.timezoneOffsetString(-60, true)).toBe('-01:00'); + expect($.timepicker.timezoneOffsetString(-480, true)).toBe('-08:00'); + expect($.timepicker.timezoneOffsetString(-720, true)).toBe('-12:00'); + expect($.timepicker.timezoneOffsetString(840, true)).toBe('+14:00'); + }); + }); + + describe('timezoneAdjust', function() { + it('does not change the date if the timezone yields NaN for an offset', function() { + var expectedDate = new Date(); + + expect($.timepicker.timezoneAdjust(expectedDate, NaN)).toEqual(expectedDate); + }); + + it('changes the minutes by the time zone offset minutes', function() { + var inputDate, + originalMillis, + expectedDifference, + adjustedDate; + + inputDate = new Date(); + originalMillis = inputDate.getTime(); + expectedDifference = -(inputDate.getTimezoneOffset() + 60) * 60 * 1000; + + adjustedDate = $.timepicker.timezoneAdjust(inputDate, '+0100'); + + expect(adjustedDate.getTime() - originalMillis).toBe(expectedDifference); + }); + }); + + describe('log', function() { + it('calls console.log with the message if the console exists', function() { + var expectedMessage = "Just what I expected!"; + spyOn(window.console, "log"); + + $.timepicker.log(expectedMessage); + + expect(window.console.log).toHaveBeenCalledWith(expectedMessage); + }); + + it('does not call console.log if there is no console', function() { + var originalConsole = window.console, + consoleLogSpy = spyOn(window.console, "log"); + window.console = undefined; + + $.timepicker.log("Don't care"); + + expect(consoleLogSpy).not.toHaveBeenCalled(); + + window.console = originalConsole; + }); + }); + + describe('range functions', function() { + var startTime = $('<p>start</p>'), + endTime = $('<p>end</p>'), + options = {}; + + describe('convenience functions', function() { + beforeEach(function() { + spyOn($.timepicker, 'handleRange'); + }); + + it('timeRange calls handleRange the right way', function() { + $.timepicker.timeRange(startTime, endTime, options); + + expect($.timepicker.handleRange).toHaveBeenCalledWith('timepicker', startTime, endTime, options); + }); + + it('datetimeRange calls handleRange the right way', function() { + $.timepicker.datetimeRange(startTime, endTime, options); + + expect($.timepicker.handleRange).toHaveBeenCalledWith('datetimepicker', startTime, endTime, options); + }); + + it('dateRange calls handleRange the right way', function() { + $.timepicker.dateRange(startTime, endTime, options); + + expect($.timepicker.handleRange).toHaveBeenCalledWith('datepicker', startTime, endTime, options); + }); + }); + + xdescribe('handleRange', function() { + // TODO: Difficult to test. Needs attention. + }); + }); }); });
\ No newline at end of file |