diff --git a/e2e-tests/fixtures/Model.ts b/e2e-tests/fixtures/Model.ts index caa75156d3..8c36279597 100644 --- a/e2e-tests/fixtures/Model.ts +++ b/e2e-tests/fixtures/Model.ts @@ -20,6 +20,7 @@ export class Model { newPlanButton: Locator; saveButton: Locator; versionInput: Locator; + viewInput: Locator; constructor( public page: Page, @@ -109,6 +110,17 @@ export class Model { await expect(this.associationTable).not.toBeVisible(); } + async updateDefaultView(viewName: string) { + await this.viewInput.selectOption('None'); + const matchingOption = await this.viewInput + .getByRole('option') + .getByText(viewName, { exact: false }) + .elementHandle(); + expect(matchingOption).toBeDefined(); + await this.viewInput.selectOption(matchingOption); + expect(await this.viewInput.inputValue()).toEqual(await matchingOption?.getAttribute('value')); + } + async updateDescription(modelDescription: string) { await this.descriptionInput.click(); await this.descriptionInput.fill(modelDescription); @@ -131,6 +143,7 @@ export class Model { this.libraryRadioButton = page.getByRole('radio', { name: 'Library' }); this.modelRadioButton = page.getByRole('radio', { exact: true, name: 'Model' }); this.nameInput = page.locator('input[name="name"]'); + this.viewInput = page.locator('select[name="view"]'); this.newPlanButton = page.getByRole('button', { name: 'New plan with model' }); this.versionInput = page.locator('input[name="version"]'); this.associationTable = page.getByRole('treegrid'); diff --git a/e2e-tests/tests/model.test.ts b/e2e-tests/tests/model.test.ts index c0f9ec335c..80132c86c7 100644 --- a/e2e-tests/tests/model.test.ts +++ b/e2e-tests/tests/model.test.ts @@ -3,17 +3,24 @@ import { adjectives, animals, colors, uniqueNamesGenerator } from 'unique-names- import { Constraints } from '../fixtures/Constraints.js'; import { Model } from '../fixtures/Model.js'; import { Models } from '../fixtures/Models.js'; +import { Plan } from '../fixtures/Plan.js'; +import { Plans } from '../fixtures/Plans.js'; import { SchedulingConditions } from '../fixtures/SchedulingConditions.js'; import { SchedulingGoals } from '../fixtures/SchedulingGoals.js'; +import { View } from '../fixtures/View.js'; let constraints: Constraints; let context: BrowserContext; let models: Models; let model: Model; let page: Page; +let plan: Plan; +let plans: Plans; let schedulingConditions: SchedulingConditions; let schedulingGoals: SchedulingGoals; let schedulingGoalName: string; +let view: View; +let viewName: string; const checkboxSelector = 'Press SPACE to toggle cell'; @@ -22,9 +29,12 @@ test.beforeAll(async ({ baseURL, browser }) => { page = await context.newPage(); models = new Models(page); + plans = new Plans(page, models); constraints = new Constraints(page); schedulingConditions = new SchedulingConditions(page); schedulingGoals = new SchedulingGoals(page); + plan = new Plan(page, plans, constraints, schedulingGoals, schedulingConditions); + view = new View(page); model = new Model(page, models, constraints, schedulingGoals, schedulingConditions); schedulingGoalName = uniqueNamesGenerator({ dictionaries: [adjectives, colors, animals] }); await constraints.gotoNew(); @@ -35,11 +45,21 @@ test.beforeAll(async ({ baseURL, browser }) => { await schedulingGoals.createSchedulingGoal(baseURL, schedulingGoalName); await models.goto(); await models.createModel(baseURL); + await plans.goto(); + await plans.createPlan(); + await plan.goto(); + viewName = await view.createViewName(); + await view.createView(viewName); await model.goto(); }); test.afterAll(async () => { - await model.deleteModel(); + await plan.goto(); + await view.deleteView(viewName); + await plans.goto(); + await plans.deletePlan(); + await models.goto(); + await models.deleteModel(); await constraints.goto(); await constraints.deleteConstraint(); await schedulingConditions.goto(); @@ -63,6 +83,10 @@ test.describe.serial('Model', () => { await model.updateVersion('2.0.0'); }); + test('Should be able to update the default view for a model', async () => { + await model.updateDefaultView(viewName); + }); + test('Should be able to add a constraint to the model and specify a version', async () => { await model.switchToConstraints(); await model.switchToLibraryView(); diff --git a/src/components/model/ModelForm.svelte b/src/components/model/ModelForm.svelte index 12eb49991c..9218b68be8 100644 --- a/src/components/model/ModelForm.svelte +++ b/src/components/model/ModelForm.svelte @@ -5,6 +5,7 @@ import { createEventDispatcher } from 'svelte'; import type { User, UserId } from '../../types/app'; import type { ModelLog, ModelSlim } from '../../types/model'; + import type { ViewSlim } from '../../types/view'; import effects from '../../utilities/effects'; import { getModelStatusRollup } from '../../utilities/model'; import { permissionHandler } from '../../utilities/permissionHandler'; @@ -19,6 +20,7 @@ export let initialModelName: string = ''; export let initialModelOwner: UserId | undefined; export let initialModelVersion: string | undefined; + export let initialModelDefaultViewId: number | null | undefined; export let activityTypeLogs: ModelLog[] | undefined; export let modelParameterLogs: ModelLog[] | undefined; export let resourceTypeLogs: ModelLog[] | undefined; @@ -26,11 +28,13 @@ export let createdAt: string | undefined; export let user: User | null; export let users: UserId[] = []; + export let views: ViewSlim[] = []; const dispatch = createEventDispatcher<{ createPlan: number; deleteModel: void; hasModelChanged: { + default_view_id: number | null; description: string; name: string; owner: UserId; @@ -60,6 +64,7 @@ $: name = initialModelName; $: owner = initialModelOwner ?? null; $: version = initialModelVersion ?? ''; + $: viewId = initialModelDefaultViewId ?? null; $: modelLogs = { refresh_activity_type_logs: activityTypeLogs ?? [], refresh_model_parameter_logs: modelParameterLogs ?? [], @@ -83,6 +88,7 @@ } $: dispatch('hasModelChanged', { + default_view_id: viewId, description, name, owner, @@ -131,7 +137,7 @@