diff --git a/README.md b/README.md
index 207169f..d6eca04 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
+
# Overview :
Generate CSV document according to given data.
@@ -35,7 +36,7 @@ This data can be *array of arrays*, *array of literal objects* or *string*.
**.i.e (array of arrays)**
```js
//array of arrays : each item is rendered as csv line
-data = =[
+data = [
['firstname', 'lastname', 'email'] ,
['Ahmed', 'Tomi' , 'ah@smthing.co.com'] ,
['Raed', 'Labes' , 'rl@smthing.co.com'] ,
diff --git a/package.json b/package.json
index 3522b24..5da01ba 100644
--- a/package.json
+++ b/package.json
@@ -44,12 +44,17 @@
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-0": "^6.16.0",
+ "console-info": "0.0.4",
"coveralls": "^2.11.15",
"enzyme": "^2.6.0",
"expect": "^1.20.2",
+ "jsdom": "9.8.3",
+ "jsdom-global": "2.1.0",
"mocha": "^3.2.0",
"mocha-lcov-reporter": "^1.2.0",
"react": "^15.4.1",
+ "react-addons-test-utils": "^15.4.1",
+ "react-dom": "^15.4.1",
"sinon": "^1.17.6"
},
"dependencies": {
diff --git a/src/components/Download.js b/src/components/Download.js
index 11e10db..18992a9 100644
--- a/src/components/Download.js
+++ b/src/components/Download.js
@@ -8,13 +8,19 @@ const defaultProps = {
class CSVDownload extends React.Component {
constructor(props) {
super(props);
+ this.state={};
}
+
+ buildURI() {
+ return buildURI(...arguments);
+ }
+
componentDidMount(){
- this.page = window.open(buildURI(this.props.data, this.props.headers), this.props.target, this.props.specs, this.props.replace);
+ this.state.page = window.open(this.buildURI(this.props.data, this.props.headers), this.props.target, this.props.specs, this.props.replace);
}
getWindow() {
- return this.page;
+ return this.state.page;
}
render(){
diff --git a/src/components/Link.js b/src/components/Link.js
index 0e3da47..17752e1 100644
--- a/src/components/Link.js
+++ b/src/components/Link.js
@@ -6,12 +6,17 @@ import XObject from 'x-object/safe';
class CSVLink extends React.Component {
constructor(props) {
super(props);
+ this.buildURI= this.buildURI.bind(this);
+ }
+
+ buildURI() {
+ return buildURI(...arguments);
}
render(){
return (
!PropsNotForwarded.includes(k))}
- href={buildURI(this.props.data, this.props.headers)}>
+ href={this.buildURI(this.props.data, this.props.headers)}>
{this.props.children}
)
diff --git a/test/ComponentsSpec.js b/test/ComponentsSpec.js
new file mode 100644
index 0000000..bf5e57b
--- /dev/null
+++ b/test/ComponentsSpec.js
@@ -0,0 +1,121 @@
+import 'jsdom-global/register';
+import React from 'react';
+import {
+ mount,
+ shallow
+} from 'enzyme';
+import sinon from 'sinon';
+import expect from 'expect';
+
+import {
+ CSVLink,
+ CSVDownload
+} from '../src';
+import {buildURI} from '../src/core';
+import 'console-info';
+
+
+const getAttrs =((htmlElment) => Array.from(
+ htmlElment.attributes
+ ).reduce((a, b) => {
+ a[b.name ==='class' ? 'className':b.name ] = b.value ;
+ return a;}
+ , {})
+);
+
+describe('CSVLink', () => {
+ let minProps;
+ beforeEach(() => {
+ minProps = {
+ data: [
+ ['X', 'Y'],
+ ['1', '2'],
+ ['3', '4']
+ ]
+ };
+ });
+ it(`renders without error if required props are passed`, () => {
+ const wrapper = shallow( Click here );
+ expect(wrapper.length).toEqual(1);
+ });
+
+ it(`renders anchor tag`, () => {
+ const wrapper = shallow( Click here );
+ expect(wrapper.find('a').length).toEqual(1);
+ });
+
+ it(`calls "buildURI" method on mounting`, () => {
+ const dataURI = `data:text/csv;some,thing`
+ const buildURI = sinon.stub(CSVLink.prototype, 'buildURI').returns(dataURI);
+ const wrapper = mount( Click here );
+ expect(buildURI.calledOnce).toBeTruthy();
+ buildURI.restore();
+ });
+ it(`generates CSV download link and bind it to "href" of element`, () => {
+ const linkPrefix = `data:text/csv`
+ const wrapper = mount( Click here );
+ const actualLink = wrapper.find(`a`).get(0).getAttribute('href');
+ expect(actualLink.startsWith(linkPrefix)).toBeTruthy();
+ });
+
+ it(`forwards props to anchor tag unless props is forbidden`, () => {
+ const extraProps = {
+ className:`btn`,
+ target:'_self'
+ };
+ const wrapper = mount( Click here );
+ const actualAnchorAttrs =getAttrs(wrapper.find(`a`).get(0));
+ expect(actualAnchorAttrs).toInclude(extraProps);
+
+ })
+
+ });
+
+ describe('CSVDownload', () => {
+ let minProps;
+ let manyProps;
+ beforeEach(() => {
+ minProps = {
+ data: [
+ ['X', 'Y'],
+ ['1', '2'],
+ ['3', '4']
+ ]
+ };
+ manyProps= Object.assign(minProps, {
+ target: '_blank',
+ specs: 'fullscreen=yes&height=200&status=yes',
+ replace:'no'
+ });
+ });
+
+ it(`does not render anything by default`, () => {
+ const wrapper = shallow( );
+ expect(wrapper.props().children).toNotExist();
+ });
+ it(`calls "buildURI" on mounting`, () => {
+ const dataURI = `data:text/csv;some,thing`
+ const buildURI = sinon.stub(CSVDownload.prototype, 'buildURI').returns(dataURI);
+ const wrapper = mount( );
+ expect(buildURI.calledOnce).toBeTruthy();
+ buildURI.restore();
+ });
+ it(`redirects in different page on mounting`, () => {
+ const openCallback = sinon.stub(window,'open').returns({
+ focus: ()=> {}
+ });
+ const wrapper = mount( );
+ expect(openCallback.calledWith(buildURI(manyProps.data), manyProps.target, manyProps.specs, manyProps.replace)).toBeTruthy();
+ expect(openCallback.calledOnce).toBeTruthy();
+ openCallback.restore();
+ });
+
+ it(`persists new opened window`, () => {
+ const openCallback = sinon.stub(window,'open').returns('newPage');
+ const wrapper = mount( );
+ const actualNewWindow= wrapper.instance().getWindow();
+ expect(actualNewWindow).toEqual('newPage');
+ openCallback.restore();
+
+ });
+ });