Datepicker.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. import './_setup.js';
  2. import Datepicker from '../../js/Datepicker.js';
  3. import defaultOptions from '../../js/options/defaultOptions.js';
  4. import {locales} from '../../js/i18n/base-locales.js';
  5. import {dateValue, today} from '../../js/lib/date.js';
  6. const esLocale = {
  7. months: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"],
  8. monthsShort: ["Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic"],
  9. };
  10. describe('Datepicker', function () {
  11. it('has locales attribute with "en" locale', function () {
  12. expect(Datepicker.locales, 'to be an object');
  13. expect(Datepicker.locales.en, 'to equal', locales.en);
  14. });
  15. describe('constructor', function () {
  16. let input;
  17. beforeEach(function () {
  18. input = document.createElement('input');
  19. testContainer.appendChild(input);
  20. });
  21. after(function () {
  22. document.querySelectorAll('.datepicker').forEach((el) => {
  23. el.parentElement.removeChild(el);
  24. });
  25. delete input.datepicker;
  26. testContainer.removeChild(input);
  27. });
  28. it('attachs the created instance to the bound element', function () {
  29. const dp = new Datepicker(input);
  30. expect(input.datepicker, 'to be', dp);
  31. });
  32. it('adds datepicker-input class to the bound element', function () {
  33. new Datepicker(input);
  34. expect(input.classList.contains('datepicker-input'), 'to be true');
  35. });
  36. it('configures the instance with the default options', function () {
  37. const dp = new Datepicker(input);
  38. // config items should be options + container, locale, multidate and weekEnd
  39. const numOfOptions = Object.keys(defaultOptions).length;
  40. expect(Object.keys(dp.config), 'to have length', numOfOptions + 5);
  41. expect(dp.config.autohide, 'to be false');
  42. expect(dp.config.beforeShowDay, 'to be null');
  43. expect(dp.config.beforeShowDecade, 'to be null');
  44. expect(dp.config.beforeShowMonth, 'to be null');
  45. expect(dp.config.beforeShowYear, 'to be null');
  46. expect(dp.config.buttonClass, 'to be', 'button');
  47. expect(dp.config.calendarWeeks, 'to be false');
  48. expect(dp.config.clearBtn, 'to be false');
  49. expect(dp.config.container, 'to be', document.body);
  50. expect(dp.config.dateDelimiter, 'to be', ',');
  51. expect(dp.config.datesDisabled, 'to equal', []);
  52. expect(dp.config.daysOfWeekDisabled, 'to equal', []);
  53. expect(dp.config.daysOfWeekHighlighted, 'to equal', []);
  54. expect(dp.config.defaultViewDate, 'to be', today());
  55. expect(dp.config.disableTouchKeyboard, 'to be false');
  56. expect(dp.config.format, 'to be', 'mm/dd/yyyy');
  57. expect(dp.config.language, 'to be', 'en');
  58. expect(dp.config.locale, 'to equal', Object.assign({
  59. format: defaultOptions.format,
  60. weekStart: defaultOptions.weekStart,
  61. }, locales.en));
  62. expect(dp.config.maxDate, 'to be undefined');
  63. expect(dp.config.maxNumberOfDates, 'to be', 1);
  64. expect(dp.config.maxView, 'to be', 3);
  65. expect(dp.config.minDate, 'to be', dateValue(0, 0, 1));
  66. expect(dp.config.multidate, 'to be false');
  67. //
  68. expect(dp.config.nextArrow, 'to be a', NodeList);
  69. expect(dp.config.nextArrow.length, 'to be', 1);
  70. expect(dp.config.nextArrow[0].wholeText, 'to be', '»');
  71. //
  72. expect(dp.config.orientation, 'to equal', {x: 'auto', y: 'auto'});
  73. expect(dp.config.pickLevel, 'to be', 0);
  74. //
  75. expect(dp.config.prevArrow, 'to be a', NodeList);
  76. expect(dp.config.prevArrow.length, 'to be', 1);
  77. expect(dp.config.prevArrow[0].wholeText, 'to be', '«');
  78. //
  79. expect(dp.config.showDaysOfWeek, 'to be true');
  80. expect(dp.config.showOnFocus, 'to be true');
  81. expect(dp.config.startView, 'to be', 0);
  82. expect(dp.config.title, 'to be', '');
  83. expect(dp.config.todayBtn, 'to be false');
  84. expect(dp.config.todayHighlight, 'to be false');
  85. expect(dp.config.updateOnBlur, 'to be true');
  86. expect(dp.config.weekStart, 'to be', 0);
  87. expect(dp.config.weekEnd, 'to be', 6);
  88. });
  89. it('append datepicker element to the container)', function () {
  90. new Datepicker(input);
  91. const dpElem = Array.from(document.body.children).find(el => el.matches('.datepicker'));
  92. expect(dpElem, 'not to be undefined');
  93. });
  94. it('does not add the active class to the picker element', function () {
  95. new Datepicker(input);
  96. const dpElem = document.querySelector('.datepicker');
  97. expect(dpElem.classList.contains('active'), 'to be false');
  98. });
  99. it('sets rangepicker properties if DateRangePicker to link is passed', function () {
  100. const fakeRangepicker = {
  101. inputs: [input],
  102. datepickers: [],
  103. };
  104. const dp = new Datepicker(input, {}, fakeRangepicker);
  105. expect(dp.rangepicker, 'to be', fakeRangepicker);
  106. });
  107. it('adds itself to rangepicker.datepickers if DateRangePicker to link is passed', function () {
  108. let fakeRangepicker = {
  109. inputs: [input],
  110. datepickers: [],
  111. };
  112. let dp = new Datepicker(input, {}, fakeRangepicker);
  113. expect(fakeRangepicker.datepickers[0], 'to be', dp);
  114. fakeRangepicker = {
  115. inputs: [undefined, input],
  116. datepickers: [],
  117. };
  118. dp = new Datepicker(input, {}, fakeRangepicker);
  119. expect(fakeRangepicker.datepickers[1], 'to be', dp);
  120. });
  121. it('throws an error if invalid rangepicker is passed', function () {
  122. const testFn = rangepicker => new Datepicker(input, {}, rangepicker);
  123. const errMsg = 'Invalid rangepicker object.';
  124. let fakeRangepicker = {
  125. inputs: [],
  126. datepickers: [],
  127. };
  128. expect(() => testFn(fakeRangepicker), 'to throw', errMsg);
  129. fakeRangepicker = {
  130. inputs: ['foo', 'bar', input],
  131. datepickers: [],
  132. };
  133. expect(() => testFn(fakeRangepicker), 'to throw', errMsg);
  134. fakeRangepicker = {
  135. inputs: [input],
  136. };
  137. expect(() => testFn(fakeRangepicker), 'to throw', errMsg);
  138. });
  139. });
  140. describe('destroy()', function () {
  141. let input;
  142. let dp;
  143. let spyHide;
  144. let returnVal;
  145. before(function () {
  146. input = document.createElement('input');
  147. testContainer.appendChild(input);
  148. dp = new Datepicker(input);
  149. spyHide = sinon.spy(dp, 'hide');
  150. returnVal = dp.destroy();
  151. });
  152. after(function () {
  153. spyHide.restore();
  154. document.querySelectorAll('.datepicker').forEach((el) => {
  155. el.parentElement.removeChild(el);
  156. });
  157. delete input.datepicker;
  158. testContainer.removeChild(input);
  159. });
  160. it('calls hide()', function () {
  161. expect(spyHide.called, 'to be true');
  162. });
  163. it('removes datepicker element from its container', function () {
  164. expect(document.body.querySelectorAll('.datepicker').length, 'to be', 0);
  165. });
  166. it('removes the instance from the bound element', function () {
  167. expect(Object.prototype.hasOwnProperty.call(input, 'datepicker'), 'to be false');
  168. });
  169. it('removes datepicker-input class from the bound element', function () {
  170. expect(input.classList.contains('datepicker-input'), 'to be false');
  171. });
  172. it('returns the instance', function () {
  173. expect(returnVal, 'to be', dp);
  174. });
  175. });
  176. describe('show()', function () {
  177. let input;
  178. let dp;
  179. let dpElem;
  180. before(function () {
  181. input = document.createElement('input');
  182. testContainer.appendChild(input);
  183. dp = new Datepicker(input);
  184. dpElem = document.querySelector('.datepicker');
  185. dp.show();
  186. });
  187. after(function () {
  188. dp.destroy();
  189. testContainer.removeChild(input);
  190. });
  191. it('adds the "active" class to the datepicker element', function () {
  192. expect(dpElem.classList.contains('active'), 'to be true');
  193. });
  194. it('sets true to the picker.active property', function () {
  195. expect(dp.picker.active, 'to be true');
  196. });
  197. });
  198. describe('hide()', function () {
  199. let input;
  200. let dp;
  201. let dpElem;
  202. before(function () {
  203. input = document.createElement('input');
  204. testContainer.appendChild(input);
  205. dp = new Datepicker(input);
  206. dpElem = document.querySelector('.datepicker');
  207. dp.picker.active = true;
  208. dpElem.classList.add('active');
  209. dp.hide();
  210. });
  211. after(function () {
  212. dp.destroy();
  213. testContainer.removeChild(input);
  214. });
  215. it('removes the "active" class from the datepicker element', function () {
  216. expect(dpElem.classList.contains('active'), 'to be false');
  217. });
  218. it('deletes the "picker.active" property', function () {
  219. expect(dp.picker, 'to have property', 'active');
  220. });
  221. });
  222. describe('static formatDate()', function () {
  223. it('formats a date or time value', function () {
  224. Datepicker.locales.es = esLocale;
  225. let date = new Date(2020, 0, 4);
  226. expect(Datepicker.formatDate(date, 'y-m-d'), 'to be', '2020-1-4');
  227. expect(Datepicker.formatDate(date.getTime(), 'dd M yy'), 'to be', '04 Jan 20');
  228. expect(Datepicker.formatDate(date, 'dd M yy', 'es'), 'to be', '04 Ene 20');
  229. expect(Datepicker.formatDate(date.getTime(), 'MM d, y', 'es'), 'to be', 'Enero 4, 2020');
  230. delete Datepicker.locales.es;
  231. // fallback to en
  232. expect(Datepicker.formatDate(date, 'dd M yy', 'es'), 'to be', '04 Jan 20');
  233. expect(Datepicker.formatDate(date.getTime(), 'MM d, y', 'es'), 'to be', 'January 4, 2020');
  234. });
  235. });
  236. describe('static parseDate()', function () {
  237. it('parses a date string and returnes the time value of the date', function () {
  238. Datepicker.locales.es = esLocale;
  239. let timeValue = new Date(2020, 0, 4).getTime();
  240. expect(Datepicker.parseDate('2020-1-4', 'y-m-d'), 'to be', timeValue);
  241. expect(Datepicker.parseDate('04 Jan 2020', 'dd M yy'), 'to be', timeValue);
  242. expect(Datepicker.parseDate('04 Ene 2020', 'dd M yy', 'es'), 'to be', timeValue);
  243. expect(Datepicker.parseDate('Enero 4, 2020', 'MM d, y', 'es'), 'to be', timeValue);
  244. expect(Datepicker.parseDate('04/20/2022', 'mm/dd/yyyy'), 'to equal', new Date(2022, 3, 20).getTime());
  245. expect(Datepicker.parseDate('5/3/1994', 'd/m/y'), 'to equal', new Date(1994, 2, 5).getTime());
  246. delete Datepicker.locales.es;
  247. // fallback to en
  248. const fallbackDate = new Date(timeValue).setMonth(new Date().getMonth());
  249. expect(Datepicker.parseDate('04 Ene 2020', 'dd M yy', 'es'), 'to be', fallbackDate);
  250. expect(Datepicker.parseDate('Enero 4, 2020', 'MM d, y', 'es'), 'to be', fallbackDate);
  251. expect(Datepicker.parseDate('04 Jan 2020', 'dd M yy', 'es'), 'to be', timeValue);
  252. expect(Datepicker.parseDate('2020-1-4', 'y-m-d', 'es'), 'to be', timeValue);
  253. });
  254. });
  255. });