Commit 437b8059d38ada7e913f105f0f691438c7e5bcf8

Authored by Sergio Crisostomo
1 parent fb847998

Added Table to CSV example and tests

examples/routers/table.vue
... ... @@ -164,43 +164,47 @@
164 164 <div class="layout" :class="{'layout-hide-text': spanLeft < 5}">
165 165 <Row type="flex">
166 166 <Col :span="spanLeft" class="layout-menu-left">
167   - <Menu active-name="1" theme="dark" width="auto">
168   - <div class="layout-logo-left"></div>
169   - <MenuItem name="1">
170   - <Icon type="ios-navigate" :size="iconSize"></Icon>
171   - <span class="layout-text">选项 1</span>
172   - </MenuItem>
173   - <MenuItem name="2">
174   - <Icon type="ios-keypad" :size="iconSize"></Icon>
175   - <span class="layout-text">选项 2</span>
176   - </MenuItem>
177   - <MenuItem name="3">
178   - <Icon type="ios-analytics" :size="iconSize"></Icon>
179   - <span class="layout-text">选项 3</span>
180   - </MenuItem>
181   - </Menu>
  167 + <Menu active-name="1" theme="dark" width="auto">
  168 + <div class="layout-logo-left"></div>
  169 + <MenuItem name="1">
  170 + <Icon type="ios-navigate" :size="iconSize"></Icon>
  171 + <span class="layout-text">选项 1</span>
  172 + </MenuItem>
  173 + <MenuItem name="2">
  174 + <Icon type="ios-keypad" :size="iconSize"></Icon>
  175 + <span class="layout-text">选项 2</span>
  176 + </MenuItem>
  177 + <MenuItem name="3">
  178 + <Icon type="ios-analytics" :size="iconSize"></Icon>
  179 + <span class="layout-text">选项 3</span>
  180 + </MenuItem>
  181 + </Menu>
182 182 </Col>
183 183 <Col :span="spanRight">
184   - <div class="layout-header">
185   - <Button type="text" @click="toggleClick">
186   - <Icon type="navicon" size="32"></Icon>
187   - </Button>
188   - </div>
189   - <div class="layout-breadcrumb">
190   - <Breadcrumb>
191   - <BreadcrumbItem href="#">首页</BreadcrumbItem>
192   - <BreadcrumbItem href="#">应用中心</BreadcrumbItem>
193   - <BreadcrumbItem>某应用</BreadcrumbItem>
194   - </Breadcrumb>
195   - </div>
196   - <div class="layout-content">
197   - <div class="layout-content-main">
198   - <Table stripe :columns="columns1" :data="data1"></Table>
  184 + <div class="layout-header">
  185 + <Button type="text" @click="toggleClick">
  186 + <Icon type="navicon" size="32"></Icon>
  187 + </Button>
  188 + </div>
  189 + <div class="layout-breadcrumb">
  190 + <Breadcrumb>
  191 + <BreadcrumbItem href="#">首页</BreadcrumbItem>
  192 + <BreadcrumbItem href="#">应用中心</BreadcrumbItem>
  193 + <BreadcrumbItem>某应用</BreadcrumbItem>
  194 + </Breadcrumb>
  195 + </div>
  196 + <div class="layout-content">
  197 + <div class="layout-content-main">
  198 + <Table stripe :columns="columns1" :data="data1"></Table>
  199 + </div>
  200 + <hr style="margin: 10px 0;" />
  201 + <div class="layout-content-main">
  202 + <Table stripe :columns="columns2" :data="data2" ref="csvTable" />
  203 + <i-button type="primary" size="large" @click="exportCSV">
  204 + <icon type="ios-download-outline"></icon> Export to CSV
  205 + </i-button>
  206 + </div>
