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)
+ })
+})