DateRangePicker.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. import './_setup.js';
  2. import DateRangePicker from '../../js/DateRangePicker.js';
  3. import {parseHTML} from '../../js/lib/dom.js';
  4. // to spy constructor with sinon, import entire module
  5. // @see: https://github.com/sinonjs/sinon/issues/1358#issuecomment-391643741
  6. import * as DP from '../../js/Datepicker.js';
  7. const Datepicker = DP.default;
  8. describe('DateRangePicker', function () {
  9. let elem;
  10. let input0;
  11. let input1;
  12. beforeEach(function () {
  13. elem = parseHTML('<div><input><input></div>').firstChild;
  14. [input0, input1] = elem.children;
  15. testContainer.appendChild(elem);
  16. });
  17. afterEach(function () {
  18. document.querySelectorAll('.datepicker').forEach((el) => {
  19. el.parentElement.removeChild(el);
  20. });
  21. delete input0.datepicker;
  22. delete input1.datepicker;
  23. delete elem.rangepicker;
  24. testContainer.removeChild(elem);
  25. });
  26. describe('constructor', function () {
  27. it('attachs the created instance to the bound element', function () {
  28. const drp = new DateRangePicker(elem);
  29. expect(elem.rangepicker, 'to be', drp);
  30. });
  31. it('configures the instance with the default values', function () {
  32. let drp = new DateRangePicker(elem);
  33. expect(drp.allowOneSidedRange, 'to be false');
  34. });
  35. it('creates datepicker for the inputs passing rangepicker and given options expect', function () {
  36. const spyDPConstructor = sinon.spy(DP, 'default');
  37. let drp = new DateRangePicker(elem);
  38. expect(spyDPConstructor.args, 'to equal', [
  39. [input0, {}, drp],
  40. [input1, {}, drp],
  41. ]);
  42. expect(input0.datepicker, 'to be a', Datepicker);
  43. expect(input1.datepicker, 'to be a', Datepicker);
  44. expect([input0.datepicker, input1.datepicker], 'to equal', drp.datepickers);
  45. spyDPConstructor.resetHistory();
  46. delete input0.datepicker;
  47. delete input1.datepicker;
  48. delete elem.rangepicker;
  49. const fakeOptions = {foo: 123, bar: 456};
  50. drp = new DateRangePicker(elem, fakeOptions);
  51. expect(spyDPConstructor.args, 'to equal', [
  52. [input0, fakeOptions, drp],
  53. [input1, fakeOptions, drp],
  54. ]);
  55. spyDPConstructor.restore();
  56. });
  57. it('makes datepickers property read-only/immutable', function () {
  58. const drp = new DateRangePicker(elem);
  59. expect(() => { drp.datepickers = []; }, 'to throw a', TypeError);
  60. expect(() => { drp.datepickers[0] = null; }, 'to throw a', TypeError);
  61. expect(() => { drp.datepickers[2] = {}; }, 'to throw a', TypeError);
  62. });
  63. it('excludes inputs, allowOneSidedRange and maxNumberOfDates from options to pass Datepicker container', function () {
  64. const spyDPConstructor = sinon.spy(DP, 'default');
  65. new DateRangePicker(elem, {
  66. inputs: [input0, input1],
  67. allowOneSidedRange: false,
  68. maxNumberOfDates: 2,
  69. foo: 123,
  70. });
  71. expect(spyDPConstructor.args[0][1], 'to equal', {foo: 123});
  72. spyDPConstructor.restore();
  73. });
  74. it('works with arbitrary input elements if they are provided in the inputs option', function () {
  75. const outsideEl = document.createElement('div');
  76. const drp = new DateRangePicker(outsideEl, {inputs: [input0, input1]});
  77. expect(outsideEl.rangepicker, 'to be', drp);
  78. expect(input0.datepicker.rangepicker, 'to be', drp);
  79. expect(input1.datepicker.rangepicker, 'to be', drp);
  80. expect([input0.datepicker, input1.datepicker], 'to equal', drp.datepickers);
  81. });
  82. it('append datepicker elements to the container)', function () {
  83. new DateRangePicker(elem);
  84. const dpElems = Array.from(document.body.children).filter(el => el.matches('.datepicker'));
  85. expect(dpElems, 'to have length', 2);
  86. });
  87. it('does not add the active class to the picker elements', function () {
  88. new DateRangePicker(elem);
  89. const dpElems = Array.from(document.querySelectorAll('.datepicker'));
  90. expect(dpElems.filter(el => el.classList.contains('active')), 'to be empty');
  91. });
  92. it('does nothing but creating an instance if number of inputs < 2', function () {
  93. elem.removeChild(input1);
  94. let drp = new DateRangePicker(elem);
  95. expect(elem, 'not to have property', 'rangepicker');
  96. expect(drp, 'not to have properties', ['inputs', 'datepickers']);
  97. expect(input0, 'not to have property', 'datepicker');
  98. expect(document.querySelectorAll('.datepicker').length, 'to be', 0);
  99. const outsideEl = document.createElement('div');
  100. drp = new DateRangePicker(outsideEl, {inputs: [input0]});
  101. expect(outsideEl, 'not to have property', 'rangepicker');
  102. expect(input0, 'not to have property', 'datepicker');
  103. expect(document.querySelectorAll('.datepicker').length, 'to be', 0);
  104. });
  105. });
  106. describe('destroy()', function () {
  107. let drp;
  108. let spyDestroy0;
  109. let spyDestroy1;
  110. beforeEach(function () {
  111. drp = new DateRangePicker(elem);
  112. spyDestroy0 = sinon.spy(input0.datepicker, 'destroy');
  113. spyDestroy1 = sinon.spy(input1.datepicker, 'destroy');
  114. });
  115. afterEach(function () {
  116. spyDestroy0.restore();
  117. spyDestroy1.restore();
  118. });
  119. it('calls destroy() of each datepickers', function () {
  120. drp.destroy();
  121. expect(spyDestroy0.called, 'to be true');
  122. expect(spyDestroy1.called, 'to be true');
  123. });
  124. it('removes the instance from the bound element', function () {
  125. drp.destroy();
  126. expect(Object.prototype.hasOwnProperty.call(elem, 'rangepicker'), 'to be false');
  127. });
  128. });
  129. describe('dates property', function () {
  130. it('contains the array of the inputs\' selected dates', function () {
  131. const drp = new DateRangePicker(elem);
  132. expect(drp.dates, 'to equal', [undefined, undefined]);
  133. const date0 = new Date(2020, 3, 20).setHours(0, 0, 0, 0);
  134. const date1 = new Date(2020, 3, 22).setHours(0, 0, 0, 0);
  135. drp.datepickers[0].dates = [date0];
  136. drp.datepickers[1].dates = [date1];
  137. expect(drp.dates, 'to equal', [date0, date1]);
  138. });
  139. });
  140. describe('setOptions()', function () {
  141. it('updates allowOneSidedRange but ignores inputs if they are in the given options', function () {
  142. const input2 = document.createElement('input');
  143. const drp = new DateRangePicker(elem);
  144. drp.setOptions({allowOneSidedRange: true, inputs: [input2, input0]});
  145. expect(drp.allowOneSidedRange, 'to be true');
  146. expect(drp.inputs, 'to equal', [input0, input1]);
  147. });
  148. it('calls each datepicker\'s setOptions() with given options except inputs, allowOneSidedRange and maxNumberOfDates', function () {
  149. const drp = new DateRangePicker(elem);
  150. const stubDP0SetOptions = sinon.stub(drp.datepickers[0], 'setOptions').callsFake(() => {});
  151. const stubDP1SetOptions = sinon.stub(drp.datepickers[1], 'setOptions').callsFake(() => {});
  152. drp.setOptions({inputs: [], allowOneSidedRange: true, maxNumberOfDates: 2, foo: 123, bar: 456});
  153. expect(stubDP0SetOptions.args, 'to equal', [[{foo: 123, bar: 456}]]);
  154. expect(stubDP1SetOptions.args, 'to equal', [[{foo: 123, bar: 456}]]);
  155. });
  156. });
  157. });