mumuki/mumuki-laboratory

View on GitHub
app/assets/javascripts/mumuki_laboratory/application/bridge.js

Summary

Maintainability
A
0 mins
Test Coverage
/**
 * @typedef {"errored"|"failed"|"passed_with_warnings"|"passed"|"pending"|"aborted"} SubmissionStatus
 */

/**
 * @typedef {{
 *  status: SubmissionStatus,
 *  test_results: [{status: SubmissionStatus, title: string}]
 * }} SubmissionClientResult
 */

/**
 * @typedef {{
  *  status: SubmissionStatus,
  *  class_for_progress_list_item?: string,
  *  guide_finished_by_solution?: boolean,
  *  title_html?: string,
  *  in_gamified_context?: boolean
  * }} SubmissionResult
  */

/**
 * @typedef {object} Solution
 */

/**
 * Contents of a submission expressed in the form of params
 * generated and accepted by laboratory HTTP Controllers
 *
 * @typedef {{"solution[content]":string}} ClassicContents
 */

/**
 * Contents of a submission expressed as an object
 * that are created programatically
 *
 * @typedef {{solution: Solution}} ProgramaticContents
 */

/**
 * Contents of a multifile submission expressed as dictionary of keys in the form
 * `solution[content[the-filename-goes-here]]`
 *
 * @typedef {object} MutifileContents
 */

/**
 * @typedef {ClassicContents|ProgramaticContents|MutifileContents} Contents
 */

/**
 * A submission, composed by:
 *
 *  * its actual contents
 *  * the client results
 *  * the _pristine flag, that tells whether the submission has been sent without previous results
 *
 * @typedef {Contents & {client_result?: SubmissionClientResult, _pristine: boolean}} Submission
 */

/**
 * @typedef {{submission?: Submission, result?: SubmissionResult}} SubmissionAndResult
 */

mumuki.bridge = (() => {

  class Laboratory {
    // ==========
    // Public API
    // ==========

    /**
     * Runs tests for the current exercise using the given submission
     * content.
     *
     * @param {object} content the content object
     * */
    runTests(content) {
      return this._submitSolution({ solution: content });
    }

    // ===========
    // Private API
    // ===========

    /**
     * Sends a solution object
     *
     * @param {Submission} submission the submission object
     * @returns {JQuery.Promise<SubmissionResult>}
     */
    _submitSolution(submission) {
      const lastSubmission = mumuki.SubmissionsStore.getSubmissionResultFor(mumuki.exercise.id, submission);
      if (submission._pristine || !lastSubmission) {
        return this._sendNewSolution(submission).done((result) => {
          mumuki.SubmissionsStore.setSubmissionResultFor(mumuki.exercise.id, {submission, result});
        });
      } else {
        return $.Deferred().resolve(lastSubmission);
      }
    }

    /**
     * @param {Submission} submission the submission object
     * @returns {JQuery.Promise<SubmissionResult>}
     */
    _sendNewSolution(submission){
      var token = new mumuki.CsrfToken();
      var request = token.newRequest({
        type: 'POST',
        url: window.location.origin + window.location.pathname + '/solutions' + window.location.search,
        data: submission
      });
      return $.ajax(request).then((result) => this._preRenderResult(result));
    }

    /**
     * @param {SubmissionResult} result
     * @returns {SubmissionResult}
     * @see mumuki.renderers.results.preRenderResult
     */
    _preRenderResult(result) {
      mumuki.renderers.results.preRenderResult(result);
      return result;
    }
  }

  return {
    Laboratory
  };
})();