199 207 </div>
200   - </div>
201   - <div class="layout-copy">
202   - 2011-2016 &copy; TalkingData
203   - </div>
204 208 </Col>
205 209 </Row>
206 210 </div>
... ... @@ -330,8 +334,44 @@
330 334 age: 26,
331 335 address: '深圳市南山区深南大道'
332 336 }
  337 + ],
  338 + columns2: [
  339 + {
  340 + title: '姓名',
  341 + key: 'name'
  342 + },
  343 + {
  344 + title: '年龄',
  345 + key: 'age'
  346 + },
  347 + {
  348 + title: '地址',
  349 + key: 'address'
  350 + }
  351 + ],
  352 + data2: [
  353 + {
  354 + name: '王小明',
  355 + age: 18,
  356 + address: '北京市朝\n阳区芍药居'
  357 + },
  358 + {
  359 + name: '张小刚',
  360 + age: 25,
  361 + address: '北京市海,淀区西二旗'
  362 + },
  363 + {
  364 + name: '李小红',
  365 + age: 30,
  366 + address: '上海市浦东\r新区世纪大道'
  367 + },
  368 + {
  369 + name: '周小伟',
  370 + age: 26,
  371 + address: '深圳市南山区深南大道'
  372 + }
333 373 ]
334   - }
  374 + };
335 375 },
336 376 computed: {
337 377 iconSize () {
... ... @@ -347,7 +387,14 @@
347 387 this.spanLeft = 5;
348 388 this.spanRight = 19;
349 389 }
  390 + },
  391 + exportCSV () {
  392 + this.$refs.csvTable.exportCsv({
  393 + filename: '原始数据',
  394 + separator: ';',
  395 + quoted: true
  396 + });
350 397 }
351 398 }
352   - }
  399 + };
