diff --git a/app/assets/javascripts/boards/services/board_service.js b/app/assets/javascripts/boards/services/board_service.js index 580d04a3649..5202620057c 100644 --- a/app/assets/javascripts/boards/services/board_service.js +++ b/app/assets/javascripts/boards/services/board_service.js @@ -62,6 +62,22 @@ export default class BoardService { static toggleIssueSubscription(endpoint) { return boardsStore.toggleIssueSubscription(endpoint); } + + allBoards() { + return boardsStore.allBoards(); + } + + recentBoards() { + return boardsStore.recentBoards(); + } + + createBoard(board) { + return boardsStore.createBoard(board); + } + + deleteBoard({ id }) { + return boardsStore.deleteBoard({ id }); + } } window.BoardService = BoardService; diff --git a/app/assets/javascripts/boards/stores/boards_store.js b/app/assets/javascripts/boards/stores/boards_store.js index b9cd4a143ef..74f0ab1f934 100644 --- a/app/assets/javascripts/boards/stores/boards_store.js +++ b/app/assets/javascripts/boards/stores/boards_store.js @@ -340,6 +340,40 @@ const boardsStore = { toggleIssueSubscription(endpoint) { return axios.post(endpoint); }, + + allBoards() { + return axios.get(this.generateBoardsPath()); + }, + + recentBoards() { + return axios.get(this.state.endpoints.recentBoardsEndpoint); + }, + + createBoard(board) { + const boardPayload = { ...board }; + boardPayload.label_ids = (board.labels || []).map(b => b.id); + + if (boardPayload.label_ids.length === 0) { + boardPayload.label_ids = ['']; + } + + if (boardPayload.assignee) { + boardPayload.assignee_id = boardPayload.assignee.id; + } + + if (boardPayload.milestone) { + boardPayload.milestone_id = boardPayload.milestone.id; + } + + if (boardPayload.id) { + return axios.put(this.generateBoardsPath(boardPayload.id), { board: boardPayload }); + } + return axios.post(this.generateBoardsPath(), { board: boardPayload }); + }, + + deleteBoard({ id }) { + return axios.delete(this.generateBoardsPath(id)); + }, }; BoardsStoreEE.initEESpecific(boardsStore); diff --git a/spec/frontend/boards/services/board_service_spec.js b/spec/frontend/boards/services/board_service_spec.js index a8a322e7237..e106c2bf1f1 100644 --- a/spec/frontend/boards/services/board_service_spec.js +++ b/spec/frontend/boards/services/board_service_spec.js @@ -389,4 +389,163 @@ describe('BoardService', () => { return expect(BoardService.toggleIssueSubscription(dummyEndpoint)).rejects.toThrow(); }); }); + + describe('allBoards', () => { + const url = `${endpoints.boardsEndpoint}.json`; + + it('makes a request to fetch all boards', () => { + axiosMock.onGet(url).replyOnce(200, dummyResponse); + const expectedResponse = expect.objectContaining({ data: dummyResponse }); + + return expect(service.allBoards()).resolves.toEqual(expectedResponse); + }); + + it('fails for error response', () => { + axiosMock.onGet(url).replyOnce(500); + + return expect(service.allBoards()).rejects.toThrow(); + }); + }); + + describe('recentBoards', () => { + const url = `${endpoints.recentBoardsEndpoint}.json`; + + it('makes a request to fetch all boards', () => { + axiosMock.onGet(url).replyOnce(200, dummyResponse); + const expectedResponse = expect.objectContaining({ data: dummyResponse }); + + return expect(service.recentBoards()).resolves.toEqual(expectedResponse); + }); + + it('fails for error response', () => { + axiosMock.onGet(url).replyOnce(500); + + return expect(service.recentBoards()).rejects.toThrow(); + }); + }); + + describe('createBoard', () => { + const labelIds = ['first label', 'second label']; + const assigneeId = 'as sign ee'; + const milestoneId = 'vegetable soup'; + const board = { + labels: labelIds.map(id => ({ id })), + assignee: { id: assigneeId }, + milestone: { id: milestoneId }, + }; + + describe('for existing board', () => { + const id = 'skate-board'; + const url = `${endpoints.boardsEndpoint}/${id}.json`; + const expectedRequest = expect.objectContaining({ + data: JSON.stringify({ + board: { + ...board, + id, + label_ids: labelIds, + assignee_id: assigneeId, + milestone_id: milestoneId, + }, + }), + }); + + let requestSpy; + + beforeEach(() => { + requestSpy = jest.fn(); + axiosMock.onPut(url).replyOnce(config => requestSpy(config)); + }); + + it('makes a request to update the board', () => { + requestSpy.mockReturnValue([200, dummyResponse]); + const expectedResponse = expect.objectContaining({ data: dummyResponse }); + + return expect( + service.createBoard({ + ...board, + id, + }), + ) + .resolves.toEqual(expectedResponse) + .then(() => { + expect(requestSpy).toHaveBeenCalledWith(expectedRequest); + }); + }); + + it('fails for error response', () => { + requestSpy.mockReturnValue([500]); + + return expect( + service.createBoard({ + ...board, + id, + }), + ) + .rejects.toThrow() + .then(() => { + expect(requestSpy).toHaveBeenCalledWith(expectedRequest); + }); + }); + }); + + describe('for new board', () => { + const url = `${endpoints.boardsEndpoint}.json`; + const expectedRequest = expect.objectContaining({ + data: JSON.stringify({ + board: { + ...board, + label_ids: labelIds, + assignee_id: assigneeId, + milestone_id: milestoneId, + }, + }), + }); + + let requestSpy; + + beforeEach(() => { + requestSpy = jest.fn(); + axiosMock.onPost(url).replyOnce(config => requestSpy(config)); + }); + + it('makes a request to create a new board', () => { + requestSpy.mockReturnValue([200, dummyResponse]); + const expectedResponse = expect.objectContaining({ data: dummyResponse }); + + return expect(service.createBoard(board)) + .resolves.toEqual(expectedResponse) + .then(() => { + expect(requestSpy).toHaveBeenCalledWith(expectedRequest); + }); + }); + + it('fails for error response', () => { + requestSpy.mockReturnValue([500]); + + return expect(service.createBoard(board)) + .rejects.toThrow() + .then(() => { + expect(requestSpy).toHaveBeenCalledWith(expectedRequest); + }); + }); + }); + }); + + describe('deleteBoard', () => { + const id = 'capsized'; + const url = `${endpoints.boardsEndpoint}/${id}.json`; + + it('makes a request to delete a boards', () => { + axiosMock.onDelete(url).replyOnce(200, dummyResponse); + const expectedResponse = expect.objectContaining({ data: dummyResponse }); + + return expect(service.deleteBoard({ id })).resolves.toEqual(expectedResponse); + }); + + it('fails for error response', () => { + axiosMock.onDelete(url).replyOnce(500); + + return expect(service.deleteBoard({ id })).rejects.toThrow(); + }); + }); });