Skip to content

Commit

Permalink
Merge pull request #124 from Watts-Lab/evan-updated
Browse files Browse the repository at this point in the history
merge main into evan branch
  • Loading branch information
evanping authored Feb 20, 2025
2 parents a8d91a2 + 3dacdb0 commit d1fc74c
Show file tree
Hide file tree
Showing 20 changed files with 3,865 additions and 185 deletions.
43 changes: 29 additions & 14 deletions @empirica-mocks/core/mocks.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useContext } from 'react';
import { isFunctionDeclaration } from "typescript";
// import { StageContext } from '@/editor/stageContext'; # don't know why this doesn't work
// import { StageContext } from '@/editor/stageContext'; // # don't know why this doesn't work

// file is in deliberation-empirica/client/node_modules/@empirica/core/mocks.js
import { StageContext } from "../../../../../src/app/editor/stageContext"
import { StageContext } from "../../src/app/editor/stageContext"
// "../../../../src/app/editor/stageContext"



Expand All @@ -16,14 +17,21 @@ export function usePlayer() {
exitStep: 0, //TODO,
gameID: 21,
position: 0, //TODO - set with toggle
stage: {
set: function (varName, value) {
this[varName] = value;
},
get: function (varName) {
return this[varName];
},
},
get: function (varName) {
return this[varName];
},
set: function (varName, value) {
this[varName] = value;
},
};

return player;
}

