select.spec.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. import { createTest, createVue, triggerEvent, destroyVM } from '../util';
  2. import Select from 'packages/select';
  3. describe('Select', () => {
  4. const getSelectVm = (configs = {}, options) => {
  5. ['multiple', 'clearable', 'filterable', 'allowCreate', 'remote'].forEach(config => {
  6. configs[config] = configs[config] || false;
  7. });
  8. configs.multipleLimit = configs.multipleLimit || 0;
  9. if (!options) {
  10. options = [{
  11. value: '选项1',
  12. label: '黄金糕',
  13. disabled: false
  14. }, {
  15. value: '选项2',
  16. label: '双皮奶',
  17. disabled: false
  18. }, {
  19. value: '选项3',
  20. label: '蚵仔煎',
  21. disabled: false
  22. }, {
  23. value: '选项4',
  24. label: '龙须面',
  25. disabled: false
  26. }, {
  27. value: '选项5',
  28. label: '北京烤鸭',
  29. disabled: false
  30. }];
  31. }
  32. const vm = createVue({
  33. template: `
  34. <div>
  35. <el-select
  36. v-model="value"
  37. :multiple="multiple"
  38. :multiple-limit="multipleLimit"
  39. :clearable="clearable"
  40. :filterable="filterable"
  41. :allow-create="allowCreate"
  42. :filterMethod="filterMethod"
  43. :remote="remote"
  44. :loading="loading"
  45. :remoteMethod="remoteMethod">
  46. <el-option
  47. v-for="item in options"
  48. :label="item.label"
  49. :disabled="item.disabled"
  50. :value="item.value">
  51. </el-option>
  52. </el-select>
  53. </div>
  54. `,
  55. data() {
  56. return {
  57. options,
  58. multiple: configs.multiple,
  59. multipleLimit: configs.multipleLimit,
  60. clearable: configs.clearable,
  61. filterable: configs.filterable,
  62. allowCreate: configs.allowCreate,
  63. loading: false,
  64. filterMethod: configs.filterMethod && configs.filterMethod(this),
  65. remote: configs.remote,
  66. remoteMethod: configs.remoteMethod && configs.remoteMethod(this),
  67. value: configs.multiple ? [] : ''
  68. };
  69. }
  70. }, true);
  71. return vm;
  72. };
  73. let vm;
  74. afterEach(() => {
  75. destroyVM(vm);
  76. });
  77. it('create', () => {
  78. vm = createTest(Select, true);
  79. expect(vm.$el.className).to.equal('el-select');
  80. expect(vm.$el.querySelector('.el-input__inner').placeholder).to.equal('请选择');
  81. vm.toggleMenu();
  82. expect(vm.visible).to.true;
  83. });
  84. it('options rendered correctly', () => {
  85. vm = getSelectVm();
  86. const options = vm.$el.querySelectorAll('.el-select-dropdown__item');
  87. const result = [].every.call(options, (option, index) => {
  88. let text = option.querySelector('span').textContent;
  89. return text === vm.options[index].label;
  90. });
  91. expect(result).to.true;
  92. });
  93. it('default value', done => {
  94. vm = createVue({
  95. template: `
  96. <div>
  97. <el-select v-model="value">
  98. <el-option
  99. v-for="item in options"
  100. :label="item.label"
  101. :value="item.value">
  102. </el-option>
  103. </el-select>
  104. </div>
  105. `,
  106. data() {
  107. return {
  108. options: [{
  109. value: '选项1',
  110. label: '黄金糕'
  111. }, {
  112. value: '选项2',
  113. label: '双皮奶'
  114. }],
  115. value: '选项2'
  116. };
  117. }
  118. }, true);
  119. setTimeout(() => {
  120. expect(vm.$el.querySelector('.el-input__inner').value).to.equal('双皮奶');
  121. done();
  122. }, 100);
  123. });
  124. it('single select', done => {
  125. sinon.stub(window.console, 'log');
  126. vm = createVue({
  127. template: `
  128. <div>
  129. <el-select v-model="value" @change="handleChange">
  130. <el-option
  131. v-for="item in options"
  132. :label="item.label"
  133. :value="item.value">
  134. <p>{{item.label}} {{item.value}}</p>
  135. </el-option>
  136. </el-select>
  137. </div>
  138. `,
  139. data() {
  140. return {
  141. options: [{
  142. value: '选项1',
  143. label: '黄金糕'
  144. }, {
  145. value: '选项2',
  146. label: '双皮奶'
  147. }, {
  148. value: '选项3',
  149. label: '蚵仔煎'
  150. }, {
  151. value: '选项4',
  152. label: '龙须面'
  153. }, {
  154. value: '选项5',
  155. label: '北京烤鸭'
  156. }],
  157. value: ''
  158. };
  159. },
  160. methods: {
  161. handleChange() {
  162. console.log('changed');
  163. }
  164. }
  165. }, true);
  166. const options = vm.$el.querySelectorAll('.el-select-dropdown__item');
  167. expect(vm.value).to.equal('');
  168. triggerEvent(options[2], 'mouseenter');
  169. options[2].click();
  170. setTimeout(() => {
  171. expect(vm.value).to.equal('选项3');
  172. expect(window.console.log.callCount).to.equal(1);
  173. options[4].click();
  174. setTimeout(() => {
  175. expect(vm.value).to.equal('选项5');
  176. expect(window.console.log.callCount).to.equal(2);
  177. window.console.log.restore();
  178. done();
  179. }, 100);
  180. }, 100);
  181. });
  182. it('disabled option', done => {
  183. vm = getSelectVm();
  184. vm.options[1].disabled = true;
  185. setTimeout(() => {
  186. const options = vm.$el.querySelectorAll('.el-select-dropdown__item');
  187. expect(options[1].classList.contains('is-disabled')).to.true;
  188. options[1].click();
  189. setTimeout(() => {
  190. expect(vm.value).to.equal('');
  191. done();
  192. }, 100);
  193. }, 100);
  194. });
  195. it('disabled select', () => {
  196. vm = createTest(Select, { disabled: true }, true);
  197. expect(vm.$el.querySelector('.el-input').classList.contains('is-disabled')).to.true;
  198. });
  199. it('keyboard operations', done => {
  200. vm = getSelectVm();
  201. const select = vm.$children[0];
  202. let i = 8;
  203. while (i--) {
  204. select.navigateOptions('next');
  205. }
  206. select.navigateOptions('prev');
  207. setTimeout(() => {
  208. expect(select.hoverIndex).to.equal(0);
  209. select.selectOption();
  210. setTimeout(() => {
  211. expect(select.value).to.equal('选项1');
  212. done();
  213. }, 100);
  214. }, 100);
  215. });
  216. it('clearable', done => {
  217. vm = getSelectVm({ clearable: true });
  218. const select = vm.$children[0];
  219. vm.value = '选项1';
  220. select.inputHovering = true;
  221. setTimeout(() => {
  222. const icon = vm.$el.querySelector('.el-input__icon');
  223. expect(icon.classList.contains('el-icon-circle-close')).to.true;
  224. icon.click();
  225. expect(vm.value).to.equal('');
  226. done();
  227. }, 100);
  228. });
  229. it('custom el-option template', () => {
  230. vm = createVue({
  231. template: `
  232. <div>
  233. <el-select v-model="value">
  234. <el-option
  235. v-for="item in options"
  236. :label="item.label"
  237. :value="item.value">
  238. <p>{{item.label}} {{item.value}}</p>
  239. </el-option>
  240. </el-select>
  241. </div>
  242. `,
  243. data() {
  244. return {
  245. options: [{
  246. value: 'value',
  247. label: 'label'
  248. }],
  249. value: ''
  250. };
  251. }
  252. }, true);
  253. expect(vm.$el.querySelector('.el-select-dropdown__item p').textContent).to.equal('label value');
  254. });
  255. it('option group', () => {
  256. vm = createVue({
  257. template: `
  258. <div>
  259. <el-select v-model="value">
  260. <el-option-group
  261. v-for="group in options"
  262. :disabled="group.disabled"
  263. :label="group.label">
  264. <el-option
  265. v-for="item in group.options"
  266. :label="item.label"
  267. :value="item.value">
  268. </el-option>
  269. </el-option-group>
  270. </el-select>
  271. </div>
  272. `,
  273. data() {
  274. return {
  275. options: [{
  276. label: '热门城市',
  277. options: [{
  278. value: 'Shanghai',
  279. label: '上海'
  280. }, {
  281. value: 'Beijing',
  282. label: '北京'
  283. }]
  284. }, {
  285. label: '城市名',
  286. disabled: true,
  287. options: [{
  288. value: 'Chengdu',
  289. label: '成都'
  290. }, {
  291. value: 'Shenzhen',
  292. label: '深圳'
  293. }, {
  294. value: 'Guangzhou',
  295. label: '广州'
  296. }, {
  297. value: 'Dalian',
  298. label: '大连'
  299. }]
  300. }],
  301. value: ''
  302. };
  303. }
  304. }, true);
  305. const groups = vm.$el.querySelectorAll('.el-select-group__wrap');
  306. const options = groups[1].querySelectorAll('.el-select-dropdown__item');
  307. expect(groups.length).to.equal(2);
  308. expect(options.length).to.equal(4);
  309. expect(options[0].querySelector('span').textContent).to.equal('成都');
  310. });
  311. it('filterable', done => {
  312. vm = getSelectVm({ filterable: true });
  313. const select = vm.$children[0];
  314. select.selectedLabel = '面';
  315. select.onInputChange();
  316. select.visible = true;
  317. setTimeout(() => {
  318. expect(select.filteredOptionsCount).to.equal(1);
  319. done();
  320. }, 100);
  321. });
  322. it('filterable with custom filter-method', done => {
  323. const filterMethod = vm => {
  324. return query => {
  325. vm.options = vm.options.filter(option => option.label.indexOf(query) === -1);
  326. };
  327. };
  328. vm = getSelectVm({ filterable: true, filterMethod });
  329. const select = vm.$children[0];
  330. select.query = '面';
  331. setTimeout(() => {
  332. expect(select.filteredOptionsCount).to.equal(4);
  333. done();
  334. }, 100);
  335. });
  336. it('allow create', done => {
  337. vm = getSelectVm({ filterable: true, allowCreate: true });
  338. const select = vm.$children[0];
  339. select.selectedLabel = 'new';
  340. select.onInputChange();
  341. select.visible = true;
  342. setTimeout(() => {
  343. const options = document.querySelectorAll('.el-select-dropdown__item span');
  344. const target = [].filter.call(options, option => option.innerText === 'new');
  345. target[0].click();
  346. setTimeout(() => {
  347. expect(select.value.indexOf('new') > -1).to.true;
  348. done();
  349. }, 50);
  350. }, 50);
  351. });
  352. it('multiple select', done => {
  353. vm = getSelectVm({ multiple: true });
  354. const options = vm.$el.querySelectorAll('.el-select-dropdown__item');
  355. vm.value = ['选项1'];
  356. setTimeout(() => {
  357. options[1].click();
  358. options[3].click();
  359. setTimeout(() => {
  360. expect(vm.value.indexOf('选项2') > -1 && vm.value.indexOf('选项4') > -1).to.true;
  361. const tagCloseIcons = vm.$el.querySelectorAll('.el-tag__close');
  362. tagCloseIcons[0].click();
  363. setTimeout(() => {
  364. expect(vm.value.indexOf('选项1')).to.equal(-1);
  365. done();
  366. }, 100);
  367. }, 100);
  368. }, 100);
  369. });
  370. it('multiple limit', done => {
  371. vm = getSelectVm({ multiple: true, multipleLimit: 1 });
  372. const options = vm.$el.querySelectorAll('.el-select-dropdown__item');
  373. options[1].click();
  374. setTimeout(() => {
  375. expect(vm.value.indexOf('选项2') > -1).to.true;
  376. options[3].click();
  377. setTimeout(() => {
  378. expect(vm.value.indexOf('选项4')).to.equal(-1);
  379. done();
  380. }, 50);
  381. }, 50);
  382. });
  383. it('multiple remote search', done => {
  384. const remoteMethod = vm => {
  385. return query => {
  386. vm.loading = true;
  387. setTimeout(() => {
  388. vm.options = vm.options.filter(option => {
  389. return option.label.indexOf(query) > -1;
  390. });
  391. vm.loading = false;
  392. }, 200);
  393. };
  394. };
  395. vm = getSelectVm({
  396. multiple: true,
  397. remote: true,
  398. filterable: true,
  399. remoteMethod
  400. });
  401. const select = vm.$children[0];
  402. vm.$nextTick(() => {
  403. select.query = '面';
  404. setTimeout(() => {
  405. expect(select.filteredOptionsCount).to.equal(1);
  406. select.query = '';
  407. select.options[0].$el.click();
  408. vm.$nextTick(() => {
  409. expect(vm.value[0]).to.equal('选项4');
  410. select.deletePrevTag({ target: select.$refs.input });
  411. select.deletePrevTag({ target: select.$refs.input });
  412. select.resetInputState({ keyCode: 1 });
  413. vm.$nextTick(() => {
  414. expect(vm.value.length).to.equal(0);
  415. done();
  416. });
  417. });
  418. }, 250);
  419. });
  420. });
  421. });