From 7becfa5889b16af193981f485a90cc9ede1a9bff Mon Sep 17 00:00:00 2001 From: Peng Zhong Date: Thu, 30 Nov 2017 13:56:04 +0900 Subject: [PATCH 01/13] better Delegate view --- .../components/staking/CardCandidate.vue | 89 +++++++++---------- .../components/staking/PageCandidates.vue | 34 +++---- .../renderer/components/staking/PanelSort.vue | 9 +- 3 files changed, 60 insertions(+), 72 deletions(-) diff --git a/app/src/renderer/components/staking/CardCandidate.vue b/app/src/renderer/components/staking/CardCandidate.vue index 0937f66da7..507c7ab14a 100644 --- a/app/src/renderer/components/staking/CardCandidate.vue +++ b/app/src/renderer/components/staking/CardCandidate.vue @@ -1,25 +1,23 @@ @@ -28,7 +26,7 @@ transition(name='ts-card-candidate'): div(:class='cssClass') import { mapGetters } from 'vuex' import num from 'scripts/num' import Btn from '@nylira/vue-button' -// import { maxBy } from 'lodash' +import { maxBy } from 'lodash' export default { name: 'card-candidate', props: ['candidate'], @@ -37,35 +35,32 @@ export default { }, computed: { ...mapGetters(['shoppingCart', 'candidates', 'user']), - cssClass () { + styles () { let value = 'card-candidate' if (this.inCart) value += ' card-candidate-active ' return value }, - signedIn () { - return this.user.signedIn - }, - maxAtoms () { - // if (this.candidates.length > 0) { - // let richestCandidate = maxBy(this.candidates, 'atoms') - // return richestCandidate.atoms - // } else { return 0 } + vpMax () { + if (this.candidates.length > 0) { + let richestCandidate = maxBy(this.candidates, 'voting_power') + return richestCandidate.voting_power + } else { return 0 } return 0 }, - atomsCss () { - let percentage = Math.round((this.candidate.atoms / this.maxAtoms) * 100) + vpStyles () { + let percentage = + Math.round((this.candidate.voting_power / this.vpMax) * 100) return { width: percentage + '%' } }, - maxDelegatedAtoms () { - // if (this.candidates) { - // let richestCandidate = maxBy(this.candidates, 'computed.delegatedAtoms') - // return richestCandidate.computed.delegatedAtoms - // } else { return 0 } - return 0 + sharesMax () { + if (this.candidates) { + let richestCandidate = maxBy(this.candidates, 'shares') + return richestCandidate.shares + } else { return 0 } }, - delegatedAtomsCss () { - let percentage = Math.round((this.candidate.delegatedAtoms / - this.maxDelegatedAtoms) * 100) + sharesStyles () { + let percentage = + Math.round((this.candidate.shares / this.sharesMax) * 100) return { width: percentage + '%' } }, inCart () { @@ -76,12 +71,8 @@ export default { num: num }), methods: { - add (candidate) { - this.$store.commit('addToCart', candidate) - }, - rm (candidate) { - this.$store.commit('removeFromCart', candidate.id) - } + add (candidate) { this.$store.commit('addToCart', candidate) }, + rm (candidate) { this.$store.commit('removeFromCart', candidate.id) } } } @@ -99,6 +90,9 @@ export default { .card-candidate-container position relative + &:hover + menu + display block .values display flex @@ -121,11 +115,9 @@ export default { i.fa margin-right 0.5rem a - color txt + color link &:hover - color bright - &.num - mono() + color hover &.bar position relative @@ -138,16 +130,14 @@ export default { line-height 2rem padding 0 0.375rem + color txt .bar height 1.5rem - background darken(app-bg, 20%) - margin-right 1rem - &.delegated - span - color dim - .bar - background accent + background alpha(link, 33.3%) + + &.delegated .bar + background alpha(accent, 33.3%) span display block @@ -166,6 +156,7 @@ export default { display flex align-items center justify-content center + display none @media screen and (max-width: 414px) .card-candidate-container menu .ni-btn .ni-btn-value diff --git a/app/src/renderer/components/staking/PageCandidates.vue b/app/src/renderer/components/staking/PageCandidates.vue index ed0775b4a8..f0a2229385 100644 --- a/app/src/renderer/components/staking/PageCandidates.vue +++ b/app/src/renderer/components/staking/PageCandidates.vue @@ -44,8 +44,8 @@ export default { computed: { ...mapGetters(['candidates', 'filters', 'shoppingCart', 'user']), pageTitle () { - if (this.user.signedIn) return `Candidates (${this.candidatesNum} Selected)` - else return 'Candidates' + if (this.user.signedIn) return `Delegate (${this.candidatesNum} Selected)` + else return 'Delegate' }, filteredCandidates () { let query = this.filters.candidates.search.query @@ -56,27 +56,19 @@ export default { return list } }, - candidatesNum () { - return this.shoppingCart.length - }, - sort () { - let props = [ - { id: 1, title: 'Keybase ID', value: 'keybaseID' }, - { id: 2, title: 'Public Key', value: 'id' }, - { id: 3, title: 'Delegated', value: 'voting_power', initial: true } - ] - if (this.user.signedIn) { - props.push({ id: 4, title: 'Delegated (Yours)', value: 'delegated' }) - } - return { - property: 'voting_power', - order: 'desc', - properties: props - } - } + candidatesNum () { return this.shoppingCart.length } }, data: () => ({ - query: '' + query: '', + sort: { + property: 'voting_power', + order: 'desc', + properties: [ + { id: 1, title: 'Keybase ID', value: 'keybaseID', initial: true }, + { id: 2, title: 'Voting Power', value: 'voting_power' }, + { id: 3, title: 'Delegated Power', value: 'shares' } + ] + } }), methods: { setSearch (bool) { this.$store.commit('setSearchVisible', ['candidates', bool]) } diff --git a/app/src/renderer/components/staking/PanelSort.vue b/app/src/renderer/components/staking/PanelSort.vue index 33a9cb033b..e5fb872524 100644 --- a/app/src/renderer/components/staking/PanelSort.vue +++ b/app/src/renderer/components/staking/PanelSort.vue @@ -14,10 +14,10 @@ export default { methods: { orderBy (property, event) { let sortBys = $(this.$el).find('.sort-by') - console.log(sortBys) + // console.log(sortBys) $(sortBys).removeClass('active desc asc') let el = $(event.target).parent() - console.log('el', el) + // console.log('el', el) if (this.sort.property === property) { if (this.sort.order === 'asc') { @@ -34,6 +34,8 @@ export default { $(el).addClass('desc') } $(el).addClass('active') + + console.log('sort details', this.sort) } }, props: ['sort'] @@ -65,6 +67,7 @@ export default { .label font-size sm color dim + text-transform uppercase padding-right 0.5rem white-space nowrap @@ -75,8 +78,10 @@ export default { display block font-family FontAwesome color dim + &.asc:after content '\f0d8' + &.desc:after content '\f0d7' From 35183fccc1288e9b5774d911c0b84538b7514768 Mon Sep 17 00:00:00 2001 From: Peng Zhong Date: Thu, 30 Nov 2017 14:08:19 +0900 Subject: [PATCH 02/13] add more fields --- app/src/renderer/components/staking/CardCandidate.vue | 4 ++-- app/src/renderer/components/staking/PageCandidates.vue | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/app/src/renderer/components/staking/CardCandidate.vue b/app/src/renderer/components/staking/CardCandidate.vue index 507c7ab14a..5cac063fa9 100644 --- a/app/src/renderer/components/staking/CardCandidate.vue +++ b/app/src/renderer/components/staking/CardCandidate.vue @@ -9,12 +9,14 @@ transition(name='ts-card-candidate'): div(:class='styles') i.fa.fa-square-o(v-else @click='add(candidate)') router-link(:to="{ name: 'candidate', params: { candidate: candidate.id }}") | {{ candidate.keybaseID}} + .value {{ candidate.country }} .value.voting_power.num.bar span {{ num.prettyInt(candidate.voting_power) }} .bar(:style='vpStyles') .value.delegated.num.bar.delegated span {{ num.prettyInt(candidate.shares) }} .bar(:style='sharesStyles') + .value {{ (candidate.commission * 100).toFixed(2) }}% menu btn(theme='cosmos' v-if='inCart' icon='delete' value='Remove' size='sm' @click.native='rm(candidate)') @@ -105,9 +107,7 @@ export default { align-items center justify-content space-between - color dim padding 0 0.25rem - font-size sm min-width 0 diff --git a/app/src/renderer/components/staking/PageCandidates.vue b/app/src/renderer/components/staking/PageCandidates.vue index f0a2229385..8377e92694 100644 --- a/app/src/renderer/components/staking/PageCandidates.vue +++ b/app/src/renderer/components/staking/PageCandidates.vue @@ -61,12 +61,14 @@ export default { data: () => ({ query: '', sort: { - property: 'voting_power', - order: 'desc', + property: 'keybaseID', + order: 'asc', properties: [ { id: 1, title: 'Keybase ID', value: 'keybaseID', initial: true }, - { id: 2, title: 'Voting Power', value: 'voting_power' }, - { id: 3, title: 'Delegated Power', value: 'shares' } + { id: 2, title: 'Country', value: 'country' }, + { id: 3, title: 'Voting Power', value: 'voting_power' }, + { id: 4, title: 'Delegated Power', value: 'shares' }, + { id: 5, title: 'Commission', value: 'commission' } ] } }), From cd4c3a255003c337c4503f8dd00afa0d429d8529 Mon Sep 17 00:00:00 2001 From: Peng Zhong Date: Thu, 30 Nov 2017 14:12:25 +0900 Subject: [PATCH 03/13] fix lint errors --- app/src/renderer/components/staking/CardCandidate.vue | 1 - app/src/renderer/components/staking/PanelSort.vue | 4 ---- 2 files changed, 5 deletions(-) diff --git a/app/src/renderer/components/staking/CardCandidate.vue b/app/src/renderer/components/staking/CardCandidate.vue index 5cac063fa9..9fc398e5d4 100644 --- a/app/src/renderer/components/staking/CardCandidate.vue +++ b/app/src/renderer/components/staking/CardCandidate.vue @@ -47,7 +47,6 @@ export default { let richestCandidate = maxBy(this.candidates, 'voting_power') return richestCandidate.voting_power } else { return 0 } - return 0 }, vpStyles () { let percentage = diff --git a/app/src/renderer/components/staking/PanelSort.vue b/app/src/renderer/components/staking/PanelSort.vue index e5fb872524..2222f4d087 100644 --- a/app/src/renderer/components/staking/PanelSort.vue +++ b/app/src/renderer/components/staking/PanelSort.vue @@ -14,10 +14,8 @@ export default { methods: { orderBy (property, event) { let sortBys = $(this.$el).find('.sort-by') - // console.log(sortBys) $(sortBys).removeClass('active desc asc') let el = $(event.target).parent() - // console.log('el', el) if (this.sort.property === property) { if (this.sort.order === 'asc') { @@ -34,8 +32,6 @@ export default { $(el).addClass('desc') } $(el).addClass('active') - - console.log('sort details', this.sort) } }, props: ['sort'] From cdaa8edce80231f08ca62e723d532bbcfb564446 Mon Sep 17 00:00:00 2001 From: Peng Zhong Date: Thu, 30 Nov 2017 15:45:42 +0900 Subject: [PATCH 04/13] update page title to 'Delegate (X Candidates Selected)' --- app/src/renderer/components/staking/PageCandidates.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/renderer/components/staking/PageCandidates.vue b/app/src/renderer/components/staking/PageCandidates.vue index 8377e92694..7d0d12e649 100644 --- a/app/src/renderer/components/staking/PageCandidates.vue +++ b/app/src/renderer/components/staking/PageCandidates.vue @@ -44,7 +44,7 @@ export default { computed: { ...mapGetters(['candidates', 'filters', 'shoppingCart', 'user']), pageTitle () { - if (this.user.signedIn) return `Delegate (${this.candidatesNum} Selected)` + if (this.user.signedIn) return `Delegate (${this.candidatesNum} Candidates Selected)` else return 'Delegate' }, filteredCandidates () { From ef16cca3b6bda5883e16189d1a5b933d111276af Mon Sep 17 00:00:00 2001 From: Peng Zhong Date: Thu, 30 Nov 2017 15:49:52 +0900 Subject: [PATCH 05/13] simplify PageCandidates title --- app/src/renderer/components/staking/PageCandidates.vue | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/renderer/components/staking/PageCandidates.vue b/app/src/renderer/components/staking/PageCandidates.vue index 7d0d12e649..ee17e760cd 100644 --- a/app/src/renderer/components/staking/PageCandidates.vue +++ b/app/src/renderer/components/staking/PageCandidates.vue @@ -44,8 +44,7 @@ export default { computed: { ...mapGetters(['candidates', 'filters', 'shoppingCart', 'user']), pageTitle () { - if (this.user.signedIn) return `Delegate (${this.candidatesNum} Candidates Selected)` - else return 'Delegate' + return `Delegate (${this.candidatesNum} Candidates Selected)` }, filteredCandidates () { let query = this.filters.candidates.search.query From 4c7aba8c684582b5cea477ed466b3a5b2ec0577a Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 30 Nov 2017 12:32:43 +0100 Subject: [PATCH 06/13] added CardCandidate test --- .../components/staking/CardCandidate.vue | 4 +- app/src/renderer/vuex/modules/shoppingCart.js | 3 +- test/unit/specs/CardCandidate.spec.js | 98 +++++++++++++++++++ .../__snapshots__/CardCandidate.spec.js.snap | 84 ++++++++++++++++ 4 files changed, 185 insertions(+), 4 deletions(-) create mode 100644 test/unit/specs/CardCandidate.spec.js create mode 100644 test/unit/specs/__snapshots__/CardCandidate.spec.js.snap diff --git a/app/src/renderer/components/staking/CardCandidate.vue b/app/src/renderer/components/staking/CardCandidate.vue index 9fc398e5d4..f747e33ec4 100644 --- a/app/src/renderer/components/staking/CardCandidate.vue +++ b/app/src/renderer/components/staking/CardCandidate.vue @@ -36,7 +36,7 @@ export default { Btn }, computed: { - ...mapGetters(['shoppingCart', 'candidates', 'user']), + ...mapGetters(['shoppingCart', 'candidates']), styles () { let value = 'card-candidate' if (this.inCart) value += ' card-candidate-active ' @@ -65,7 +65,7 @@ export default { return { width: percentage + '%' } }, inCart () { - return this.shoppingCart.find(c => c.id === this.candidate.id) + return this.shoppingCart.candidates.find(c => c.id === this.candidate.id) } }, data: () => ({ diff --git a/app/src/renderer/vuex/modules/shoppingCart.js b/app/src/renderer/vuex/modules/shoppingCart.js index 5004784a39..3bda68b052 100644 --- a/app/src/renderer/vuex/modules/shoppingCart.js +++ b/app/src/renderer/vuex/modules/shoppingCart.js @@ -9,13 +9,12 @@ export default ({ commit, basecoin }) => { candidate: Object.assign({}, candidate), atoms: 0 }) - console.log(`+ ADD ${candidate.keybaseID} to cart`) }, removeFromCart (state, candidate) { + state.candidates = state.candidates.filter(({id}) => id !== candidate) let index = findIndex(state.candidates, c => { return c.candidate.id === candidate }) - // console.log(`- RM ${JSON.stringify(state.candidates[index])} from cart[${index}]`) let candidates = state.candidates.slice() candidates.splice(index, 1) state.candidates = candidates diff --git a/test/unit/specs/CardCandidate.spec.js b/test/unit/specs/CardCandidate.spec.js new file mode 100644 index 0000000000..a0907c465a --- /dev/null +++ b/test/unit/specs/CardCandidate.spec.js @@ -0,0 +1,98 @@ +import Vuex from 'vuex' +import { mount, createLocalVue } from 'vue-test-utils' +import CardCandidate from 'renderer/components/staking/CardCandidate' + +const shoppingCart = require('renderer/vuex/modules/shoppingCart').default({}) +const candidates = require('renderer/vuex/modules/candidates').default({}) + +const localVue = createLocalVue() +localVue.use(Vuex) + +describe('CardCandidate', () => { + let wrapper, store + + beforeEach(() => { + store = new Vuex.Store({ + getters: { + shoppingCart: () => shoppingCart.state, + candidates: () => candidates.state + }, + modules: { + shoppingCart, + candidates + } + }) + + store.commit('addCandidate', { + pubkey: 'pubkeyX', + description: JSON.stringify({ + id: 'idX', + description: 'descriptionX', + voting_power: 10000, + shares: 5000, + keybaseID: 'keybaseX', + country: 'USA' + }) + }) + store.commit('addCandidate', { + pubkey: 'pubkeyY', + description: JSON.stringify({ + id: 'idY', + description: 'descriptionY', + voting_power: 30000, + shares: 10000, + keybaseID: 'keybaseY', + country: 'Canada' + }) + }) + + let candidate = store.state.candidates[0] + + wrapper = mount(CardCandidate, { + localVue, + store, + propsData: { + candidate + } + }) + + jest.spyOn(store, 'commit') + }) + + it('has the expected html structure', () => { + expect(wrapper.vm.$el).toMatchSnapshot() + }) + + it('should show the country', () => { + expect(wrapper.html()).toContain('USA') + }) + + it('should show the voting power', () => { + expect(wrapper.html()).toContain('10,000') + }) + + it('should show the relative voting power as a bar', () => { + expect(wrapper.vm.$el.querySelector('.voting_power .bar').style.width).toBe(Math.floor(10000 / 30000 * 100) + '%') + }) + + it('should show the relative shares hold as a bar', () => { + expect(wrapper.vm.$el.querySelector('.voting_power .bar').style.width).toBe(Math.floor(5000 / 15000 * 100) + '%') + }) + + it('should add to cart', () => { + expect(wrapper.html()).not.toContain('card-candidate-active') + wrapper.find('menu .ni-btn').trigger('click') + expect(store.commit).toHaveBeenCalledWith('addToCart', store.state.candidates[0]) + expect(wrapper.html()).toContain('card-candidate-active') + }) + + it('should remove from cart', () => { + wrapper.find('menu .ni-btn').trigger('click') + wrapper.find('menu .ni-btn').trigger('click') + expect(store.commit).toHaveBeenCalledWith('removeFromCart', store.state.candidates[0].id) + + // TODO still has the candidate in the shopping cart + // console.log(store.state.candidates[0].id, store.state.shoppingCart.candidates.map(x => x.id)) + // expect(wrapper.html()).not.toContain('card-candidate-active') + }) +}) diff --git a/test/unit/specs/__snapshots__/CardCandidate.spec.js.snap b/test/unit/specs/__snapshots__/CardCandidate.spec.js.snap new file mode 100644 index 0000000000..e47ac1093f --- /dev/null +++ b/test/unit/specs/__snapshots__/CardCandidate.spec.js.snap @@ -0,0 +1,84 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CardCandidate has the expected html structure 1`] = ` +
+
+
+
+ + + + keybaseX + + +
+
+ USA +
+
+ + 10,000 + +
+
+
+ + 5,000 + +
+
+
+ NaN% +
+
+ + + +
+
+`; From 3f547d3ea2bd9c027f44f6f87b0e9058464fe825 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 30 Nov 2017 12:34:33 +0100 Subject: [PATCH 07/13] forgot to remove line --- app/src/renderer/vuex/modules/shoppingCart.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/renderer/vuex/modules/shoppingCart.js b/app/src/renderer/vuex/modules/shoppingCart.js index 3bda68b052..e564209587 100644 --- a/app/src/renderer/vuex/modules/shoppingCart.js +++ b/app/src/renderer/vuex/modules/shoppingCart.js @@ -11,7 +11,6 @@ export default ({ commit, basecoin }) => { }) }, removeFromCart (state, candidate) { - state.candidates = state.candidates.filter(({id}) => id !== candidate) let index = findIndex(state.candidates, c => { return c.candidate.id === candidate }) From 1130a6d236187002ff5fff7eb100884e03f45ba7 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 30 Nov 2017 12:37:22 +0100 Subject: [PATCH 08/13] linted --- test/unit/specs/CardCandidate.spec.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/unit/specs/CardCandidate.spec.js b/test/unit/specs/CardCandidate.spec.js index a0907c465a..6cd4e72e8b 100644 --- a/test/unit/specs/CardCandidate.spec.js +++ b/test/unit/specs/CardCandidate.spec.js @@ -62,30 +62,30 @@ describe('CardCandidate', () => { it('has the expected html structure', () => { expect(wrapper.vm.$el).toMatchSnapshot() }) - + it('should show the country', () => { expect(wrapper.html()).toContain('USA') }) - + it('should show the voting power', () => { expect(wrapper.html()).toContain('10,000') }) - + it('should show the relative voting power as a bar', () => { expect(wrapper.vm.$el.querySelector('.voting_power .bar').style.width).toBe(Math.floor(10000 / 30000 * 100) + '%') }) - + it('should show the relative shares hold as a bar', () => { expect(wrapper.vm.$el.querySelector('.voting_power .bar').style.width).toBe(Math.floor(5000 / 15000 * 100) + '%') }) - + it('should add to cart', () => { expect(wrapper.html()).not.toContain('card-candidate-active') wrapper.find('menu .ni-btn').trigger('click') expect(store.commit).toHaveBeenCalledWith('addToCart', store.state.candidates[0]) expect(wrapper.html()).toContain('card-candidate-active') }) - + it('should remove from cart', () => { wrapper.find('menu .ni-btn').trigger('click') wrapper.find('menu .ni-btn').trigger('click') From 3967a7187eb914b669aebb34e3346346ff1158e4 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 30 Nov 2017 14:07:43 +0100 Subject: [PATCH 09/13] added pageCandidates test --- .../components/staking/PageCandidates.vue | 6 +- test/unit/specs/PageCandidates.spec.js | 84 +++++ .../__snapshots__/PageCandidates.spec.js.snap | 315 ++++++++++++++++++ 3 files changed, 402 insertions(+), 3 deletions(-) create mode 100644 test/unit/specs/PageCandidates.spec.js create mode 100644 test/unit/specs/__snapshots__/PageCandidates.spec.js.snap diff --git a/app/src/renderer/components/staking/PageCandidates.vue b/app/src/renderer/components/staking/PageCandidates.vue index ee17e760cd..61c91af5f9 100644 --- a/app/src/renderer/components/staking/PageCandidates.vue +++ b/app/src/renderer/components/staking/PageCandidates.vue @@ -4,7 +4,7 @@ page(:title='pageTitle') a(@click='setSearch(true)') i.material-icons search .label Search - router-link(v-if="" to='/staking/delegate') + router-link(to='/staking/delegate') i.material-icons check_circle .label Delegate modal-search(v-if="filters.candidates.search.visible" type="candidates") @@ -42,7 +42,7 @@ export default { ToolBar }, computed: { - ...mapGetters(['candidates', 'filters', 'shoppingCart', 'user']), + ...mapGetters(['candidates', 'filters', 'shoppingCart']), pageTitle () { return `Delegate (${this.candidatesNum} Candidates Selected)` }, @@ -50,7 +50,7 @@ export default { let query = this.filters.candidates.search.query let list = orderBy(this.candidates, [this.sort.property], [this.sort.order]) if (this.filters.candidates.search.visible) { - return list.filter(i => includes(i.keybaseID.toLowerCase(), query)) + return list.filter(i => includes(i.keybaseID.toLowerCase(), query.toLowerCase())) } else { return list } diff --git a/test/unit/specs/PageCandidates.spec.js b/test/unit/specs/PageCandidates.spec.js new file mode 100644 index 0000000000..d9a858eab2 --- /dev/null +++ b/test/unit/specs/PageCandidates.spec.js @@ -0,0 +1,84 @@ +import Vuex from 'vuex' +import { mount, createLocalVue } from 'vue-test-utils' +import PageCandidates from 'renderer/components/staking/PageCandidates' + +const shoppingCart = require('renderer/vuex/modules/shoppingCart').default({}) +const candidates = require('renderer/vuex/modules/candidates').default({}) +const filters = require('renderer/vuex/modules/filters').default({}) + +const localVue = createLocalVue() +localVue.use(Vuex) + +describe('PageCandidates', () => { + let wrapper, store + + beforeEach(() => { + store = new Vuex.Store({ + getters: { + shoppingCart: () => shoppingCart.state, + candidates: () => candidates.state, + filters: () => filters.state + }, + modules: { + shoppingCart, + candidates, + filters + } + }) + + store.commit('addCandidate', { + pubkey: 'pubkeyY', + description: JSON.stringify({ + id: 'idY', + description: 'descriptionY', + voting_power: 30000, + shares: 10000, + keybaseID: 'keybaseY', + country: 'Canada' + }) + }) + store.commit('addCandidate', { + pubkey: 'pubkeyX', + description: JSON.stringify({ + id: 'idX', + description: 'descriptionX', + voting_power: 2000, + shares: 5000, + keybaseID: 'keybaseX', + country: 'USA' + }) + }) + + wrapper = mount(PageCandidates, { + localVue, + store + }) + + jest.spyOn(store, 'commit') + }) + + it('has the expected html structure', () => { + expect(wrapper.vm.$el).toMatchSnapshot() + }) + + it('should show the search on click', () => { + wrapper.find('.ni-tool-bar i').trigger('click') + expect(wrapper.contains('.ni-modal-search')).toBe(true) + }) + + it('should sort the candidates by selected property', () => { + expect(wrapper.vm.filteredCandidates.map(x => x.id)).toEqual(['idX', 'idY']) + wrapper.vm.sort = 'voting_power' + wrapper.update() + expect(wrapper.vm.filteredCandidates.map(x => x.id)).toEqual(['idY', 'idX']) + }) + + it('should filter the candidates', () => { + store.commit('setSearchVisible', ['candidates', true]) + store.commit('setSearchQuery', ['candidates', 'baseX']) + expect(wrapper.vm.filteredCandidates.map(x => x.id)).toEqual(['idX']) + expect(wrapper.html()).toMatchSnapshot() + store.commit('setSearchQuery', ['candidates', 'baseY']) + expect(wrapper.vm.filteredCandidates.map(x => x.id)).toEqual(['idY']) + }) +}) diff --git a/test/unit/specs/__snapshots__/PageCandidates.spec.js.snap b/test/unit/specs/__snapshots__/PageCandidates.spec.js.snap new file mode 100644 index 0000000000..bc98232668 --- /dev/null +++ b/test/unit/specs/__snapshots__/PageCandidates.spec.js.snap @@ -0,0 +1,315 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PageCandidates has the expected html structure 1`] = ` +
+
+
+
+
+ +
+ Delegate (undefined Candidates Selected) +
+
+
+
+ +
+
+
+ +
+
+
+
+
+ + + search + +
+ Search +
+
+ + + check_circle + +
+ Delegate +
+
+
+ + + help_outline + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ Keybase ID +
+
+
+
+ Country +
+
+
+
+ Voting Power +
+
+
+
+ Delegated Power +
+
+
+
+ Commission +
+
+
+
+
+
+
+
+ + + + keybaseX + + +
+
+ USA +
+
+ + 2,000 + +
+
+
+ + 5,000 + +
+
+
+ NaN% +
+
+ + + +
+
+
+
+
+
+ + + + keybaseY + + +
+
+ Canada +
+
+ + 30,000 + +
+
+
+ + 10,000 + +
+
+
+ NaN% +
+
+ + + +
+
+
+
+
+
+
+`; + +exports[`PageCandidates should filter the candidates 1`] = `"
Delegate (undefined Candidates Selected)
search
Search
check_circle
Delegate
help_outline
Keybase ID
Country
Voting Power
Delegated Power
Commission
keybaseX
USA
2,000
5,000
NaN%
keybaseY
Canada
30,000
10,000
NaN%
"`; From 7f873e98e949851c96a040bf7f8175e64cf4b286 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 30 Nov 2017 14:21:25 +0100 Subject: [PATCH 10/13] added pageCandidates test --- .../components/staking/PageCandidates.vue | 2 +- test/unit/specs/PageCandidates.spec.js | 43 +++++++++++++++++-- .../__snapshots__/PageCandidates.spec.js.snap | 4 +- 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/app/src/renderer/components/staking/PageCandidates.vue b/app/src/renderer/components/staking/PageCandidates.vue index 61c91af5f9..1dc8f530b5 100644 --- a/app/src/renderer/components/staking/PageCandidates.vue +++ b/app/src/renderer/components/staking/PageCandidates.vue @@ -55,7 +55,7 @@ export default { return list } }, - candidatesNum () { return this.shoppingCart.length } + candidatesNum () { return this.shoppingCart.candidates.length } }, data: () => ({ query: '', diff --git a/test/unit/specs/PageCandidates.spec.js b/test/unit/specs/PageCandidates.spec.js index d9a858eab2..12eee0085c 100644 --- a/test/unit/specs/PageCandidates.spec.js +++ b/test/unit/specs/PageCandidates.spec.js @@ -51,7 +51,10 @@ describe('PageCandidates', () => { wrapper = mount(PageCandidates, { localVue, - store + store, + stubs: { + 'data-error': '' + } }) jest.spyOn(store, 'commit') @@ -60,16 +63,15 @@ describe('PageCandidates', () => { it('has the expected html structure', () => { expect(wrapper.vm.$el).toMatchSnapshot() }) - + it('should show the search on click', () => { wrapper.find('.ni-tool-bar i').trigger('click') expect(wrapper.contains('.ni-modal-search')).toBe(true) }) - + it('should sort the candidates by selected property', () => { expect(wrapper.vm.filteredCandidates.map(x => x.id)).toEqual(['idX', 'idY']) wrapper.vm.sort = 'voting_power' - wrapper.update() expect(wrapper.vm.filteredCandidates.map(x => x.id)).toEqual(['idY', 'idX']) }) @@ -81,4 +83,37 @@ describe('PageCandidates', () => { store.commit('setSearchQuery', ['candidates', 'baseY']) expect(wrapper.vm.filteredCandidates.map(x => x.id)).toEqual(['idY']) }) + + it('should show the amount of selected candidates', () => { + store.commit('addToCart', store.state.candidates[0]) + store.commit('addToCart', store.state.candidates[1]) + wrapper.update() + expect(wrapper.html()).toContain('2 Candidates Selected') + }) + + it('should show an error if there are no candidates', () => { + let store = new Vuex.Store({ + getters: { + shoppingCart: () => shoppingCart.state, + candidates: () => [], + filters: () => filters.state + }, + modules: { + shoppingCart, + candidates, + filters + } + }) + + let wrapper = mount(PageCandidates, { + localVue, + store, + stubs: { + 'data-error': '' + } + }) + + console.log(wrapper.html()) + expect(wrapper.contains('data-error')).toBe(true) + }) }) diff --git a/test/unit/specs/__snapshots__/PageCandidates.spec.js.snap b/test/unit/specs/__snapshots__/PageCandidates.spec.js.snap index bc98232668..c4685e269b 100644 --- a/test/unit/specs/__snapshots__/PageCandidates.spec.js.snap +++ b/test/unit/specs/__snapshots__/PageCandidates.spec.js.snap @@ -18,7 +18,7 @@ exports[`PageCandidates has the expected html structure 1`] = ` >
- Delegate (undefined Candidates Selected) + Delegate (0 Candidates Selected)
`; -exports[`PageCandidates should filter the candidates 1`] = `"
Delegate (undefined Candidates Selected)
search
Search
check_circle
Delegate
help_outline
Keybase ID
Country
Voting Power
Delegated Power
Commission
keybaseX
USA
2,000
5,000
NaN%
keybaseY
Canada
30,000
10,000
NaN%
"`; +exports[`PageCandidates should filter the candidates 1`] = `"
Delegate (0 Candidates Selected)
search
Search
check_circle
Delegate
help_outline
Keybase ID
Country
Voting Power
Delegated Power
Commission
keybaseX
USA
2,000
5,000
NaN%
keybaseY
Canada
30,000
10,000
NaN%
"`; From eeae816f083d124f873381c50dea9d872cdbc67f Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 30 Nov 2017 14:25:54 +0100 Subject: [PATCH 11/13] removed a comment --- test/unit/specs/PageCandidates.spec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unit/specs/PageCandidates.spec.js b/test/unit/specs/PageCandidates.spec.js index 12eee0085c..8dc54cda7e 100644 --- a/test/unit/specs/PageCandidates.spec.js +++ b/test/unit/specs/PageCandidates.spec.js @@ -113,7 +113,6 @@ describe('PageCandidates', () => { } }) - console.log(wrapper.html()) expect(wrapper.contains('data-error')).toBe(true) }) }) From e37434bf46eaf74cbeaa579251766841e41b4469 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 1 Dec 2017 00:09:25 +0100 Subject: [PATCH 12/13] fixed tests --- app/src/renderer/vuex/modules/shoppingCart.js | 8 ++----- test/unit/specs/CardCandidate.spec.js | 22 ++++++++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/app/src/renderer/vuex/modules/shoppingCart.js b/app/src/renderer/vuex/modules/shoppingCart.js index e564209587..4f342bac75 100644 --- a/app/src/renderer/vuex/modules/shoppingCart.js +++ b/app/src/renderer/vuex/modules/shoppingCart.js @@ -1,4 +1,5 @@ import { findIndex } from 'lodash' +import { start } from 'repl'; export default ({ commit, basecoin }) => { let state = { candidates: [] } @@ -11,12 +12,7 @@ export default ({ commit, basecoin }) => { }) }, removeFromCart (state, candidate) { - let index = findIndex(state.candidates, c => { - return c.candidate.id === candidate - }) - let candidates = state.candidates.slice() - candidates.splice(index, 1) - state.candidates = candidates + state.candidates = state.candidates.filter(c => c.id !== candidate) } } diff --git a/test/unit/specs/CardCandidate.spec.js b/test/unit/specs/CardCandidate.spec.js index 6cd4e72e8b..58c4e933cf 100644 --- a/test/unit/specs/CardCandidate.spec.js +++ b/test/unit/specs/CardCandidate.spec.js @@ -9,7 +9,7 @@ const localVue = createLocalVue() localVue.use(Vuex) describe('CardCandidate', () => { - let wrapper, store + let wrapper, store, candidate beforeEach(() => { store = new Vuex.Store({ @@ -46,7 +46,7 @@ describe('CardCandidate', () => { }) }) - let candidate = store.state.candidates[0] + candidate = store.state.candidates[0] wrapper = mount(CardCandidate, { localVue, @@ -80,19 +80,25 @@ describe('CardCandidate', () => { }) it('should add to cart', () => { + expect(wrapper.vm.shoppingCart.candidates).toEqual([]) + expect(wrapper.vm.inCart).toBeFalsy() + expect(wrapper.find('menu .ni-btn').text()).toContain('Add') expect(wrapper.html()).not.toContain('card-candidate-active') wrapper.find('menu .ni-btn').trigger('click') + expect(wrapper.vm.inCart).toBeTruthy() expect(store.commit).toHaveBeenCalledWith('addToCart', store.state.candidates[0]) expect(wrapper.html()).toContain('card-candidate-active') }) it('should remove from cart', () => { + store.commit('addToCart', store.state.candidates[0]) + wrapper.update() + expect(wrapper.vm.inCart).toBeTruthy() + expect(wrapper.find('menu .ni-btn').text()).toContain('Remove') wrapper.find('menu .ni-btn').trigger('click') - wrapper.find('menu .ni-btn').trigger('click') - expect(store.commit).toHaveBeenCalledWith('removeFromCart', store.state.candidates[0].id) - - // TODO still has the candidate in the shopping cart - // console.log(store.state.candidates[0].id, store.state.shoppingCart.candidates.map(x => x.id)) - // expect(wrapper.html()).not.toContain('card-candidate-active') + expect(store.commit).toHaveBeenCalledWith('removeFromCart', candidate.id) + expect(wrapper.vm.shoppingCart.candidates).toEqual([]) + expect(wrapper.vm.inCart).toBeFalsy() + expect(wrapper.html()).not.toContain('card-candidate-active') }) }) From 72f43423fd39596738fad63e08da385c56ee46f9 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 1 Dec 2017 00:23:24 +0100 Subject: [PATCH 13/13] fixed linting --- app/src/renderer/vuex/modules/shoppingCart.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/renderer/vuex/modules/shoppingCart.js b/app/src/renderer/vuex/modules/shoppingCart.js index 4f342bac75..bb4d3378d6 100644 --- a/app/src/renderer/vuex/modules/shoppingCart.js +++ b/app/src/renderer/vuex/modules/shoppingCart.js @@ -1,5 +1,3 @@ -import { findIndex } from 'lodash' -import { start } from 'repl'; export default ({ commit, basecoin }) => { let state = { candidates: [] }