Expand All @@ -46,6 +54,8 @@ export function useGame() {
export function useStageTimer() {
const stage = useContext(StageContext);
console.log("useStageTimerMock", stage)
console.log("StageElapsed", stage.elapsed)


// This is a mock function that returns a mock stage timer object
const stageTimer = {
Expand All @@ -69,6 +79,8 @@ export function useStage() {
setTreatment,
templatesMap,
setTemplatesMap,
selectedTreatmentIndex,
setSelectedTreatmentIndex,
refData,
setRefData,
} = useContext(StageContext)
Expand Down Expand Up @@ -115,20 +127,23 @@ export function useStage() {
if (tempStage) {
elements = tempStage.elements;
} else {
elements = treatment.treatments[0]?.gameStages[currentStageIndex]?.elements;
elements = treatment.treatments[selectedTreatmentIndex]?.gameStages[currentStageIndex]?.elements;
}

console.log("CURRELEMENTS", elements)

// TODO: change to template if needed
// map to templates first
elements = elements.flatMap((element) => {
if (element.template) {
return templatesMap.get(element.template);
} else {
return element;
}
})
if (Array.isArray(elements)) {
elements = elements.flatMap((element) => {
if (element.template) {
return templatesMap.get(element.template);
}
return [element];
});
} else {
elements = [];
}

//console.log("ELEMENTS_TO_DISPLAY", elements)
// check all conditions
Expand Down Expand Up @@ -185,15 +200,15 @@ export function useStage() {
return tempStage.discussion || [];
}

return treatment.treatments[0]?.gameStages[currentStageIndex]?.discussion || [];
return treatment.treatments[selectedTreatmentIndex]?.gameStages[currentStageIndex]?.discussion || [];
} else if (varName === "name") {
if (tempStage) {
return tempStage.name;
}
return treatment.treatments[0]?.gameStages[currentStageIndex]?.name
return treatment.treatments[selectedTreatmentIndex]?.gameStages[currentStageIndex]?.name

} else if (varName === "index") {
return currentStageIndex
return currentStageIndex;
}
},

Expand Down
217 changes: 181 additions & 36 deletions cypress/e2e/filterTreatment.cy.ts
Original file line number Diff line number Diff line change
@@ -1,95 +1,240 @@
describe('timeline filter treatment', () => {
describe('timeline filter stages and treatments', () => {
beforeEach(() => {
// load initial treatment file
let yamltreatment = "treatments: \n - name: filter_timeline_test\n playerCount: 1\ngameStages: []";
let yamltreatment = "treatments:\n- name: treatment_one\n playerCount: 1\ngameStages: []\n";
cy.viewport(2000, 1000, { log: false });
cy.visit('http://localhost:3000/editor');
cy.typeInCodeEditor(`{ctrl+a}{del}${yamltreatment}`) // equivalent to clear() in cypress
cy.typeInCodeEditor(`{backspace}`);
let secondTreatment = "- name: treatment_two\n playerCount: 1\ngameStages: []\n";
cy.typeInCodeEditor(`${secondTreatment}`);

// verify initial text in editor

// text values from monaco-editor will include line numbers and no line breaks
// the yamltreatment variable has no line numbers and line breaks
// so right now comparison is only on the treatmentName
cy.containsInCodeEditor('filter_timeline_test')
// save treatment file
cy.containsInCodeEditor('treatment_one')
cy.get('[data-cy="yaml-save"]').realClick()

// first stage
// ensure that the default treatment (treatment 0) is selected when the page is loaded
cy.get('[data-cy="treatments-dropdown"] select').should('have.value', '0');

// treatment one, first stage
cy.get('[data-cy="add-stage-button"]').click();
cy.get('[data-cy="edit-stage-name-new"]').type("Role Assignment and General Instructions");
cy.get('[data-cy="edit-stage-duration-new"]').type("{backspace}300");
cy.get('[data-cy="edit-stage-save-new"]').click();

// second stage
// treatment one, second stage
cy.get('[data-cy="add-stage-button"]').click();
cy.get('[data-cy="edit-stage-name-new"]').type("Main Discussion");
cy.get('[data-cy="edit-stage-duration-new"]').type("{backspace}200");
cy.get('[data-cy="edit-stage-save-new"]').click();

// third stage
// switch to the second treatment
cy.get('[data-cy="treatments-dropdown"] select').select('1');
cy.get('[data-cy="treatments-dropdown"] select').should('have.value', '1');

// treatment two, first stage
cy.get('[data-cy="add-stage-button"]').click();
cy.get('[data-cy="edit-stage-name-new"]').type("test");
cy.get('[data-cy="edit-stage-duration-new"]').type("{backspace}200");
cy.get('[data-cy="edit-stage-save-new"]').click();

// treatment two, second stage
cy.get('[data-cy="add-stage-button"]').click();
cy.get('[data-cy="edit-stage-name-new"]').type("Post Discussion Survey");
cy.get('[data-cy="edit-stage-name-new"]').type("test2");
cy.get('[data-cy="edit-stage-duration-new"]').type("{backspace}200");
cy.get('[data-cy="edit-stage-save-new"]').click();

// all sections should initially be visible
// verify all stages in second treatment are visible
cy.get('[data-cy="stage-0"]').contains("test").should("be.visible");
cy.get('[data-cy="stage-1"]').contains("test2").should("be.visible");
cy.get('[data-cy^="stage-"]').should('have.length', 2);

// switch back to first treatment
cy.get('[data-cy="treatments-dropdown"] select').select('0');
cy.get('[data-cy="treatments-dropdown"] select').should('have.value', '0');

// all stages in treatment 0 should initially be visible
cy.get('[data-cy="stage-0"]').contains("Role Assignment and General Instructions").should("be.visible");
cy.get('[data-cy="stage-1"]').contains("Main Discussion").should("be.visible");
cy.get('[data-cy="stage-2"]').contains("Post Discussion Survey").should("be.visible");
cy.get('[data-cy^="stage-"]').should('have.length', 3);
cy.get('[data-cy^="stage-"]').should('have.length', 2);
});

it('should dynamically populate filter options based on treatment file', () => {
cy.get('[data-cy="filter-dropdown"] select').within(() => {
cy.get('option').should('have.length', 4);
it('should dynamically populate stage options in stages dropdown', () => {
cy.get('[data-cy="stages-dropdown"] select').within(() => {
cy.get('option').should('have.length', 3);
cy.get('option').eq(0).should('have.text', 'All Stages');
cy.get('option').eq(1).should('have.text', 'Role Assignment and General Instructions');
cy.get('option').eq(2).should('have.text', 'Main Discussion');
cy.get('option').eq(3).should('have.text', 'Post Discussion Survey');
});
})

it('allows filtering stages by criteria', () => {
it('should dynamically populate treatment options in treatments dropdown', () => {
cy.get('[data-cy="treatments-dropdown"] select').within(() => {
cy.get('option').should('have.length', 2);
cy.get('option').eq(0).should('have.text', 'treatment_one');
cy.get('option').eq(1).should('have.text', 'treatment_two');
});
})

it('allows filtering by stage name', () => {
// default option
cy.get('[data-cy="filter-dropdown"] select').should('have.value', 'all');
cy.get('[data-cy="stages-dropdown"] select').should('have.value', 'all');

// select one section and ensure no other sections are visible
cy.get('[data-cy="filter-dropdown"] select').select('Main Discussion');
cy.get('[data-cy="filter-dropdown"] select').should('have.value', 'Main Discussion');
// select one stage and ensure no other stages are visible (assuming all stages have different names)
cy.get('[data-cy="stages-dropdown"] select').select('Main Discussion');
cy.get('[data-cy="stages-dropdown"] select').should('have.value', 'Main Discussion');
cy.get('[data-cy="stage-0"]').should('not.exist');
cy.get('[data-cy="stage-2"]').should('not.exist');
cy.get('[data-cy="stage-1"]').contains("Main Discussion").should("be.visible");
cy.get('[data-cy^="stage-"]').should('have.length', 1);

// verify that currentStageIndex in context and currentStageName in localStorage are correct after stage change
cy.window().its('stageContext').then((stageContext) => {
expect(stageContext.currentStageIndex).to.equal(1);
});
cy.window().then((win) => {
expect(win.localStorage.getItem('currentStageName')).to.equal('Main Discussion');
});

// reset to all stages when filter option is cleared
cy.get('[data-cy="filter-dropdown"] select').select('all');
cy.get('[data-cy="filter-dropdown"] select').should('have.value', 'all');
cy.get('[data-cy="stages-dropdown"] select').select('all');
cy.get('[data-cy="stages-dropdown"] select').should('have.value', 'all');
cy.get('[data-cy="stage-0"]').contains("Role Assignment and General Instructions").should("be.visible");
cy.get('[data-cy="stage-1"]').contains("Main Discussion").should("be.visible");
cy.get('[data-cy^="stage-"]').should('have.length', 2);

// verify that currentStageIndex and currentStageName are reset after clearing filter
cy.window().its('stageContext').then((stageContext) => {
expect(stageContext.currentStageIndex).to.equal(0);
});
cy.window().then((win) => {
expect(win.localStorage.getItem('currentStageName')).to.equal('all');
});
})

it('allows filtering by treatment name', () => {
// Select the second treatment
cy.get('[data-cy="treatments-dropdown"] select').select('1');
cy.get('[data-cy="treatments-dropdown"] select').should('have.value', '1');

// Verify that selectedTreatmentIndex in both context and localStorage is correct
cy.window().its('stageContext').then((stageContext) => {
expect(stageContext.selectedTreatmentIndex).to.equal(1);
});
cy.window().then((win) => {
expect(win.localStorage.getItem('selectedTreatmentIndex')).to.equal('1');
});

// Verify that the stages for the second treatment are displayed
cy.get('[data-cy="stage-0"]').contains("test").should("be.visible");
cy.get('[data-cy="stage-1"]').contains("test2").should("be.visible");
cy.get('[data-cy^="stage-"]').should('have.length', 2);

// Verify that selecting stages works in second treatment
cy.get('[data-cy="stages-dropdown"] select').select('test2');
cy.get('[data-cy="stages-dropdown"] select').should('have.value', 'test2');
cy.get('[data-cy="stage-0"]').should('not.exist');
cy.get('[data-cy="stage-1"]').contains("test").should("be.visible");
cy.get('[data-cy^="stage-"]').should('have.length', 1);

// Verify that currentStageIndex in context and currentStageName in localStorage are correct after stage change
cy.window().its('stageContext').then((stageContext) => {
expect(stageContext.currentStageIndex).to.equal(1);
});
cy.window().then((win) => {
expect(win.localStorage.getItem('currentStageName')).to.equal('test2');
});

// Switch back to the first treatment
cy.get('[data-cy="treatments-dropdown"] select').select('0');
cy.get('[data-cy="treatments-dropdown"] select').should('have.value', '0');

// Verify that the selectedTreatmentIndex in context and localStorage is correct
cy.window().its('stageContext').then((stageContext) => {
expect(stageContext.selectedTreatmentIndex).to.equal(0);
});
cy.window().then((win) => {
expect(win.localStorage.getItem('selectedTreatmentIndex')).to.equal('0');
});

// Verify that currentStageIndex and currentStageName are reset after switching treatments
cy.window().its('stageContext').then((stageContext) => {
expect(stageContext.currentStageIndex).to.equal(0);
});
cy.window().then((win) => {
expect(win.localStorage.getItem('currentStageName')).to.equal('all');
});

// Verify that the stages for the first treatment are displayed
cy.get('[data-cy="stage-0"]').contains("Role Assignment and General Instructions").should("be.visible");
cy.get('[data-cy="stage-1"]').contains("Main Discussion").should("be.visible");
cy.get('[data-cy="stage-2"]').contains("Post Discussion Survey").should("be.visible");
cy.get('[data-cy^="stage-"]').should('have.length', 3);
cy.get('[data-cy^="stage-"]').should('have.length', 2);
})

it('should persist selected filter after page reload', () => {
cy.get('[data-cy="filter-dropdown"] select').should('have.value', 'all');
it('should persist selected stage after page reload', () => {
// Initial stage
cy.get('[data-cy="stages-dropdown"] select').should('have.value', 'all');

cy.get('[data-cy="filter-dropdown"] select').select('Main Discussion');
// Select a new stage
cy.get('[data-cy="stages-dropdown"] select').select('Main Discussion');
cy.get('[data-cy="stage-0"]').should('not.exist');
cy.get('[data-cy="stage-2"]').should('not.exist');
cy.get('[data-cy="stage-1"]').contains("Main Discussion").should("be.visible");
cy.get('[data-cy^="stage-"]').should('have.length', 1);

cy.reload(); // reload page

cy.get('[data-cy="filter-dropdown"] select').select('Main Discussion');
cy.get('[data-cy="filter-dropdown"] select').should('have.value', 'Main Discussion');
// Verify that stage selection persists
cy.get('[data-cy="stages-dropdown"] select').should('have.value', 'Main Discussion');
cy.get('[data-cy="stage-0"]').should('not.exist');
cy.get('[data-cy="stage-2"]').should('not.exist');
cy.get('[data-cy="stage-1"]').contains("Main Discussion").should("be.visible");
cy.get('[data-cy^="stage-"]').should('have.length', 1);
})

// add test for same named stages
it('should persist selected treatment after page reload', () => {
// Initial treatment
cy.get('[data-cy="treatments-dropdown"] select').should('have.value', '0');

// Select a new treatment and verify timeline contents
cy.get('[data-cy="treatments-dropdown"] select').select('1');
cy.get('[data-cy="treatments-dropdown"] select').should('have.value', '1');
cy.get('[data-cy="stage-0"]').contains("test").should("be.visible");
cy.get('[data-cy="stage-1"]').contains("test2").should("be.visible");
cy.get('[data-cy^="stage-"]').should('have.length', 2);

cy.reload(); // reload page

// Verify that timeline persists
cy.get('[data-cy="treatments-dropdown"] select').should('have.value', '1');
cy.get('[data-cy="stage-0"]').contains("test").should("be.visible");
cy.get('[data-cy="stage-1"]').contains("test2").should("be.visible");
cy.get('[data-cy^="stage-"]').should('have.length', 2);
})

it('should show a useful message when stages array is empty', () => {
// Add a treatment with an empty stages array
cy.typeInCodeEditor(`\n`);
cy.typeInCodeEditor(` `);
cy.typeInCodeEditor(` `);
let emptyStagesTreatment = "- name: treatment_three\n playerCount: 1\ngameStages: []\n";
cy.typeInCodeEditor(`${emptyStagesTreatment}`);
cy.get('[data-cy="yaml-save"]').realClick();

// Select the treatment with empty stages
cy.get('[data-cy="treatments-dropdown"] select').select('2');
cy.get('[data-cy="treatments-dropdown"] select').should('have.value', '2');

// Verify the message
cy.get('[data-cy="stages-dropdown"] select').should('contain', 'Nothing available');
})

it('should show a useful message when treatments array is empty', () => {
// Load an empty treatments array
let emptyTreatments = "treatments: []\n";
cy.typeInCodeEditor(`{ctrl+a}{del}${emptyTreatments}`);
cy.get('[data-cy="yaml-save"]').realClick();

// make sure stageIndex is updated
// Verify the messages
cy.get('[data-cy="treatments-dropdown"] select').should('contain', 'Nothing available');
})
})
Loading

0 comments on commit d1fc74c

Please sign in to comment.