import {
  SUBMISSION_UPDATE_SUBJECT
} from '@instructure/quiz-common/lib/constants'

import {postQuizSessionResults} from '../updateResults'
import {postToParent} from '../../../common/actions/postMessage'
import {addQuizSessionResults} from '../../../common/actions/quizSessionResults'

import makeFakeFetch from '../../../../tests/util/fakeFetch'
import Fetcher from '../../../common/util/Fetcher'

import {jsoniblePromise} from '../../../common/util/jsonify'

describe('postQuizSessionResults action', () => {
  const fetchStub = sinon.stub()
  const dispatchStub = sinon.stub()
  const fetchQuizSessionCb = sinon.stub()
  const getStateStub = sinon.stub()
  useFakeFetching({dispatchStub, getStateStub, fetchStub})

  // for the async tests
  const quizSessionResultsResponse = {id: '99'}
  const response = jsoniblePromise(quizSessionResultsResponse)
  const fakeFetch = makeFakeFetch(response)

  const sessionId = '1'
  const sessionItemResultsMods = [{}]
  const fudgePoints = 5

  const postQuizSessionResultsThunk = postQuizSessionResults(
    sessionId, sessionItemResultsMods, fudgePoints, fetchQuizSessionCb)
  const stubbedPostQuizSessionResultsCall = () => {
    Fetcher.fakeFetch = fetchStub
    return postQuizSessionResultsThunk(dispatchStub, getStateStub)
  }

  const fakedAsyncPostQuizSessionResultsCall = () => {
    Fetcher.fakeFetch = fakeFetch
    return postQuizSessionResultsThunk(dispatchStub, getStateStub)
  }

  it('makes a call to the quizSessionResults endpoint', () => {
    stubbedPostQuizSessionResultsCall()
    expect(fetchStub.calledWith(`/api/quiz_sessions/${sessionId}/results`)).to.be.true()
  })

  it('posts a submissionUpdate update message to the parent window', (done) => {
    Fetcher.fakeFetch = fakeFetch
    const fetchPromise = fakedAsyncPostQuizSessionResultsCall()
    const expectedPostMessageAction = postToParent({subject: SUBMISSION_UPDATE_SUBJECT})

    fetchPromise.then(() => {
      checkActionDispatched(dispatchStub, expectedPostMessageAction)
      done()
    })
  })

  it('updates the quizSessionResults on success', (done) => {
    Fetcher.fakeFetch = fakeFetch
    const fetchPromise = fakedAsyncPostQuizSessionResultsCall()
    const expectedQuizSessionResultsAction = addQuizSessionResults([quizSessionResultsResponse])

    fetchPromise.then(() => {
      checkActionDispatched(dispatchStub, expectedQuizSessionResultsAction)
      done()
    })
  })

  it('fetches a new quiz session on success', (done) => {
    Fetcher.fakeFetch = fakeFetch
    const fetchPromise = fakedAsyncPostQuizSessionResultsCall()

    fetchPromise.then(() => {
      expect(fetchQuizSessionCb.called).to.be.true()
      done()
    })
  })
})
