diff --git a/frontend/src/components/pages/AddPlayers.component.js b/frontend/src/components/pages/AddPlayers.component.js index d18a8be..da72288 100644 --- a/frontend/src/components/pages/AddPlayers.component.js +++ b/frontend/src/components/pages/AddPlayers.component.js @@ -1,6 +1,4 @@ import { Component } from '../../../lib/vues6.js' -import { fake_players } from '../../module/fake_data.js' -import { clone } from '../../module/util.js' import { api } from '../../module/api.js' const template = ` @@ -96,7 +94,7 @@ class AddPlayersComponent extends Component { * All available players, whether they are on the user's team or not. * @type {object[]} */ - all_players = clone(fake_players) + all_players = [] /** * Called when the page is instantiated. diff --git a/frontend/src/components/pages/DraftBoard.component.js b/frontend/src/components/pages/DraftBoard.component.js index 5fd5985..8d26888 100644 --- a/frontend/src/components/pages/DraftBoard.component.js +++ b/frontend/src/components/pages/DraftBoard.component.js @@ -1,8 +1,6 @@ import {Component} from '../../../lib/vues6.js' -import {fake_players} from '../../module/fake_data.js' import {GridCellRenderType} from '../Grid.component.js' import {api} from '../../module/api.js' -import {clone} from '../../module/util.js' const template = `
@@ -106,7 +104,7 @@ class DraftBoardComponent extends Component { header: '', key: 'stats', type: GridCellRenderType.Component, - component: Vue.component('app-action-button'), + component: window.Vue ? Vue.component('app-action-button') : undefined, button_color: (row, col) => '#CC5746', button_text: (row, col) => 'Draft', button_hidden: (row, col) => this.top_picks.includes(row), diff --git a/frontend/src/components/pages/MyTeam.component.js b/frontend/src/components/pages/MyTeam.component.js index 88b13c0..e2975f2 100644 --- a/frontend/src/components/pages/MyTeam.component.js +++ b/frontend/src/components/pages/MyTeam.component.js @@ -120,7 +120,7 @@ class MyTeamComponent extends Component { header: '', key: 'name', type: GridCellRenderType.Component, - component: Vue.component('app-action-button'), + component: window.Vue ? Vue.component('app-action-button') : undefined, button_color: (row, col) => this.moving_player ? '#CC5746' : '#0582CA', button_text: (row, col) => { return this.moving_player ? 'Here' : 'Move' diff --git a/frontend/src/components/pages/Scores.component.js b/frontend/src/components/pages/Scores.component.js index 58037bd..e02c094 100644 --- a/frontend/src/components/pages/Scores.component.js +++ b/frontend/src/components/pages/Scores.component.js @@ -99,7 +99,7 @@ class ScoresComponent extends Component { type: GridCellRenderType.HTML, key: 'winner', renderer: (_, data) => { - if ( data?.winner ) { + if ( data && data.winner ) { return `
Winner: ${data.winner}
Score: ${data.winner_score} / ${data.loser_score}
diff --git a/frontend/src/module/api.js b/frontend/src/module/api.js index fd5b99c..b8f17df 100644 --- a/frontend/src/module/api.js +++ b/frontend/src/module/api.js @@ -1,6 +1,8 @@ class API { + _fetch = (...all) => fetch(...all) + constructor() { - this.base_url = APP_BASE_PATH.replace('/app/', '/api/v1/') + this.base_url = typeof window !== 'undefined' ? APP_BASE_PATH.replace('/app/', '/api/v1/') : '/api/v1/' } async get_status() { @@ -47,7 +49,7 @@ class API { if ( !Array.isArray(parts) ) parts = [parts] const url = this.build_url(...parts) - const result = await fetch(url, { + const result = await this._fetch(url, { method: 'POST', headers: { Accept: 'application/json', @@ -61,7 +63,7 @@ class API { async get_request(...parts) { const url = this.build_url(...parts) - const result = await fetch(url) + const result = await this._fetch(url) return (await result.json()).data } diff --git a/test/frontend/module_api.spec.js b/test/frontend/module_api.spec.js new file mode 100644 index 0000000..629aec5 --- /dev/null +++ b/test/frontend/module_api.spec.js @@ -0,0 +1,58 @@ +import { expect } from 'chai' +import sinon from 'sinon' +import {api} from '../../frontend/src/module/api' + +// Since we're testing code meant for the browser, not node, mock this +global.window = global + +api.base_url = 'http://fake.url/api/v1/' + +describe('the api helper class', function() { + it('should be a functional class', function() { + expect(api).to.exist + }) + + it('should build URLs using the APP BASE URL', function() { + expect(api.build_url('my-team', 'lineup')).to.be.equal('http://fake.url/api/v1/my-team/lineup') + expect(api.build_url('league')).to.be.equal('http://fake.url/api/v1/league') + }) + + it('should call the correct GET endpoints', async function() { + const old = api.get_request + + const test_endpoint = async (method, endp) => { + api.get_request = sinon.spy() + await api[method]() + + expect(api.get_request.calledOnce).to.be.true + expect(api.get_request.getCall(0).args[0]).to.be.equal(endp) + } + + await test_endpoint('get_status', 'status') + await test_endpoint('get_standings', 'league-standings') + await test_endpoint('get_matchups', 'matchups') + await test_endpoint('get_available_draft_players', 'draft-board/available') + await test_endpoint('get_my_team', 'my-team') + await test_endpoint('get_my_team_players', 'my-team/players') + await test_endpoint('get_my_team_current_lineup', 'my-team/lineup') + + api.get_request = old + }) + + it('should call the correct POST endpoints', async function() { + const old = api.post_request + + const test_endpoint = async (method, endp, args = [], data = {}) => { + api.post_request = sinon.spy() + await api[method](...args) + + expect(api.post_request.calledOnce).to.be.true + expect(api.post_request.getCall(0).args[0]).to.be.equal(endp) + expect(api.post_request.getCall(0).args[1]).to.be.eql(data) + } + + await test_endpoint('draft_player', 'draft-board/draft-player', [394588], { player_id: 394588 }) + await test_endpoint('save_my_team', 'my-team', [{ fubar: 394588 }], { fubar: 394588 }) + await test_endpoint('save_my_team_lineup', 'my-team/lineup', [{ fubar: 123583 }], { fubar: 123583 }) + }) +}) diff --git a/test/frontend/pages_AddPlayers.spec.js b/test/frontend/pages_AddPlayers.spec.js new file mode 100644 index 0000000..a5b9260 --- /dev/null +++ b/test/frontend/pages_AddPlayers.spec.js @@ -0,0 +1,99 @@ +import { expect } from 'chai' +import sinon from 'sinon' +import AddPlayersComponent from '../../frontend/src/components/pages/AddPlayers.component' + +// Since we're testing code meant for the browser, not node, mock this +global.window = global +global.APP_BASE_PATH = 'http://fake.url/app/' + +const get_inst = () => { + return [new AddPlayersComponent(), [ + { + name: 'Lorem', + position: 'Ipsum', + }, + { + name: 'Dolor', + position: 'Sit', + }, + { + name: 'Amet', + position: 'Fubar', + }, + ]] +} + +describe('the add players page component', function() { + it('should extend the component class', function() { + expect(get_inst()[0]).to.be.an.instanceOf(AddPlayersComponent) + }) + + it('should quick-filter the players', function() { + const [inst, players] = get_inst() + + inst.possible_players = players + inst.quick_filter = 'lorem' + + inst.on_filter_change() + + expect(inst.filtered_players).to.be.an('array') + expect(inst.filtered_players.length).to.be.equal(1) + expect(inst.filtered_players[0]).to.be.eql({ + name: 'Lorem', + position: 'Ipsum', + }) + }) + + it('should allow switching to my team only', function() { + const [inst, players] = get_inst() + const my_team = [players[1]] + + inst.all_players = players + inst.my_team = my_team + + inst.to_my_team_only() + + expect(inst.possible_players).to.be.eql(my_team) + expect(inst.my_team_only).to.be.true + }) + + it('should allow switching to view all players', function() { + const [inst, players] = get_inst() + const my_team = [players[1]] + + inst.all_players = players + inst.my_team = my_team + + inst.to_all_players() + + expect(inst.possible_players).to.be.eql(players) + expect(inst.my_team_only).to.be.false + }) + + it('should allow adding a player', function() { + const [inst, players] = get_inst() + + inst.my_team = [] + + inst.add_to_team(players[0]) + inst.add_to_team(players[0]) + inst.add_to_team(players[0]) + + expect(inst.my_team.length).to.be.equal(1) + expect(inst.my_team[0]).to.be.eql(players[0]) + }) + + it('should allow removing a player', function() { + const [inst, players] = get_inst() + + inst.my_team = [...players] + const removed = [players[0], players[2]] + + inst.remove_from_team(players[1]) + inst.remove_from_team(players[1]) + inst.remove_from_team(players[1]) + + expect(inst.my_team.length).to.be.equal(2) + expect(inst.my_team).to.be.eql(removed) + }) +}) diff --git a/test/frontend/pages_DraftBoard.spec.js b/test/frontend/pages_DraftBoard.spec.js new file mode 100644 index 0000000..e42f541 --- /dev/null +++ b/test/frontend/pages_DraftBoard.spec.js @@ -0,0 +1,46 @@ +import { expect } from 'chai' +import sinon from 'sinon' +import DraftBoardComponent from '../../frontend/src/components/pages/DraftBoard.component' + +// Since we're testing code meant for the browser, not node, mock this +global.window = global +global.APP_BASE_PATH = 'http://fake.url/app/' + +const get_inst = () => { + return [new DraftBoardComponent(), [ + { + name: 'Lorem', + position: 'Ipsum', + }, + { + name: 'Dolor', + position: 'Sit', + }, + { + name: 'Amet', + position: 'Fubar', + }, + ]] +} + +describe('the draft board page component', function() { + it('should extend the component class', function() { + expect(get_inst()[0]).to.be.an.instanceOf(DraftBoardComponent) + }) + + it('should show one column for the top picks grid', function() { + const [inst, players] = get_inst() + + expect(inst.top_picks_column_defs.length).to.be.equal(1) + expect(inst.top_picks_column_defs[0].key).to.be.equal('name') + }) + + it('should show 6 columns for the draft board grid', function() { + const [inst, players] = get_inst() + + expect(inst.column_defs.length).to.be.equal(6) + expect(inst.column_defs.map(x => x.key)).to.be.eql([ + 'name', 'team_name', 'position', 'points', 'stats', 'stats', + ]) + }) +}) diff --git a/test/frontend/pages_League.spec.js b/test/frontend/pages_League.spec.js new file mode 100644 index 0000000..16820cd --- /dev/null +++ b/test/frontend/pages_League.spec.js @@ -0,0 +1,26 @@ +import { expect } from 'chai' +import sinon from 'sinon' +import LeagueComponent from '../../frontend/src/components/pages/League.component' + +// Since we're testing code meant for the browser, not node, mock this +global.window = global +global.APP_BASE_PATH = 'http://fake.url/app/' + +const get_inst = () => { + return [new LeagueComponent()] +} + +describe('the league page component', function() { + it('should extend the component class', function() { + expect(get_inst()[0]).to.be.an.instanceOf(LeagueComponent) + }) + + it('should show 3 columns for the main grid', function() { + const [inst] = get_inst() + + expect(inst.column_defs.length).to.be.equal(3) + expect(inst.column_defs.map(x => x.key)).to.be.eql([ + 'standing', 'team_name', 'stats' + ]) + }) +}) diff --git a/test/frontend/pages_MyTeam.spec.js b/test/frontend/pages_MyTeam.spec.js new file mode 100644 index 0000000..fcca46c --- /dev/null +++ b/test/frontend/pages_MyTeam.spec.js @@ -0,0 +1,54 @@ +import { expect } from 'chai' +import sinon from 'sinon' +import MyTeamComponent from '../../frontend/src/components/pages/MyTeam.component' + +// Since we're testing code meant for the browser, not node, mock this +global.window = global +global.APP_BASE_PATH = 'http://fake.url/app/' + +const get_inst = () => { + return [new MyTeamComponent()] +} + +describe('the my team page component', function() { + it('should extend the component class', function() { + expect(get_inst()[0]).to.be.an.instanceOf(MyTeamComponent) + }) + + it('should show 3 columns for the lineup grids', function() { + const [inst] = get_inst() + + expect(inst.lineup_column_defs.length).to.be.equal(3) + expect(inst.lineup_column_defs.map(x => x.key)).to.be.eql([ + 'position', 'name', 'name' + ]) + }) + + it('should show 3 columns for the overall column definitions', function() { + const [inst] = get_inst() + + expect(inst.overall_column_defs.length).to.be.equal(3) + expect(inst.overall_column_defs.map(x => x.key)).to.be.eql([ + 'name', 'position', 'ecr', + ]) + }) + + it('should change the save text on mark_dirty', function() { + const [inst] = get_inst() + const original = inst.save_text + + inst.mark_dirty() + + expect(inst.save_text).to.not.equal(original) + }) + + it('should change the save text on team name change', function() { + const [inst] = get_inst() + const original = inst.save_text + + inst.team_name = 'something else!' + inst.watch_team_name() + + expect(inst.save_text).to.not.equal(original) + }) +}) diff --git a/test/frontend/pages_Scores.spec.js b/test/frontend/pages_Scores.spec.js new file mode 100644 index 0000000..1528cfa --- /dev/null +++ b/test/frontend/pages_Scores.spec.js @@ -0,0 +1,77 @@ +import { expect } from 'chai' +import sinon from 'sinon' +import ScoresComponent from '../../frontend/src/components/pages/Scores.component' + +// Since we're testing code meant for the browser, not node, mock this +global.window = global +global.APP_BASE_PATH = 'http://fake.url/app/' + +const get_inst = () => { + return [new ScoresComponent()] +} + +describe('the my team page component', function() { + it('should extend the component class', function() { + expect(get_inst()[0]).to.be.an.instanceOf(ScoresComponent) + }) + + it('should default to the first week', function() { + const [inst] = get_inst() + + expect(inst.current_week).to.be.equal(1) + expect(inst.max_week).to.be.equal(1) + expect(inst.min_week).to.be.equal(1) + }) + + it('should show 4 columns in the standings grid', function() { + const [inst] = get_inst() + + expect(inst.column_defs.length).to.be.equal(4) + expect(inst.column_defs.map(x => x.key)).to.be.eql([ + 'date', 'team_1', 'team_2', 'winner' + ]) + }) + + it('should allow advancing the week until we hit the max', function() { + const [inst] = get_inst() + inst.max_week = 4 + + expect(inst.current_week).to.be.equal(1) + + inst.to_next_week() + expect(inst.current_week).to.be.equal(2) + + inst.to_next_week() + expect(inst.current_week).to.be.equal(3) + + inst.to_next_week() + expect(inst.current_week).to.be.equal(4) + + inst.to_next_week() + expect(inst.current_week).to.be.equal(4) + + inst.to_next_week() + expect(inst.current_week).to.be.equal(4) + }) + + it('should allow un-advancing the week until we hit the min', function() { + const [inst] = get_inst() + inst.max_week = 4 + inst.current_week = 4 + + inst.to_previous_week() + expect(inst.current_week).to.be.equal(3) + + inst.to_previous_week() + expect(inst.current_week).to.be.equal(2) + + inst.to_previous_week() + expect(inst.current_week).to.be.equal(1) + + inst.to_previous_week() + expect(inst.current_week).to.be.equal(1) + + inst.to_previous_week() + expect(inst.current_week).to.be.equal(1) + }) +})