select.spec.js 11 KB

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