32 KiB
Test data factories
Domain objects are created through factories in src/test/, one per object type:
| Factory | Builds |
|---|---|
createVm |
FrontXoVm |
createHost |
FrontXoHost |
createServer |
FrontXoServer |
createPool |
FrontXoPool (also OTHER_POOL_ID, the id of another pool, DISKOR_POOL_NAME, a name apart from its default, and UNKNOWN_POOL_ID, an id no pool has) |
createSr |
FrontXoSr |
createVbd |
FrontXoVbd |
createVdi |
FrontXoVdi |
createNetwork |
FrontXoNetwork |
createPif, createManagementPif |
FrontXoPif, the management PIF of a pool master |
createVmTemplate |
FrontXoVmTemplate |
createVif |
FrontXoVif |
createPbd |
FrontXoPbd |
createVmSnapshot |
FrontXoVmSnapshot |
createTask / createV2vImportTask |
FrontXoTask, still pending / a V2V import task of the given sourceVmIds (any value, to build malformed ones) |
createPlugin |
FrontXoPlugin |
createHostStats |
XapiHostStats |
createVmStats |
XapiVmStats |
createPoolStats |
XapiPoolStats |
createPoolDashboardTopFiveUsage |
XoPoolDashboard (top-five usage section) |
createV2vConnection / createV2vRememberedConnection |
XoV2vConnection / V2vRememberedConnection |
createV2vInventory, createV2vVm, createV2vVmWithDisks, createV2vDatacenter, createV2vHost, createV2vDatastore, createV2vDisk |
XoV2vInventory and its VM (optionally from partial disks) / datacenter / host / datastore / disk; also V2V_VM_ID, the id every single-VM V2V factory gives its VM |
createV2vNic, createV2vPortGroup |
XoV2vNic / XoV2vPortGroup |
createV2vImportVm |
FrontXoVm imported by V2V (its markers, isImporting for a start locked without source snapshot, then VM overrides) |
createV2vColdAndWarmImportVms |
one cold and one warm V2V import of the test source |
createV2vPartialImportSnapshot / createV2vCompleteImportSnapshot |
the FrontXoVmSnapshot a partial import / the cutover leaves on the createV2vImportVm VM |
createV2vImportedDisk |
the vdi-<name> an import made on an SR from a source disk path, and the vbd-<name> plugging it into the import VM |
createV2vMigrationList, createV2vDestinationDefaults, createV2vMigrationListVm, createV2vMigrationListVms |
V2vMigrationList, its defaults, one VM (with its overrides) and count VMs |
createV2vMigrationListVmsOf |
the VMs of the given ids |
createV2vVmRow, createV2vVmRowsInput |
V2vVmRow of an inventory VM of its own id, built by buildV2vVmRows, then overrides / the empty V2vVmRowsInput |
createV2vLaunchSettings, createV2vLaunchPlanItem, createV2vStartVm, createV2vStartPayloadInput, createV2vVmLaunchOptionsRow, createV2vMigratedVm |
V2vLaunchSettings of a new launch / a new ready VM of the launch plan / a new VM to start, on the list defaults / the buildV2vStartPayload input of that VM / a row of the per-VM launch options, on the launch settings / a VM of the review already cut over to another pool, its second copy not confirmed; also V2V_START_TASK_ID, stubV2vStartAccepted / stubV2vStartProblems (the V2V start route accepting / refusing a launch) |
createTableSelectionBindings |
SelectionBindings of a table with nothing selected, for a table component given its selection as props |
createV2vSelectedVm, createV2vListPair |
V2vSelectedVm (literal labels) / V2vListPair (source host and pool name), the props of the selected VMs panel components |
createV2vMappingVmHeading |
V2vMappingVmHeading (literal labels), the heading of the VM the mapping step shows |
createPoolStats composes createHostStats, since pool stats are one entry per host: pass a Partial<XapiHostStats> per host id, or an { error } entry for a host whose stats the pool could not fetch.
const poolStats = createPoolStats({
'host-1': { stats: { cpus: { '0': [10, 20] } } },
'host-2': { error: { code: 'boom' } },
})
createPoolDashboardTopFiveUsage builds the hosts and vms top-five usage sections of an XoPoolDashboard. Both metrics of a section default to empty, so a card test fills in only the one it exercises:
const dashboard = createPoolDashboardTopFiveUsage({ cpu: [createHostCpuUsage()] }, { cpu: [createVmCpuUsage()] })
Shared helper factories live there too — mount-composable.ts, mount-chart-card.ts, create-enhanced-data-helpers.ts, global-test-config.ts, create-test-router.ts, create-job-result.ts (what a mocked defineJob composable returns), create-action-item.ts (a menu / button LeafActionItem), create-plugin-actions.ts (what a mocked useXoPluginActions returns), v2v-vm-kind-actions.ts (describeV2vVmKindActions: the cases every per-kind V2V VM action component shares, its composable called on its VM, its actions handed to its slot, its removal emitted; V2V_VM_ACTIONS_SLOTS, the slot to mount such a component with, and findV2vVmSlotActions, the actions it handed to that slot; getV2vVmKindActionList, the actions a mocked kind composable returned, as handed to the slot; mountV2vVmKindActions, a kind action component mounted with that slot), find-rendered-values.ts, find-tags.ts (the labels of the rendered tags), find-titles.ts (findTitles, the card and section titles; findTitle, the .title of a VtsSuccessStateHero or a list item, undefined without one), find-tooltip-content.ts (the tooltip an element shows on hover), find-shown-components.ts (findShownComponents: which of several alternative components a wrapper renders, in the given order), get-button.ts (by its label, or the aria-label of an icon button: findButton / getButton the <button> to click, getUiButton the UiButton whose busy / disabled props the app sets), get-checkbox.ts (the input of a UiCheckbox by its label), drawer.ts (submit or cancel a drawer, read its buttons), select.ts (open a VtsSelect, read the selection it shows, read or pick its options), mount-json-schema-form.ts (a JSON schema form, or a composable run in one of its fields), json-schema-item-label.ts (the labels of the items of a JSON schema list), find-parts.ts, find-input-labels.ts, find-input-messages.ts, find-accented-labels.ts (findAccentedTags / findAccentedInfos: each UiTag / UiInfo as { label, accent }), find-card-title.ts (findCardTitle, the whole title; findCardTitleLabel, its label alone; findPanelCardTitle / findPanelCardTitles, the label of the first / every UiPanelCardTitle, sub-titles included), find-generic-components.ts (getGenericComponent / findAllGenericComponents: a generic component looked up by its name, its props and emits typed, where a lookup by its definition types it as a plain element), create-select-bindings.ts, find-select-stub-labels.ts, mount-with-select.ts, form-messages.ts, credentials-error-wiring.ts, v2v-target-cells.ts, stub-fetch-response.ts (also stubFetchServerError, see mocking.md), stub-v2v-invalid-credentials-response.ts (the 422 the V2V routes answer to rejected credentials), create-api-error.ts (createApiError(status, cause?): the ApiError fetchRequest throws for that status and body), v2v-selected-vm-checks.ts (V2V_SELECTED_VM_CHECK: one check of each type a V2V selected VM can get; V2V_VM_CHECK: the checks a source VM passes; createV2vUnsupportedCheck(reason): the unsupported check of that disk reason), job-running.ts (expectJobRunning(job, message): starts a job whose request never settles, expects it running with its "in progress" message), fetch-requests.ts (hasRequested(method, endpoint, body?): whether the stubbed fetch sent that request to the REST API), silence-console-error.ts, reset-v2v-collection-mocks.ts (resetV2vCollectionMocks: resets the V2V VM rows, destination, VM device and delete modal mocks, in a V2V wizard step test's beforeEach), create-v2v-wizard-router.ts (and V2V_VMS_FILTER_QUERY_KEY, the route key of the VMs step filter; findV2vRouteQuery, the query of the wizard route), mount-on-v2v-wizard.ts (mountOnV2vWizard: stores a migration list, routes the wizard to a step, on the pool of the list unless given a query, mounts with that router and the connection of a source; mountComposableOnV2vWizard: the same for a composable of a step; mountComponentOnV2vWizard(component, { props, stubs }, setup): the same for a component, returning { wrapper, router }), mount-v2v-vms-step.ts (mountV2vVmsStep: mounts a composable on the VMs step, with a stored list and a connected source), mount-v2v-launch-form.ts (mountV2vLaunchForm: the launch form of the review step, its bindings unwrapped as a component receives them), mount-v2v-list-step.ts (mountV2vListStep: seeds the fixtures of the mapping or the review step, then mounts that step or one of its composables on the list, and one of its VMs when given, with a connected source unless isSourceConnected: false), create-v2v-vm-row.ts (also getV2vVmNames / getV2vVmIds, the names / ids of V2V VMs or rows, in order), v2v-vms-fixtures.ts (two datastores and one inventory VM per case the VMs step tells apart: on one datastore, on both, unsupported, in the list, and the list holding that last one), v2v-mapping-fixtures.ts (an inventory VM of two disks, one with a snapshot chain, and two NICs, and the pool offers of a mapping: the targets of the list defaults plus one other SR, network and template; the inventory the VM is read from, the target options its selects list and the disk and NIC rows of its mapping; the import VM of that VM once resumed, with the VBD, VDI and VIFs its first sync left, the source VM still on the snapshot that sync read, and the rows of its active mapping; V2V_DEFAULT_OFFERS, a pool offering the list defaults alone; V2V_MIGRATED_VM_TAGS, the tags of a VM without override; createV2vOfferedTarget, a resolved target among the pool offers, coming from the default unless told), mount-v2v-vm-mapping.ts (mountV2vVmMapping: stores a list holding a VM, by default the mapped VM with an override on a disk and a NIC, on a pool offering the mapping fixtures, then mounts a mapping composable with the migration list of that pool and a connected source; mountV2vVmMappingComponent, the same for a mapping component handed that list; readV2vStoredListVm, that VM as last written; V2V_LIST_VM_OVERRIDES, the overrides of that default VM, V2V_FULLY_OVERRIDDEN_LIST_VM, the same with its options overridden too, V2V_OTHER_LIST_VM, another VM of the list, the mapped one then missing from it), v2v-mapping-card.ts (describeV2vMappingCardLayout: the cases every mapping card of the V2V side panel shares, its title, then its disk and network adapter sections, each set apart, left out without devices, and the pool alone while loading; countDividers), create-v2v-mapping-step-vm.ts (createV2vNewMappingStepVm / createV2vResumedMappingStepVm / createV2vNotFoundMappingStepVm: the mapping step VM of each kind, on the mapping fixtures; V2V_NEW_STEP_VM / V2V_RESUMED_STEP_VM / V2V_NOT_FOUND_STEP_VM, one of each, as created by default; createV2vMappingStepRow: a row of the mapping table, a VM with its item of the selected VMs), seed-v2v-resumed-vm.ts (seedV2vResumedVmCollections: the pool of the list, the targets and devices of that resumed VM, in the mocked collections), v2v-mapping-step-fixtures.ts (a list of a new, a resumed and a gone VM, the inventory locating them, the import VM and sync snapshot of the resumed one, and seedV2vMappingStepCollections, the collections the mapping step reads them from), v2v-review-step-fixtures.ts (createV2vReviewStepList: a list on the pool and defaults of the review step, on the given VMs; the mapping step list plus a VM cut over to another pool, its import, pool, SR and cutover snapshot, the disks of the resumed and the migrated imports, and seedV2vReviewStepCollections, the collections the review step reads them from; V2V_REVIEW_STEP_EXCLUDED_LIST, a list of a gone VM alone, nothing to launch), v2v-wizard-fixtures.ts (the connected source, a list stored for a pool without VMs then with some, that pool and another one), find-table-cells.ts (see Testing components), query-builder-filters.ts (UNPARSABLE_FILTER), local-storage.ts, v2v-remembered-connections-storage.ts, v2v-migration-list-storage.ts (seed or read the stored list; readV2vMigrationListVmIds, the ids of its VMs), fill-v2v-connection-form.ts, choose-v2v-destination.ts (choose the pool of the V2V destination form, or a complete destination), seed-v2v-destination-pools.ts (the collections a V2V destination pool offers its prefill from), seed-v2v-list-pool.ts (seedV2vListPool: the pool of the V2V list in the mocked collections, offering the list defaults unless given other offers, none of a kind left out, beside the other pool if asked), v2v-connection-provide.ts (the V2V connection the migration page provides), v2v-connection-reader.ts (a component that reads the V2V connection its parent provides), now.ts (the fixed date of the fake timers), group-by.ts, i18n.ts and linear-chart-stub.ts. The shared module mocks (mock-xo-*.ts, mock-delete-modal.ts) live there as well, see mocking.md.
Each factory returns a fully-populated object of the real front-end type and accepts a Partial<T> of overrides, spread last, so a test only states the fields relevant to its case:
const runningVm = createVm({ power_state: VM_POWER_STATE.RUNNING })
const host = createHost({ memory: { size: 8 * 1024 ** 3, usage: 3 * 1024 ** 3 } })
Rules:
- Reuse factories, never duplicate the object shape inline.
- Type fixtures from the real source types so they drift with production. For a shape local to one test, derive it — e.g.
type StorageUsage = NonNullable<NonNullable<XoPoolDashboard['srs']>['topFiveUsage']>[number]— and write a small localcreateStorageUsagehelper. - Cast branded ids with the honest type (
'host-1' as XoHost['id']), neveras never.
Form messages
form-messages.ts builds the message a validated-form field binding carries, so a form test asserts the exact error instead of toBeDefined():
expect(form.passwordInputBindings.error).toEqual(dangerMessage(form.t('password-required')))
expect(form.usernameInputBindings.error).toEqual(invalidCredentialsMessage())
expect(form.hostInputBindings.error).toEqual(requiredMessage())
v2v-target-cells.ts declares the cases every V2V mapping table shares for its last two cells, the target select and where its value comes from, editable then read only: describeV2vTargetCells({ mountTable, targetHeader, changeEvent, rows, options }), mountTable taking { readonly, withoutOptions } overrides. Its getV2vTargetSelect finds the V2vTargetSelect of a wrapper by its name: found by its definition, a generic component is typed as a plain element.
credentials-error-wiring.ts declares the showCredentialsError cases every form using useCredentialsError shares (error on the username and the password, cleared when either changes): describeCredentialsErrorWiring(mountForm, fillRequiredFields).
requiredMessage() is the message of a required rule without its own withMessage: the app-wide form:error:required, installed by createGlobalTestConfig() like in main.ts.