Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Selectable Treatments and Stages/Elements #119

Merged
merged 18 commits into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 16 additions & 10 deletions @empirica-mocks/core/mocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ export function useStage() {
setTreatment,
templatesMap,
setTemplatesMap,
selectedTreatmentIndex,
setSelectedTreatmentIndex
} = useContext(StageContext)
// const stage1 = useContext(StageContext);
// console.log("useStageMock", stage1)
Expand All @@ -91,21 +93,25 @@ export function useStage() {
//const treatmentString = localStorage.getItem("treatment");
//const treatment = JSON.parse(treatmentString);
if (varName === "elements") {
var elements = treatment.treatments[0]?.gameStages[currentStageIndex]?.elements
elements = elements.flatMap((element) => {
if (element.template) {
return templatesMap.get(element.template);
}
return [element];
});
let elements = treatment.treatments[selectedTreatmentIndex]?.gameStages[currentStageIndex]?.elements;
if (Array.isArray(elements)) {
elements = elements.flatMap((element) => {
if (element.template) {
return templatesMap.get(element.template);
}
return [element];
});
} else {
elements = [];
}
console.log("revised elements", elements)
return elements;
} else if (varName === "discussion") {
return treatment.treatments[0]?.gameStages[currentStageIndex]?.discussion
return treatment.treatments[selectedTreatmentIndex]?.gameStages[currentStageIndex]?.discussion;
} else if (varName === "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
Loading