Skip to content

Commit

Permalink
Update sequence when trial finishes
Browse files Browse the repository at this point in the history
  • Loading branch information
okaycj committed Sep 3, 2024
1 parent 8d60af6 commit d2135fb
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 8 deletions.
File renamed without changes.
2 changes: 1 addition & 1 deletion packages/data/src/lookitS3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
S3Client,
UploadPartCommand,
} from "@aws-sdk/client-s3";
import { AWSMissingAttrError, UploadPartError } from "./error";
import { AWSMissingAttrError, UploadPartError } from "./errors";

/** Provides functionality to upload videos incrementally to an AWS S3 Bucket. */
class LookitS3 {
Expand Down
12 changes: 12 additions & 0 deletions packages/lookit-initjspsych/src/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/** Error when the upload part retries run out. */
export class SequenceExpDataError extends Error {
/**
* Error when the upload part retries run out.
*
* @param error - Error object generated by upload part function.

Check failure on line 6 in packages/lookit-initjspsych/src/errors.ts

View workflow job for this annotation

GitHub Actions / Build, lint, and test on Node.js 20

@param "error" does not match an existing function parameter
*/
public constructor() {
super("Experiment sequence or data missing.");
this.name = "SequenceExpDataError";
}
}
104 changes: 98 additions & 6 deletions packages/lookit-initjspsych/src/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { DataCollection } from "jspsych";

import { Child, JsPsychExpData, Study } from "@lookit/data/dist/types";
import { Timeline } from "./types";
import { on_data_update, on_finish } from "./utils";

delete global.window.location;
Expand Down Expand Up @@ -47,7 +48,7 @@ test("jsPsych's on_data_update with no exp_data", async () => {
json: () => Promise.resolve(jsonData),
ok: true,
} as Response;
const data = {} as DataCollection;
const data = {} as JsPsychExpData;

const userFn = jest.fn();
global.fetch = jest.fn(() => Promise.resolve(response));
Expand All @@ -60,12 +61,19 @@ test("jsPsych's on_data_update with no exp_data", async () => {
});

test("jsPsych's on_finish", async () => {
const exp_data = [{ key: "value" }];
const jsonData = {
data: { attributes: { exp_data: {} } },
data: {
attributes: { exp_data, sequence: ["0-value"] },
},
};
const data = {
/** Mocked jsPsych Data Collection. */
values: () => {},
/**
* Mocked jsPsych Data Collection.
*
* @returns Exp data.
*/
values: () => exp_data,
} as DataCollection;
const response = {
/**
Expand All @@ -91,6 +99,90 @@ test("jsPsych's on_finish", async () => {

expect(await on_finish("some id", userFn)(data)).toBeUndefined();
expect(userFn).toHaveBeenCalledTimes(1);
expect(fetch).toHaveBeenCalledTimes(1);
expect(Request).toHaveBeenCalledTimes(1);
expect(fetch).toHaveBeenCalledTimes(2);
expect(Request).toHaveBeenCalledTimes(2);
});

test("Is an error thrown when experiment data is empty?", () => {
const exp_data: Timeline[] = [];
const jsonData = {
data: {
attributes: { exp_data, sequence: ["0-value"] },
},
};
const data = {
/**
* Mocked jsPsych Data Collection.
*
* @returns Exp data.
*/
values: () => exp_data,
} as DataCollection;
const response = {
/**
* Mocked json function used in API calls.
*
* @returns Promise containing mocked json data.
*/
json: () => Promise.resolve(jsonData),
ok: true,
} as Response;

const userFn = jest.fn();
global.fetch = jest.fn(() => Promise.resolve(response));
global.Request = jest.fn();

Object.assign(window, {
chs: {
study: { attributes: { exit_url: "exit url" } } as Study,
child: {} as Child,
pastSessions: {} as Response[],
},
});

expect(async () => {
await on_finish("some id", userFn)(data);
}).rejects.toThrow("Experiment sequence or data missing.");
});

test("Is an error thrown when experiment sequence is undefined?", () => {
const exp_data = [{ key: "value" }];
const jsonData = {
data: {
attributes: { exp_data, sequence: undefined },
},
};
const data = {
/**
* Mocked jsPsych Data Collection.
*
* @returns Exp data.
*/
values: () => exp_data,
} as DataCollection;
const response = {
/**
* Mocked json function used in API calls.
*
* @returns Promise containing mocked json data.
*/
json: () => Promise.resolve(jsonData),
ok: true,
} as Response;

const userFn = jest.fn();
global.fetch = jest.fn(() => Promise.resolve(response));
global.Request = jest.fn();

Object.assign(window, {
chs: {
study: { attributes: { exit_url: "exit url" } } as Study,
child: {} as Child,
pastSessions: {} as Response[],
},
});

expect(async () => {
await on_finish("some id", userFn)(data);
}).rejects.toThrow("Experiment sequence or data missing.");
});
15 changes: 14 additions & 1 deletion packages/lookit-initjspsych/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Api from "@lookit/data";
import { JsPsychExpData, LookitWindow } from "@lookit/data/dist/types";
import { DataCollection } from "jspsych";
import { SequenceExpDataError } from "./errors";
import { UserFuncOnDataUpdate, UserFuncOnFinish } from "./types";

declare let window: LookitWindow;
Expand Down Expand Up @@ -55,7 +56,18 @@ export const on_finish = (
userFunc?: UserFuncOnFinish,
) => {
return async function (data: DataCollection) {
const {
attributes: { sequence },
} = await Api.retrieveResponse(responseUuid);

const exp_data: JsPsychExpData[] = data.values();

if (!sequence || sequence.length === 0 || exp_data.length === 0) {
throw new SequenceExpDataError();
}

const { exit_url } = window.chs.study.attributes;
const last_exp = exp_data[exp_data.length - 1];

// Don't call the function if not defined by user.
if (typeof userFunc === "function") {
Expand All @@ -64,7 +76,8 @@ export const on_finish = (

await Api.finish();
await Api.updateResponse(responseUuid, {
exp_data: data.values() as JsPsychExpData[],
exp_data,
sequence: [...sequence, `${last_exp.trial_index}-${last_exp.trial_type}`],
completed: true,
});

Expand Down

0 comments on commit d2135fb

Please sign in to comment.