select.spec.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  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('visible event', done => {
  200. vm = createVue({
  201. template: `
  202. <div>
  203. <el-select v-model="value" @visible-change="handleVisibleChange">
  204. <el-option
  205. v-for="item in options"
  206. :label="item.label"
  207. :value="item.value">
  208. </el-option>
  209. </el-select>
  210. </div>
  211. `,
  212. data() {
  213. return {
  214. options: [],
  215. value: '',
  216. visible: ''
  217. };
  218. },
  219. methods: {
  220. handleVisibleChange(val) {
  221. this.visible = val;
  222. }
  223. }
  224. }, true);
  225. vm.$children[0].visible = true;
  226. setTimeout(() => {
  227. expect(vm.visible).to.true;
  228. done();
  229. }, 50);
  230. });
  231. it('keyboard operations', done => {
  232. vm = getSelectVm();
  233. const select = vm.$children[0];
  234. let i = 8;
  235. while (i--) {
  236. select.navigateOptions('next');
  237. }
  238. select.navigateOptions('prev');
  239. setTimeout(() => {
  240. expect(select.hoverIndex).to.equal(0);
  241. select.selectOption();
  242. setTimeout(() => {
  243. expect(select.value).to.equal('选项1');
  244. done();
  245. }, 100);
  246. }, 100);
  247. });
  248. it('clearable', done => {
  249. vm = getSelectVm({ clearable: true });
  250. const select = vm.$children[0];
  251. vm.value = '选项1';
  252. select.inputHovering = true;
  253. setTimeout(() => {
  254. const icon = vm.$el.querySelector('.el-input__icon');
  255. expect(icon.classList.contains('el-icon-circle-close')).to.true;
  256. icon.click();
  257. expect(vm.value).to.equal('');
  258. done();
  259. }, 100);
  260. });
  261. it('custom el-option template', () => {
  262. vm = createVue({
  263. template: `
  264. <div>
  265. <el-select v-model="value">
  266. <el-option
  267. v-for="item in options"
  268. :label="item.label"
  269. :value="item.value">
  270. <p>{{item.label}} {{item.value}}</p>
  271. </el-option>
  272. </el-select>
  273. </div>
  274. `,
  275. data() {
  276. return {
  277. options: [{
  278. value: 'value',
  279. label: 'label'
  280. }],
  281. value: ''
  282. };
  283. }
  284. }, true);
  285. expect(vm.$el.querySelector('.el-select-dropdown__item p').textContent).to.equal('label value');
  286. });
  287. it('option group', () => {
  288. vm = createVue({
  289. template: `
  290. <div>
  291. <el-select v-model="value">
  292. <el-option-group
  293. v-for="group in options"
  294. :disabled="group.disabled"
  295. :label="group.label">
  296. <el-option
  297. v-for="item in group.options"
  298. :label="item.label"
  299. :value="item.value">
  300. </el-option>
  301. </el-option-group>
  302. </el-select>
  303. </div>
  304. `,
  305. data() {
  306. return {
  307. options: [{
  308. label: '热门城市',
  309. options: [{
  310. value: 'Shanghai',
  311. label: '上海'
  312. }, {
  313. value: 'Beijing',
  314. label: '北京'
  315. }]
  316. }, {
  317. label: '城市名',
  318. disabled: true,
  319. options: [{
  320. value: 'Chengdu',
  321. label: '成都'
  322. }, {
  323. value: 'Shenzhen',
  324. label: '深圳'
  325. }, {
  326. value: 'Guangzhou',
  327. label: '广州'
  328. }, {
  329. value: 'Dalian',
  330. label: '大连'
  331. }]
  332. }],
  333. value: ''
  334. };
  335. }
  336. }, true);
  337. const groups = vm.$el.querySelectorAll('.el-select-group__wrap');
  338. const options = groups[1].querySelectorAll('.el-select-dropdown__item');
  339. expect(groups.length).to.equal(2);
  340. expect(options.length).to.equal(4);
  341. expect(options[0].querySelector('span').textContent).to.equal('成都');
  342. });
  343. it('filterable', done => {
  344. vm = getSelectVm({ filterable: true });
  345. const select = vm.$children[0];
  346. select.selectedLabel = '面';
  347. select.onInputChange();
  348. select.visible = true;
  349. setTimeout(() => {
  350. expect(select.filteredOptionsCount).to.equal(1);
  351. done();
  352. }, 100);
  353. });
  354. it('filterable with custom filter-method', done => {
  355. const filterMethod = vm => {
  356. return query => {
  357. vm.options = vm.options.filter(option => option.label.indexOf(query) === -1);
  358. };
  359. };
  360. vm = getSelectVm({ filterable: true, filterMethod });
  361. const select = vm.$children[0];
  362. select.query = '面';
  363. setTimeout(() => {
  364. expect(select.filteredOptionsCount).to.equal(4);
  365. done();
  366. }, 100);
  367. });
  368. it('allow create', done => {
  369. vm = getSelectVm({ filterable: true, allowCreate: true });
  370. const select = vm.$children[0];
  371. select.selectedLabel = 'new';
  372. select.onInputChange();
  373. select.visible = true;
  374. setTimeout(() => {
  375. const options = document.querySelectorAll('.el-select-dropdown__item span');
  376. const target = [].filter.call(options, option => option.innerText === 'new');
  377. target[0].click();
  378. setTimeout(() => {
  379. expect(select.value.indexOf('new') > -1).to.true;
  380. done();
  381. }, 50);
  382. }, 50);
  383. });
  384. it('multiple select', done => {
  385. vm = getSelectVm({ multiple: true });
  386. const options = vm.$el.querySelectorAll('.el-select-dropdown__item');
  387. vm.value = ['选项1'];
  388. setTimeout(() => {
  389. options[1].click();
  390. options[3].click();
  391. setTimeout(() => {
  392. expect(vm.value.indexOf('选项2') > -1 && vm.value.indexOf('选项4') > -1).to.true;
  393. const tagCloseIcons = vm.$el.querySelectorAll('.el-tag__close');
  394. tagCloseIcons[0].click();
  395. setTimeout(() => {
  396. expect(vm.value.indexOf('选项1')).to.equal(-1);
  397. done();
  398. }, 100);
  399. }, 100);
  400. }, 100);
  401. });
  402. it('multiple limit', done => {
  403. vm = getSelectVm({ multiple: true, multipleLimit: 1 });
  404. const options = vm.$el.querySelectorAll('.el-select-dropdown__item');
  405. options[1].click();
  406. setTimeout(() => {
  407. expect(vm.value.indexOf('选项2') > -1).to.true;
  408. options[3].click();
  409. setTimeout(() => {
  410. expect(vm.value.indexOf('选项4')).to.equal(-1);
  411. done();
  412. }, 50);
  413. }, 50);
  414. });
  415. it('multiple remote search', done => {
  416. const remoteMethod = vm => {
  417. return query => {
  418. vm.loading = true;
  419. setTimeout(() => {
  420. vm.options = vm.options.filter(option => {
  421. return option.label.indexOf(query) > -1;
  422. });
  423. vm.loading = false;
  424. }, 200);
  425. };
  426. };
  427. vm = getSelectVm({
  428. multiple: true,
  429. remote: true,
  430. filterable: true,
  431. remoteMethod
  432. });
  433. const select = vm.$children[0];
  434. vm.$nextTick(() => {
  435. select.query = '面';
  436. setTimeout(() => {
  437. expect(select.filteredOptionsCount).to.equal(1);
  438. select.query = '';
  439. select.options[0].$el.click();
  440. vm.$nextTick(() => {
  441. expect(vm.value[0]).to.equal('选项4');
  442. select.deletePrevTag({ target: select.$refs.input });
  443. select.deletePrevTag({ target: select.$refs.input });
  444. select.resetInputState({ keyCode: 1 });
  445. vm.$nextTick(() => {
  446. expect(vm.value.length).to.equal(0);
  447. done();
  448. });
  449. });
  450. }, 250);
  451. });
  452. });
  453. });