parent
e9f0bc9c27
commit
e166855e9c
@ -0,0 +1,15 @@
|
||||
{
|
||||
"env": {
|
||||
"test": {
|
||||
"presets": [
|
||||
["env", { "targets": { "node": "current" } }]
|
||||
],
|
||||
"plugins": [
|
||||
"transform-vue-jsx",
|
||||
"transform-object-assign",
|
||||
"transform-object-rest-spread",
|
||||
"transform-class-properties"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
const libDir = process.env.LIB_DIR;
|
||||
|
||||
const transformIgnorePatterns = [
|
||||
'/dist/',
|
||||
'node_modules\/[^/]+?\/(?!(es|node_modules)\/)', // Ignore modules without es dir
|
||||
];
|
||||
|
||||
module.exports = {
|
||||
setupFiles: [
|
||||
'./tests/setup.js',
|
||||
],
|
||||
moduleFileExtensions: [
|
||||
"js",
|
||||
"jsx",
|
||||
"json",
|
||||
"vue",
|
||||
"md"
|
||||
],
|
||||
modulePathIgnorePatterns: [
|
||||
'/_site/',
|
||||
],
|
||||
testPathIgnorePatterns: [
|
||||
'/node_modules/',
|
||||
'node',
|
||||
],
|
||||
transform: {
|
||||
".*\\.(vue|md)$": "<rootDir>/node_modules/vue-jest",
|
||||
"^.+\\.(js|jsx)$": "<rootDir>/node_modules/babel-jest"
|
||||
},
|
||||
testRegex: libDir === 'dist' ? 'demo\\.test\\.js$' : '.*\\.test\\.js$',
|
||||
moduleNameMapper: {
|
||||
"^@/(.*)$": "<rootDir>/$1",
|
||||
"vue-antd-ui": "<rootDir>/components/index.js",
|
||||
},
|
||||
snapshotSerializers: [
|
||||
"<rootDir>/node_modules/jest-serializer-vue"
|
||||
],
|
||||
collectCoverage: process.env.COVERAGE === 'true',
|
||||
collectCoverageFrom: [
|
||||
"components/**/*.{js,jsx,vue}",
|
||||
'!components/*/style/index.{js,jsx}',
|
||||
'!components/style/index.{js,jsx}',
|
||||
'!components/*/locale/index.{js,jsx}',
|
||||
'!components/*/__tests__/**/type.{js,jsx}',
|
||||
"!**/node_modules/**"
|
||||
],
|
||||
transformIgnorePatterns,
|
||||
};
|
@ -1,28 +0,0 @@
|
||||
# `Button`
|
||||
|
||||
#### `create primary button`
|
||||
|
||||
```
|
||||
"<button type=\"button\" class=\"ant-btn ant-btn-primary\"><span>按 钮</span></button>"
|
||||
```
|
||||
|
||||
#### `should support link button`
|
||||
|
||||
```
|
||||
"<button target=\"_blank\" href=\"http://ant.design\" type=\"button\" class=\"ant-btn ant-btn-default\"><span>link button</span></button>"
|
||||
```
|
||||
|
||||
#### `fixbug renders {0} , 0 and {false}`
|
||||
|
||||
```
|
||||
"<button type=\"button\" class=\"ant-btn ant-btn-default\"><span>0</span></button>"
|
||||
```
|
||||
|
||||
```
|
||||
"<button type=\"button\" class=\"ant-btn ant-btn-default\"><span>0</span></button>"
|
||||
```
|
||||
|
||||
```
|
||||
"<button type=\"button\" class=\"ant-btn ant-btn-default\"></button>"
|
||||
```
|
||||
|
@ -1,140 +0,0 @@
|
||||
import Button from '../index'
|
||||
import Icon from '../../icon'
|
||||
import { mount } from 'avoriaz'
|
||||
import Vue from 'vue'
|
||||
import { matchSnapshot } from "chai-karma-snapshot";
|
||||
import { use, expect, assert } from "chai";
|
||||
use(matchSnapshot);
|
||||
|
||||
describe('Button', () => {
|
||||
it('create primary button', () => {
|
||||
const wrapper = mount({
|
||||
render (h) {
|
||||
return <Button type='primary'>按钮</Button>
|
||||
},
|
||||
})
|
||||
expect(wrapper.html()).to.matchSnapshot();
|
||||
expect(wrapper.hasClass('ant-btn-primary')).to.equal(true)
|
||||
})
|
||||
it('renders Chinese characters correctly', (done) => {
|
||||
const wrapper = mount(
|
||||
{
|
||||
render (h) {
|
||||
return <Button>按钮</Button>
|
||||
},
|
||||
}
|
||||
)
|
||||
expect(wrapper.text()).to.equal('按 钮')
|
||||
|
||||
const wrapper1 = mount(
|
||||
{
|
||||
render (h) {
|
||||
return <Button icon='search'>按钮</Button>
|
||||
},
|
||||
}
|
||||
)
|
||||
expect(wrapper1.text()).to.equal('按钮')
|
||||
|
||||
const wrapper2 = mount(
|
||||
{
|
||||
render (h) {
|
||||
return <Button><Icon type="search" />按钮</Button>
|
||||
},
|
||||
}
|
||||
)
|
||||
expect(wrapper2.text()).to.equal('按钮')
|
||||
|
||||
const wrapper3 = mount(
|
||||
{
|
||||
render (h) {
|
||||
return <Button><span>按钮</span></Button>
|
||||
},
|
||||
}
|
||||
)
|
||||
Vue.nextTick(() => {
|
||||
expect(wrapper3.find('.ant-btn')[0].hasClass('ant-btn-two-chinese-chars')).to.equal(true);
|
||||
done()
|
||||
})
|
||||
})
|
||||
it('should change loading state instantly by default', () => {
|
||||
const DefaultButton = {
|
||||
data(){
|
||||
return {
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
enterLoading () {
|
||||
this.loading = true
|
||||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
return <Button loading={this.loading} onClick={this.enterLoading}>Button</Button>;
|
||||
}
|
||||
}
|
||||
const wrapper = mount(DefaultButton)
|
||||
wrapper.trigger('click');
|
||||
Vue.nextTick(() => {
|
||||
expect(wrapper.find('.ant-btn-loading').length).to.equal(1);
|
||||
})
|
||||
});
|
||||
|
||||
it('should change loading state with delay', () => {
|
||||
const DefaultButton = {
|
||||
data(){
|
||||
return {
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
enterLoading () {
|
||||
this.loading = { delay: 1000 }
|
||||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
return <Button loading={this.loading} onClick={this.enterLoading}>Button</Button>;
|
||||
}
|
||||
}
|
||||
const wrapper = mount(DefaultButton)
|
||||
wrapper.trigger('click');
|
||||
Vue.nextTick(() => {
|
||||
expect(wrapper.hasClass('ant-btn-loading').length).to.equal(false);
|
||||
})
|
||||
});
|
||||
|
||||
it('should support link button', () => {
|
||||
const wrapper = mount({
|
||||
render (h) {
|
||||
return <Button target="_blank" href="http://ant.design">link button</Button>
|
||||
},
|
||||
})
|
||||
expect(wrapper.html()).to.matchSnapshot();
|
||||
})
|
||||
|
||||
it('fixbug renders {0} , 0 and {false}', () => {
|
||||
const wrapper = mount({
|
||||
render (h) {
|
||||
return <Button>{0}</Button>
|
||||
},
|
||||
})
|
||||
expect(wrapper.html()).to.matchSnapshot();
|
||||
|
||||
const wrapper1 = mount({
|
||||
render (h) {
|
||||
return <Button>0</Button>
|
||||
},
|
||||
})
|
||||
expect(wrapper1.html()).to.matchSnapshot();
|
||||
|
||||
const wrapper2 = mount({
|
||||
render (h) {
|
||||
return <Button>{false}</Button>
|
||||
},
|
||||
})
|
||||
expect(wrapper2.html()).to.matchSnapshot();
|
||||
|
||||
})
|
||||
|
||||
})
|
@ -0,0 +1,162 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders ./components/button/demo/basic.md correctly 1`] = `
|
||||
<div>
|
||||
<button type="button" class="ant-btn ant-btn-primary"><span>Primary</span></button>
|
||||
<button type="button" class="ant-btn ant-btn-default"><span>Default</span></button>
|
||||
<button type="button" class="ant-btn ant-btn-dashed"><span>Dashed</span></button>
|
||||
<button type="button" class="ant-btn ant-btn-danger"><span>Danger</span></button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/button/demo/button-group.md correctly 1`] = `
|
||||
<div id="components-button-demo-button-group">
|
||||
<h4>Basic</h4>
|
||||
<div class="ant-btn-group">
|
||||
<button type="button" class="ant-btn ant-btn-default"><span>Cancel</span></button>
|
||||
<button type="button" class="ant-btn ant-btn-primary"><span>OK</span></button>
|
||||
</div>
|
||||
<div class="ant-btn-group">
|
||||
<button type="button" disabled="disabled" class="ant-btn ant-btn-default"><span>L</span></button>
|
||||
<button type="button" disabled="disabled" class="ant-btn ant-btn-default"><span>M</span></button>
|
||||
<button type="button" disabled="disabled" class="ant-btn ant-btn-default"><span>R</span></button>
|
||||
</div>
|
||||
<div class="ant-btn-group">
|
||||
<button type="button" class="ant-btn ant-btn-primary"><span>L</span></button>
|
||||
<button type="button" class="ant-btn ant-btn-default"><span>M</span></button>
|
||||
<button type="button" class="ant-btn ant-btn-default"><span>M</span></button>
|
||||
<button type="button" class="ant-btn ant-btn-dashed"><span>R</span></button>
|
||||
</div>
|
||||
<h4>With Icon</h4>
|
||||
<div class="ant-btn-group">
|
||||
<button type="button" class="ant-btn ant-btn-primary">
|
||||
<i class="anticon anticon-left"></i>Go back
|
||||
</button>
|
||||
<button type="button" class="ant-btn ant-btn-primary">
|
||||
Go forward
|
||||
<i class="anticon anticon-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="ant-btn-group">
|
||||
<button type="button" class="ant-btn ant-btn-primary">
|
||||
<i class="anticon anticon-cloud"></i>
|
||||
</button>
|
||||
<button type="button" class="ant-btn ant-btn-primary">
|
||||
<i class="anticon anticon-cloud-download"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/button/demo/disabled.md correctly 1`] = `
|
||||
<div>
|
||||
<button type="button" class="ant-btn ant-btn-primary"><span>Primary</span></button>
|
||||
<button type="button" disabled="disabled" class="ant-btn ant-btn-primary"><span>Primary(disabled)</span></button>
|
||||
<br>
|
||||
<button type="button" class="ant-btn ant-btn-default"><span>Default</span></button>
|
||||
<button type="button" disabled="disabled" class="ant-btn ant-btn-default"><span>Default(disabled)</span></button>
|
||||
<br>
|
||||
<button type="button" class="ant-btn ant-btn-default"><span>Ghost</span></button>
|
||||
<button type="button" disabled="disabled" class="ant-btn ant-btn-default"><span>Ghost(disabled)</span></button>
|
||||
<br>
|
||||
<button type="button" class="ant-btn ant-btn-dashed"><span>Dashed</span></button>
|
||||
<button type="button" disabled="disabled" class="ant-btn ant-btn-dashed"><span>Dashed(disabled)</span></button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/button/demo/ghost.md correctly 1`] = `
|
||||
<div style="background:rgb(190, 200, 200);padding:26px 16px 16px;">
|
||||
<button type="button" class="ant-btn ant-btn-primary ant-btn-background-ghost"><span>Primary</span></button>
|
||||
<button type="button" class="ant-btn ant-btn-default ant-btn-background-ghost"><span>Default</span></button>
|
||||
<button type="button" class="ant-btn ant-btn-dashed ant-btn-background-ghost"><span>Dashed</span></button>
|
||||
<button type="button" class="ant-btn ant-btn-danger ant-btn-background-ghost"><span>danger</span></button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/button/demo/icon.md correctly 1`] = `
|
||||
<div>
|
||||
<button type="button" class="ant-btn ant-btn-primary ant-btn-circle">
|
||||
<i class="anticon anticon-search"></i>
|
||||
</button>
|
||||
<button type="button" class="ant-btn ant-btn-primary">
|
||||
<i class="anticon anticon-search"></i><span>Search</span></button>
|
||||
<button type="button" class="ant-btn ant-btn-default ant-btn-circle">
|
||||
<i class="anticon anticon-search"></i>
|
||||
</button>
|
||||
<button type="button" class="ant-btn ant-btn-default">
|
||||
<i class="anticon anticon-search"></i><span>Search</span></button>
|
||||
<button type="button" class="ant-btn ant-btn-default ant-btn-circle">
|
||||
<i class="anticon anticon-search"></i>
|
||||
</button>
|
||||
<button type="button" class="ant-btn ant-btn-default">
|
||||
<i class="anticon anticon-search"></i><span>Search</span></button>
|
||||
<button type="button" class="ant-btn ant-btn-dashed ant-btn-circle">
|
||||
<i class="anticon anticon-search"></i>
|
||||
</button>
|
||||
<button type="button" class="ant-btn ant-btn-dashed">
|
||||
<i class="anticon anticon-search"></i><span>Search</span></button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/button/demo/loading.md correctly 1`] = `
|
||||
<div>
|
||||
<button type="button" class="ant-btn ant-btn-primary ant-btn-loading">
|
||||
<i class="anticon anticon-loading anticon-spin"></i><span>Loading</span></button>
|
||||
<button type="button" class="ant-btn ant-btn-primary ant-btn-sm ant-btn-loading">
|
||||
<i class="anticon anticon-loading anticon-spin"></i><span>Loading</span></button>
|
||||
<br>
|
||||
<button type="button" class="ant-btn ant-btn-primary"><span>mouseenter me!</span></button>
|
||||
<button type="button" class="ant-btn ant-btn-primary">
|
||||
<i class="anticon anticon-poweroff"></i><span>延迟1s</span></button>
|
||||
<br>
|
||||
<button type="button" class="ant-btn ant-btn-default ant-btn-circle ant-btn-loading">
|
||||
<i class="anticon anticon-loading anticon-spin"></i>
|
||||
</button>
|
||||
<button type="button" class="ant-btn ant-btn-primary ant-btn-circle ant-btn-loading">
|
||||
<i class="anticon anticon-loading anticon-spin"></i>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/button/demo/multiple.md correctly 1`] = `
|
||||
<div>
|
||||
<button type="button" class="ant-btn ant-btn-primary"><span>Primary</span></button>
|
||||
<button type="button" class="ant-btn ant-btn-default"><span>secondary</span></button>
|
||||
<button type="button" class="ant-btn ant-btn-default ant-dropdown-trigger">
|
||||
Actions
|
||||
<i class="anticon anticon-down"></i>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/button/demo/size.md correctly 1`] = `
|
||||
<div>
|
||||
<div class="ant-radio-group ant-radio-group-default">
|
||||
<label class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"><span class="ant-radio-button ant-radio-button-checked"><input type="radio" checked="checked" class="ant-radio-button-input"><span class="ant-radio-button-inner"></span></span><span>Large</span></label>
|
||||
<label class="ant-radio-button-wrapper"><span class="ant-radio-button"><input type="radio" class="ant-radio-button-input"><span class="ant-radio-button-inner"></span></span><span>Default</span></label>
|
||||
<label class="ant-radio-button-wrapper"><span class="ant-radio-button"><input type="radio" class="ant-radio-button-input"><span class="ant-radio-button-inner"></span></span><span>Small</span></label>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<button type="button" class="ant-btn ant-btn-primary ant-btn-lg"><span>Primary</span></button>
|
||||
<button type="button" class="ant-btn ant-btn-default ant-btn-lg"><span>Normal</span></button>
|
||||
<button type="button" class="ant-btn ant-btn-dashed ant-btn-lg"><span>Dashed</span></button>
|
||||
<button type="button" class="ant-btn ant-btn-danger ant-btn-lg"><span>Danger</span></button>
|
||||
<br>
|
||||
<button type="button" class="ant-btn ant-btn-primary ant-btn-circle ant-btn-lg">
|
||||
<i class="anticon anticon-download"></i>
|
||||
</button>
|
||||
<button type="button" class="ant-btn ant-btn-primary ant-btn-lg">
|
||||
<i class="anticon anticon-download"></i><span>Download</span></button>
|
||||
<br>
|
||||
<div class="ant-btn-group ant-btn-group-lg">
|
||||
<button type="button" class="ant-btn ant-btn-primary">
|
||||
<i class="anticon anticon-left"></i>Backward
|
||||
</button>
|
||||
<button type="button" class="ant-btn ant-btn-primary">
|
||||
Forward
|
||||
<i class="anticon anticon-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -0,0 +1,3 @@
|
||||
import demoTest from '../../../tests/shared/demoTest'
|
||||
|
||||
demoTest('button')
|
@ -0,0 +1,135 @@
|
||||
import Button from '../index'
|
||||
import Icon from '../../icon'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import Vue from 'vue'
|
||||
|
||||
describe('Button', () => {
|
||||
it('create primary button', () => {
|
||||
const wrapper = mount({
|
||||
render (h) {
|
||||
return <Button type='primary'>按钮</Button>
|
||||
},
|
||||
})
|
||||
expect(wrapper.contains('.ant-btn-primary')).toBe(true)
|
||||
})
|
||||
// it('renders Chinese characters correctly', (done) => {
|
||||
// const wrapper = mount(
|
||||
// {
|
||||
// render (h) {
|
||||
// return <Button>按钮</Button>
|
||||
// },
|
||||
// }
|
||||
// )
|
||||
// expect(wrapper.text()).to.equal('按 钮')
|
||||
|
||||
// const wrapper1 = mount(
|
||||
// {
|
||||
// render (h) {
|
||||
// return <Button icon='search'>按钮</Button>
|
||||
// },
|
||||
// }
|
||||
// )
|
||||
// expect(wrapper1.text()).to.equal('按钮')
|
||||
|
||||
// const wrapper2 = mount(
|
||||
// {
|
||||
// render (h) {
|
||||
// return <Button><Icon type="search" />按钮</Button>
|
||||
// },
|
||||
// }
|
||||
// )
|
||||
// expect(wrapper2.text()).to.equal('按钮')
|
||||
|
||||
// const wrapper3 = mount(
|
||||
// {
|
||||
// render (h) {
|
||||
// return <Button><span>按钮</span></Button>
|
||||
// },
|
||||
// }
|
||||
// )
|
||||
// Vue.nextTick(() => {
|
||||
// expect(wrapper3.find('.ant-btn')[0].hasClass('ant-btn-two-chinese-chars')).to.equal(true);
|
||||
// done()
|
||||
// })
|
||||
// })
|
||||
// it('should change loading state instantly by default', () => {
|
||||
// const DefaultButton = {
|
||||
// data(){
|
||||
// return {
|
||||
// loading: false,
|
||||
// }
|
||||
// },
|
||||
// methods: {
|
||||
// enterLoading () {
|
||||
// this.loading = true
|
||||
// }
|
||||
// },
|
||||
|
||||
// render() {
|
||||
// return <Button loading={this.loading} onClick={this.enterLoading}>Button</Button>;
|
||||
// }
|
||||
// }
|
||||
// const wrapper = mount(DefaultButton)
|
||||
// wrapper.trigger('click');
|
||||
// Vue.nextTick(() => {
|
||||
// expect(wrapper.find('.ant-btn-loading').length).to.equal(1);
|
||||
// })
|
||||
// });
|
||||
|
||||
// it('should change loading state with delay', () => {
|
||||
// const DefaultButton = {
|
||||
// data(){
|
||||
// return {
|
||||
// loading: false,
|
||||
// }
|
||||
// },
|
||||
// methods: {
|
||||
// enterLoading () {
|
||||
// this.loading = { delay: 1000 }
|
||||
// }
|
||||
// },
|
||||
|
||||
// render() {
|
||||
// return <Button loading={this.loading} onClick={this.enterLoading}>Button</Button>;
|
||||
// }
|
||||
// }
|
||||
// const wrapper = mount(DefaultButton)
|
||||
// wrapper.trigger('click');
|
||||
// Vue.nextTick(() => {
|
||||
// expect(wrapper.hasClass('ant-btn-loading').length).to.equal(false);
|
||||
// })
|
||||
// });
|
||||
|
||||
// it('should support link button', () => {
|
||||
// const wrapper = mount({
|
||||
// render (h) {
|
||||
// return <Button target="_blank" href="http://ant.design">link button</Button>
|
||||
// },
|
||||
// })
|
||||
// expect(wrapper.html()).to.matchSnapshot();
|
||||
// })
|
||||
|
||||
// it('fixbug renders {0} , 0 and {false}', () => {
|
||||
// const wrapper = mount({
|
||||
// render (h) {
|
||||
// return <Button>{0}</Button>
|
||||
// },
|
||||
// })
|
||||
// expect(wrapper.html()).to.matchSnapshot();
|
||||
|
||||
// const wrapper1 = mount({
|
||||
// render (h) {
|
||||
// return <Button>0</Button>
|
||||
// },
|
||||
// })
|
||||
// expect(wrapper1.html()).to.matchSnapshot();
|
||||
|
||||
// const wrapper2 = mount({
|
||||
// render (h) {
|
||||
// return <Button>{false}</Button>
|
||||
// },
|
||||
// })
|
||||
// expect(wrapper2.html()).to.matchSnapshot();
|
||||
|
||||
// })
|
||||
})
|
@ -1,181 +1,172 @@
|
||||
{
|
||||
"name": "vue-antd-ui",
|
||||
"version": "0.5.1",
|
||||
"title": "Ant Design Vue",
|
||||
"description": "An enterprise-class UI design language and Vue-based implementation",
|
||||
"keywords": [
|
||||
"ant",
|
||||
"design",
|
||||
"antd",
|
||||
"vue",
|
||||
"vueComponent",
|
||||
"component",
|
||||
"components",
|
||||
"ui",
|
||||
"framework",
|
||||
"frontend"
|
||||
],
|
||||
"main": "dist/antd.min.js",
|
||||
"files": [
|
||||
"dist",
|
||||
"lib",
|
||||
"es"
|
||||
],
|
||||
"scripts": {
|
||||
"start": "NODE_ENV=development ./node_modules/.bin/webpack-dev-server --open --hot",
|
||||
"test": "cross-env BABEL_ENV=test karma start test/karma.conf.js --single-run",
|
||||
"site": "node scripts/run.js site-dist",
|
||||
"copy": "node scripts/run.js copy-html",
|
||||
"compile": "node antd-tools/cli/run.js compile",
|
||||
"pub": "node antd-tools/cli/run.js pub",
|
||||
"prepublish": "node antd-tools/cli/run.js guard",
|
||||
"dist": "node antd-tools/cli/run.js dist",
|
||||
"lint": "eslint -c ./.eslintrc --fix --ext .jsx,.js,.vue ./components",
|
||||
"lint:style": "stylelint \"./examples/**/*.less\" --fix --syntax less",
|
||||
"commitmsg": "validate-commit-msg",
|
||||
"cm": "git-cz",
|
||||
"codecov": "codecov"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/vueComponent/ant-design.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/vueComponent/ant-design/issues"
|
||||
},
|
||||
"homepage": "https://github.com/vueComponent/ant-design",
|
||||
"pre-commit": [
|
||||
"lint:style",
|
||||
"lint"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"vue": ">=2.5.0",
|
||||
"vue-template-compiler": ">=2.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@octokit/rest": "^15.2.6",
|
||||
"autoprefixer": "^8.1.0",
|
||||
"avoriaz": "^6.3.0",
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-eslint": "^8.0.1",
|
||||
"babel-helper-vue-jsx-merge-props": "^2.0.3",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-plugin-add-module-exports": "^0.2.1",
|
||||
"babel-plugin-import": "^1.1.1",
|
||||
"babel-plugin-istanbul": "^4.1.1",
|
||||
"babel-plugin-syntax-dynamic-import": "^6.18.0",
|
||||
"babel-plugin-syntax-jsx": "^6.18.0",
|
||||
"babel-plugin-transform-class-properties": "^6.24.1",
|
||||
"babel-plugin-transform-decorators": "^6.24.1",
|
||||
"babel-plugin-transform-decorators-legacy": "^1.3.4",
|
||||
"babel-plugin-transform-es3-member-expression-literals": "^6.22.0",
|
||||
"babel-plugin-transform-es3-property-literals": "^6.22.0",
|
||||
"babel-plugin-transform-object-assign": "^6.22.0",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||
"babel-plugin-transform-runtime": "~6.23.0",
|
||||
"babel-plugin-transform-vue-jsx": "^3.7.0",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"case-sensitive-paths-webpack-plugin": "^2.1.2",
|
||||
"chai": "^4.1.2",
|
||||
"chai-karma-snapshot": "^0.7.0",
|
||||
"chalk": "^2.3.2",
|
||||
"cheerio": "^1.0.0-rc.2",
|
||||
"codecov": "^3.0.0",
|
||||
"colorful": "^2.1.0",
|
||||
"commander": "^2.15.0",
|
||||
"commitizen": "^2.9.6",
|
||||
"cross-env": "^5.1.4",
|
||||
"css-loader": "^0.28.7",
|
||||
"deep-assign": "^2.0.0",
|
||||
"eslint": "^4.7.2",
|
||||
"eslint-plugin-html": "^3.2.2",
|
||||
"eslint-plugin-vue": "^3.13.0",
|
||||
"eslint-plugin-vue-libs": "^1.2.1",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"fetch-jsonp": "^1.1.3",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-babel": "^7.0.0",
|
||||
"gulp-strip-code": "^0.1.4",
|
||||
"highlight.js": "^9.12.0",
|
||||
"html-webpack-plugin": "^2.30.1",
|
||||
"husky": "^0.14.3",
|
||||
"istanbul-instrumenter-loader": "^3.0.0",
|
||||
"jsonp": "^0.2.1",
|
||||
"karma": "^2.0.2",
|
||||
"karma-babel-preprocessor": "^7.0.0",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-coverage": "^1.1.1",
|
||||
"karma-coverage-istanbul-reporter": "^1.3.0",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"karma-mocha-reporter": "^2.2.5",
|
||||
"karma-mocha-snapshot": "^0.2.1",
|
||||
"karma-sinon-chai": "^1.3.1",
|
||||
"karma-snapshot": "^0.6.0",
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
"karma-spec-reporter": "0.0.31",
|
||||
"karma-webpack": "^2.0.13",
|
||||
"less": "^2.7.2",
|
||||
"less-loader": "^4.0.5",
|
||||
"less-plugin-npm-import": "^2.1.0",
|
||||
"markdown-it": "^8.4.0",
|
||||
"markdown-it-anchor": "^4.0.0",
|
||||
"marked": "^0.3.7",
|
||||
"merge2": "^1.2.1",
|
||||
"minimist": "^1.2.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"mocha": "^3.5.3",
|
||||
"mockdate": "^2.0.2",
|
||||
"postcss": "^6.0.20",
|
||||
"postcss-loader": "^2.1.2",
|
||||
"pre-commit": "^1.2.2",
|
||||
"puppeteer": "^1.3.0",
|
||||
"querystring": "^0.2.0",
|
||||
"raw-loader": "^1.0.0-beta.0",
|
||||
"reqwest": "^2.0.5",
|
||||
"rimraf": "^2.6.2",
|
||||
"rucksack-css": "^1.0.2",
|
||||
"selenium-server": "^3.0.1",
|
||||
"semver": "^5.3.0",
|
||||
"sinon": "^4.0.2",
|
||||
"sinon-chai": "^2.8.0",
|
||||
"style-loader": "^0.18.2",
|
||||
"stylelint": "^8.1.1",
|
||||
"stylelint-config-standard": "^17.0.0",
|
||||
"through2": "^2.0.3",
|
||||
"validate-commit-msg": "^2.14.0",
|
||||
"vue": "^2.5.16",
|
||||
"vue-antd-md-loader": "^1.0.3",
|
||||
"vue-clipboard2": "0.0.8",
|
||||
"vue-loader": "^13.0.5",
|
||||
"vue-router": "^3.0.1",
|
||||
"vue-template-compiler": "^2.5.16",
|
||||
"webpack": "^3.11.0",
|
||||
"webpack-chunk-hash": "^0.5.0",
|
||||
"webpack-dev-server": "^2.8.2",
|
||||
"webpack-merge": "^4.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"add-dom-event-listener": "^1.0.2",
|
||||
"array-tree-filter": "^2.1.0",
|
||||
"async-validator": "^1.8.2",
|
||||
"babel-helper-vue-jsx-merge-props": "^2.0.3",
|
||||
"babel-runtime": "6.x",
|
||||
"classnames": "^2.2.5",
|
||||
"component-classes": "^1.2.6",
|
||||
"css-animation": "^1.4.1",
|
||||
"dom-align": "^1.6.7",
|
||||
"dom-closest": "^0.2.0",
|
||||
"dom-scroll-into-view": "^1.2.1",
|
||||
"enquire.js": "^2.1.6",
|
||||
"is-negative-zero": "^2.0.0",
|
||||
"lodash": "^4.17.5",
|
||||
"moment": "^2.21.0",
|
||||
"omit.js": "^1.0.0",
|
||||
"shallow-equal": "^1.0.0",
|
||||
"shallowequal": "^1.0.2",
|
||||
"warning": "^3.0.0"
|
||||
}
|
||||
}
|
||||
"name": "vue-antd-ui",
|
||||
"version": "0.5.1",
|
||||
"title": "Ant Design Vue",
|
||||
"description": "An enterprise-class UI design language and Vue-based implementation",
|
||||
"keywords": [
|
||||
"ant",
|
||||
"design",
|
||||
"antd",
|
||||
"vue",
|
||||
"vueComponent",
|
||||
"component",
|
||||
"components",
|
||||
"ui",
|
||||
"framework",
|
||||
"frontend"
|
||||
],
|
||||
"main": "dist/antd.min.js",
|
||||
"files": [
|
||||
"dist",
|
||||
"lib",
|
||||
"es"
|
||||
],
|
||||
"scripts": {
|
||||
"start": "NODE_ENV=development ./node_modules/.bin/webpack-dev-server --open --hot",
|
||||
"test": "jest --config .jest.js",
|
||||
"site": "node scripts/run.js site-dist",
|
||||
"copy": "node scripts/run.js copy-html",
|
||||
"compile": "node antd-tools/cli/run.js compile",
|
||||
"pub": "node antd-tools/cli/run.js pub",
|
||||
"prepublish": "node antd-tools/cli/run.js guard",
|
||||
"dist": "node antd-tools/cli/run.js dist",
|
||||
"lint": "eslint -c ./.eslintrc --fix --ext .jsx,.js,.vue ./components",
|
||||
"lint:style": "stylelint \"./examples/**/*.less\" --fix --syntax less",
|
||||
"commitmsg": "validate-commit-msg",
|
||||
"cm": "git-cz",
|
||||
"codecov": "codecov"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/vueComponent/ant-design.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/vueComponent/ant-design/issues"
|
||||
},
|
||||
"homepage": "https://github.com/vueComponent/ant-design",
|
||||
"pre-commit": [
|
||||
"lint:style",
|
||||
"lint"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"vue": ">=2.5.0",
|
||||
"vue-template-compiler": ">=2.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/server-test-utils": "^1.0.0-beta.16",
|
||||
"@vue/test-utils": "^1.0.0-beta.16",
|
||||
"autoprefixer": "^8.1.0",
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-eslint": "^8.0.1",
|
||||
"babel-helper-vue-jsx-merge-props": "^2.0.3",
|
||||
"babel-jest": "^22.4.3",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-plugin-add-module-exports": "^0.2.1",
|
||||
"babel-plugin-import": "^1.1.1",
|
||||
"babel-plugin-istanbul": "^4.1.1",
|
||||
"babel-plugin-syntax-dynamic-import": "^6.18.0",
|
||||
"babel-plugin-syntax-jsx": "^6.18.0",
|
||||
"babel-plugin-transform-class-properties": "^6.24.1",
|
||||
"babel-plugin-transform-decorators": "^6.24.1",
|
||||
"babel-plugin-transform-decorators-legacy": "^1.3.4",
|
||||
"babel-plugin-transform-es3-member-expression-literals": "^6.22.0",
|
||||
"babel-plugin-transform-es3-property-literals": "^6.22.0",
|
||||
"babel-plugin-transform-object-assign": "^6.22.0",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||
"babel-plugin-transform-runtime": "~6.23.0",
|
||||
"babel-plugin-transform-vue-jsx": "^3.7.0",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"case-sensitive-paths-webpack-plugin": "^2.1.2",
|
||||
"chalk": "^2.3.2",
|
||||
"cheerio": "^1.0.0-rc.2",
|
||||
"codecov": "^3.0.0",
|
||||
"colorful": "^2.1.0",
|
||||
"commander": "^2.15.0",
|
||||
"commitizen": "^2.9.6",
|
||||
"cross-env": "^5.1.4",
|
||||
"css-loader": "^0.28.7",
|
||||
"deep-assign": "^2.0.0",
|
||||
"eslint": "^4.7.2",
|
||||
"eslint-plugin-html": "^3.2.2",
|
||||
"eslint-plugin-vue": "^3.13.0",
|
||||
"eslint-plugin-vue-libs": "^1.2.1",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"fetch-jsonp": "^1.1.3",
|
||||
"glob": "^7.1.2",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-babel": "^7.0.0",
|
||||
"gulp-strip-code": "^0.1.4",
|
||||
"highlight.js": "^9.12.0",
|
||||
"html-webpack-plugin": "^2.30.1",
|
||||
"husky": "^0.14.3",
|
||||
"istanbul-instrumenter-loader": "^3.0.0",
|
||||
"jest": "^22.4.3",
|
||||
"jest-serializer-vue": "^1.0.0",
|
||||
"jsonp": "^0.2.1",
|
||||
"less": "^2.7.2",
|
||||
"less-loader": "^4.0.5",
|
||||
"less-plugin-npm-import": "^2.1.0",
|
||||
"markdown-it": "^8.4.0",
|
||||
"markdown-it-anchor": "^4.0.0",
|
||||
"marked": "^0.3.7",
|
||||
"merge2": "^1.2.1",
|
||||
"minimist": "^1.2.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"mocha": "^3.5.3",
|
||||
"mockdate": "^2.0.2",
|
||||
"postcss": "^6.0.20",
|
||||
"postcss-loader": "^2.1.2",
|
||||
"pre-commit": "^1.2.2",
|
||||
"puppeteer": "^1.3.0",
|
||||
"querystring": "^0.2.0",
|
||||
"raw-loader": "^1.0.0-beta.0",
|
||||
"reqwest": "^2.0.5",
|
||||
"rimraf": "^2.6.2",
|
||||
"rucksack-css": "^1.0.2",
|
||||
"selenium-server": "^3.0.1",
|
||||
"semver": "^5.3.0",
|
||||
"sinon": "^4.0.2",
|
||||
"sinon-chai": "^2.8.0",
|
||||
"style-loader": "^0.18.2",
|
||||
"stylelint": "^8.1.1",
|
||||
"stylelint-config-standard": "^17.0.0",
|
||||
"through2": "^2.0.3",
|
||||
"validate-commit-msg": "^2.14.0",
|
||||
"vue": "^2.5.16",
|
||||
"vue-antd-md-loader": "^1.0.3",
|
||||
"vue-clipboard2": "0.0.8",
|
||||
"vue-jest": "^2.5.0",
|
||||
"vue-loader": "^13.0.5",
|
||||
"vue-router": "^3.0.1",
|
||||
"vue-server-renderer": "^2.5.16",
|
||||
"vue-template-compiler": "^2.5.16",
|
||||
"webpack": "^3.11.0",
|
||||
"webpack-chunk-hash": "^0.5.0",
|
||||
"webpack-dev-server": "^2.8.2",
|
||||
"webpack-merge": "^4.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"add-dom-event-listener": "^1.0.2",
|
||||
"array-tree-filter": "^2.1.0",
|
||||
"async-validator": "^1.8.2",
|
||||
"babel-helper-vue-jsx-merge-props": "^2.0.3",
|
||||
"babel-runtime": "6.x",
|
||||
"classnames": "^2.2.5",
|
||||
"component-classes": "^1.2.6",
|
||||
"css-animation": "^1.4.1",
|
||||
"dom-align": "^1.6.7",
|
||||
"dom-closest": "^0.2.0",
|
||||
"dom-scroll-into-view": "^1.2.1",
|
||||
"enquire.js": "^2.1.6",
|
||||
"is-negative-zero": "^2.0.0",
|
||||
"lodash": "^4.17.5",
|
||||
"moment": "^2.21.0",
|
||||
"omit.js": "^1.0.0",
|
||||
"shallow-equal": "^1.0.0",
|
||||
"shallowequal": "^1.0.2",
|
||||
"warning": "^3.0.0"
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
{
|
||||
"extends": ["plugin:vue-libs/recommended"],
|
||||
"rules": {
|
||||
"comma-dangle": [2, "always-multiline"],
|
||||
"no-var": "error"
|
||||
},
|
||||
"globals": {
|
||||
"it": true,
|
||||
"describe": true,
|
||||
"expect": true
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
|
||||
import Vue from 'vue'
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
// require all test files (files that ends with .spec.js)
|
||||
const testsContext = require.context(`../components/${process.env.SCOPE}`, true, /\.spec$/)
|
||||
testsContext.keys().forEach(testsContext)
|
||||
|
||||
// require all src files except main.js for coverage.
|
||||
// you can also change this to match only the subset of files that
|
||||
// you want coverage for.
|
||||
const srcContext = require.context(`../components/${process.env.SCOPE}`, true, /^\.(\.js|\.jsx)?$/)
|
||||
srcContext.keys().forEach(srcContext)
|
@ -1,63 +0,0 @@
|
||||
// This is a karma config file. For more details see
|
||||
// http://karma-runner.github.io/0.13/config/configuration-file.html
|
||||
// we are also using it with karma-webpack
|
||||
// https://github.com/webpack/karma-webpack
|
||||
|
||||
const path = require('path')
|
||||
const webpack = require('webpack')
|
||||
const webpackConfig = require('../webpack.config')
|
||||
const merge = require('webpack-merge')
|
||||
delete webpackConfig.entry
|
||||
const scope = process.argv[5] || ''
|
||||
process.env.CHROME_BIN = require('puppeteer').executablePath()
|
||||
function resolve (basePath, suiteName = '') {
|
||||
return path.join(basePath, '../components', suiteName.toLowerCase(), '__test__/__snapshots__', 'index.test.md')
|
||||
}
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
// to run in additional browsers:
|
||||
// 1. install corresponding karma launcher
|
||||
// http://karma-runner.github.io/0.13/config/browsers.html
|
||||
// 2. add it to the `browsers` array below.
|
||||
browsers: ['ChromeHeadless'],
|
||||
frameworks: ['mocha', 'snapshot', 'mocha-snapshot', 'sinon-chai'],
|
||||
reporters: ['spec', 'coverage'],
|
||||
files: ['../components/**/__snapshots__/**/*.md', './index.js'],
|
||||
preprocessors: {
|
||||
'../components/**/__snapshots__/**/*.md': ['snapshot'],
|
||||
'./index.js': ['webpack', 'sourcemap'],
|
||||
},
|
||||
port: 9876,
|
||||
colors: true,
|
||||
autoWatch: true,
|
||||
webpack: merge(
|
||||
{
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
NODE_ENV: '"testing"',
|
||||
SCOPE: `"${scope}"`,
|
||||
},
|
||||
}),
|
||||
],
|
||||
},
|
||||
webpackConfig
|
||||
),
|
||||
webpackMiddleware: {
|
||||
noInfo: true,
|
||||
},
|
||||
snapshot: {
|
||||
update: !!process.env.UPDATE,
|
||||
prune: !!process.env.PRUNE,
|
||||
pathResolver: resolve, // Custom path resolver,
|
||||
},
|
||||
coverageReporter: {
|
||||
dir: './coverage',
|
||||
reporters: [
|
||||
{ type: 'lcov', subdir: '.' },
|
||||
{ type: 'text-summary' },
|
||||
],
|
||||
includeAllSources: false,
|
||||
},
|
||||
})
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`antd dist files exports modules correctly 1`] = `
|
||||
Array [
|
||||
"version",
|
||||
"install",
|
||||
"message",
|
||||
"notification",
|
||||
"Affix",
|
||||
"AutoComplete",
|
||||
"Alert",
|
||||
"Avatar",
|
||||
"BackTop",
|
||||
"Badge",
|
||||
"Breadcrumb",
|
||||
"Button",
|
||||
"Calendar",
|
||||
"Card",
|
||||
"Collapse",
|
||||
"Cascader",
|
||||
"Checkbox",
|
||||
"Col",
|
||||
"DatePicker",
|
||||
"Divider",
|
||||
"Dropdown",
|
||||
"Form",
|
||||
"Icon",
|
||||
"Input",
|
||||
"InputNumber",
|
||||
"Layout",
|
||||
"LocaleProvider",
|
||||
"Menu",
|
||||
"Modal",
|
||||
"Pagination",
|
||||
"Popconfirm",
|
||||
"Popover",
|
||||
"Progress",
|
||||
"Radio",
|
||||
"Rate",
|
||||
"Row",
|
||||
"Select",
|
||||
"Slider",
|
||||
"Spin",
|
||||
"Steps",
|
||||
"Switch",
|
||||
"Table",
|
||||
"Transfer",
|
||||
"Tree",
|
||||
"Tabs",
|
||||
"Tag",
|
||||
"TimePicker",
|
||||
"Timeline",
|
||||
"Tooltip",
|
||||
"Upload",
|
||||
"default",
|
||||
]
|
||||
`;
|
@ -0,0 +1,21 @@
|
||||
import pkg from '../package.json'
|
||||
|
||||
const testDist = process.env.LIB_DIR === 'dist'
|
||||
|
||||
describe('antd dist files', () => {
|
||||
// https://github.com/ant-design/ant-design/issues/1638
|
||||
// https://github.com/ant-design/ant-design/issues/1968
|
||||
it('exports modules correctly', () => {
|
||||
const antd = testDist ? require('../dist/antd') : require('../components') // eslint-disable-line global-require
|
||||
expect(Object.keys(antd)).toMatchSnapshot()
|
||||
})
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/1970
|
||||
// https://github.com/ant-design/ant-design/issues/1804
|
||||
if (testDist) {
|
||||
it('should have antd.version', () => {
|
||||
const antd = require('../dist/antd') // eslint-disable-line global-require
|
||||
expect(antd.version).toBe(pkg.version)
|
||||
})
|
||||
}
|
||||
})
|
@ -0,0 +1,22 @@
|
||||
import Vue from 'vue'
|
||||
import antd from 'vue-antd-ui'
|
||||
Vue.use(antd)
|
||||
/* eslint-disable global-require */
|
||||
if (typeof window !== 'undefined') {
|
||||
global.window.resizeTo = (width, height) => {
|
||||
global.window.innerWidth = width || global.window.innerWidth
|
||||
global.window.innerHeight = height || global.window.innerHeight
|
||||
global.window.dispatchEvent(new Event('resize'))
|
||||
}
|
||||
}
|
||||
|
||||
// The built-in requestAnimationFrame and cancelAnimationFrame not working with jest.runFakeTimes()
|
||||
// https://github.com/facebook/jest/issues/5147
|
||||
global.requestAnimationFrame = function (cb) {
|
||||
return setTimeout(cb, 0)
|
||||
}
|
||||
|
||||
global.cancelAnimationFrame = function (cb) {
|
||||
return clearTimeout(cb, 0)
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
import glob from 'glob'
|
||||
import { renderToString } from '@vue/server-test-utils'
|
||||
import MockDate from 'mockdate'
|
||||
import moment from 'moment'
|
||||
|
||||
export default function demoTest (component, options = {}) {
|
||||
const files = glob.sync(`./components/${component}/demo/*.md`)
|
||||
|
||||
files.forEach((file) => {
|
||||
let testMethod = options.skip === true ? test.skip : test
|
||||
if (Array.isArray(options.skip) && options.skip.some(c => file.includes(c))) {
|
||||
testMethod = test.skip
|
||||
}
|
||||
testMethod(`renders ${file} correctly`, () => {
|
||||
MockDate.set(moment('2016-11-22'))
|
||||
const demo = require(`../.${file}`).default || require(`../.${file}`)// eslint-disable-line global-require, import/no-dynamic-require
|
||||
const wrapper = renderToString(demo)
|
||||
expect(wrapper).toMatchSnapshot()
|
||||
MockDate.reset()
|
||||
})
|
||||
})
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
import moment from 'moment'
|
||||
import MockDate from 'mockdate'
|
||||
|
||||
export function setMockDate (dateString = '2017-09-18T03:30:07.795') {
|
||||
MockDate.set(moment(dateString))
|
||||
}
|
||||
|
||||
export function resetMockDate () {
|
||||
MockDate.reset()
|
||||
}
|
Loading…
Reference in new issue