353 400 </script>
... ...
test/unit/specs/assets/table/csvData.js 0 → 100644
  1 +export const csvA = {
  2 + columns: [
  3 + {
  4 + title: '名称',
  5 + key: 'name',
  6 + fixed: 'left',
  7 + width: 200
  8 + },
  9 + {
  10 + title: '展示',
  11 + key: 'show',
  12 + width: 150,
  13 + sortable: true
  14 + },
  15 + {
  16 + title: '唤醒',
  17 + key: 'weak',
  18 + width: 150,
  19 + sortable: true
  20 + },
  21 + {
  22 + title: '登录',
  23 + key: 'signin',
  24 + width: 150,
  25 + sortable: true
  26 + },
  27 + {
  28 + title: '点击',
  29 + key: 'click',
  30 + width: 150,
  31 + sortable: true
  32 + },
  33 + {
  34 + title: '激活',
  35 + key: 'active',
  36 + width: 150,
  37 + sortable: true
  38 + },
  39 + {
  40 + title: '7日留存',
  41 + key: 'day7',
  42 + width: 150,
  43 + sortable: true
  44 + },
  45 + {
  46 + title: '30日留存',
  47 + key: 'day30',
  48 + width: 150,
  49 + sortable: true
  50 + },
  51 + {
  52 + title: '次日留存',
  53 + key: 'tomorrow',
  54 + width: 150,
  55 + sortable: true
  56 + },
  57 + {
  58 + title: '日活跃',
  59 + key: 'day',
  60 + width: 150,
  61 + sortable: true
  62 + },
  63 + {
  64 + title: '周活跃',
  65 + key: 'week',
  66 + width: 150,
  67 + sortable: true
  68 + },
  69 + {
  70 + title: '月活跃',
  71 + key: 'month',
  72 + width: 150,
  73 + sortable: true
  74 + }
  75 + ],
  76 + data: [
  77 + {
  78 + name: '推广名称1',
  79 + fav: 0,
  80 + show: 7302,
  81 + weak: 5627,
  82 + signin: 1563,
  83 + click: 4254,
  84 + active: 1438,
  85 + day7: 274,
  86 + day30: 285,
  87 + tomorrow: 1727,
  88 + day: 558,
  89 + week: 4440,
  90 + month: 5610
  91 + },
  92 + {
  93 + name: '推广名称2',
  94 + fav: 0,
  95 + show: 4720,
  96 + weak: 4086,
  97 + signin: 3792,
  98 + click: 8690,
  99 + active: 8470,
  100 + day7: 8172,
  101 + day30: 5197,
  102 + tomorrow: 1684,
  103 + day: 2593,
  104 + week: 2507,
  105 + month: 1537
  106 + },
  107 + {
  108 + name: '推广名称3',
  109 + fav: 0,
  110 + show: 7181,
  111 + weak: 8007,
  112 + signin: 8477,
  113 + click: 1879,
  114 + active: 16,
  115 + day7: 2249,
  116 + day30: 3450,
  117 + tomorrow: 377,
  118 + day: 1561,
  119 + week: 3219,
  120 + month: 1588
  121 + },
  122 + {
  123 + name: '推广名称4',
  124 + fav: 0,
  125 + show: 9911,
  126 + weak: 8976,
  127 + signin: 8807,
  128 + click: 8050,
  129 + active: 7668,
  130 + day7: 1547,
  131 + day30: 2357,
  132 + tomorrow: 7278,
  133 + day: 5309,
  134 + week: 1655,
  135 + month: 9043
  136 + },
  137 + {
  138 + name: '推广名称5',
  139 + fav: 0,
  140 + show: 934,
  141 + weak: 1394,
  142 + signin: 6463,
  143 + click: 5278,
  144 + active: 9256,
  145 + day7: 209,
  146 + day30: 3563,
  147 + tomorrow: 8285,
  148 + day: 1230,
  149 + week: 4840,
  150 + month: 9908
  151 + },
  152 + {
  153 + name: '推广名称6',
  154 + fav: 0,
  155 + show: 6856,
  156 + weak: 1608,
  157 + signin: 457,
  158 + click: 4949,
  159 + active: 2909,
  160 + day7: 4525,
  161 + day30: 6171,
  162 + tomorrow: 1920,
  163 + day: 1966,
  164 + week: 904,
  165 + month: 6851
  166 + },
  167 + {
  168 + name: '推广名称7',
  169 + fav: 0,
  170 + show: 5107,
  171 + weak: 6407,
  172 + signin: 4166,
  173 + click: 7970,
  174 + active: 1002,
  175 + day7: 8701,
  176 + day30: 9040,
  177 + tomorrow: 7632,
  178 + day: 4061,
  179 + week: 4359,
  180 + month: 3676
  181 + },
  182 + {
  183 + name: '推广名称8',
  184 + fav: 0,
  185 + show: 862,
  186 + weak: 6520,
  187 + signin: 6696,
  188 + click: 3209,
  189 + active: 6801,
  190 + day7: 6364,
  191 + day30: 6850,
  192 + tomorrow: 9408,
  193 + day: 2481,
  194 + week: 1479,
  195 + month: 2346
  196 + },
  197 + {
  198 + name: '推广名称9',
  199 + fav: 0,
  200 + show: 567,
  201 + weak: 5859,
  202 + signin: 128,
  203 + click: 6593,
  204 + active: 1971,
  205 + day7: 7596,
  206 + day30: 3546,
  207 + tomorrow: 6641,
  208 + day: 1611,
  209 + week: 5534,
  210 + month: 3190
  211 + },
  212 + {
  213 + name: '推广名称10',
  214 + fav: 0,
  215 + show: 3651,
  216 + weak: 1819,
  217 + signin: 4595,
  218 + click: 7499,
  219 + active: 7405,
  220 + day7: 8710,
  221 + day30: 5518,
  222 + tomorrow: 428,
  223 + day: 9768,
  224 + week: 2864,
  225 + month: 5811
  226 + }
  227 + ],
  228 + expected: `
  229 + 名称,展示,唤醒,登录,点击,激活,7日留存,30日留存,次日留存,日活跃,周活跃,月活跃
  230 + 推广名称1,7302,5627,1563,4254,1438,274,285,1727,558,4440,5610
  231 + 推广名称2,4720,4086,3792,8690,8470,8172,5197,1684,2593,2507,1537
  232 + 推广名称3,7181,8007,8477,1879,16,2249,3450,377,1561,3219,1588
  233 + 推广名称4,9911,8976,8807,8050,7668,1547,2357,7278,5309,1655,9043
  234 + 推广名称5,934,1394,6463,5278,9256,209,3563,8285,1230,4840,9908
  235 + 推广名称6,6856,1608,457,4949,2909,4525,6171,1920,1966,904,6851
  236 + 推广名称7,5107,6407,4166,7970,1002,8701,9040,7632,4061,4359,3676
  237 + 推广名称8,862,6520,6696,3209,6801,6364,6850,9408,2481,1479,2346
  238 + 推广名称9,567,5859,128,6593,1971,7596,3546,6641,1611,5534,3190
  239 + 推广名称10,3651,1819,4595,7499,7405,8710,5518,428,9768,2864,5811
  240 + `
  241 +};
  242 +
  243 +export const csvB = {
  244 + columns: [
  245 + {
  246 + title: '姓名',
  247 + key: 'name'
  248 + },
  249 + {
  250 + title: '年龄',
  251 + key: 'age'
  252 + },
  253 + {
  254 + title: '地址',
  255 + key: 'address'
  256 + }
  257 + ],
  258 + data: [
  259 + {
  260 + name: '王小明',
  261 + age: 18,
  262 + address: '北京市朝\n阳区芍药居'
  263 + },
  264 + {
  265 + name: '张小刚',
  266 + age: 25,
  267 + address: '北京市海,淀区西二旗'
  268 + },
  269 + {
  270 + name: '李小红',
  271 + age: 30,
  272 + address: '上海市浦东\r新区世纪大道'
  273 + },
  274 + {
  275 + name: '周小伟',
  276 + age: 26,
  277 + address: '深圳市南山区深南大道'
  278 + }
  279 + ],
  280 + expected: `
  281 + "姓名";"年龄";"地址"
  282 + "王小明";"18";"北京市朝\n阳区芍药居"
  283 + "张小刚";"25";"北京市海,淀区西二旗"
  284 + "李小红";"30";"上海市浦东\r新区世纪大道"
  285 + "周小伟";"26";"深圳市南山区深南大道"
  286 + `
  287 +};
