From 8f8ed4c472a5b0a239f64fc12be2dbffbf1c7c2d Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Sat, 25 Jun 2016 11:54:17 +0530 Subject: [PATCH 01/43] Fixed ratio help for operators --- app/components/query.builder.jsx | 16 ++++++++++------ app/components/ratio.gallery.jsx | 3 +-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/app/components/query.builder.jsx b/app/components/query.builder.jsx index 53c62a4..fb6687a 100644 --- a/app/components/query.builder.jsx +++ b/app/components/query.builder.jsx @@ -187,13 +187,17 @@ class QueryBuilder extends React.Component { } handleInsert(ratio) { - var selected = { - unit: ratio[0], - name: ratio[1], - description: ratio[2] + if(ratio.constructor === Array) { + var selected = { + unit: ratio[0], + name: ratio[1], + description: ratio[2] + } + this.refs.textarea.insertThis(selected.name + " ", "") + this.setState({selected: selected}) + } else { + this.refs.textarea.insertThis(ratio + " ", "") } - this.refs.textarea.insertThis(selected.name, "") - this.setState({selected: selected}) } handleSelect(selected) { diff --git a/app/components/ratio.gallery.jsx b/app/components/ratio.gallery.jsx index 09617dc..7523b59 100644 --- a/app/components/ratio.gallery.jsx +++ b/app/components/ratio.gallery.jsx @@ -108,10 +108,9 @@ class RatioGallery extends React.Component { {operators.map((operator, idx) => { - var ratio = ["", operator, ""] return this.props.onRatioClick(ratio)} + onClick={() => this.props.onRatioClick(operator)} > {operator} {" "} From e5f25b9d83050f5189b54fd7bc3056533ae94080 Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Sat, 25 Jun 2016 15:09:01 +0530 Subject: [PATCH 02/43] Updated packages --- package.json | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index 86a3901..2ba023d 100644 --- a/package.json +++ b/package.json @@ -4,33 +4,33 @@ "description": "Screener.in frontend based on Reactjs", "main": "app/index.js", "dependencies": { - "chartist": "0.9.7", - "classnames": "2.2.3", - "es6-promise": "3.1.2", + "chartist": "0.9.8", + "classnames": "2.2.5", + "es6-promise": "3.2.1", "fetch-on-rest": "1.6.6", "jest-cli": "0.8.2", - "lodash": "4.8.2", - "react": "15.0.0", - "react-addons-test-utils": "15.0.0", - "react-bootstrap": "0.28.5", - "react-dom": "15.0.0", - "react-router": "2.0.1", - "urijs": "1.17.1", - "whatwg-fetch": "0.11.0" + "lodash": "4.13.1", + "react": "15.1.0", + "react-addons-test-utils": "15.1.0", + "react-bootstrap": "0.29.5", + "react-dom": "15.1.0", + "react-router": "2.5.1", + "urijs": "1.18.1", + "whatwg-fetch": "1.0.0" }, "devDependencies": { - "babel-eslint": "^6.0.2", + "babel-eslint": "^6.1.0", "babel-loader": "6.2.4", - "babel-polyfill": "^6.7.4", - "babel-preset-es2015": "6.6.0", - "babel-preset-jest": "^10.0.1", + "babel-polyfill": "^6.9.1", + "babel-preset-es2015": "6.9.0", + "babel-preset-jest": "^13.0.0", "babel-preset-react": "6.5.0", - "eslint": "^2.7.0", - "eslint-plugin-react": "4.3.0", + "eslint": "^2.13.1", + "eslint-plugin-react": "5.2.2", "exports-loader": "0.6.3", - "http-proxy": "1.13.2", - "jest-webpack-alias": "2.2.0", - "webpack": "1.12.14" + "http-proxy": "1.14.0", + "jest-webpack-alias": "2.3.0", + "webpack": "1.13.1" }, "scripts": { "prestart": "webpack -d && (node server.js&)", From 33341bed06af04fb0eec64f3a2b24151bfea17f3 Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Sun, 26 Jun 2016 13:54:36 +0530 Subject: [PATCH 03/43] Updated Packages. Tests migrated to new version. --- app/__tests__/api-tests.js | 10 ++--- app/__tests__/watchlist-tests.js | 37 ++++++++----------- app/company/__tests__/misc-tests.js | 2 +- app/company/__tests__/peers-tests.js | 20 +++++----- app/company/company.jsx | 2 +- app/company/misc.jsx | 4 +- app/company/peers.jsx | 8 ++-- app/company/pricechart.jsx | 2 +- app/company/quickratios.jsx | 6 +-- app/company/ratios.jsx | 2 +- app/company/results.jsx | 2 +- app/components/__tests__/alerts-tests.js | 11 +++--- .../__tests__/company.search-tests.js | 14 +++---- app/components/__tests__/confirm-tests.js | 6 +-- app/components/__tests__/modal-tests.js | 11 +++--- app/components/__tests__/notify-tests.js | 5 +-- .../__tests__/query.builder-tests.js | 4 +- .../__tests__/ratio.gallery-tests.js | 2 +- .../__tests__/ratio.search-tests.js | 12 +++--- app/components/__tests__/typeahead-tests.js | 3 +- app/components/alerts.jsx | 4 +- app/components/company.search.jsx | 2 +- app/components/confirm.jsx | 2 +- app/components/modal.jsx | 2 +- app/components/notify.jsx | 3 +- app/components/query.builder.jsx | 4 +- app/components/ratio.gallery.jsx | 4 +- app/components/ratio.search.jsx | 2 +- app/components/utils.js | 2 +- app/dash.jsx | 6 +-- app/home.jsx | 2 +- app/modals/__tests__/action.rows-tests.js | 3 +- app/modals/__tests__/columns.modal-tests.js | 18 +++------ .../__tests__/watchlist.button-tests.js | 17 +++++---- app/modals/action.rows.jsx | 3 +- app/modals/columns.modal.jsx | 8 ++-- app/modals/login.modal.jsx | 3 +- app/modals/quickratios.modal.jsx | 2 +- app/modals/savescreen.modal.jsx | 9 ++--- app/modals/watchlist.button.jsx | 5 +-- app/ratios/__tests__/delete-tests.js | 14 +++---- app/ratios/__tests__/edit-tests.js | 12 +++--- app/ratios/__tests__/form-tests.js | 25 ++++++------- app/ratios/create.jsx | 4 +- app/ratios/delete.jsx | 6 +-- app/ratios/edit.jsx | 4 +- app/ratios/form.jsx | 10 ++--- app/screens/__tests__/saved.screen-tests.js | 22 +++++------ app/screens/__tests__/screens-tests.js | 28 +++++++------- app/screens/__tests__/table-tests.js | 4 +- app/screens/base.jsx | 2 +- app/screens/query.form.jsx | 2 +- app/screens/query.results.jsx | 2 +- app/screens/saved.screen.jsx | 12 +++--- app/screens/screens.jsx | 6 +-- app/screens/table.jsx | 4 +- app/talks/__tests__/talks-tests.js | 24 ++++++------ app/talks/submit.jsx | 6 +-- app/talks/talks.jsx | 8 ++-- app/user/__tests__/manage.alerts-tests.js | 27 +++++++------- app/user/__tests__/profile-tests.js | 20 +++++----- app/user/manage.alerts.jsx | 8 ++-- app/user/profile.jsx | 10 ++--- app/watchlist.jsx | 10 ++--- jest/preprocessor.js | 22 ----------- package.json | 18 ++++----- 66 files changed, 256 insertions(+), 318 deletions(-) delete mode 100644 jest/preprocessor.js diff --git a/app/__tests__/api-tests.js b/app/__tests__/api-tests.js index d5fb929..da8ec25 100644 --- a/app/__tests__/api-tests.js +++ b/app/__tests__/api-tests.js @@ -1,15 +1,15 @@ "use strict"; jest.autoMockOff(); jest.mock('fetch-on-rest'); +var api = require('../api.js'); describe('test REST apis', function () { - var api = require('app/api.js'); afterEach(function() { expect(api.getPending()).toEqual([]); }); - pit('calls the get api', function() { + it('calls the get api', function() { api.setResponse('/api/users/me/', JSON.stringify({foo: 'bar'})); return api.get(api.me).then(resp => { expect(resp).toEqual({foo: 'bar'}); @@ -26,7 +26,7 @@ describe('test REST apis', function () { }) }); - pit('calls the post api', function() { + it('calls the post api', function() { api.setResponse('/logout/', JSON.stringify({})); return api.logout().then(() => { expect(window.fetch.mock.calls.length).toBe(1); @@ -43,7 +43,7 @@ describe('test REST apis', function () { }); }); - pit('calls the delete api', function() { + it('calls the delete api', function() { api.setResponse('/api/screens/33/?foo=bar', "{}"); return api.delete(['screens', 33], {foo: 'bar'}).then(() => { expect(window.fetch).toBeCalledWith( @@ -64,7 +64,7 @@ describe('test REST apis', function () { describe('test dependent libraries', function(){ it('checks expansions', function() { - var api = require('app/api.js'); + var api = require('../api.js'); expect(api._getUrl(api.me)).toEqual('/api/users/me/'); expect(api._getUrl(api.me, {})).toEqual('/api/users/me/'); expect(api._getUrl(api.me, {foo: 'bar'})).toEqual('/api/users/me/?foo=bar'); diff --git a/app/__tests__/watchlist-tests.js b/app/__tests__/watchlist-tests.js index 8c5c199..0f454db 100644 --- a/app/__tests__/watchlist-tests.js +++ b/app/__tests__/watchlist-tests.js @@ -1,9 +1,13 @@ 'use strict'; -jest.autoMockOff(); -jest.mock('fetch-on-rest'); - - -var screen = { +jest.disableAutomock() +jest.mock('fetch-on-rest') +var api = require('../api.js'); +var React = require('react'); +var ReactDOM = require('react-dom'); +var Watchlist = require('../watchlist.jsx'); +var TestUtils = require('react-addons-test-utils'); + +var SCREEN = { ratios: [[ "Current price", "CMP", @@ -15,19 +19,17 @@ var screen = { }; describe('watchlist Tests', function() { - var api = require('app/api.js'); - var watchlist, TestUtils; + var watchlist beforeEach(function() { - var React = require('react'); - var Watchlist = require('../watchlist.jsx'); - window.loggedIn = true; - TestUtils = require('react-addons-test-utils'); var params = { search: '', query: {}, pathname: '/watchlist/' }; + window.loggedIn = true; + api.setResponse('/api/users/watchlist/', + JSON.stringify(SCREEN)); watchlist = TestUtils.renderIntoDocument( ); @@ -37,21 +39,14 @@ describe('watchlist Tests', function() { expect(api.getPending()).toEqual([]); }); - it('should show loading', function() { - var ReactDOM = require('react-dom'); + it('should load watchlist', function() { var dom = ReactDOM.findDOMNode(watchlist); expect(dom.textContent).toEqual('Loading...'); - }); - - pit('should load watchlist', function() { - api.setResponse('/api/users/watchlist/', - JSON.stringify(screen)); - return watchlist.componentDidMount().then(() => { - expect(watchlist.state.screen).toEqual(screen); + return watchlist._req.then(() => { + expect(watchlist.state.screen).toEqual(SCREEN); var table = TestUtils.findRenderedDOMComponentWithTag( watchlist, 'table'); expect(table).toBeDefined(); }); }); - }); diff --git a/app/company/__tests__/misc-tests.js b/app/company/__tests__/misc-tests.js index cada432..1615b82 100644 --- a/app/company/__tests__/misc-tests.js +++ b/app/company/__tests__/misc-tests.js @@ -29,7 +29,7 @@ var kitex = { describe('Walk tests', function () { - var api = require('app/api.js'); + var api = require('../../api.js'); var Misc, TestUtils, api, ReactDOM, React; beforeEach(function() { diff --git a/app/company/__tests__/peers-tests.js b/app/company/__tests__/peers-tests.js index 013faf8..e4092c3 100644 --- a/app/company/__tests__/peers-tests.js +++ b/app/company/__tests__/peers-tests.js @@ -1,9 +1,13 @@ "use strict"; -jest.autoMockOff(); +jest.disableAutomock(); jest.mock('fetch-on-rest'); +var api = require('../../api.js'); +var React = require('react'); +var ReactDOM = require('react-dom'); +var TestUtils = require('react-addons-test-utils'); +var Peers = require('../peers.jsx'); describe('Peers tests', function () { - var api = require('app/api.js'); var peerResults = { ratios: [], results: [] @@ -13,18 +17,14 @@ describe('Peers tests', function () { expect(api.getPending()).toEqual([]); }); - pit('renders a peers table', function() { - var React = require('react'); - var ReactDOM = require('react-dom'); - var TestUtils = require('react-addons-test-utils'); - var Peers = require('../peers.jsx'); + it('renders a peers table', function() { var props = {wid: 22, industry: 'Hi', short_name: 'hi'}; + api.setResponse('/api/company/22/peers/?industry=Hi', + JSON.stringify(peerResults)); var peers = TestUtils.renderIntoDocument( ); - api.setResponse('/api/company/22/peers/?industry=Hi', - JSON.stringify(peerResults)); - return peers.componentDidMount().then(() => { + return peers._req.then(() => { var dom = ReactDOM.findDOMNode(peers); expect(dom.textContent).toContain('Peer Comparison '); }) diff --git a/app/company/company.jsx b/app/company/company.jsx index e1e782e..25d111e 100644 --- a/app/company/company.jsx +++ b/app/company/company.jsx @@ -3,7 +3,7 @@ var React = require('react'); var isEqual = require('lodash/isEqual'); -var Utils = require('app/components/utils.js'); +var Utils = require('../components/utils.js'); var Api = require('../api.js'); var Misc = require('./misc.jsx'); var Peers = require('./peers.jsx'); diff --git a/app/company/misc.jsx b/app/company/misc.jsx index 7327b30..68c432a 100644 --- a/app/company/misc.jsx +++ b/app/company/misc.jsx @@ -1,8 +1,8 @@ "use strict"; /* global require, document, window */ var React = require('react'); -var Icon = require('app/components/icon.jsx'); -var Button = require('app/components/button.jsx'); +var Icon = require('../components/icon.jsx'); +var Button = require('../components/button.jsx'); function CompanyHeader(props) { diff --git a/app/company/peers.jsx b/app/company/peers.jsx index 82865a6..788179e 100644 --- a/app/company/peers.jsx +++ b/app/company/peers.jsx @@ -1,11 +1,9 @@ "use strict"; -/* global require, window, document */ - var React = require('react'); var api = require('../api.js'); var Link = require('react-router').Link; -var Utils = require('app/components/utils.js'); -var ManageColumns = require('app/modals/columns.modal.jsx'); +var Utils = require('../components/utils.js'); +var ManageColumns = require('../modals/columns.modal.jsx'); var Peers = React.createClass({ @@ -15,7 +13,7 @@ var Peers = React.createClass({ }, componentDidMount: function() { - return this.fetchPeers(this.props); + this._req = this.fetchPeers(this.props); }, componentWillReceiveProps: function(props) { diff --git a/app/company/pricechart.jsx b/app/company/pricechart.jsx index 88e37dc..7ef0665 100644 --- a/app/company/pricechart.jsx +++ b/app/company/pricechart.jsx @@ -5,7 +5,7 @@ var React = require('react'); var classNames = require('classnames'); var Api = require('../api.js'); var Chartist = require('chartist'); -var Utils = require('app/components/utils.js'); +var Utils = require('../components/utils.js'); var PriceChart = React.createClass({ barI: 0, diff --git a/app/company/quickratios.jsx b/app/company/quickratios.jsx index 3dfbfd6..13c4f94 100644 --- a/app/company/quickratios.jsx +++ b/app/company/quickratios.jsx @@ -3,9 +3,9 @@ var React = require('react'); var Link = require('react-router').Link; var Api = require('../api.js'); -var Utils = require('app/components/utils.js'); -var RatioSearch = require('app/components/ratio.search.jsx'); -var QuickRatiosModal = require('app/modals/quickratios.modal.jsx'); +var Utils = require('../components/utils.js'); +var RatioSearch = require('../components/ratio.search.jsx'); +var QuickRatiosModal = require('../modals/quickratios.modal.jsx'); var QuickRatios = React.createClass({ diff --git a/app/company/ratios.jsx b/app/company/ratios.jsx index ccfdf2a..3a963a0 100644 --- a/app/company/ratios.jsx +++ b/app/company/ratios.jsx @@ -1,7 +1,7 @@ "use strict"; /* global require */ var React = require('react'); -var Utils = require('app/components/utils.js'); +var Utils = require('../components/utils.js'); var URITemplate = require('urijs/src/URITemplate'); diff --git a/app/company/results.jsx b/app/company/results.jsx index 603707c..dedc6c3 100644 --- a/app/company/results.jsx +++ b/app/company/results.jsx @@ -4,7 +4,7 @@ var React = require('react'); var Api = require('../api.js'); var Link = require('react-router').Link; var classNames = require('classnames'); -var Utils = require('app/components/utils.js'); +var Utils = require('../components/utils.js'); var defaults = require('lodash/defaults'); diff --git a/app/components/__tests__/alerts-tests.js b/app/components/__tests__/alerts-tests.js index 784ffb9..a622601 100644 --- a/app/components/__tests__/alerts-tests.js +++ b/app/components/__tests__/alerts-tests.js @@ -1,14 +1,13 @@ 'use strict'; -/* global jest, require */ -jest.dontMock('../alerts.jsx'); +jest.disableAutomock(); +var React = require('react'); +var Alert = require('../alerts.jsx'); +var TestUtils = require('react-addons-test-utils'); describe('alerts Tests', function() { - var alerts, TestUtils; + var alerts beforeEach(function() { - var React = require('react'); - var Alert = require('../alerts.jsx'); - TestUtils = require('react-addons-test-utils'); var errors = new Error('Bad request'); errors.json = { display_name: 'cannot be blank' diff --git a/app/components/__tests__/company.search-tests.js b/app/components/__tests__/company.search-tests.js index b1583cb..ba95b38 100644 --- a/app/components/__tests__/company.search-tests.js +++ b/app/components/__tests__/company.search-tests.js @@ -1,15 +1,15 @@ 'use strict'; -jest.autoMockOff(); +jest.disableAutomock(); jest.mock('fetch-on-rest'); +var api = require('../../api.js'); +var React = require('react'); +var TestUtils = require('react-addons-test-utils'); +var CompanySearch = require('../company.search.jsx'); describe('Company Search Tests', function() { - var api = require('app/api.js'); - var search, TestUtils, dummy; + var search, dummy; beforeEach(function() { - var React = require('react'); - TestUtils = require('react-addons-test-utils'); - var CompanySearch = require('../company.search.jsx'); dummy = jest.genMockFunction(); search = TestUtils.renderIntoDocument( @@ -20,7 +20,7 @@ describe('Company Search Tests', function() { expect(api.getPending()).toEqual([]); }); - pit('should trigger select', function() { + it('should trigger select', function() { var company = {name: 'Patanjali', id: 7, url: '/ramdev/'}; api.setResponse('/api/company/search/?q=Patanjali', JSON.stringify([company])); var input = TestUtils.findRenderedDOMComponentWithTag( diff --git a/app/components/__tests__/confirm-tests.js b/app/components/__tests__/confirm-tests.js index bf2e620..0899adb 100644 --- a/app/components/__tests__/confirm-tests.js +++ b/app/components/__tests__/confirm-tests.js @@ -1,13 +1,13 @@ 'use strict'; -/* global jest, require */ -jest.dontMock('../confirm.jsx'); +jest.unmock('../button.jsx'); +jest.unmock('../confirm.jsx'); describe('Confirm tests', function(){ it('walk confirm test', function() { var React = require('react'); var TestUtils = require('react-addons-test-utils'); - var handleDelete = jest.genMockFunction(); + var handleDelete = jest.fn(); var Confirm = require('../confirm.jsx'); var confirm = TestUtils.renderIntoDocument( diff --git a/app/components/__tests__/modal-tests.js b/app/components/__tests__/modal-tests.js index e5f3bdd..22b619f 100644 --- a/app/components/__tests__/modal-tests.js +++ b/app/components/__tests__/modal-tests.js @@ -1,14 +1,13 @@ 'use strict'; -/* global jest, require, window */ -jest.dontMock('../modal.jsx'); +jest.disableAutomock() +var React = require('react'); +var Modal = require('../modal.jsx'); +var TestUtils = require('react-addons-test-utils'); describe('Modal Tests', function() { - var modal, TestUtils, onOpen, onClose; + var modal, onOpen, onClose; beforeEach(function() { - var React = require('react'); - var Modal = require('../modal.jsx'); - TestUtils = require('react-addons-test-utils'); window.loggedIn = true; onOpen = jest.genMockFunction(); onClose = jest.genMockFunction(); diff --git a/app/components/__tests__/notify-tests.js b/app/components/__tests__/notify-tests.js index adc7127..b5048a3 100644 --- a/app/components/__tests__/notify-tests.js +++ b/app/components/__tests__/notify-tests.js @@ -1,6 +1,5 @@ 'use strict'; -/* global setTimeout */ -jest.dontMock('app/components/button.jsx'); +jest.unmock('../../components/button.jsx'); describe('Notify Tests', function() { var notify, button, TestUtils, dummy; @@ -30,7 +29,7 @@ describe('Notify Tests', function() { ); }); - pit('should show proceccsing', function() { + it('should show proceccsing', function() { expect(dummy).not.toBeCalled(); expect(notify.state.status).toBe('initial'); TestUtils.Simulate.click(button); diff --git a/app/components/__tests__/query.builder-tests.js b/app/components/__tests__/query.builder-tests.js index b8c4c6a..a1efea6 100644 --- a/app/components/__tests__/query.builder-tests.js +++ b/app/components/__tests__/query.builder-tests.js @@ -1,7 +1,5 @@ 'use strict' -jest.dontMock('../typeahead.util.js'); -jest.dontMock('../query.builder.jsx'); -jest.dontMock('../cursor.js'); +jest.disableAutomock() var OPTIONS = [{"short_name":"B.V.","name":"Book value","unit":"Rs.","description":"Book value per share"},{"short_name":"CMP / BV","name":"Price to book value","unit":"","description":"Price to book value of the stock."},{"short_name":"BV Unq Invest","name":"Book value of unquoted investments","unit":"Rs.Cr.","description":"Book value of unquoted investments from latest balance sheet."},{"short_name":"PB X PE","name":"PB X PE","unit":"","description":"Graham number is the formula Ben Graham used to calculate the maximum price one should pay for a stock. As per this rule, the product of a stock’s price to earnings (P/E) and price to book value (P/BV) should not be more than 22.5 i.e., P/E of 15 multiplied by P/BV of 1.5."},{"short_name":"Net worth","name":"Net worth","unit":"Rs.Cr.","description":"Company's net worth (or total book value)"},{"short_name":"Ind PBV","name":"Industry PBV","unit":"","description":"Industrial Price to Book Value"}] diff --git a/app/components/__tests__/ratio.gallery-tests.js b/app/components/__tests__/ratio.gallery-tests.js index 3adf061..2a0ce70 100644 --- a/app/components/__tests__/ratio.gallery-tests.js +++ b/app/components/__tests__/ratio.gallery-tests.js @@ -1,5 +1,5 @@ 'use strict'; -jest.dontMock('../ratio.gallery.jsx'); +jest.disableAutomock(); var RATIOS = { "user_ratios":[], "system_ratios":[ diff --git a/app/components/__tests__/ratio.search-tests.js b/app/components/__tests__/ratio.search-tests.js index 3323cd8..684252c 100644 --- a/app/components/__tests__/ratio.search-tests.js +++ b/app/components/__tests__/ratio.search-tests.js @@ -1,16 +1,16 @@ 'use strict'; jest.autoMockOff(); jest.mock('fetch-on-rest'); +var api = require('../../api.js'); +var React = require('react'); +var RatioSearch = require('../ratio.search.jsx'); +var TestUtils = require('react-addons-test-utils'); describe('Ratio Search Tests', function() { - var api = require('app/api.js'); - var RatioSearch, search, TestUtils, dummy, React; + var search, dummy; beforeEach(function() { - React = require('react'); - RatioSearch = require('../ratio.search.jsx'); - TestUtils = require('react-addons-test-utils'); dummy = jest.genMockFunction(); window.loggedIn = true; search = TestUtils.renderIntoDocument( @@ -34,7 +34,7 @@ describe('Ratio Search Tests', function() { expect(divs.textContent).toEqual('Please login to use this feature.'); }); - pit('should trigger select', function() { + it('should trigger select', function() { var input = TestUtils.findRenderedDOMComponentWithTag( search, 'input' ); diff --git a/app/components/__tests__/typeahead-tests.js b/app/components/__tests__/typeahead-tests.js index 97981fc..b970aad 100644 --- a/app/components/__tests__/typeahead-tests.js +++ b/app/components/__tests__/typeahead-tests.js @@ -1,6 +1,5 @@ 'use strict'; -jest.dontMock('../typeahead.util.js'); -jest.dontMock('../typeahead.jsx'); +jest.disableAutomock() describe('Typeahead', function(){ diff --git a/app/components/alerts.jsx b/app/components/alerts.jsx index a9e30dd..ff4c437 100644 --- a/app/components/alerts.jsx +++ b/app/components/alerts.jsx @@ -1,10 +1,8 @@ "use strict"; -/* global require, document, window */ - var React = require('react'); var map = require('lodash/map'); var startCase = require('lodash/startCase'); -var Icon = require('app/components/icon.jsx'); +var Icon = require('./icon.jsx'); function Alerts(props) { diff --git a/app/components/company.search.jsx b/app/components/company.search.jsx index e3d4e62..3104ff4 100644 --- a/app/components/company.search.jsx +++ b/app/components/company.search.jsx @@ -2,7 +2,7 @@ /* global require, window */ var React = require('react'); var classNames = require('classnames'); -var api = require('app/api.js'); +var api = require('../api.js'); var Typeahead = require('./typeahead.jsx'); var Icon = require('./icon.jsx'); diff --git a/app/components/confirm.jsx b/app/components/confirm.jsx index 6853dbc..2ae96af 100644 --- a/app/components/confirm.jsx +++ b/app/components/confirm.jsx @@ -1,7 +1,7 @@ "use strict"; var React = require('react'); var classNames = require('classnames'); -var Button = require('app/components/button.jsx'); +var Button = require('./button.jsx'); class Confirm extends React.Component { diff --git a/app/components/modal.jsx b/app/components/modal.jsx index 8268293..db9cfa8 100644 --- a/app/components/modal.jsx +++ b/app/components/modal.jsx @@ -2,7 +2,7 @@ /* global require, document, window */ var React = require('react'); -var Button = require('app/components/button.jsx'); +var Button = require('../components/button.jsx'); var Login = require('./login.jsx'); diff --git a/app/components/notify.jsx b/app/components/notify.jsx index 18ecffa..46c87bb 100644 --- a/app/components/notify.jsx +++ b/app/components/notify.jsx @@ -1,7 +1,6 @@ "use strict"; - var React = require('react'); -var Button = require('app/components/button.jsx'); +var Button = require('./button.jsx'); class Confirm extends React.Component { diff --git a/app/components/query.builder.jsx b/app/components/query.builder.jsx index fb6687a..6b806a4 100644 --- a/app/components/query.builder.jsx +++ b/app/components/query.builder.jsx @@ -1,10 +1,10 @@ "use strict"; import React from 'react' import classNames from 'classnames' -import TypeUtil from 'app/components/typeahead.util.js' +import TypeUtil from './typeahead.util.js' import endsWith from 'lodash/endsWith' import debounce from 'lodash/debounce' -import Api from 'app/api.js' +import Api from '../api.js' import getLastWord from './cursor.js' import RatioGallery from './ratio.gallery.jsx' diff --git a/app/components/ratio.gallery.jsx b/app/components/ratio.gallery.jsx index 7523b59..3360f55 100644 --- a/app/components/ratio.gallery.jsx +++ b/app/components/ratio.gallery.jsx @@ -1,7 +1,7 @@ "use strict"; import React from 'react' -import Button from 'app/components/button.jsx' -import Api from 'app/api.js' +import Button from './button.jsx' +import Api from '../api.js' function RatiosList(props) { diff --git a/app/components/ratio.search.jsx b/app/components/ratio.search.jsx index bd241fe..45ed035 100644 --- a/app/components/ratio.search.jsx +++ b/app/components/ratio.search.jsx @@ -1,7 +1,7 @@ "use strict"; /* global require */ var React = require('react'); -var Typeahead = require('app/components/typeahead.jsx'); +var Typeahead = require('./typeahead.jsx'); var api = require('../api.js'); diff --git a/app/components/utils.js b/app/components/utils.js index ed96535..1e98761 100644 --- a/app/components/utils.js +++ b/app/components/utils.js @@ -4,7 +4,7 @@ function setTitle(title) { var fullTitle = title.trim() + ' - Screener.in'; - document.title = fullTitle; + window.document.title = fullTitle; var location = window.location.pathname; if (process.env.NODE_ENV !== "production") { return; diff --git a/app/dash.jsx b/app/dash.jsx index 1cf42df..a49d4db 100644 --- a/app/dash.jsx +++ b/app/dash.jsx @@ -2,10 +2,10 @@ /* global require, document, window */ var React = require('react'); -var WatchlistButton = require('app/modals/watchlist.button.jsx'); -var QueryForm = require('app/screens/query.form.jsx'); +var WatchlistButton = require('./modals/watchlist.button.jsx'); +var QueryForm = require('./screens/query.form.jsx'); var Link = require('react-router').Link; -var Utils = require('app/components/utils.js'); +var Utils = require('./components/utils.js'); var Api = require('./api.js'); diff --git a/app/home.jsx b/app/home.jsx index 383f559..4362139 100644 --- a/app/home.jsx +++ b/app/home.jsx @@ -2,7 +2,7 @@ /* global require, document */ var React = require('react'); -var CompanySearch = require('app/components/company.search.jsx'); +var CompanySearch = require('./components/company.search.jsx'); function Home(props, context) { diff --git a/app/modals/__tests__/action.rows-tests.js b/app/modals/__tests__/action.rows-tests.js index f8d05fd..e04eba4 100644 --- a/app/modals/__tests__/action.rows-tests.js +++ b/app/modals/__tests__/action.rows-tests.js @@ -1,6 +1,5 @@ 'use strict'; -/* global jest, require */ -jest.dontMock('../action.rows.jsx'); +jest.disableAutomock() describe('action.rows Tests', function() { var actions, TestUtils, dummy; diff --git a/app/modals/__tests__/columns.modal-tests.js b/app/modals/__tests__/columns.modal-tests.js index 74b599b..2746274 100644 --- a/app/modals/__tests__/columns.modal-tests.js +++ b/app/modals/__tests__/columns.modal-tests.js @@ -1,19 +1,13 @@ 'use strict'; -/* global jest, require, window */ -jest.autoMockOff(); +jest.disableAutomock(); jest.mock('fetch-on-rest'); +var api = require('../../api.js'); +var React = require('react'); +var TestUtils = require('react-addons-test-utils'); +var ManageColumns = require('../columns.modal.jsx'); describe('Columns modal tests', function() { - var api = require('app/api.js'); - var React, TestUtils, ManageColumns; - - beforeEach(function() { - React = require('react'); - TestUtils = require('react-addons-test-utils'); - ManageColumns = require('../columns.modal.jsx'); - }); - afterEach(function() { expect(api.getPending()).toEqual([]); }); @@ -32,7 +26,7 @@ describe('Columns modal tests', function() { expect(title.textContent).toEqual('Please register to use this feature'); }); - pit('shows modal box', function() { + it('shows modal box', function() { window.loggedIn = true; api.setResponse('/api/users/me/', JSON.stringify({icolumns: 'PE;CMP'})); var onClose = jest.genMockFunction(); diff --git a/app/modals/__tests__/watchlist.button-tests.js b/app/modals/__tests__/watchlist.button-tests.js index cee4d2c..fd58e4d 100644 --- a/app/modals/__tests__/watchlist.button-tests.js +++ b/app/modals/__tests__/watchlist.button-tests.js @@ -1,16 +1,17 @@ 'use strict'; -jest.autoMockOff(); +jest.disableAutomock(); jest.mock('fetch-on-rest'); +var TestUtils = require('react-addons-test-utils'); +var React = require('react'); +var WatchlistButton = require('../watchlist.button.jsx'); +var api = require('../../api.js'); + describe('Watchlist Button tests', function() { - var api = require('../../api.js'); - var TestUtils, watchlist; + var watchlist; beforeEach(function() { window.loggedIn = true; - TestUtils = require('react-addons-test-utils'); - var React = require('react'); - var WatchlistButton = require('../watchlist.button.jsx'); var onClose = jest.genMockFunction(); watchlist = TestUtils.renderIntoDocument( @@ -21,7 +22,7 @@ describe('Watchlist Button tests', function() { expect(api.getPending()).toEqual([]); }); - pit('should load companies on open', function() { + it('should load companies on open', function() { // Open the modal var button = TestUtils.findRenderedDOMComponentWithTag( watchlist, 'button' @@ -34,7 +35,7 @@ describe('Watchlist Button tests', function() { }); }) - pit('adds company', function() { + it('adds company', function() { var company = {name: 'Patanjali', id: 7, url: '/ramdev/'}; api.setResponse('/api/company/7/favorite/', JSON.stringify([company])); return watchlist.handleAdd(company).then(() => { diff --git a/app/modals/action.rows.jsx b/app/modals/action.rows.jsx index 51e01bb..57f594f 100644 --- a/app/modals/action.rows.jsx +++ b/app/modals/action.rows.jsx @@ -1,8 +1,7 @@ "use strict"; var React = require('react'); var classNames = require('classnames'); -var Icon = require('app/components/icon.jsx'); -var Button = require('app/components/button.jsx'); +var Icon = require('../components/icon.jsx'); var ActionRows = React.createClass({ diff --git a/app/modals/columns.modal.jsx b/app/modals/columns.modal.jsx index f62c65d..508f659 100644 --- a/app/modals/columns.modal.jsx +++ b/app/modals/columns.modal.jsx @@ -1,11 +1,11 @@ "use strict"; /* global require, window */ var React = require('react'); -var Modal = require('app/components/modal.jsx'); -var Confirm = require('app/components/confirm.jsx'); -var Icon = require('app/components/icon.jsx'); +var Modal = require('../components/modal.jsx'); +var Confirm = require('../components/confirm.jsx'); +var Icon = require('../components/icon.jsx'); var Link = require('react-router').Link; -var RatioSearch = require('app/components/ratio.search.jsx'); +var RatioSearch = require('../components/ratio.search.jsx'); var api = require('../api.js'); var ActionRows = require('./action.rows.jsx'); diff --git a/app/modals/login.modal.jsx b/app/modals/login.modal.jsx index 346ad2b..60af5d8 100644 --- a/app/modals/login.modal.jsx +++ b/app/modals/login.modal.jsx @@ -1,7 +1,6 @@ "use strict"; -/* global require, window */ var React = require('react'); -var Modal = require('app/components/modal.jsx'); +var Modal = require('./modal.jsx'); var LoginModal = React.createClass({ diff --git a/app/modals/quickratios.modal.jsx b/app/modals/quickratios.modal.jsx index 38cca89..852bf2c 100644 --- a/app/modals/quickratios.modal.jsx +++ b/app/modals/quickratios.modal.jsx @@ -1,7 +1,7 @@ "use strict"; /* global require */ var React = require('react'); -var Modal = require('app/components/modal.jsx'); +var Modal = require('../components/modal.jsx'); var Api = require('../api.js'); var ActionRows = require('./action.rows.jsx'); diff --git a/app/modals/savescreen.modal.jsx b/app/modals/savescreen.modal.jsx index c309642..25f7fbc 100644 --- a/app/modals/savescreen.modal.jsx +++ b/app/modals/savescreen.modal.jsx @@ -1,11 +1,10 @@ "use strict"; -/* global require */ var React = require('react'); -var Button = require('app/components/button.jsx'); -var Modal = require('app/components/modal.jsx'); +var Button = require('../components/button.jsx'); +var Modal = require('../components/modal.jsx'); var Api = require('../api.js'); -var Alerts = require('app/components/alerts.jsx'); -var utils = require('app/components/utils.js'); +var Alerts = require('../components/alerts.jsx'); +var utils = require('../components/utils.js'); var SaveScreenModal = React.createClass({ diff --git a/app/modals/watchlist.button.jsx b/app/modals/watchlist.button.jsx index 8d0b89b..465e11a 100644 --- a/app/modals/watchlist.button.jsx +++ b/app/modals/watchlist.button.jsx @@ -1,8 +1,7 @@ "use strict"; -/* global require, window */ var React = require('react'); -var Modal = require('app/components/modal.jsx'); -var CompanySearch = require('app/components/company.search.jsx'); +var Modal = require('../components/modal.jsx'); +var CompanySearch = require('../components/company.search.jsx'); var api = require('../api.js'); var ActionRows = require('./action.rows.jsx'); diff --git a/app/ratios/__tests__/delete-tests.js b/app/ratios/__tests__/delete-tests.js index b510c3e..1197f9b 100644 --- a/app/ratios/__tests__/delete-tests.js +++ b/app/ratios/__tests__/delete-tests.js @@ -1,6 +1,11 @@ 'use strict' -jest.autoMockOff() +jest.disableAutomock() jest.mock('fetch-on-rest') +var api = require('../../api.js') +var React = require('react') +var RatioDelete = require('../delete.jsx') +var TestUtils = require('react-addons-test-utils') + var DEPENDENTS = { "screens":[], @@ -10,14 +15,9 @@ var DEPENDENTS = { } describe('Ratio Delete Unit Tests', function() { - var api = require('app/api.js') var confirm beforeEach(function() { - var React = require('react') - var RatioDelete = require('../delete.jsx') - var TestUtils = require('react-addons-test-utils') - api.setResponse('/api/ratios/33/', JSON.stringify(DEPENDENTS)) confirm = TestUtils.renderIntoDocument( @@ -28,7 +28,7 @@ describe('Ratio Delete Unit Tests', function() { expect(api.getPending()).toEqual([]) }) - pit('should confirm delete', function() { + it('should confirm delete', function() { return confirm._req.then(() => { expect(confirm.state.dependents).toEqual(DEPENDENTS) api.setResponse('/api/ratios/33/?confirm=true', '[]') diff --git a/app/ratios/__tests__/edit-tests.js b/app/ratios/__tests__/edit-tests.js index fb8c238..6ba272f 100644 --- a/app/ratios/__tests__/edit-tests.js +++ b/app/ratios/__tests__/edit-tests.js @@ -1,19 +1,19 @@ 'use strict' jest.autoMockOff() jest.mock('fetch-on-rest') +var api = require('../../api.js') +var React = require('react') +var RatioEdit = require('../edit.jsx') +var TestUtils = require('react-addons-test-utils') + var FORMHTML = '' var RATIO = {"id":33,"formula":"Current price / EPS latest quarter","ratio_unit":"","ratio_name":"Quarterly PE2","short_name":"PE Qtr2","description":"Wow"} describe('Ratio Edit Unit Tests', function() { - var api = require('app/api.js') var form beforeEach(function() { - var React = require('react') - var RatioEdit = require('../edit.jsx') - var TestUtils = require('react-addons-test-utils') - api.setResponse('/api/ratios/33.html', FORMHTML) api.setResponse('/api/ratios/33/', JSON.stringify(RATIO)) form = TestUtils.renderIntoDocument( @@ -25,7 +25,7 @@ describe('Ratio Edit Unit Tests', function() { expect(api.getPending()).toEqual([]) }) - pit('should load form and ratio', function() { + it('should load form and ratio', function() { expect(form.state.formHTML).toEqual(false) return form._req.then(() => { expect(form.state.ratio).toEqual(RATIO) diff --git a/app/ratios/__tests__/form-tests.js b/app/ratios/__tests__/form-tests.js index 5c29fe2..fb02579 100644 --- a/app/ratios/__tests__/form-tests.js +++ b/app/ratios/__tests__/form-tests.js @@ -1,7 +1,10 @@ 'use strict' -jest.autoMockOff() +jest.disableAutomock() jest.mock('fetch-on-rest') -var api = require('app/api.js') +var api = require('../../api.js') +var React = require('react') +var RatioForm = require('../form.jsx') +var TestUtils = require('react-addons-test-utils') var PREVIEW = [{"preview": 100.1, "short_name": "Reliance Inds."}, {"preview": 50.76, "short_name": "TCS"}] @@ -10,12 +13,9 @@ var EVENT = { } describe('Form Tests for creation', function() { - var form, TestUtils + var form beforeEach(function() { - var React = require('react') - var RatioForm = require('../form.jsx') - TestUtils = require('react-addons-test-utils') var formHTML = '' form = TestUtils.renderIntoDocument( @@ -26,7 +26,7 @@ describe('Form Tests for creation', function() { expect(api.getPending()).toEqual([]) }) - pit('should show preview', function() { + it('should show preview', function() { expect(form.state.isPreview).toEqual(false) api.setResponse('/api/ratios/preview/', '[]') return form.handleSubmit(EVENT).then(() => { @@ -35,7 +35,7 @@ describe('Form Tests for creation', function() { }) }) - pit('should create new ratio', function() { + it('should create new ratio', function() { form.setState({isPreview: PREVIEW}) jest.runAllTimers() api.setResponse('/api/ratios/', '[]') @@ -47,12 +47,9 @@ describe('Form Tests for creation', function() { describe('Form Tests for updation', function() { - var form, TestUtils + var form beforeEach(function() { - var React = require('react') - var RatioForm = require('../form.jsx') - TestUtils = require('react-addons-test-utils') var formHTML = '' form = TestUtils.renderIntoDocument( { expect(form.state.isPreview).toEqual([]) }) }) - pit('should update existing ratio', function() { + it('should update existing ratio', function() { form.setState({isPreview: PREVIEW}) jest.runAllTimers() api.setResponse('/api/ratios/33/', '[]') diff --git a/app/ratios/create.jsx b/app/ratios/create.jsx index 541d0f1..eacfefd 100644 --- a/app/ratios/create.jsx +++ b/app/ratios/create.jsx @@ -1,7 +1,7 @@ "use strict"; import React from 'react' -import api from 'app/api.js' -import Utils from 'app/components/utils.js' +import api from '../api.js' +import Utils from '../components/utils.js' import RatioForm from './form.jsx' import {Link} from 'react-router'; diff --git a/app/ratios/delete.jsx b/app/ratios/delete.jsx index e41d8b7..adcf479 100644 --- a/app/ratios/delete.jsx +++ b/app/ratios/delete.jsx @@ -1,9 +1,9 @@ "use strict"; import React from 'react' import {Link} from 'react-router' -import api from 'app/api.js' -import Button from 'app/components/button.jsx' -import Utils from 'app/components/utils.js' +import api from '../api.js' +import Button from '../components/button.jsx' +import Utils from '../components/utils.js' class DeleteRatio extends React.Component { diff --git a/app/ratios/edit.jsx b/app/ratios/edit.jsx index 7781364..3c15ace 100644 --- a/app/ratios/edit.jsx +++ b/app/ratios/edit.jsx @@ -1,7 +1,7 @@ "use strict"; import React from 'react' -import api from 'app/api.js' -import Utils from 'app/components/utils.js' +import api from '../api.js' +import Utils from '../components/utils.js' import RatioForm from './form.jsx' diff --git a/app/ratios/form.jsx b/app/ratios/form.jsx index 99ff240..ff103cf 100644 --- a/app/ratios/form.jsx +++ b/app/ratios/form.jsx @@ -1,11 +1,11 @@ "use strict"; import React from 'react' -import api from 'app/api.js' +import api from '../api.js' import classNames from 'classnames' -import QueryBuilder from 'app/components/query.builder.jsx' -import Alert from 'app/components/alerts.jsx' -import Utils from 'app/components/utils.js' -import Icon from 'app/components/icon.jsx' +import QueryBuilder from '../components/query.builder.jsx' +import Alert from '../components/alerts.jsx' +import Utils from '../components/utils.js' +import Icon from '../components/icon.jsx' class RatioForm extends React.Component { diff --git a/app/screens/__tests__/saved.screen-tests.js b/app/screens/__tests__/saved.screen-tests.js index 2da923d..48a064e 100644 --- a/app/screens/__tests__/saved.screen-tests.js +++ b/app/screens/__tests__/saved.screen-tests.js @@ -1,7 +1,11 @@ 'use strict'; -/* global jest, require */ -jest.autoMockOff(); +jest.disableAutomock(); jest.mock('fetch-on-rest'); +jest.mock('../../components/utils.js') +var api = require('../../api.js'); +var React = require('react'); +var Screen = require('../saved.screen.jsx'); +var TestUtils = require('react-addons-test-utils'); const screenResult = { name: 'Foo Bar', @@ -14,13 +18,11 @@ const screenResult = { }; describe('Tests for Saved Screen', function() { - var api = require('app/api.js'); - var screen, TestUtils; + var screen beforeEach(function() { - var React = require('react'); - var Screen = require('../saved.screen.jsx'); - TestUtils = require('react-addons-test-utils'); + api.setResponse('/api/screens/3/?foo=bar', + JSON.stringify(screenResult)); screen = TestUtils.renderIntoDocument( { + it('should load the screen', function() { + return screen._req.then(() => { expect(1).toEqual(1); }) }) diff --git a/app/screens/__tests__/screens-tests.js b/app/screens/__tests__/screens-tests.js index 572e79c..400cb74 100644 --- a/app/screens/__tests__/screens-tests.js +++ b/app/screens/__tests__/screens-tests.js @@ -1,16 +1,21 @@ 'use strict'; -jest.autoMockOff(); -jest.mock('fetch-on-rest'); +jest.disableAutomock() +jest.mock('fetch-on-rest') +var api = require('../../api.js'); +var React = require('react'); +var Screens = require('../screens.jsx'); +var TestUtils = require('react-addons-test-utils'); describe('Screens Tests', function() { - var api = require('../../api.js'); - var screens, TestUtils; + var results = [ + {url: '/foo/', name: 'Foo', description: 'FooBar'}, + {url: '/bar/', name: 'Bar', description: 'BarOne'} + ]; + var screens; beforeEach(function() { - var React = require('react'); - var Screens = require('../screens.jsx'); - TestUtils = require('react-addons-test-utils'); + api.setResponse('/api/screens/popular/', JSON.stringify({results: results})); screens = TestUtils.renderIntoDocument(); }); @@ -18,13 +23,8 @@ describe('Screens Tests', function() { expect(api.getPending()).toEqual([]); }); - pit('should fetch screens', function() { - var results = [ - {url: '/foo/', name: 'Foo', description: 'FooBar'}, - {url: '/bar/', name: 'Bar', description: 'BarOne'} - ]; - api.setResponse('/api/screens/popular/', JSON.stringify({results: results})); - return screens.componentDidMount().then(() => { + it('should fetch screens', function() { + return screens._req.then(() => { expect(screens.state.screens.results).toEqual(results); }) }); diff --git a/app/screens/__tests__/table-tests.js b/app/screens/__tests__/table-tests.js index 1bded9d..49400ac 100644 --- a/app/screens/__tests__/table-tests.js +++ b/app/screens/__tests__/table-tests.js @@ -1,7 +1,5 @@ 'use strict'; -/* global jest, require */ -jest.dontMock('../table.jsx'); -jest.dontMock('app/components/utils.js'); +jest.autoMockOff() describe('Table Tests', function(){ diff --git a/app/screens/base.jsx b/app/screens/base.jsx index 1d09a15..28f4df9 100644 --- a/app/screens/base.jsx +++ b/app/screens/base.jsx @@ -3,7 +3,7 @@ var React = require('react'); var QueryForm = require('./query.form.jsx'); -var Alerts = require('app/components/alerts.jsx'); +var Alerts = require('../components/alerts.jsx'); function ScreenBase(props) { diff --git a/app/screens/query.form.jsx b/app/screens/query.form.jsx index f2a7d9b..d02240a 100644 --- a/app/screens/query.form.jsx +++ b/app/screens/query.form.jsx @@ -1,6 +1,6 @@ "use strict"; var React = require('react'); -var QueryBuilder = require('app/components/query.builder.jsx'); +var QueryBuilder = require('../components/query.builder.jsx'); function QueryForm(props) { var assist = { diff --git a/app/screens/query.results.jsx b/app/screens/query.results.jsx index d1feaa7..df23d04 100644 --- a/app/screens/query.results.jsx +++ b/app/screens/query.results.jsx @@ -2,7 +2,7 @@ var React = require('react'); var ManageColumns = require('app/modals/columns.modal.jsx'); var SaveScreenModal = require('app/modals/savescreen.modal.jsx'); -var Utils = require('app/components/utils.js'); +var Utils = require('../components/utils.js'); var Api = require('../api.js'); var UserTable = require('./table.jsx'); var ScreenBase = require('./base.jsx'); diff --git a/app/screens/saved.screen.jsx b/app/screens/saved.screen.jsx index c4f0e63..800c5f7 100644 --- a/app/screens/saved.screen.jsx +++ b/app/screens/saved.screen.jsx @@ -1,12 +1,10 @@ "use strict"; -/* global require, document */ - var React = require('react'); -var ManageColumns = require('app/modals/columns.modal.jsx'); -var Confirm = require('app/components/confirm.jsx'); -var Notify = require('app/components/notify.jsx'); +var ManageColumns = require('../modals/columns.modal.jsx'); +var Confirm = require('../components/confirm.jsx'); +var Notify = require('../components/notify.jsx'); var api = require('../api.js'); -var Utils = require('app/components/utils.js'); +var Utils = require('../components/utils.js'); var UserTable = require('./table.jsx'); var ScreenBase = require('./base.jsx'); @@ -25,7 +23,7 @@ class Screen extends React.Component { } componentDidMount() { - return this.fetchResults( + this._req = this.fetchResults( this.props.params.screenId, this.props.location.query ); diff --git a/app/screens/screens.jsx b/app/screens/screens.jsx index 25dfa6c..40a8a84 100644 --- a/app/screens/screens.jsx +++ b/app/screens/screens.jsx @@ -1,10 +1,10 @@ "use strict"; /* global document */ var React = require('react'); -var Button = require('app/components/button.jsx'); +var Button = require('../components/button.jsx'); var Link = require('react-router').Link; var api = require('../api.js'); -var Utils = require('app/components/utils.js'); +var Utils = require('../components/utils.js'); function SearchForm(props) { @@ -71,7 +71,7 @@ var Screens = React.createClass({ componentDidMount: function() { Utils.setTitle('Browse Screens'); - return api.get(['screens', 'popular']).then(resp => { + this._req = api.get(['screens', 'popular']).then(resp => { this.setState({ screens: resp, searched: false diff --git a/app/screens/table.jsx b/app/screens/table.jsx index 362df51..d2b5199 100644 --- a/app/screens/table.jsx +++ b/app/screens/table.jsx @@ -1,9 +1,7 @@ "use strict"; -/* global require, window, document */ - var React = require('react'); var Link = require('react-router').Link; -var Utils = require('app/components/utils.js'); +var Utils = require('../components/utils.js'); var defaults = require('lodash/defaults'); var classNames = require('classnames'); diff --git a/app/talks/__tests__/talks-tests.js b/app/talks/__tests__/talks-tests.js index 1b53ec4..de9d36e 100644 --- a/app/talks/__tests__/talks-tests.js +++ b/app/talks/__tests__/talks-tests.js @@ -1,6 +1,10 @@ 'use strict'; -jest.autoMockOff(); +jest.disableAutomock(); jest.mock('fetch-on-rest'); +var api = require('../../api.js'); +var React = require('react'); +var Talks = require('../talks.jsx'); +var TestUtils = require('react-addons-test-utils'); var results = [ { @@ -9,17 +13,16 @@ var results = [ ]; describe('talks Tests', function() { - var api = require('app/api.js'); - var talks, TestUtils; + var talks beforeEach(function() { - var React = require('react'); - var Talks = require('../talks.jsx'); - TestUtils = require('react-addons-test-utils'); var params = {}; var location = {query: {}}; window.loggedIn = true; window.userId = 32; + api.setResponse('/api/talks/?tab=top&page=1', + JSON.stringify({results: results})); + api.setResponse('/api/talks/voted/', []); talks = TestUtils.renderIntoDocument( ); @@ -29,18 +32,15 @@ describe('talks Tests', function() { expect(api.getPending()).toEqual([]); }); - pit('should load talks', function() { - api.setResponse('/api/talks/?tab=top&page=1', - JSON.stringify({results: results})); - api.setResponse('/api/talks/voted/', []); - return talks.componentDidMount().then(() => { + it('should load talks', function() { + return talks._req.then(() => { expect(talks.state.talks.results).toEqual(results); var latest = TestUtils.scryRenderedDOMComponentsWithTag(talks, 'a')[0]; expect(latest.textContent).toEqual('Goto Latest Links'); }) }); - pit('should fetch new talks', function() { + it('should fetch new talks', function() { var newProps = { params: {tab: 'latest'}, location: {query: {}} diff --git a/app/talks/submit.jsx b/app/talks/submit.jsx index 9124914..1d4e046 100644 --- a/app/talks/submit.jsx +++ b/app/talks/submit.jsx @@ -1,9 +1,9 @@ "use strict"; var React = require('react'); var api = require('../api.js'); -var Utils = require('app/components/utils.js'); -var Alerts = require('app/components/alerts.jsx'); -var Icon = require('app/components/icon.jsx'); +var Utils = require('../components/utils.js'); +var Alerts = require('../components/alerts.jsx'); +var Icon = require('../components/icon.jsx'); function Header() { diff --git a/app/talks/talks.jsx b/app/talks/talks.jsx index b1eb95d..6026e11 100644 --- a/app/talks/talks.jsx +++ b/app/talks/talks.jsx @@ -1,9 +1,9 @@ "use strict"; var React = require('react'); var Link = require('react-router').Link; -var Utils = require('app/components/utils.js'); -var Icon = require('app/components/icon.jsx'); -var api = require('app/api.js'); +var Utils = require('../components/utils.js'); +var Icon = require('../components/icon.jsx'); +var api = require('../api.js'); var startCase = require('lodash/startCase'); @@ -44,7 +44,7 @@ var Talks = React.createClass({ componentDidMount: function() { this.fetchStats(); - return this.fetchResults(this.props); + this._req = this.fetchResults(this.props); }, componentWillReceiveProps: function(props) { diff --git a/app/user/__tests__/manage.alerts-tests.js b/app/user/__tests__/manage.alerts-tests.js index eb89ca3..16e1e85 100644 --- a/app/user/__tests__/manage.alerts-tests.js +++ b/app/user/__tests__/manage.alerts-tests.js @@ -1,18 +1,21 @@ 'use strict'; -/* global jest, require */ -jest.autoMockOff(); +jest.disableAutomock(); jest.mock('fetch-on-rest'); +var ManageAlerts = require('../manage.alerts.jsx'); +var React = require('react'); +var TestUtils = require('react-addons-test-utils'); +var api = require('../../api.js'); describe('alerts Tests', function() { - var api = require('../../api.js'); - var alerts, TestUtils; + var alerts beforeEach(function() { - var React = require('react'); - var ManageAlerts = require('../manage.alerts.jsx'); - TestUtils = require('react-addons-test-utils'); window.loggedIn = true; window.userId = 7; + api.setResponse('/api/alerts/', JSON.stringify( + {results: [{name: 'Foo'}]})); + api.setResponse('/api/users/me/', JSON.stringify({ + watchlist_alert: false})); alerts = TestUtils.renderIntoDocument( ); @@ -22,17 +25,13 @@ describe('alerts Tests', function() { expect(api.getPending()).toEqual([]); }); - pit("should get user's alerts", function() { - api.setResponse('/api/users/me/', JSON.stringify({ - watchlist_alert: false})); - api.setResponse('/api/alerts/', JSON.stringify( - {results: [{name: 'Foo'}]})); - return alerts.componentDidMount().then(() => { + it("should get user's alerts", function() { + return alerts._req.then(() => { expect(alerts.state.watchlistAlert).toBe(false); }) }); - pit("should toggle watchlist alerts", function() { + it("should toggle watchlist alerts", function() { window.fetch.mockClear(); api.setResponse('/api/users/7/', '{}'); return alerts.handleWatchlistToggle().then(() => { diff --git a/app/user/__tests__/profile-tests.js b/app/user/__tests__/profile-tests.js index beffecf..50740e6 100644 --- a/app/user/__tests__/profile-tests.js +++ b/app/user/__tests__/profile-tests.js @@ -1,18 +1,19 @@ 'use strict'; /* global jest, require */ -jest.autoMockOff(); +jest.disableAutomock() jest.mock('fetch-on-rest'); +var api = require('../../api.js'); +var React = require('react'); +var Profile = require('../profile.jsx'); +var TestUtils = require('react-addons-test-utils'); describe('profile Tests', function() { - var api = require('../../api.js'); - var profile, TestUtils; + var profile beforeEach(function() { - var React = require('react'); - var Profile = require('../profile.jsx'); - TestUtils = require('react-addons-test-utils'); window.loggedIn = true; window.userId = 33; + api.setResponse('/api/users/33.html', ''); profile = TestUtils.renderIntoDocument( ); @@ -22,10 +23,9 @@ describe('profile Tests', function() { expect(api.getPending()).toEqual([]); }); - pit('should load form', function() { - api.setResponse('/api/users/33.html', ''); - return profile.componentDidMount().then(() => { - var Utils = require('app/components/utils.js'); + it('should load form', function() { + return profile._req.then(() => { + var Utils = require('../../components/utils.js'); var data = Utils.getFormData(profile.refs.form); expect(data.name).toEqual('hi'); }); diff --git a/app/user/manage.alerts.jsx b/app/user/manage.alerts.jsx index a7078b4..54671f6 100644 --- a/app/user/manage.alerts.jsx +++ b/app/user/manage.alerts.jsx @@ -1,9 +1,9 @@ "use strict"; var React = require('react'); var api = require('../api.js'); -var ActionRows = require('app/modals/action.rows.jsx'); -var Utils = require('app/components/utils.js'); -var Button = require('app/components/button.jsx'); +var ActionRows = require('../modals/action.rows.jsx'); +var Utils = require('../components/utils.js'); +var Button = require('../components/button.jsx'); class Alerts extends React.Component { @@ -23,7 +23,7 @@ class Alerts extends React.Component { api.get(['alerts']).then(resp => { this.setState({screens: resp}); }); - return api.get(['users', 'me']).then(resp => { + this._req = api.get(['users', 'me']).then(resp => { this.setState({ watchlistAlert: resp.watchlist_alert }); diff --git a/app/user/profile.jsx b/app/user/profile.jsx index 0995a03..85fd4bc 100644 --- a/app/user/profile.jsx +++ b/app/user/profile.jsx @@ -1,10 +1,10 @@ "use strict"; var React = require('react'); var Link = require('react-router').Link; -var api = require('app/api.js'); -var Utils = require('app/components/utils.js'); -var Icon = require('app/components/icon.jsx'); -var Alert = require('app/components/alerts.jsx'); +var api = require('../api.js'); +var Utils = require('../components/utils.js'); +var Icon = require('../components/icon.jsx'); +var Alert = require('../components/alerts.jsx'); class Profile extends React.Component { @@ -23,7 +23,7 @@ class Profile extends React.Component { return (window.location = '/register/'); Utils.setTitle('Profile'); var url = '/users/' + window.userId + '.html'; - return api.rawGet(url).then(resp => { + this._req = api.rawGet(url).then(resp => { this.setState({ form: {__html: resp} }); diff --git a/app/watchlist.jsx b/app/watchlist.jsx index caa9327..dc87034 100644 --- a/app/watchlist.jsx +++ b/app/watchlist.jsx @@ -2,10 +2,10 @@ /* global require, document */ var React = require('react'); -var WatchlistButton = require('app/modals/watchlist.button.jsx'); -var ManageColumns = require('app/modals/columns.modal.jsx'); -var api = require('app/api.js'); -var Utils = require('app/components/utils.js'); +var WatchlistButton = require('./modals/watchlist.button.jsx'); +var ManageColumns = require('./modals/columns.modal.jsx'); +var api = require('./api.js'); +var Utils = require('./components/utils.js'); var UserTable = require('./screens/table.jsx'); @@ -18,7 +18,7 @@ var Watchlist = React.createClass({ componentDidMount: function() { if(!window.loggedIn) return (window.location = '/register/'); - return this.fetchResults(this.props.location.query); + this._req = this.fetchResults(this.props.location.query) }, componentWillReceiveProps: function(props) { diff --git a/jest/preprocessor.js b/jest/preprocessor.js deleted file mode 100644 index e5e0f52..0000000 --- a/jest/preprocessor.js +++ /dev/null @@ -1,22 +0,0 @@ -"use strict"; - -const babel = require('babel-core'); -const jestPreset = require('babel-preset-jest'); -var webpackAlias = require('jest-webpack-alias'); - -module.exports = { - process(src, filename) { - if (filename.indexOf('node_modules') === -1) { - if (babel.util.canCompile(filename)) { - src = babel.transform(src, { - auxiliaryCommentBefore: ' istanbul ignore next ', - filename, - presets: [jestPreset], - retainLines: true - }).code; - } - src = webpackAlias.process(src, filename); - } - return src; - } -}; diff --git a/package.json b/package.json index 2ba023d..f27f44d 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,7 @@ "chartist": "0.9.8", "classnames": "2.2.5", "es6-promise": "3.2.1", - "fetch-on-rest": "1.6.6", - "jest-cli": "0.8.2", + "fetch-on-rest": "1.7.1", "lodash": "4.13.1", "react": "15.1.0", "react-addons-test-utils": "15.1.0", @@ -20,6 +19,7 @@ }, "devDependencies": { "babel-eslint": "^6.1.0", + "babel-jest": "^13.0.0", "babel-loader": "6.2.4", "babel-polyfill": "^6.9.1", "babel-preset-es2015": "6.9.0", @@ -29,6 +29,7 @@ "eslint-plugin-react": "5.2.2", "exports-loader": "0.6.3", "http-proxy": "1.14.0", + "jest-cli": "^13.0.0", "jest-webpack-alias": "2.3.0", "webpack": "1.13.1" }, @@ -39,16 +40,11 @@ "test": "jest --verbose" }, "jest": { - "testRunner": "/node_modules/jest-cli/src/testRunners/jasmine/jasmine2.js", - "scriptPreprocessor": "/jest/preprocessor.js", "unmockedModulePathPatterns": [ - "/node_modules/react", - "/node_modules/react-dom", - "/node_modules/react-addons-test-utils", - "/node_modules/fbjs" - ], - "modulePathIgnorePatterns": [ - "/node_modules/" + "/node_modules/react/", + "/node_modules/react-dom/", + "/node_modules/react-addons-test-utils/", + "/node_modules/fbjs/" ] }, "repository": { From dda3dd5d4653b3a6861d64387bf973a72ad25a2d Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Sun, 26 Jun 2016 13:59:00 +0530 Subject: [PATCH 04/43] Updated to new syntax --- app/screens/__tests__/table-tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/screens/__tests__/table-tests.js b/app/screens/__tests__/table-tests.js index 49400ac..cfc711d 100644 --- a/app/screens/__tests__/table-tests.js +++ b/app/screens/__tests__/table-tests.js @@ -1,5 +1,5 @@ 'use strict'; -jest.autoMockOff() +jest.disableAutomock() describe('Table Tests', function(){ From 8449b0b25afcd9aa0b03ff514212a6555bd24abd Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Sun, 26 Jun 2016 17:08:35 +0530 Subject: [PATCH 05/43] Added missed categories --- app/components/ratio.gallery.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/components/ratio.gallery.jsx b/app/components/ratio.gallery.jsx index 3360f55..80366fa 100644 --- a/app/components/ratio.gallery.jsx +++ b/app/components/ratio.gallery.jsx @@ -133,10 +133,13 @@ class RatioGallery extends React.Component { renderOpen() { var categories = [ + "Quarterly Results", + "Quarterly Variations", "Annual Results", + "Annual Variations", + "Trailing 12 Months", "Balance Sheet", "Cash Flow Statement", - "Quarterly Results", "Valuation", "Ratios", "User Ratios" From 3ce6674b9db37839bac00cd31d9ac9578dd700d0 Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Tue, 28 Jun 2016 12:26:23 +0530 Subject: [PATCH 06/43] Updated company search to new syntax --- app/components/company.search.jsx | 65 +++++++++++++++++-------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/app/components/company.search.jsx b/app/components/company.search.jsx index 3104ff4..2527d7b 100644 --- a/app/components/company.search.jsx +++ b/app/components/company.search.jsx @@ -1,39 +1,38 @@ "use strict"; -/* global require, window */ -var React = require('react'); -var classNames = require('classnames'); -var api = require('../api.js'); -var Typeahead = require('./typeahead.jsx'); -var Icon = require('./icon.jsx'); - - -var CompanySearch = React.createClass({ - propTypes: { - onSelect: React.PropTypes.func.isRequired, - large: React.PropTypes.bool, - placeholder: React.PropTypes.string - }, - - getInitialState: function() { - return {options: []}; - }, - - onChange: function(term) { +var React = require('react') +var classNames = require('classnames') +var api = require('../api.js') +var Typeahead = require('./typeahead.jsx') +var Icon = require('./icon.jsx') + + +class CompanySearch extends React.Component { + + constructor(props, context) { + super(props, context) + this.onChange = this.onChange.bind(this) + this.onSelect = this.onSelect.bind(this) + this.state = { + options: [] + } + } + + onChange(term) { this.req = api.get(api.search, {q: term}).then( resp => this.setState({options: resp}) - ); - }, + ) + } - onSelect: function(idx) { - var selected = this.state.options[idx]; - this.props.onSelect(selected); - }, + onSelect(idx) { + var selected = this.state.options[idx] + this.props.onSelect(selected) + } - render: function() { + render() { var buttonClass = classNames( 'btn btn-primary', this.props.large && 'btn-lg' - ); + ) return
Search -
; + } -}); +} + +CompanySearch.propTypes = { + onSelect: React.PropTypes.func.isRequired, + large: React.PropTypes.bool, + placeholder: React.PropTypes.string +} module.exports = CompanySearch; From 4df88b6301b09bda25e9d2cd1ecd497de78d8a81 Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Tue, 28 Jun 2016 13:18:56 +0530 Subject: [PATCH 07/43] Added tests for results table --- app/company/__tests__/results-tests.js | 45 ++++++++++++++++++++++++++ app/company/results.jsx | 16 ++++----- 2 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 app/company/__tests__/results-tests.js diff --git a/app/company/__tests__/results-tests.js b/app/company/__tests__/results-tests.js new file mode 100644 index 0000000..5d444c3 --- /dev/null +++ b/app/company/__tests__/results-tests.js @@ -0,0 +1,45 @@ +'use strict' +jest.disableAutomock() +import React from 'react' +import ReactDOM from 'react-dom' +import Results from '../results.jsx' +import TestUtils from 'react-addons-test-utils' + + +var NUMBERS = [ + ["Sales",{"2008-03-31":1033.36,"2009-03-31":1002.53}], + ["Expenses",{"2008-03-31":915.16,"2009-03-31":1136.98}], + ["Material Cost %",{"2008-03-31":11.16,"2009-03-31":11.98}], + ["Operating Profit",{"2008-03-31":118.2,"2009-03-31":-134.45}], + ["OPM",{"2008-03-31":11.44,"2009-03-31":-13.41}] +] + + +describe('Basic rendering Tests', function() { + var result + + beforeEach(function() { + var company = { + cid: 33, + warehouse_set: { + result_type: 'sa', + pair_url: '' + }, + number_set: { + quarters: [["Sales", {}]], + annual: NUMBERS + } + } + result = TestUtils.renderIntoDocument( + + ) + }) + + it('should treat Material Cost % as %', function() { + var dom = ReactDOM.findDOMNode(result) + var normalRow = 'Sales' + var percentRow = 'Material Cost %' + expect(dom.innerHTML).toContain(normalRow) + expect(dom.innerHTML).toContain(percentRow) + }) +}) diff --git a/app/company/results.jsx b/app/company/results.jsx index dedc6c3..fb9fdc5 100644 --- a/app/company/results.jsx +++ b/app/company/results.jsx @@ -1,11 +1,11 @@ "use strict"; -/* global require, document, window */ -var React = require('react'); -var Api = require('../api.js'); -var Link = require('react-router').Link; -var classNames = require('classnames'); -var Utils = require('../components/utils.js'); -var defaults = require('lodash/defaults'); +import React from 'react' +import Api from '../api.js' +import {Link} from 'react-router' +import classNames from 'classnames' +import endsWith from 'lodash/endsWith' +import defaults from 'lodash/defaults' +import Utils from '../components/utils.js' function getCaption(report) { @@ -105,7 +105,7 @@ var Results = React.createClass({ 'mom': schedules, 'child': childIdx !== false, 'strong': highlights.indexOf(field) >= 0, - 'percent': percents.indexOf(field) >= 0, + 'percent': percents.indexOf(field) >= 0 || endsWith(field, '%'), 'odd': ( childIdx === false ? idx : childIdx ) % 2 == 0 }); var Cells = dates.map(function(rdt, iidx) { From 02ca19baf0738618ba92964fa134389a91ad88fd Mon Sep 17 00:00:00 2001 From: mh Date: Wed, 6 Jul 2016 15:02:01 +0530 Subject: [PATCH 08/43] Add an option to compare Annual Results of a company with another company --- app/company/__tests__/company-tests.js | 94 ++++++++++++++++++++++++++ app/company/company.jsx | 29 +++++++- app/company/results.jsx | 31 ++++++++- 3 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 app/company/__tests__/company-tests.js diff --git a/app/company/__tests__/company-tests.js b/app/company/__tests__/company-tests.js new file mode 100644 index 0000000..c7e4001 --- /dev/null +++ b/app/company/__tests__/company-tests.js @@ -0,0 +1,94 @@ +'use strict' +jest.disableAutomock() +import React from 'react' +import ReactDOM from 'react-dom' +import Results from '../results.jsx' +import TestUtils from 'react-addons-test-utils' + + +var NUMBERS = [ + ["Sales",{"2008-03-31":1033.36,"2009-03-31":1002.53}], + ["Expenses",{"2008-03-31":915.16,"2009-03-31":1136.98}], + ["Material Cost %",{"2008-03-31":11.26,"2009-03-31":11.38}], + ["Manufacturing Cost %",{"2008-03-31":8.64,"2009-03-31":8.43}], + ["Employee Cost %",{"2008-03-31":91.23,"2009-03-31":98.93}], + ["Other Cost %",{"2008-03-31":2.61,"2009-03-31":3.41}], + ["Operating Profit",{"2008-03-31":118.2,"2009-03-31":-134.45}], + ["OPM",{"2008-03-31":11.44,"2009-03-31":-13.41}] +] + + +var COMPARENUMBERS = [ + ["Sales",{"2008-03-31":533.36,"2009-03-31":502.53}], + ["Expenses",{"2008-03-31":415.16,"2009-03-31":536.98}], + ["Material Cost %",{"2008-03-31":5.26,"2009-03-31":5.38}], + ["Manufacturing Cost %",{"2008-03-31":4.64,"2009-03-31":4.43}], + ["Employee Cost %",{"2008-03-31":71.23,"2009-03-31":78.93}], + ["Other Cost %",{"2008-03-31":2.21,"2009-03-31":3.11}], + ["Operating Profit",{"2008-03-31":58.2,"2009-03-31":-74.45}], + ["OPM",{"2008-03-31":9.44,"2009-03-31":-11.41}] +] + +describe('Basic rendering Tests', function() { + var result + var company // https://www.screener.in/api/company/512573/ + var compareCompany // https://www.screener.in/api/company/539168/ + + beforeEach(function() { + company = { + id: 341, + warehouse_set: { + result_type: 'sa', + pair_url: '' + }, + number_set: { + quarters: [["Sales", {}]], + annual: NUMBERS + }, + bse_code: "512573", + short_name: "Avanti Feeds", + name: "Avanti Feeds Ltd" + }; + compareCompany = { + id: 1270856, + warehouse_set: { + result_type: 'sa', + pair_url: '' + }, + number_set: { + quarters: [["Sales", {}]], + annual: COMPARENUMBERS + }, + bse_code: "539168", + short_name: "Spisys", + name: "Spisys Ltd" + }; + }) + + it('Company results without comparing another company', function() { + result = TestUtils.renderIntoDocument( + + ) + var dom = ReactDOM.findDOMNode(result) + var salesRow = 'Sales1,033.36' + var materialRow = 'Material Cost %11.26' + var normalComparisonRow = 'Spisys Ltd' + expect(dom.innerHTML).toContain(salesRow) + expect(dom.innerHTML).toContain(materialRow) + expect(dom.innerHTML).not.toContain(normalComparisonRow) + }) + + it('Company results comparing with another company', function() { + result = TestUtils.renderIntoDocument( + + ) + var dom = ReactDOM.findDOMNode(result) + var salesRow = 'SalesAvanti Feeds Ltd1,033.36' + var materialRow = 'Material Cost %Avanti Feeds Ltd11.26' + var salesComparisonRow = 'Spisys Ltd533.36' +// console.log(dom.innerHTML) + expect(dom.innerHTML).toContain(salesRow) + expect(dom.innerHTML).toContain(materialRow) + expect(dom.innerHTML).toContain(salesComparisonRow) + }) +}) diff --git a/app/company/company.jsx b/app/company/company.jsx index 25d111e..455654b 100644 --- a/app/company/company.jsx +++ b/app/company/company.jsx @@ -12,6 +12,7 @@ var ScrollBar = require('./scrollbar.jsx'); var CompanyRatios = require('./ratios.jsx'); var PriceChart = require('./pricechart.jsx'); var QuickRatios = require('./quickratios.jsx'); +var CompanySearch = require('../components/company.search.jsx'); var Company = React.createClass({ @@ -23,6 +24,10 @@ var Company = React.createClass({ industry: 'Industry', warehouse_set: {status: 'Active'} }, + compareCompany: { + exchange_code: null, + companyData : null + }, favorites: [] }; }, @@ -41,6 +46,8 @@ var Company = React.createClass({ fetchCompany: function(params) { var exc = params.exchange_code; var con = params.consolidated; + if (this.state.compareCompany.exchange_code) + this.fetchCompareCompany(this.state.compareCompany.exchange_code, con); Api.get(Api.company(exc, con)).then(function(response) { Utils.setTitle(response.name); this.setState({company: response}); @@ -66,6 +73,20 @@ var Company = React.createClass({ }.bind(this)); }, + fetchCompareCompany: function(exc, con) { + Api.get(Api.company(exc, con)).then(function(response) { + var hasData = Object.keys(response.number_set['annual'][0][1]).length; + this.setState({compareCompany: {exchange_code: exc, companyData: hasData > 0 ? response : null}}); + }.bind(this)); + }, + + handleCompareCompany: function(company) { + var regsplres = company.url.split("\/"); + var exc = regsplres[2]; + var con = this.props.params.consolidated; + this.fetchCompareCompany(exc, con); + }, + render: function() { var company = this.state.company; var wid = company.warehouse_set.id; @@ -81,7 +102,13 @@ var Company = React.createClass({
- +

Compare with another company

+ this.setState({compareCompany: {exchange_code: null, companyData: null}})} + >Remove comparison + +
diff --git a/app/company/results.jsx b/app/company/results.jsx index fb9fdc5..d201ef1 100644 --- a/app/company/results.jsx +++ b/app/company/results.jsx @@ -98,7 +98,7 @@ var Results = React.createClass({ }.bind(this)); }, - renderRow: function(trailing, dates, childIdx, row, idx) { + renderRow: function(trailing, dates, childIdx, numbersCompareCompany, trailingCompareCompany, row, idx) { var field = row[0]; var schedules = this.state.schedules[field]; var rowClass = classNames({ @@ -112,13 +112,33 @@ var Results = React.createClass({ return {Utils.toLocalNumber(row[1][rdt])}; }); var TTMCell = trailing ? {trailing[field]} : false; + var isCompanyCompared = this.props.compareCompany && this.props.compareCompany.id; + var addCompanyName = isCompanyCompared && childIdx === false ? {this.props.company.name} : isCompanyCompared ? : null; + var idxCompare = idx + 50; // Need a good reason for this number + var CellsCompare = isCompanyCompared && childIdx === false ? dates.map(function(rdt, iidx) { + var cellValue = numbersCompareCompany[idx][1][rdt]; + return cellValue ? {Utils.toLocalNumber(cellValue)} : ; + }) : null; + var TTMCellCompare = isCompanyCompared && childIdx === false && trailingCompareCompany ? {trailingCompareCompany[field]} : false; + var addComparingCompany = isCompanyCompared && childIdx === false ? + + + {this.props.compareCompany.name} + {CellsCompare} + {TTMCellCompare} + + : null; + return [ {row[0]} + {addCompanyName} {Cells} {TTMCell} - , schedules && schedules.map(this.renderRow.bind(this, trailing, dates, idx))]; + , + schedules && schedules.map(this.renderRow.bind(this, trailing, dates, idx, null, null)), + addComparingCompany]; }, render: function () { @@ -129,6 +149,10 @@ var Results = React.createClass({ var numbers = company.number_set[this.props.report]; var dates = Object.keys(numbers[0][1]).sort(); var trailing = getTrailing(this.props.report, company.number_set, dates); + var isCompanyCompared = this.props.compareCompany && this.props.compareCompany.id; + var blankHeader = isCompanyCompared ? : null; + var numbersCompareCompany = isCompanyCompared ? this.props.compareCompany.number_set[this.props.report] : null; + var trailingCompareCompany = isCompanyCompared && trailing ? getTrailing(this.props.report, this.props.compareCompany.number_set, dates) : null; var Heads = dates.map(function(rdt, idx) { return {Utils.toMonthYear(rdt)}; @@ -147,12 +171,13 @@ var Results = React.createClass({ + {blankHeader} {Heads} {TTMHead} - {numbers.map(this.renderRow.bind(this, trailing, dates, false))} + {numbers.map(this.renderRow.bind(this, trailing, dates, false, numbersCompareCompany, trailingCompareCompany))} From 52737fd5a8733db4dfddce9a6752e165f9e18a6f Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Thu, 7 Jul 2016 13:47:34 +0530 Subject: [PATCH 09/43] Refractorered some code to make it aesthetics modifications easier in future --- app/company/company.jsx | 21 +++++++------ app/company/compare.jsx | 57 +++++++++++++++++++++++++++++++++++ app/components/icon.jsx | 3 ++ app/components/under.icon.jsx | 32 ++++++++++++++++++++ 4 files changed, 103 insertions(+), 10 deletions(-) create mode 100644 app/company/compare.jsx create mode 100644 app/components/under.icon.jsx diff --git a/app/company/company.jsx b/app/company/company.jsx index 455654b..a151798 100644 --- a/app/company/company.jsx +++ b/app/company/company.jsx @@ -1,6 +1,4 @@ "use strict"; -/* global require */ - var React = require('react'); var isEqual = require('lodash/isEqual'); var Utils = require('../components/utils.js'); @@ -12,7 +10,7 @@ var ScrollBar = require('./scrollbar.jsx'); var CompanyRatios = require('./ratios.jsx'); var PriceChart = require('./pricechart.jsx'); var QuickRatios = require('./quickratios.jsx'); -var CompanySearch = require('../components/company.search.jsx'); +var AddCompare = require('./compare.jsx'); var Company = React.createClass({ @@ -80,13 +78,19 @@ var Company = React.createClass({ }.bind(this)); }, - handleCompareCompany: function(company) { + handleAddCompare: function(company) { var regsplres = company.url.split("\/"); var exc = regsplres[2]; var con = this.props.params.consolidated; this.fetchCompareCompany(exc, con); }, + handleRemoveCompare: function() { + this.setState({ + compareCompany: {exchange_code: null, companyData: null} + }) + }, + render: function() { var company = this.state.company; var wid = company.warehouse_set.id; @@ -102,12 +106,9 @@ var Company = React.createClass({
-

Compare with another company

- this.setState({compareCompany: {exchange_code: null, companyData: null}})} - >Remove comparison - +
+ +
diff --git a/app/company/compare.jsx b/app/company/compare.jsx new file mode 100644 index 0000000..e6cb97d --- /dev/null +++ b/app/company/compare.jsx @@ -0,0 +1,57 @@ +"use strict"; +import React from 'react' +import CompanySearch from '../components/company.search.jsx' +import UnderIcon from '../components/under.icon.jsx' +import Icon from '../components/icon.jsx' + + +class AddCompare extends React.Component { + constructor(props, context) { + super(props, context) + this.handleAdd = this.handleAdd.bind(this) + this.handleRemove = this.handleRemove.bind(this) + this.state = { + selectedCompany: undefined + } + } + + handleAdd(company) { + this.setState({selectedCompany: company}) + this.props.onAdd(company) + } + + handleRemove() { + this.setState({selectedCompany: undefined}) + this.props.onRemove() + } + + renderAlreadyComparing() { + var companyName = this.state.selectedCompany.name + return + Comparing {companyName} +
+ + + Remove Comparison + +
+ } + + render() { + if (this.state.selectedCompany) + return this.renderAlreadyComparing() + return +
+ Company for comparison + +
+
+ } +} + +AddCompare.propTypes = { + onAdd: React.PropTypes.func.isRequired, + onRemove: React.PropTypes.func.isRequired +} + +module.exports = AddCompare diff --git a/app/components/icon.jsx b/app/components/icon.jsx index 293dca6..5f79600 100644 --- a/app/components/icon.jsx +++ b/app/components/icon.jsx @@ -8,5 +8,8 @@ function Icon(props) { className={name} />; } +Icon.propTypes = { + name: React.PropTypes.string.isRequired +} module.exports = Icon; diff --git a/app/components/under.icon.jsx b/app/components/under.icon.jsx new file mode 100644 index 0000000..3e205fd --- /dev/null +++ b/app/components/under.icon.jsx @@ -0,0 +1,32 @@ +"use strict"; +import React from 'react' +import Icon from './icon.jsx' + +class UnderIcon extends React.Component { + constructor(props, context) { + super(props, context) + this.state = { + isClicked: false + } + } + + render() { + var innerContent = this.state.isClicked && this.props.children + var iconClass = this.state.isClicked ? 'hide' : '' + return
+ {innerContent} +
this.setState({isClicked: true})}> + +
+
+ } +} + +UnderIcon.propTypes = { + children: React.PropTypes.element.isRequired, + icon: React.PropTypes.string.isRequired +} + +module.exports = UnderIcon From db0b47b8fec6aaf4180f685d607efe118fbed0d0 Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Thu, 7 Jul 2016 13:54:49 +0530 Subject: [PATCH 10/43] Fixed test warnings --- app/company/__tests__/misc-tests.js | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/app/company/__tests__/misc-tests.js b/app/company/__tests__/misc-tests.js index 1615b82..5a26174 100644 --- a/app/company/__tests__/misc-tests.js +++ b/app/company/__tests__/misc-tests.js @@ -1,6 +1,9 @@ "use strict"; -jest.autoMockOff(); -jest.mock('fetch-on-rest'); +jest.disableAutomock(); +var React = require('react'); +var ReactDOM = require('react-dom'); +var TestUtils = require('react-addons-test-utils'); +var Misc = require('../misc.jsx'); var kitex = { id: 1950, @@ -29,26 +32,9 @@ var kitex = { describe('Walk tests', function () { - var api = require('../../api.js'); - var Misc, TestUtils, api, ReactDOM, React; - - beforeEach(function() { - React = require('react'); - ReactDOM = require('react-dom'); - TestUtils = require('react-addons-test-utils'); - Misc = require.requireActual('../misc.jsx'); - }); - - afterEach(function() { - expect(api.getPending()).toEqual([]); - }); it('test visible add to watchlist button', function() { - var dummy = jest.genMockFunction().mockImplementation( - function(cid) { - return api.post(['company', cid, 'favorite']); - } - ); + var dummy = jest.genMockFunction() var header = TestUtils.renderIntoDocument(
Date: Thu, 7 Jul 2016 14:08:29 +0530 Subject: [PATCH 11/43] Fixed url parsing for comparison company --- app/company/company.jsx | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/app/company/company.jsx b/app/company/company.jsx index a151798..c2ac0a4 100644 --- a/app/company/company.jsx +++ b/app/company/company.jsx @@ -22,10 +22,7 @@ var Company = React.createClass({ industry: 'Industry', warehouse_set: {status: 'Active'} }, - compareCompany: { - exchange_code: null, - companyData : null - }, + compareCompany: undefined, favorites: [] }; }, @@ -44,8 +41,6 @@ var Company = React.createClass({ fetchCompany: function(params) { var exc = params.exchange_code; var con = params.consolidated; - if (this.state.compareCompany.exchange_code) - this.fetchCompareCompany(this.state.compareCompany.exchange_code, con); Api.get(Api.company(exc, con)).then(function(response) { Utils.setTitle(response.name); this.setState({company: response}); @@ -71,28 +66,19 @@ var Company = React.createClass({ }.bind(this)); }, - fetchCompareCompany: function(exc, con) { - Api.get(Api.company(exc, con)).then(function(response) { - var hasData = Object.keys(response.number_set['annual'][0][1]).length; - this.setState({compareCompany: {exchange_code: exc, companyData: hasData > 0 ? response : null}}); - }.bind(this)); - }, - handleAddCompare: function(company) { - var regsplres = company.url.split("\/"); - var exc = regsplres[2]; - var con = this.props.params.consolidated; - this.fetchCompareCompany(exc, con); + Api.get(company.url).then(response => { + this.setState({compareCompany: response}); + }); }, handleRemoveCompare: function() { - this.setState({ - compareCompany: {exchange_code: null, companyData: null} - }) + this.setState({compareCompany: undefined}) }, render: function() { var company = this.state.company; + var compareCompany = this.state.compareCompany var wid = company.warehouse_set.id; var quickratios = company.id ? : ''; var loaded = company.id ?
@@ -109,7 +95,7 @@ var Company = React.createClass({
- +
From c761b02430281db3c673a144670bfba3c290c336 Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Thu, 7 Jul 2016 14:19:24 +0530 Subject: [PATCH 12/43] Refractored code to make loading explicit --- app/company/company.jsx | 54 ++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/app/company/company.jsx b/app/company/company.jsx index c2ac0a4..7a53e8d 100644 --- a/app/company/company.jsx +++ b/app/company/company.jsx @@ -16,12 +16,7 @@ var AddCompare = require('./compare.jsx'); var Company = React.createClass({ getInitialState: function() { return { - company: { - name: this.props.params.exchange_code + ' Loading...', - short_name: 'Company name', - industry: 'Industry', - warehouse_set: {status: 'Active'} - }, + company: undefined, compareCompany: undefined, favorites: [] }; @@ -76,12 +71,33 @@ var Company = React.createClass({ this.setState({compareCompany: undefined}) }, + renderLoading: function() { + return

+ Loading {this.props.params.exchange_code}... +

+ }, + render: function() { - var company = this.state.company; + var company = this.state.company var compareCompany = this.state.compareCompany - var wid = company.warehouse_set.id; - var quickratios = company.id ? : ''; - var loaded = company.id ?
+ if (!company) + return this.renderLoading() + var wid = company.warehouse_set.id + var quickratios = + return
+ + +
+ + {quickratios} +
+
+ +
@@ -115,23 +131,7 @@ var Company = React.createClass({
-
:

Loading...

; - return
- - -
- - {quickratios} -
-
- -
- {loaded} -
; +
} }); From 96fb42c4085a6738de8c71761f503e7c80411957 Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Thu, 7 Jul 2016 15:11:25 +0530 Subject: [PATCH 13/43] Added section gaps in code as well --- app/company/company.jsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/company/company.jsx b/app/company/company.jsx index 7a53e8d..c72e3bb 100644 --- a/app/company/company.jsx +++ b/app/company/company.jsx @@ -90,23 +90,30 @@ var Company = React.createClass({ favorites={this.state.favorites} handleFavorite={this.handleFavorite} /> + +
{quickratios}
+
+
+
+
+
@@ -114,12 +121,15 @@ var Company = React.createClass({
+
+
+
From d8008ec41c65871b15053cebc26f3583458c4a39 Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Thu, 7 Jul 2016 15:37:50 +0530 Subject: [PATCH 14/43] Changed syntax to new class component for better PropTypes validation --- app/company/__tests__/company-tests.js | 8 +- app/company/results.jsx | 181 +++++++++++++------------ 2 files changed, 101 insertions(+), 88 deletions(-) diff --git a/app/company/__tests__/company-tests.js b/app/company/__tests__/company-tests.js index c7e4001..3aac2de 100644 --- a/app/company/__tests__/company-tests.js +++ b/app/company/__tests__/company-tests.js @@ -72,7 +72,7 @@ describe('Basic rendering Tests', function() { var dom = ReactDOM.findDOMNode(result) var salesRow = 'Sales1,033.36' var materialRow = 'Material Cost %11.26' - var normalComparisonRow = 'Spisys Ltd' + var normalComparisonRow = 'Spisys' expect(dom.innerHTML).toContain(salesRow) expect(dom.innerHTML).toContain(materialRow) expect(dom.innerHTML).not.toContain(normalComparisonRow) @@ -83,9 +83,9 @@ describe('Basic rendering Tests', function() { ) var dom = ReactDOM.findDOMNode(result) - var salesRow = 'SalesAvanti Feeds Ltd1,033.36' - var materialRow = 'Material Cost %Avanti Feeds Ltd11.26' - var salesComparisonRow = 'Spisys Ltd533.36' + var salesRow = 'SalesAvanti Feeds1,033.36' + var materialRow = 'Material Cost %Avanti Feeds11.26' + var salesComparisonRow = 'Spisys533.36' // console.log(dom.innerHTML) expect(dom.innerHTML).toContain(salesRow) expect(dom.innerHTML).toContain(materialRow) diff --git a/app/company/results.jsx b/app/company/results.jsx index d201ef1..3bdfdbc 100644 --- a/app/company/results.jsx +++ b/app/company/results.jsx @@ -1,4 +1,4 @@ -"use strict"; +"use strict" import React from 'react' import Api from '../api.js' import {Link} from 'react-router' @@ -10,124 +10,126 @@ import Utils from '../components/utils.js' function getCaption(report) { if(report == 'quarters') - return 'Quarterly Results'; + return 'Quarterly Results' if(report == 'annual') - return 'Annual Results'; + return 'Annual Results' if(report == 'balancesheet') - return 'Balance Sheet'; + return 'Balance Sheet' if(report == 'cashflow') - return 'Cash Flow'; + return 'Cash Flow' } function getPrefix(pair_url, standalone) { if(pair_url === null) - return ''; - return standalone ? 'Standalone ': 'Consolidated '; + return '' + return standalone ? 'Standalone ': 'Consolidated ' } function getSuffix(pair_url, standalone, prime) { if(pair_url === null) - return ''; - var suffix = standalone ? 'View Consolidated' : 'View Standalone'; - var bprime = (prime == 'sa'); + return '' + var suffix = standalone ? 'View Consolidated' : 'View Standalone' + var bprime = (prime == 'sa') if(bprime != standalone) - suffix = {suffix}; - return / {suffix}; + suffix = {suffix} + return / {suffix} } function getTrailing(report, number_set, ann_dates) { if(report != 'annual') - return; - var last_ann = ann_dates[ann_dates.length -1]; - var quarters = number_set.quarters; - var qtr_dates = Object.keys(quarters[0][1]).sort(); - var last_qtr = qtr_dates[qtr_dates.length - 1]; + return + var last_ann = ann_dates[ann_dates.length -1] + var quarters = number_set.quarters + var qtr_dates = Object.keys(quarters[0][1]).sort() + var last_qtr = qtr_dates[qtr_dates.length - 1] if(qtr_dates.length < 4 || last_qtr <= last_ann) - return; + return - var four_qtrs = qtr_dates.slice(-4); - var trailing = {}; + var four_qtrs = qtr_dates.slice(-4) + var trailing = {} for(var i=0; i < quarters.length; i++) { - var field = quarters[i][0]; - var vals = quarters[i][1]; - var value = 0; + var field = quarters[i][0] + var vals = quarters[i][1] + var value = 0 for(var j=0; j < four_qtrs.length; j++) { - value += vals[four_qtrs[j]]; + value += vals[four_qtrs[j]] } - var final_val = field == 'OPM' ? value / four_qtrs.length : value; - trailing[field] = final_val.toFixed(2); + var final_val = field == 'OPM' ? value / four_qtrs.length : value + trailing[field] = final_val.toFixed(2) } - return trailing; + return trailing } var highlights = [ 'Operating Profit', 'Profit before tax', 'Net Profit', 'Total Liabilities', 'Total Assets', 'Net Cash Flow' -]; -var percents = ['OPM', 'Dividend Payout']; +] +var percents = ['OPM', 'Dividend Payout'] -var Results = React.createClass({ - getInitialState: function() { - return {schedules: {}}; - }, +class Results extends React.Component { - componentWillReceiveProps: function(props) { - this.setState(this.getInitialState()); - }, + constructor(props, context) { + super(props, context) + this.state = {schedules: {}} + } + + componentWillReceiveProps() { + this.setState({schedules: {}}) + } - handleExpand: function(field) { + handleExpand(field) { if(this.state.schedules[field]) - return; - var cid = this.props.company.id; + return + var cid = this.props.company.id var params = { id: cid, r: this.props.company.warehouse_set.result_type, f: this.props.report, q: field - }; + } Api.get(Api.cid(cid, 'schedules'), params) .then(function(response) { if (response.length === 0) - return; - var schedules = defaults({}, this.state.schedules); - schedules[field] = response; - this.setState({schedules: schedules}); - }.bind(this)); - }, - - renderRow: function(trailing, dates, childIdx, numbersCompareCompany, trailingCompareCompany, row, idx) { - var field = row[0]; - var schedules = this.state.schedules[field]; + return + var schedules = defaults({}, this.state.schedules) + schedules[field] = response + this.setState({schedules: schedules}) + }.bind(this)) + } + + renderRow(trailing, dates, childIdx, numbersCompareCompany, trailingCompareCompany, row, idx) { + var field = row[0] + var schedules = this.state.schedules[field] var rowClass = classNames({ 'mom': schedules, 'child': childIdx !== false, 'strong': highlights.indexOf(field) >= 0, 'percent': percents.indexOf(field) >= 0 || endsWith(field, '%'), 'odd': ( childIdx === false ? idx : childIdx ) % 2 == 0 - }); + }) var Cells = dates.map(function(rdt, iidx) { - return {Utils.toLocalNumber(row[1][rdt])}; - }); - var TTMCell = trailing ? {trailing[field]} : false; - var isCompanyCompared = this.props.compareCompany && this.props.compareCompany.id; - var addCompanyName = isCompanyCompared && childIdx === false ? {this.props.company.name} : isCompanyCompared ? : null; - var idxCompare = idx + 50; // Need a good reason for this number + return {Utils.toLocalNumber(row[1][rdt])} + }) + var TTMCell = trailing ? {trailing[field]} : false + var isCompanyCompared = this.props.compareCompany && this.props.compareCompany.id + var addCompanyName = isCompanyCompared && childIdx === false ? {this.props.company.short_name} : isCompanyCompared ? : null + var idxCompare = idx + 50 // Need a good reason for this number var CellsCompare = isCompanyCompared && childIdx === false ? dates.map(function(rdt, iidx) { - var cellValue = numbersCompareCompany[idx][1][rdt]; - return cellValue ? {Utils.toLocalNumber(cellValue)} : ; - }) : null; - var TTMCellCompare = isCompanyCompared && childIdx === false && trailingCompareCompany ? {trailingCompareCompany[field]} : false; + var cellValue = numbersCompareCompany[idx][1][rdt] + return cellValue ? {Utils.toLocalNumber(cellValue)} : + }) : null + var TTMCellCompare = isCompanyCompared && childIdx === false && trailingCompareCompany ? {trailingCompareCompany[field]} : false var addComparingCompany = isCompanyCompared && childIdx === false ? - {this.props.compareCompany.name} + {this.props.compareCompany.short_name} {CellsCompare} {TTMCellCompare} - : null; + : null return [ @@ -138,28 +140,32 @@ var Results = React.createClass({ {TTMCell} , schedules && schedules.map(this.renderRow.bind(this, trailing, dates, idx, null, null)), - addComparingCompany]; - }, - - render: function () { - var company = this.props.company; - var standalone = company.warehouse_set.result_type == 'sa'; - var pair_url = company.warehouse_set.pair_url; - var pair_link = getSuffix(pair_url, standalone, company.prime); - var numbers = company.number_set[this.props.report]; - var dates = Object.keys(numbers[0][1]).sort(); - var trailing = getTrailing(this.props.report, company.number_set, dates); - var isCompanyCompared = this.props.compareCompany && this.props.compareCompany.id; - var blankHeader = isCompanyCompared ? : null; - var numbersCompareCompany = isCompanyCompared ? this.props.compareCompany.number_set[this.props.report] : null; - var trailingCompareCompany = isCompanyCompared && trailing ? getTrailing(this.props.report, this.props.compareCompany.number_set, dates) : null; + addComparingCompany] + } + + render() { + var company = this.props.company + var standalone = company.warehouse_set.result_type == 'sa' + var pair_url = company.warehouse_set.pair_url + var pair_link = getSuffix(pair_url, standalone, company.prime) + var numbers = company.number_set[this.props.report] + var dates = Object.keys(numbers[0][1]).sort() + var trailing = getTrailing(this.props.report, company.number_set, dates) + var isCompanyCompared = this.props.compareCompany && this.props.compareCompany.id + var blankHeader = isCompanyCompared ? : null + var numbersCompareCompany = isCompanyCompared ? this.props.compareCompany.number_set[this.props.report] : null + var trailingCompareCompany = isCompanyCompared && trailing ? getTrailing(this.props.report, this.props.compareCompany.number_set, dates) : null var Heads = dates.map(function(rdt, idx) { - return {Utils.toMonthYear(rdt)}; - }); - var TTMHead = trailing && TTM; + return {Utils.toMonthYear(rdt)} + }) + var TTMHead = trailing && TTM return
+
+ {this.props.children} +
+

{getCaption(this.props.report)} {getPrefix(pair_url, standalone)} Figures in Rs. Crores {pair_link} @@ -181,8 +187,15 @@ var Results = React.createClass({

-
; + } -}); +} + +Results.propTypes = { + company: React.PropTypes.object.isRequired, + compareCompany: React.PropTypes.object, + report: React.PropTypes.string.isRequired, + children: React.PropTypes.element +} -module.exports = Results; +module.exports = Results From 2c17085c4fe46336fbcc6ba52afd83ca1a6c4a43 Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Thu, 7 Jul 2016 16:53:55 +0530 Subject: [PATCH 15/43] Added tests for schedule expansion --- app/company/__tests__/results-tests.js | 25 ++++++++++++++++++++++++- app/company/results.jsx | 8 ++++---- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/app/company/__tests__/results-tests.js b/app/company/__tests__/results-tests.js index 5d444c3..e4602ce 100644 --- a/app/company/__tests__/results-tests.js +++ b/app/company/__tests__/results-tests.js @@ -1,5 +1,7 @@ 'use strict' jest.disableAutomock() +jest.mock('fetch-on-rest') +import api from '../../api.js' import React from 'react' import ReactDOM from 'react-dom' import Results from '../results.jsx' @@ -14,13 +16,18 @@ var NUMBERS = [ ["OPM",{"2008-03-31":11.44,"2009-03-31":-13.41}] ] +var SCHEDULE = [ + ["Schedule A",{"2008-03-31":77.27,"2009-03-31":75.49}], + ["Schedule B",{"2008-03-31":77.27,"2009-03-31":75.49}], +] + describe('Basic rendering Tests', function() { var result beforeEach(function() { var company = { - cid: 33, + id: 33, warehouse_set: { result_type: 'sa', pair_url: '' @@ -35,6 +42,22 @@ describe('Basic rendering Tests', function() { ) }) + afterEach(function() { + expect(api.getPending()).toEqual([]) + }) + + it('should expand schedules', function() { + var dom = ReactDOM.findDOMNode(result) + var row = dom.getElementsByTagName('tr')[1] + var field = row.getElementsByTagName('td')[0] + expect(dom.innerHTML).not.toContain('Schedule A') + api.setResponse('/api/company/33/schedules/?id=33&r=sa&f=annual&q=Sales', JSON.stringify(SCHEDULE)) + TestUtils.Simulate.click(field) + return result._req.then(() => { + expect(dom.innerHTML).toContain('Schedule A') + }) + }) + it('should treat Material Cost % as %', function() { var dom = ReactDOM.findDOMNode(result) var normalRow = 'Sales' diff --git a/app/company/results.jsx b/app/company/results.jsx index 3bdfdbc..ad8d97c 100644 --- a/app/company/results.jsx +++ b/app/company/results.jsx @@ -90,14 +90,14 @@ class Results extends React.Component { f: this.props.report, q: field } - Api.get(Api.cid(cid, 'schedules'), params) - .then(function(response) { + this._req = Api.get(Api.cid(cid, 'schedules'), params) + .then(response => { if (response.length === 0) return var schedules = defaults({}, this.state.schedules) schedules[field] = response this.setState({schedules: schedules}) - }.bind(this)) + }) } renderRow(trailing, dates, childIdx, numbersCompareCompany, trailingCompareCompany, row, idx) { @@ -132,7 +132,7 @@ class Results extends React.Component { : null return [ - + this.handleExpand(field)}> {row[0]} {addCompanyName} From 6d895191cee753d82f64a7e85f48f2dc8f811b51 Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Thu, 7 Jul 2016 18:31:53 +0530 Subject: [PATCH 16/43] Simplified the compare algorithm --- app/company/__tests__/company-tests.js | 7 +- app/company/__tests__/results-tests.js | 2 +- app/company/results.jsx | 127 ++++++++++++++----------- 3 files changed, 77 insertions(+), 59 deletions(-) diff --git a/app/company/__tests__/company-tests.js b/app/company/__tests__/company-tests.js index 3aac2de..6eb3511 100644 --- a/app/company/__tests__/company-tests.js +++ b/app/company/__tests__/company-tests.js @@ -71,7 +71,7 @@ describe('Basic rendering Tests', function() { ) var dom = ReactDOM.findDOMNode(result) var salesRow = 'Sales1,033.36' - var materialRow = 'Material Cost %11.26' + var materialRow = 'Material Cost %11.26' var normalComparisonRow = 'Spisys' expect(dom.innerHTML).toContain(salesRow) expect(dom.innerHTML).toContain(materialRow) @@ -84,9 +84,8 @@ describe('Basic rendering Tests', function() { ) var dom = ReactDOM.findDOMNode(result) var salesRow = 'SalesAvanti Feeds1,033.36' - var materialRow = 'Material Cost %Avanti Feeds11.26' - var salesComparisonRow = 'Spisys533.36' -// console.log(dom.innerHTML) + var materialRow = 'Material Cost %Avanti Feeds11.26' + var salesComparisonRow = 'Spisys533.36' expect(dom.innerHTML).toContain(salesRow) expect(dom.innerHTML).toContain(materialRow) expect(dom.innerHTML).toContain(salesComparisonRow) diff --git a/app/company/__tests__/results-tests.js b/app/company/__tests__/results-tests.js index e4602ce..9f77a5d 100644 --- a/app/company/__tests__/results-tests.js +++ b/app/company/__tests__/results-tests.js @@ -61,7 +61,7 @@ describe('Basic rendering Tests', function() { it('should treat Material Cost % as %', function() { var dom = ReactDOM.findDOMNode(result) var normalRow = 'Sales' - var percentRow = 'Material Cost %' + var percentRow = 'Material Cost %' expect(dom.innerHTML).toContain(normalRow) expect(dom.innerHTML).toContain(percentRow) }) diff --git a/app/company/results.jsx b/app/company/results.jsx index ad8d97c..8a41e0f 100644 --- a/app/company/results.jsx +++ b/app/company/results.jsx @@ -36,6 +36,15 @@ function getSuffix(pair_url, standalone, prime) { return / {suffix} } +function getFieldNumbers(numbers, field) { + for (var i = 0; i < numbers.length; i++) { + var row = numbers[i] + if(row[0] == field) + return row + } + return [field, {}] +} + function getTrailing(report, number_set, ann_dates) { if(report != 'annual') return @@ -70,13 +79,22 @@ var percents = ['OPM', 'Dividend Payout'] class Results extends React.Component { + updateClassVariables(props) { + this.company = props.company + this.numbers = this.company.number_set[props.report] + this.dates = Object.keys(this.numbers[0][1]).sort() + this.trailing = getTrailing(props.report, this.company.number_set, this.dates) + this.isComparison = props.compareCompany + } constructor(props, context) { super(props, context) + this.updateClassVariables(props) this.state = {schedules: {}} } - componentWillReceiveProps() { + componentWillReceiveProps(props) { + this.updateClassVariables(props) this.setState({schedules: {}}) } @@ -100,67 +118,68 @@ class Results extends React.Component { }) } - renderRow(trailing, dates, childIdx, numbersCompareCompany, trailingCompareCompany, row, idx) { - var field = row[0] + renderSchedules(field, company, momClass) { var schedules = this.state.schedules[field] - var rowClass = classNames({ - 'mom': schedules, - 'child': childIdx !== false, + if(!schedules) + return + return schedules.map(this.renderRow.bind(this, company, ['child', momClass])) + } + + renderComparisons(field, momClass) { + var compared = this.props.compareCompany + if(!this.isComparison) + return + var row = getFieldNumbers(compared.number_set[this.props.report], field) + return this.renderRow(compared, ['compared', momClass], row, 2) + } + + renderRow(company, classes, row, idx) { + var field = row[0] + var oddEvenClass = idx % 2 == 0 ? 'odd' : 'even' + var isPrimary = company.id == this.company.id + var rowClass = classNames(classes || oddEvenClass, { + 'mom': field in this.state.schedules, 'strong': highlights.indexOf(field) >= 0, - 'percent': percents.indexOf(field) >= 0 || endsWith(field, '%'), - 'odd': ( childIdx === false ? idx : childIdx ) % 2 == 0 + 'percent': percents.indexOf(field) >= 0 || endsWith(field, '%') }) - var Cells = dates.map(function(rdt, iidx) { - return {Utils.toLocalNumber(row[1][rdt])} - }) - var TTMCell = trailing ? {trailing[field]} : false - var isCompanyCompared = this.props.compareCompany && this.props.compareCompany.id - var addCompanyName = isCompanyCompared && childIdx === false ? {this.props.company.short_name} : isCompanyCompared ? : null - var idxCompare = idx + 50 // Need a good reason for this number - var CellsCompare = isCompanyCompared && childIdx === false ? dates.map(function(rdt, iidx) { - var cellValue = numbersCompareCompany[idx][1][rdt] - return cellValue ? {Utils.toLocalNumber(cellValue)} : - }) : null - var TTMCellCompare = isCompanyCompared && childIdx === false && trailingCompareCompany ? {trailingCompareCompany[field]} : false - var addComparingCompany = isCompanyCompared && childIdx === false ? - - - {this.props.compareCompany.short_name} - {CellsCompare} - {TTMCellCompare} - - : null - - return [ - this.handleExpand(field)}> + + var fieldCell = isPrimary ? this.handleExpand(field)}> {row[0]} + : + var companyNameCell = this.isComparison && + {company.short_name} + + var dataCells = this.dates.map(function(date, iidx) { + return + {Utils.toLocalNumber(row[1][date])} - {addCompanyName} - {Cells} - {TTMCell} - , - schedules && schedules.map(this.renderRow.bind(this, trailing, dates, idx, null, null)), - addComparingCompany] + }) + var ttmCell = this.trailing && {this.trailing[field]} + + return [ + + {fieldCell} + {companyNameCell} + {dataCells} + {ttmCell} + , + isPrimary && this.renderComparisons(field, oddEvenClass), + this.renderSchedules(field, company, oddEvenClass) + ] } render() { - var company = this.props.company + var company = this.company var standalone = company.warehouse_set.result_type == 'sa' var pair_url = company.warehouse_set.pair_url var pair_link = getSuffix(pair_url, standalone, company.prime) - var numbers = company.number_set[this.props.report] - var dates = Object.keys(numbers[0][1]).sort() - var trailing = getTrailing(this.props.report, company.number_set, dates) - var isCompanyCompared = this.props.compareCompany && this.props.compareCompany.id - var blankHeader = isCompanyCompared ? : null - var numbersCompareCompany = isCompanyCompared ? this.props.compareCompany.number_set[this.props.report] : null - var trailingCompareCompany = isCompanyCompared && trailing ? getTrailing(this.props.report, this.props.compareCompany.number_set, dates) : null - - var Heads = dates.map(function(rdt, idx) { - return {Utils.toMonthYear(rdt)} + var compareHead = this.isComparison && + var dateHeads = this.dates.map(function(resultDate, idx) { + return {Utils.toMonthYear(resultDate)} }) - var TTMHead = trailing && TTM - + var ttmHead = this.trailing && TTM return
{this.props.children} @@ -177,13 +196,13 @@ class Results extends React.Component { - {blankHeader} - {Heads} - {TTMHead} + {compareHead} + {dateHeads} + {ttmHead} - {numbers.map(this.renderRow.bind(this, trailing, dates, false, numbersCompareCompany, trailingCompareCompany))} + {this.numbers.map(this.renderRow.bind(this, this.company, false))}
From 000f2965e527508dfd35eb6d6b19b6fe698132fa Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Thu, 7 Jul 2016 18:52:43 +0530 Subject: [PATCH 17/43] Added support for multiple comparisons --- app/company/__tests__/company-tests.js | 2 +- app/company/company.jsx | 10 +++++----- app/company/results.jsx | 12 +++++++----- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/app/company/__tests__/company-tests.js b/app/company/__tests__/company-tests.js index 6eb3511..c117e68 100644 --- a/app/company/__tests__/company-tests.js +++ b/app/company/__tests__/company-tests.js @@ -80,7 +80,7 @@ describe('Basic rendering Tests', function() { it('Company results comparing with another company', function() { result = TestUtils.renderIntoDocument( - + ) var dom = ReactDOM.findDOMNode(result) var salesRow = 'SalesAvanti Feeds1,033.36' diff --git a/app/company/company.jsx b/app/company/company.jsx index c72e3bb..f49afe4 100644 --- a/app/company/company.jsx +++ b/app/company/company.jsx @@ -17,7 +17,7 @@ var Company = React.createClass({ getInitialState: function() { return { company: undefined, - compareCompany: undefined, + comparisons: [], favorites: [] }; }, @@ -63,12 +63,13 @@ var Company = React.createClass({ handleAddCompare: function(company) { Api.get(company.url).then(response => { - this.setState({compareCompany: response}); + var comparisons = this.state.comparisons.concat(response) + this.setState({comparisons: comparisons}); }); }, handleRemoveCompare: function() { - this.setState({compareCompany: undefined}) + this.setState({comparisons: []}) }, renderLoading: function() { @@ -79,7 +80,6 @@ var Company = React.createClass({ render: function() { var company = this.state.company - var compareCompany = this.state.compareCompany if (!company) return this.renderLoading() var wid = company.warehouse_set.id @@ -118,7 +118,7 @@ var Company = React.createClass({
- +
diff --git a/app/company/results.jsx b/app/company/results.jsx index 8a41e0f..6a4084d 100644 --- a/app/company/results.jsx +++ b/app/company/results.jsx @@ -84,7 +84,7 @@ class Results extends React.Component { this.numbers = this.company.number_set[props.report] this.dates = Object.keys(this.numbers[0][1]).sort() this.trailing = getTrailing(props.report, this.company.number_set, this.dates) - this.isComparison = props.compareCompany + this.isComparison = props.comparisons && props.comparisons.length > 0 } constructor(props, context) { @@ -126,11 +126,13 @@ class Results extends React.Component { } renderComparisons(field, momClass) { - var compared = this.props.compareCompany if(!this.isComparison) return - var row = getFieldNumbers(compared.number_set[this.props.report], field) - return this.renderRow(compared, ['compared', momClass], row, 2) + var comparisons = this.props.comparisons + return comparisons.map((compared, idx) => { + var row = getFieldNumbers(compared.number_set[this.props.report], field) + return this.renderRow(compared, ['compared', momClass], row, idx) + }) } renderRow(company, classes, row, idx) { @@ -212,7 +214,7 @@ class Results extends React.Component { Results.propTypes = { company: React.PropTypes.object.isRequired, - compareCompany: React.PropTypes.object, + comparisons: React.PropTypes.array, report: React.PropTypes.string.isRequired, children: React.PropTypes.element } From e8fc27251bd6667da1157d17ac904f394d423a9a Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Thu, 7 Jul 2016 23:21:14 +0530 Subject: [PATCH 18/43] Improved css --- app/company/company.jsx | 4 +--- app/company/results.jsx | 12 ++++++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/app/company/company.jsx b/app/company/company.jsx index f49afe4..398a2de 100644 --- a/app/company/company.jsx +++ b/app/company/company.jsx @@ -108,6 +108,7 @@ var Company = React.createClass({
+
@@ -115,9 +116,6 @@ var Company = React.createClass({
-
- -
diff --git a/app/company/results.jsx b/app/company/results.jsx index 6a4084d..cfccd04 100644 --- a/app/company/results.jsx +++ b/app/company/results.jsx @@ -70,6 +70,9 @@ function getTrailing(report, number_set, ann_dates) { return trailing } +var skipInComparison = [ + 'Expenses', 'Operating Profit' +] var highlights = [ 'Operating Profit', 'Profit before tax', 'Net Profit', 'Total Liabilities', 'Total Assets', @@ -137,6 +140,8 @@ class Results extends React.Component { renderRow(company, classes, row, idx) { var field = row[0] + if(this.isComparison && skipInComparison.indexOf(field) >= 0) + return var oddEvenClass = idx % 2 == 0 ? 'odd' : 'even' var isPrimary = company.id == this.company.id var rowClass = classNames(classes || oddEvenClass, { @@ -183,10 +188,6 @@ class Results extends React.Component { }) var ttmHead = this.trailing && TTM return
-
- {this.props.children} -
-

{getCaption(this.props.report)} {getPrefix(pair_url, standalone)} Figures in Rs. Crores {pair_link} @@ -215,8 +216,7 @@ class Results extends React.Component { Results.propTypes = { company: React.PropTypes.object.isRequired, comparisons: React.PropTypes.array, - report: React.PropTypes.string.isRequired, - children: React.PropTypes.element + report: React.PropTypes.string.isRequired } module.exports = Results From 3cee29c41b883844302bcd0859af36657c1d9d13 Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Fri, 8 Jul 2016 16:26:04 +0530 Subject: [PATCH 19/43] Improved css --- app/company/results.jsx | 15 +++++++-------- custom.css | 12 +++++++----- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/app/company/results.jsx b/app/company/results.jsx index cfccd04..ed048c0 100644 --- a/app/company/results.jsx +++ b/app/company/results.jsx @@ -70,9 +70,6 @@ function getTrailing(report, number_set, ann_dates) { return trailing } -var skipInComparison = [ - 'Expenses', 'Operating Profit' -] var highlights = [ 'Operating Profit', 'Profit before tax', 'Net Profit', 'Total Liabilities', 'Total Assets', @@ -86,8 +83,10 @@ class Results extends React.Component { this.company = props.company this.numbers = this.company.number_set[props.report] this.dates = Object.keys(this.numbers[0][1]).sort() - this.trailing = getTrailing(props.report, this.company.number_set, this.dates) this.isComparison = props.comparisons && props.comparisons.length > 0 + this.trailing = !this.isComparison && getTrailing( + props.report, this.company.number_set, this.dates + ) } constructor(props, context) { @@ -125,7 +124,9 @@ class Results extends React.Component { var schedules = this.state.schedules[field] if(!schedules) return - return schedules.map(this.renderRow.bind(this, company, ['child', momClass])) + return schedules.map( + this.renderRow.bind(this, company, ['child', momClass]) + ) } renderComparisons(field, momClass) { @@ -140,8 +141,6 @@ class Results extends React.Component { renderRow(company, classes, row, idx) { var field = row[0] - if(this.isComparison && skipInComparison.indexOf(field) >= 0) - return var oddEvenClass = idx % 2 == 0 ? 'odd' : 'even' var isPrimary = company.id == this.company.id var rowClass = classNames(classes || oddEvenClass, { @@ -154,7 +153,7 @@ class Results extends React.Component { className="text" onClick={() => this.handleExpand(field)}> {row[0]} - : + : var companyNameCell = this.isComparison && {company.short_name} diff --git a/custom.css b/custom.css index c17ed91..6fb05cf 100644 --- a/custom.css +++ b/custom.css @@ -134,20 +134,22 @@ th:hover .tooltip { table .text { text-align: left; + max-width: 150px; + text-overflow: ellipsis; + /* Required for text-overflow to do anything */ + white-space: nowrap; + overflow: hidden; } table .odd { background-color: #f9f9f9; } -.percent td:after { +.percent td:not(.text):after { content: '%'; } -.percent td:first-child:after { - content: ''; -} .child .text:before { content: "﹂ "; } -.table > tbody > .child > td { +.table > tbody > .child > td, .table > tbody > .compared > td { border-top: none; } .mom { From c2b67571cc94575f773c282ba919b257aa82e9ae Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Mon, 11 Jul 2016 15:37:20 +0530 Subject: [PATCH 20/43] Tests passing --- app/company/__tests__/company-tests.js | 93 -------------------------- app/company/__tests__/peers-tests.js | 10 ++- app/company/__tests__/results-tests.js | 67 +++++++++++++++---- app/company/company.jsx | 35 +++++++--- app/company/compare.jsx | 81 +++++++++++----------- app/company/peers.jsx | 92 +++++++++++++------------ app/company/results.jsx | 27 +++++--- app/components/under.icon.jsx | 32 --------- 8 files changed, 194 insertions(+), 243 deletions(-) delete mode 100644 app/company/__tests__/company-tests.js delete mode 100644 app/components/under.icon.jsx diff --git a/app/company/__tests__/company-tests.js b/app/company/__tests__/company-tests.js deleted file mode 100644 index c117e68..0000000 --- a/app/company/__tests__/company-tests.js +++ /dev/null @@ -1,93 +0,0 @@ -'use strict' -jest.disableAutomock() -import React from 'react' -import ReactDOM from 'react-dom' -import Results from '../results.jsx' -import TestUtils from 'react-addons-test-utils' - - -var NUMBERS = [ - ["Sales",{"2008-03-31":1033.36,"2009-03-31":1002.53}], - ["Expenses",{"2008-03-31":915.16,"2009-03-31":1136.98}], - ["Material Cost %",{"2008-03-31":11.26,"2009-03-31":11.38}], - ["Manufacturing Cost %",{"2008-03-31":8.64,"2009-03-31":8.43}], - ["Employee Cost %",{"2008-03-31":91.23,"2009-03-31":98.93}], - ["Other Cost %",{"2008-03-31":2.61,"2009-03-31":3.41}], - ["Operating Profit",{"2008-03-31":118.2,"2009-03-31":-134.45}], - ["OPM",{"2008-03-31":11.44,"2009-03-31":-13.41}] -] - - -var COMPARENUMBERS = [ - ["Sales",{"2008-03-31":533.36,"2009-03-31":502.53}], - ["Expenses",{"2008-03-31":415.16,"2009-03-31":536.98}], - ["Material Cost %",{"2008-03-31":5.26,"2009-03-31":5.38}], - ["Manufacturing Cost %",{"2008-03-31":4.64,"2009-03-31":4.43}], - ["Employee Cost %",{"2008-03-31":71.23,"2009-03-31":78.93}], - ["Other Cost %",{"2008-03-31":2.21,"2009-03-31":3.11}], - ["Operating Profit",{"2008-03-31":58.2,"2009-03-31":-74.45}], - ["OPM",{"2008-03-31":9.44,"2009-03-31":-11.41}] -] - -describe('Basic rendering Tests', function() { - var result - var company // https://www.screener.in/api/company/512573/ - var compareCompany // https://www.screener.in/api/company/539168/ - - beforeEach(function() { - company = { - id: 341, - warehouse_set: { - result_type: 'sa', - pair_url: '' - }, - number_set: { - quarters: [["Sales", {}]], - annual: NUMBERS - }, - bse_code: "512573", - short_name: "Avanti Feeds", - name: "Avanti Feeds Ltd" - }; - compareCompany = { - id: 1270856, - warehouse_set: { - result_type: 'sa', - pair_url: '' - }, - number_set: { - quarters: [["Sales", {}]], - annual: COMPARENUMBERS - }, - bse_code: "539168", - short_name: "Spisys", - name: "Spisys Ltd" - }; - }) - - it('Company results without comparing another company', function() { - result = TestUtils.renderIntoDocument( - - ) - var dom = ReactDOM.findDOMNode(result) - var salesRow = 'Sales1,033.36' - var materialRow = 'Material Cost %11.26' - var normalComparisonRow = 'Spisys' - expect(dom.innerHTML).toContain(salesRow) - expect(dom.innerHTML).toContain(materialRow) - expect(dom.innerHTML).not.toContain(normalComparisonRow) - }) - - it('Company results comparing with another company', function() { - result = TestUtils.renderIntoDocument( - - ) - var dom = ReactDOM.findDOMNode(result) - var salesRow = 'SalesAvanti Feeds1,033.36' - var materialRow = 'Material Cost %Avanti Feeds11.26' - var salesComparisonRow = 'Spisys533.36' - expect(dom.innerHTML).toContain(salesRow) - expect(dom.innerHTML).toContain(materialRow) - expect(dom.innerHTML).toContain(salesComparisonRow) - }) -}) diff --git a/app/company/__tests__/peers-tests.js b/app/company/__tests__/peers-tests.js index e4092c3..14efbf8 100644 --- a/app/company/__tests__/peers-tests.js +++ b/app/company/__tests__/peers-tests.js @@ -18,11 +18,17 @@ describe('Peers tests', function () { }); it('renders a peers table', function() { - var props = {wid: 22, industry: 'Hi', short_name: 'hi'}; + var company = { + short_name: 'hi', + warehouse_set: { + id: 22, + industry: 'Hi' + } + } api.setResponse('/api/company/22/peers/?industry=Hi', JSON.stringify(peerResults)); var peers = TestUtils.renderIntoDocument( - + ); return peers._req.then(() => { var dom = ReactDOM.findDOMNode(peers); diff --git a/app/company/__tests__/results-tests.js b/app/company/__tests__/results-tests.js index 9f77a5d..8837d89 100644 --- a/app/company/__tests__/results-tests.js +++ b/app/company/__tests__/results-tests.js @@ -18,27 +18,41 @@ var NUMBERS = [ var SCHEDULE = [ ["Schedule A",{"2008-03-31":77.27,"2009-03-31":75.49}], - ["Schedule B",{"2008-03-31":77.27,"2009-03-31":75.49}], + ["Schedule B",{"2008-03-31":77.27,"2009-03-31":75.49}] ] +var FooCompany = { + id: 33, + short_name: 'Foo', + warehouse_set: { + result_type: 'sa', + pair_url: '' + }, + number_set: { + quarters: [["Sales", {}]], + annual: NUMBERS + } +} + +var BarCompany = { + id: 55, + short_name: 'Bar', + warehouse_set: { + result_type: 'sa', + pair_url: '' + }, + number_set: { + quarters: [["Sales", {}]], + annual: NUMBERS + } +} describe('Basic rendering Tests', function() { var result beforeEach(function() { - var company = { - id: 33, - warehouse_set: { - result_type: 'sa', - pair_url: '' - }, - number_set: { - quarters: [["Sales", {}]], - annual: NUMBERS - } - } result = TestUtils.renderIntoDocument( - + ) }) @@ -66,3 +80,30 @@ describe('Basic rendering Tests', function() { expect(dom.innerHTML).toContain(percentRow) }) }) + + +describe('Comparison rendering Tests', function() { + var result + + beforeEach(function() { + result = TestUtils.renderIntoDocument( + + ) + }) + + afterEach(function() { + expect(api.getPending()).toEqual([]) + }) + + it('should add comparison row', function() { + var dom = ReactDOM.findDOMNode(result) + var salesFoo = 'SalesFoo1,033.36' + var salesBar = 'Bar1,033.36' + expect(dom.innerHTML).toContain(salesFoo) + expect(dom.innerHTML).toContain(salesBar) + }) +}) diff --git a/app/company/company.jsx b/app/company/company.jsx index 398a2de..3546f4d 100644 --- a/app/company/company.jsx +++ b/app/company/company.jsx @@ -38,7 +38,10 @@ var Company = React.createClass({ var con = params.consolidated; Api.get(Api.company(exc, con)).then(function(response) { Utils.setTitle(response.name); - this.setState({company: response}); + this.setState({ + company: response, + comparisons: [] + }); }.bind(this)); }, @@ -61,8 +64,15 @@ var Company = React.createClass({ }.bind(this)); }, + handleStartCompare: function() { + var company = this.state.company + Api.get(Api.cid(company.id, 'comparison')).then(response => { + this.setState({comparisons: [response]}); + }); + }, + handleAddCompare: function(company) { - Api.get(company.url).then(response => { + Api.get(Api.cid(company.id, 'comparison')).then(response => { var comparisons = this.state.comparisons.concat(response) this.setState({comparisons: comparisons}); }); @@ -80,10 +90,9 @@ var Company = React.createClass({ render: function() { var company = this.state.company + var comparisons = this.state.comparisons if (!company) return this.renderLoading() - var wid = company.warehouse_set.id - var quickratios = return
- {quickratios} +
@@ -107,25 +116,29 @@ var Company = React.createClass({
- - + +
- +
- +
- +
- +
diff --git a/app/company/compare.jsx b/app/company/compare.jsx index e6cb97d..677fb1a 100644 --- a/app/company/compare.jsx +++ b/app/company/compare.jsx @@ -1,57 +1,52 @@ "use strict"; import React from 'react' import CompanySearch from '../components/company.search.jsx' -import UnderIcon from '../components/under.icon.jsx' -import Icon from '../components/icon.jsx' - - -class AddCompare extends React.Component { - constructor(props, context) { - super(props, context) - this.handleAdd = this.handleAdd.bind(this) - this.handleRemove = this.handleRemove.bind(this) - this.state = { - selectedCompany: undefined - } +import Button from '../components/button.jsx' + + +function AddCompare(props) { + + function renderRemoveOptions() { + if (props.comparisons.length == 0) + return + return
+
} - handleAdd(company) { - this.setState({selectedCompany: company}) - this.props.onAdd(company) + function renderStart() { + return
} -}); +} +Peers.propTypes = { + company: React.PropTypes.object.isRequired +} -module.exports = Peers; +module.exports = Peers diff --git a/app/company/results.jsx b/app/company/results.jsx index ed048c0..ea1dee2 100644 --- a/app/company/results.jsx +++ b/app/company/results.jsx @@ -64,7 +64,7 @@ function getTrailing(report, number_set, ann_dates) { for(var j=0; j < four_qtrs.length; j++) { value += vals[four_qtrs[j]] } - var final_val = field == 'OPM' ? value / four_qtrs.length : value + var final_val = ttmAverages.indexOf(field) >= 0 ? value / four_qtrs.length : value trailing[field] = final_val.toFixed(2) } return trailing @@ -75,17 +75,25 @@ var highlights = [ 'Total Liabilities', 'Total Assets', 'Net Cash Flow' ] +var compareHighlights = [ + 'OPM', 'Profit before tax', 'Net Profit', + 'Debt / Equity', 'ROCE %', + 'Debtor Days', 'Net Cash Flow' +] +var ttmAverages = ['OPM', 'Tax %'] var percents = ['OPM', 'Dividend Payout'] class Results extends React.Component { updateClassVariables(props) { this.company = props.company - this.numbers = this.company.number_set[props.report] - this.dates = Object.keys(this.numbers[0][1]).sort() this.isComparison = props.comparisons && props.comparisons.length > 0 + this.isMulti = props.comparisons && props.comparisons.length > 1 + var primary = this.isComparison ? props.comparisons[0] : this.company + this.numbers = primary.number_set[props.report] + this.dates = Object.keys(this.numbers[0][1]).sort() this.trailing = !this.isComparison && getTrailing( - props.report, this.company.number_set, this.dates + props.report, primary.number_set, this.dates ) } @@ -130,10 +138,12 @@ class Results extends React.Component { } renderComparisons(field, momClass) { - if(!this.isComparison) + if(!this.isMulti) return var comparisons = this.props.comparisons return comparisons.map((compared, idx) => { + if (idx == 0) + return var row = getFieldNumbers(compared.number_set[this.props.report], field) return this.renderRow(compared, ['compared', momClass], row, idx) }) @@ -143,9 +153,10 @@ class Results extends React.Component { var field = row[0] var oddEvenClass = idx % 2 == 0 ? 'odd' : 'even' var isPrimary = company.id == this.company.id + var strongs = this.isComparison ? compareHighlights : highlights var rowClass = classNames(classes || oddEvenClass, { 'mom': field in this.state.schedules, - 'strong': highlights.indexOf(field) >= 0, + 'strong': strongs.indexOf(field) >= 0, 'percent': percents.indexOf(field) >= 0 || endsWith(field, '%') }) @@ -154,7 +165,7 @@ class Results extends React.Component { onClick={() => this.handleExpand(field)}> {row[0]} : - var companyNameCell = this.isComparison && + var companyNameCell = this.isMulti && {company.short_name} var dataCells = this.dates.map(function(date, iidx) { @@ -181,7 +192,7 @@ class Results extends React.Component { var standalone = company.warehouse_set.result_type == 'sa' var pair_url = company.warehouse_set.pair_url var pair_link = getSuffix(pair_url, standalone, company.prime) - var compareHead = this.isComparison && + var compareHead = this.isMulti && var dateHeads = this.dates.map(function(resultDate, idx) { return {Utils.toMonthYear(resultDate)} }) diff --git a/app/components/under.icon.jsx b/app/components/under.icon.jsx deleted file mode 100644 index 3e205fd..0000000 --- a/app/components/under.icon.jsx +++ /dev/null @@ -1,32 +0,0 @@ -"use strict"; -import React from 'react' -import Icon from './icon.jsx' - -class UnderIcon extends React.Component { - constructor(props, context) { - super(props, context) - this.state = { - isClicked: false - } - } - - render() { - var innerContent = this.state.isClicked && this.props.children - var iconClass = this.state.isClicked ? 'hide' : '' - return
- {innerContent} -
this.setState({isClicked: true})}> - -
-
- } -} - -UnderIcon.propTypes = { - children: React.PropTypes.element.isRequired, - icon: React.PropTypes.string.isRequired -} - -module.exports = UnderIcon From 585c35ed60002f7e75fb5b4589439ccda40e2ea5 Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Mon, 11 Jul 2016 15:42:02 +0530 Subject: [PATCH 21/43] Fixed page refresh at home --- app/home.jsx | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/app/home.jsx b/app/home.jsx index 4362139..f37b2b2 100644 --- a/app/home.jsx +++ b/app/home.jsx @@ -1,7 +1,6 @@ "use strict"; -/* global require, document */ - var React = require('react'); +var Link = require('react-router').Link; var CompanySearch = require('./components/company.search.jsx'); function Home(props, context) { @@ -27,16 +26,16 @@ function Home(props, context) {

- Or Analyse: - Avanti Feeds, - AYM Syntex, - Can-Fin Homes, - Kalyani Steels, - Kitex Garments, - Shilpa Medicare, - Sanghvi Movers, - Stovec Industries, - Tata Metaliks ... + Or Analyse: + Avanti Feeds, + AYM Syntex, + Can-Fin Homes, + Kalyani Steels, + Kitex Garments, + Shilpa Medicare, + Sanghvi Movers, + Stovec Industries, + Tata Metaliks ...

From 60acb5ed6cabe5fecf8729800804582bcb3af54e Mon Sep 17 00:00:00 2001 From: mh Date: Sun, 24 Jul 2016 11:29:33 +0530 Subject: [PATCH 22/43] Allow users to update existing screens by updating queries used for the screens they own --- app/modals/savescreen.modal.jsx | 45 ++++++++++++++++++++++++++++++++- app/screens/query.form.jsx | 5 ++++ app/screens/query.results.jsx | 2 +- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/app/modals/savescreen.modal.jsx b/app/modals/savescreen.modal.jsx index 25f7fbc..e1123ed 100644 --- a/app/modals/savescreen.modal.jsx +++ b/app/modals/savescreen.modal.jsx @@ -20,11 +20,19 @@ var SaveScreenModal = React.createClass({ getInitialState: function() { return { form: {__html: '

Loading...

'}, + updateScreen: undefined, errors: false }; }, onOpen: function() { + var screenId = this.props.update; + if (screenId) { + Api.get(['screens', screenId]).then(resp => { + this.setState({updateScreen: resp.is_owner ? resp : undefined}); + }); + } + return Api.rawGet('screens.html').then(resp => { this.setState({ form: {__html: resp} @@ -34,6 +42,26 @@ var SaveScreenModal = React.createClass({ onClose: function() {}, + updateScreen: function(event) { + event.preventDefault(); + var screen = this.props.screen; + var data = utils.getFormData(this.refs.form); + data.query = screen.query; + data.latest = screen.latest; + data.order = screen.order; + data.sort = screen.sort; + + data.id = this.state.updateScreen.id; + var url = 'screens/' + data.id; + Api.put([url], data).then( + function(response) { + this.context.router.push(response.url); + }.bind(this), + function(errors) { + this.setState({errors: errors}); + }.bind(this)); + }, + handleSubmit: function(event) { event.preventDefault(); var screen = this.props.screen; @@ -42,6 +70,7 @@ var SaveScreenModal = React.createClass({ data.latest = screen.latest; data.order = screen.order; data.sort = screen.sort; + Api.post(['screens'], data).then( function(response) { this.context.router.push(response.url); @@ -57,6 +86,18 @@ var SaveScreenModal = React.createClass({ render: function() { var formCls = this.state.errors && 'has-error'; + + var txtSaveBtn = this.state.updateScreen === undefined ? 'Save' : 'Save as new screen'; + var updateBtn; + if(this.state.updateScreen) { + // This won't work if the form is not already added. + // this.refs.form.name.value = this.state.updateScreen.name; + // this.refs.form.description.value = this.state.updateScreen.description; + updateBtn = ; + } + return
+ {updateBtn} + {' '}
+ {updateBtn} - {' '} - ; } From 836c4f9721efe65b217b6bbb3050d6e33555fe35 Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Tue, 30 Aug 2016 20:31:21 +0530 Subject: [PATCH 25/43] Populate Update Param only when required --- app/screens/query.form.jsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/screens/query.form.jsx b/app/screens/query.form.jsx index d04fde3..cb307e5 100644 --- a/app/screens/query.form.jsx +++ b/app/screens/query.form.jsx @@ -16,8 +16,9 @@ function QueryForm(props) { } - var is_owner = props.defaults.is_owner; - var screenId = is_owner ? props.defaults.id : props.defaults.update; + var updateField + if(props.defaults.is_owner && props.defaults.id) + updateField = return

Query Builder

@@ -38,8 +39,8 @@ function QueryForm(props) { defaultChecked={props.defaults.latest} /> Show only latest results? - + {updateField} From 89e4aed00d63de0df1083ba152c691d5ca2d07fb Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Tue, 30 Aug 2016 20:55:57 +0530 Subject: [PATCH 26/43] Fixed Checkbox uncontrolled to controlled warning --- app/screens/query.form.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/screens/query.form.jsx b/app/screens/query.form.jsx index cb307e5..1bb5db4 100644 --- a/app/screens/query.form.jsx +++ b/app/screens/query.form.jsx @@ -35,7 +35,7 @@ function QueryForm(props) { Show only latest results? From eb4cc9bdeccdac85ac692b2322c49eb5619df91e Mon Sep 17 00:00:00 2001 From: Pratyush Mittal Date: Fri, 16 Sep 2016 15:16:06 +0530 Subject: [PATCH 27/43] Added tests --- .../__tests__/savescreen.modal-tests.js | 85 ++++++++++++++++ app/modals/savescreen.modal.jsx | 97 +++++-------------- app/screens/query.form.jsx | 6 +- 3 files changed, 113 insertions(+), 75 deletions(-) create mode 100644 app/modals/__tests__/savescreen.modal-tests.js diff --git a/app/modals/__tests__/savescreen.modal-tests.js b/app/modals/__tests__/savescreen.modal-tests.js new file mode 100644 index 0000000..e254758 --- /dev/null +++ b/app/modals/__tests__/savescreen.modal-tests.js @@ -0,0 +1,85 @@ +'use strict'; +jest.disableAutomock(); +jest.mock('fetch-on-rest'); +var TestUtils = require('react-addons-test-utils'); +var React = require('react'); +var SaveScreenModal = require('../savescreen.modal.jsx'); +var api = require('../../api.js'); + +var SCREEN = { + query: '1=1', + ratios: [[ + "Current price", + "CMP", + "Rs." + ]], + results: [ + ['/foo/', 'Foo', 115] + ] +} + + +describe('SaveScreen Modal tests', function() { + beforeEach(function() { + window.loggedIn = true; + }); + + afterEach(function() { + expect(api.getPending()).toEqual([]); + }); + + it('should POST on form submit', function() { + var modal = TestUtils.renderIntoDocument( + + ) + var button = TestUtils.findRenderedDOMComponentWithTag( + modal, 'button') + TestUtils.Simulate.click(button) + var form = TestUtils.findRenderedDOMComponentWithTag( + modal, 'form' + ); + var html = '' + api.setResponse('/api/screens.html', html); + TestUtils.Simulate.submit(form); + return modal._req.then(() => { + expect(window.fetch).toBeCalledWith('/api/screens/', { + body: '{"csrfmiddlewaretoken":"","":"","query":"1=1"}', + credentials: 'same-origin', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + 'X-CSRFToken': '' + }, + method: 'post' + }); + }); + }) + + it('should PUT on form submit', function() { + var modal = TestUtils.renderIntoDocument( + + ) + var button = TestUtils.findRenderedDOMComponentWithTag( + modal, 'button') + TestUtils.Simulate.click(button) + var html = '' + api.setResponse('/api/screens/2.html', html); + var form = TestUtils.findRenderedDOMComponentWithTag( + modal, 'form' + ); + TestUtils.Simulate.submit(form); + return modal._req.then(() => { + expect(window.fetch).toBeCalledWith('/api/screens/2/', { + body: '{"csrfmiddlewaretoken":"","":"","query":"1=1"}', + credentials: 'same-origin', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + 'X-CSRFToken': '' + }, + method: 'put' + }); + }); + }) + +}); diff --git a/app/modals/savescreen.modal.jsx b/app/modals/savescreen.modal.jsx index 6914d7c..2b9701f 100644 --- a/app/modals/savescreen.modal.jsx +++ b/app/modals/savescreen.modal.jsx @@ -1,5 +1,6 @@ "use strict"; var React = require('react'); +var classNames = require('classnames'); var Button = require('../components/button.jsx'); var Modal = require('../components/modal.jsx'); var Api = require('../api.js'); @@ -14,44 +15,30 @@ var SaveScreenModal = React.createClass({ }, propTypes: { - screen: React.PropTypes.object.isRequired + screen: React.PropTypes.object.isRequired, + update: React.PropTypes.string }, getInitialState: function() { return { form: {__html: '

Loading...

'}, - isOwner: true, - savedScreen: undefined, errors: false }; }, onOpen: function() { - var screenId = this.props.update; - if (screenId) { - Api.get(['screens', screenId]).then(resp => { - this.setState({ - isOwner: resp.is_owner, - savedScreen: resp.is_owner ? resp : undefined - }); - }); - } - - return Api.rawGet('screens.html').then(resp => { + var uid = this.props.update + var url = uid ? 'screens/' + uid + '.html' : 'screens.html' + return Api.rawGet(url).then(resp => { this.setState({ form: {__html: resp} }); - - if (screenId) { - this.updateForm(); - } }); }, onClose: function() {}, - updateScreen: function(event) { - event.preventDefault(); + handleSubmit: function(uid) { var screen = this.props.screen; var data = utils.getFormData(this.refs.form); data.query = screen.query; @@ -59,9 +46,9 @@ var SaveScreenModal = React.createClass({ data.order = screen.order; data.sort = screen.sort; - data.id = this.state.savedScreen.id; - var url = 'screens/' + data.id; - Api.put([url], data).then( + var save = uid ? 'put' : 'post' + var url = uid ? ['screens', uid] : ['screens'] + this._req = Api[save](url, data).then( function(response) { this.context.router.push(response.url); }.bind(this), @@ -70,51 +57,23 @@ var SaveScreenModal = React.createClass({ }.bind(this)); }, - handleSubmit: function(event) { - event.preventDefault(); - var screen = this.props.screen; - var data = utils.getFormData(this.refs.form); - data.query = screen.query; - data.latest = screen.latest; - data.order = screen.order; - data.sort = screen.sort; - - Api.post(['screens'], data).then( - function(response) { - this.context.router.push(response.url); - }.bind(this), - function(errors) { - this.setState({errors: errors}); - }.bind(this)); - }, - - updateFields: function() { - if(this.state.savedScreen) { - this.refs.form.name.value = this.state.savedScreen.name; - this.refs.form.description.value = this.state.savedScreen.description; - } else if (this.state.isOwner) { - this.updateForm(); - } - }, - - updateForm: function() { - setTimeout( () => this.updateFields(), 200); - }, - handleCancel: function() { this.refs.modal.handleClose(); }, render: function() { - var formCls = this.state.errors && 'has-error'; - - var txtSaveBtn = this.state.savedScreen === undefined ? 'Save' : 'Save as new screen'; - var updateBtn; - if(this.state.savedScreen) { - updateBtn = ; - } + var btnCls = classNames('btn', this.props.update ? 'btn-link' : 'btn-primary') + var btnText = this.props.update ? 'Save as new screen' : + Save + + var createNewBtn = this.handleSubmit()} className={btnCls}> + {btnText} + + var updateBtn = this.props.update && this.handleSubmit(this.props.update)} + className="btn btn-primary"> + Save Changes + return event.preventDefault() || this.handleSubmit(this.props.update)} ref="form" - className={formCls} + className={this.state.errors && 'has-error'} >
-
-    - -
- {updateBtn} + {createNewBtn} {updateBtn}