... ...
test/unit/specs/table.spec.js 0 → 100644
  1 +import { createVue, destroyVM } from '../util';
  2 +import { csvA, csvB } from './assets/table/csvData.js';
  3 +
  4 +const cleanCSV = (str) => str.split('\n').map(s => s.trim()).filter(Boolean).join('\n');
  5 +
  6 +describe('Table.vue', () => {
  7 + let vm;
  8 + afterEach(() => {
  9 + destroyVM(vm);
  10 + });
  11 +
  12 + describe('CSV export', () => {
  13 + it('should export simple data to CSV - test A', done => {
  14 + vm = createVue({
  15 + template: '<div><Table :columns="columns" :data="data" ref="tableA" /></div>',
  16 + data() {
  17 + return csvA;
  18 + },
  19 + mounted() {
  20 + this.$refs.tableA.exportCsv({callback: data => {
  21 + expect(cleanCSV(data)).to.equal(cleanCSV(this.expected));
  22 + expect(cleanCSV(data).length > 0).to.equal(true);
  23 + done();
  24 + }});
  25 + }
  26 + });
  27 + });
  28 +
  29 + it('should export data with commas and line breaks to CSV - test B', done => {
  30 + vm = createVue({
  31 + template: '<div><Table :columns="columns" :data="data" ref="tableB" /></div>',
  32 + data() {
  33 + return csvB;
  34 + },
  35 + mounted() {
  36 + this.$refs.tableB.exportCsv({separator: ';', quoted: true, callback: data => {
  37 + expect(cleanCSV(data)).to.equal(cleanCSV(this.expected));
  38 + expect(cleanCSV(data).length > 0).to.equal(true);
  39 + done();
  40 + }});
  41 + }
  42 + });
  43 + });
  44 +
  45 + });
  46 +
  47 +});
... ...