From 5b29e87fe89f5111c65f9c84c9af770ec6bcfbd1 Mon Sep 17 00:00:00 2001 From: Alice Date: Mon, 23 Sep 2024 15:15:23 +0200 Subject: [PATCH 1/6] chore: export necessary constant to migrate data viewer --- docs/_docs/contributing/new-step.md | 7 +- ui/src/components/ActionToolbar.vue | 2 +- ui/src/components/ActionToolbarButton.vue | 11 +- ui/src/components/ActionToolbarSearch.vue | 13 +- ui/src/components/constants.ts | 297 +++++++++------------- ui/src/main.ts | 10 + 6 files changed, 148 insertions(+), 192 deletions(-) diff --git a/docs/_docs/contributing/new-step.md b/docs/_docs/contributing/new-step.md index 8fc4188329..7cd6f6c62d 100644 --- a/docs/_docs/contributing/new-step.md +++ b/docs/_docs/contributing/new-step.md @@ -415,8 +415,7 @@ The step should also be found in the search bar. #### In the action bar Actions are defined in `ui/src/components/constants.ts`. -Add to `ACTION_CATEGORIES` an object with the `name` of your new step and its -action `label` into the adequate category. +Add to `ACTION_CATEGORIES` a relation between step `name` and action `label` into the adequate category. ### In columns contextual menus @@ -439,9 +438,9 @@ its contextual menu. To achieve this, add your action directly in the template o #### In the search bar -Searchable actions are defined in the `SEARCH_ACTION` constant in `ui/src/components/constants.ts`. +Searchable actions are defined in the `ACTION_CATEGORIES` constant in `ui/src/components/constants.ts`. All actions from `ACTION_CATEGORIES` are imported. You should add in `type: 'Others actions'` -any action not defined in `ACTION_CATEGORIES`, such as contextual ones. +any action not defined in other category, such as contextual ones. ## Adding documentation diff --git a/ui/src/components/ActionToolbar.vue b/ui/src/components/ActionToolbar.vue index d608bde0e4..abac45043e 100644 --- a/ui/src/components/ActionToolbar.vue +++ b/ui/src/components/ActionToolbar.vue @@ -67,7 +67,7 @@ export default class ActionToolbar extends Vue { get featureFlagsAllowedButtons(): ButtonDef[] { return CATEGORY_BUTTONS.filter((d) => { if (!d.featureFlag) { - return true; + return !!d.enable; } else { return !this.featureFlags ? false : this.featureFlags[d.featureFlag] === 'enable'; } diff --git a/ui/src/components/ActionToolbarButton.vue b/ui/src/components/ActionToolbarButton.vue index 29cfd5bd5c..aa74bbc10c 100644 --- a/ui/src/components/ActionToolbarButton.vue +++ b/ui/src/components/ActionToolbarButton.vue @@ -22,7 +22,12 @@ import Vue from 'vue'; import { Component, Prop } from 'vue-property-decorator'; -import { ACTION_CATEGORIES, POPOVER_ALIGN } from '@/components/constants'; +import { + ACTION_CATEGORIES, + PipelineStepCategory, + POPOVER_ALIGN, + STEP_LABELS, +} from '@/components/constants'; import FAIcon from '@/components/FAIcon.vue'; import type * as S from '@/lib/steps'; import { Action, Getter, State } from 'pinia-class'; @@ -60,7 +65,7 @@ export default class ActionToolbarButton extends Vue { @Prop({ type: String, }) - category!: string; + category!: PipelineStepCategory; @Getter(VQBModule) computedActiveStepIndex!: number; @Getter(VQBModule) isEditingStep!: boolean; @@ -106,7 +111,7 @@ export default class ActionToolbarButton extends Vue { // Filter out unsupported steps get items() { - return ACTION_CATEGORIES[this.category]; + return ACTION_CATEGORIES[this.category].map((name) => ({ name, label: STEP_LABELS[name] })); } } diff --git a/ui/src/components/ActionToolbarSearch.vue b/ui/src/components/ActionToolbarSearch.vue index 60b899f805..edb12482e5 100644 --- a/ui/src/components/ActionToolbarSearch.vue +++ b/ui/src/components/ActionToolbarSearch.vue @@ -38,7 +38,7 @@ import type { PipelineStepName } from '@/lib/steps'; import { State, Getter } from 'pinia-class'; import { VQBModule } from '@/store'; -import { SEARCH_ACTION } from './constants'; +import { ACTION_CATEGORIES, CATEGORY_BUTTONS, STEP_LABELS } from './constants'; import Popover from './Popover.vue'; @Component({ @@ -68,9 +68,14 @@ export default class SearchActions extends Vue { } get actionOptions() { - return SEARCH_ACTION.map((e) => ({ - ...e, - actions: e.actions.filter((a) => !this.unsupportedSteps.includes(a.name)), + return CATEGORY_BUTTONS.map((button) => ({ + type: button.label, + actions: ACTION_CATEGORIES[button.category] + .map((name) => ({ + name, + label: STEP_LABELS[name], + })) + .filter((a) => !this.unsupportedSteps.includes(a.name)), })); } diff --git a/ui/src/components/constants.ts b/ui/src/components/constants.ts index fc14c6a237..6adec287d5 100644 --- a/ui/src/components/constants.ts +++ b/ui/src/components/constants.ts @@ -3,204 +3,141 @@ import type { PipelineStepName } from '@/lib/steps'; export type ButtonDef = Readonly<{ icon: string; label: string; - category: string; + category: PipelineStepCategory; enable: boolean; featureFlag?: string; }>; -export type ActionCategories = { - add: ActionCategory[]; - compute: ActionCategory[]; - filter: ActionCategory[]; - text: ActionCategory[]; - date: ActionCategory[]; - reshape: ActionCategory[]; - combine: ActionCategory[]; - geo: ActionCategory[]; - [key: string]: ActionCategory[]; -}; +export type PipelineStepCategory = + | 'add' + | 'filter' + | 'aggregate' + | 'compute' + | 'text' + | 'date' + | 'reshape' + | 'combine' + | 'geo' + | 'other_actions'; -export type ActionCategory = { - name: PipelineStepName; - label: string; - defaults?: { [prop: string]: any }; -}; +export type ActionCategories = Record; -export type groupActions = { - type: string; - actions: ActionCategory[]; +export const STEP_LABELS: Record = { + text: 'Add text column', + ifthenelse: 'Add conditional column', + delete: 'Delete columns', + select: 'Keep columns', + filter: 'Filter rows', + top: 'Top N rows', + argmax: 'Argmax', + argmin: 'Argmin', + aggregate: 'Group by', + totals: 'Add total rows', + rollup: 'Hierarchical rollup', + uniquegroups: 'Get unique groups/values', + formula: 'Add formula column', + evolution: 'Compute evolution', + cumsum: 'Cumulated sum', + percentage: 'Percentage of total', + rank: 'Rank', + movingaverage: 'Moving average', + statistics: 'Compute Statistics', + absolutevalue: 'Absolute value', + concatenate: 'Concatenate', + split: 'Split column', + substring: 'Extract substring', + lowercase: 'To lowercase', + uppercase: 'To uppercase', + comparetext: 'Compare text columns', + trim: 'Trim spaces', + replacetext: 'Replace text', + todate: 'Convert text to date', + fromdate: 'Convert date to text', + dateextract: 'Extract date information', + addmissingdates: 'Add missing dates', + duration: 'Compute duration', + pivot: 'Pivot', + unpivot: 'Unpivot', + waterfall: 'Waterfall', + append: 'Append datasets', + join: 'Join datasets', + dissolve: 'Geographic dissolve', + hierarchy: 'Geographic hierarchy', + simplify: 'Geographic simplify', + duplicate: 'Duplicate column', + custom: 'Custom step', + customsql: 'Custom step', + convert: 'Convert column data type', + fillna: 'Fill null values', + domain: '', + rename: 'Rename column', + sort: 'Sort values', + replace: 'Replace values', }; export const ACTION_CATEGORIES: ActionCategories = { - add: [ - { name: 'text', label: 'Add text column' }, - { name: 'formula', label: 'Add formula column' }, - { name: 'ifthenelse', label: 'Add conditional column' }, - ], - filter: [ - { name: 'delete', label: 'Delete columns' }, - { name: 'select', label: 'Keep columns' }, - { name: 'filter', label: 'Filter rows' }, - { name: 'top', label: 'Top N rows' }, - { name: 'argmax', label: 'Argmax' }, - { name: 'argmin', label: 'Argmin' }, - ], - aggregate: [ - { name: 'aggregate', label: 'Group by' }, - { name: 'totals', label: 'Add total rows' }, - { name: 'rollup', label: 'Hierarchical rollup' }, - { name: 'uniquegroups', label: 'Get unique groups/values' }, - ], + add: ['text', 'formula', 'ifthenelse'], + filter: ['delete', 'select', 'filter', 'top', 'argmax', 'argmin'], + aggregate: ['aggregate', 'totals', 'rollup', 'uniquegroups'], compute: [ - { name: 'formula', label: 'Formula' }, - { name: 'evolution', label: 'Compute evolution' }, - { name: 'cumsum', label: 'Cumulated sum' }, - { name: 'percentage', label: 'Percentage of total' }, - { name: 'rank', label: 'Rank' }, - { name: 'movingaverage', label: 'Moving average' }, - { name: 'statistics', label: 'Statistics' }, - { name: 'absolutevalue', label: 'Absolute value' }, + 'formula', + 'evolution', + 'cumsum', + 'percentage', + 'rank', + 'movingaverage', + 'statistics', + 'absolutevalue', ], text: [ - { name: 'text', label: 'Add text column' }, - { name: 'concatenate', label: 'Concatenate' }, - { name: 'split', label: 'Split column' }, - { name: 'substring', label: 'Extract substring' }, - { name: 'lowercase', label: 'To lowercase' }, - { name: 'uppercase', label: 'To uppercase' }, - { name: 'comparetext', label: 'Compare text columns' }, - { name: 'trim', label: 'Trim spaces' }, - { name: 'replacetext', label: 'Replace text' }, - ], - date: [ - { name: 'todate', label: 'Convert text to date' }, - { name: 'fromdate', label: 'Convert date to text' }, - { name: 'dateextract', label: 'Extract date information' }, - { name: 'addmissingdates', label: 'Add missing dates' }, - { name: 'duration', label: 'Compute duration' }, - ], - reshape: [ - { name: 'pivot', label: 'Pivot' }, - { name: 'unpivot', label: 'Unpivot' }, - { name: 'waterfall', label: 'Waterfall' }, - ], - combine: [ - { name: 'append', label: 'Append datasets' }, - { name: 'join', label: 'Join datasets' }, - ], - geo: [ - { name: 'dissolve', label: 'Geographic dissolve' }, - { name: 'hierarchy', label: 'Geographic hierarchy' }, - { name: 'simplify', label: 'Geographic simplify' }, + 'text', + 'concatenate', + 'split', + 'substring', + 'lowercase', + 'uppercase', + 'comparetext', + 'trim', + 'replacetext', ], + date: ['todate', 'fromdate', 'dateextract', 'addmissingdates', 'duration'], + reshape: ['pivot', 'unpivot', 'waterfall'], + combine: ['append', 'join'], + geo: ['dissolve', 'hierarchy', 'simplify'], + other_actions: ['convert', 'duplicate', 'fillna', 'rename', 'replace', 'sort'], }; -export const SEARCH_ACTION: groupActions[] = [ - { - type: 'add', - actions: [...ACTION_CATEGORIES.add], - }, - { - type: 'aggregate', - actions: [...ACTION_CATEGORIES.aggregate], - }, - { - type: 'filter', - actions: [...ACTION_CATEGORIES.filter], - }, - { - type: 'compute', - actions: [...ACTION_CATEGORIES.compute], - }, - { - type: 'text', - actions: [...ACTION_CATEGORIES.text], - }, - { - type: 'date', - actions: [...ACTION_CATEGORIES.date], - }, - { - type: 'reshape', - actions: [...ACTION_CATEGORIES.reshape], - }, - { - type: 'combine', - actions: [...ACTION_CATEGORIES.combine], - }, - { - type: 'geo', - actions: [...ACTION_CATEGORIES.geo], - }, - { - type: 'Others actions', - actions: [ - { name: 'convert', label: 'Convert column data type' }, - { name: 'duplicate', label: 'Duplicate column' }, - { name: 'fillna', label: 'Fill null values' }, - { name: 'rename', label: 'Rename column' }, - { name: 'replace', label: 'Replace values' }, - { name: 'sort', label: 'Sort values' }, - ], - }, +export const CATEGORY_BUTTONS: ButtonDef[] = [ + { category: 'add', enable: true, icon: 'plus', label: 'Add' }, + { category: 'filter', enable: true, icon: 'filter', label: 'Filter' }, + { category: 'aggregate', enable: true, icon: 'code-branch', label: 'Aggregate' }, + { category: 'compute', enable: true, icon: 'calculator', label: 'Compute' }, + { category: 'text', enable: true, icon: 'font', label: 'Text' }, + { category: 'date', enable: true, icon: 'calendar', label: 'Date' }, + { category: 'reshape', enable: true, icon: 'draw-polygon', label: 'Reshape' }, + { category: 'combine', enable: true, icon: 'object-group', label: 'Combine' }, + { category: 'geo', enable: true, icon: 'map-marked-alt', label: 'Geo' }, + { category: 'other_actions', enable: false, icon: '', label: 'Others actions' }, ]; -export const CATEGORY_BUTTONS: ButtonDef[] = [ - { - category: 'add', - enable: true, - icon: 'plus', - label: 'Add', - }, - { - category: 'filter', - enable: true, - icon: 'filter', - label: 'Filter', - }, - { - category: 'aggregate', - enable: true, - icon: 'code-branch', - label: 'Aggregate', - }, - { - category: 'compute', - enable: true, - icon: 'calculator', - label: 'Compute', - }, - { - category: 'text', - enable: true, - icon: 'font', - label: 'Text', - }, - { - category: 'date', - enable: true, - icon: 'calendar', - label: 'Date', - }, - { - category: 'reshape', - enable: true, - icon: 'draw-polygon', - label: 'Reshape', - }, - { - category: 'combine', - enable: true, - icon: 'object-group', - label: 'Combine', - }, - { - category: 'geo', - enable: true, - icon: 'map-marked-alt', - label: 'Geo', - }, +export const COLUMN_MAIN_ACTIONS: PipelineStepName[] = ['rename', 'duplicate', 'delete']; +export const COLUMN_OTHER_ACTIONS: PipelineStepName[] = [ + 'filter', + 'top', + 'fillna', + 'replace', + 'sort', + 'trim', + 'uniquegroups', + 'statistics', ]; +export const COLUMN_TYPES = { + integer: { icon: '123', label: 'Integer' }, + float: { icon: '1.2', label: 'Float' }, + text: { icon: 'ABC', label: 'Text' }, + date: { icon: 'calendar-alt', label: 'Date' }, + boolean: { icon: 'check', label: 'Boolean' }, +}; export const POPOVER_ALIGN = { CENTER: 'center', diff --git a/ui/src/main.ts b/ui/src/main.ts index d2d831e348..aa94b25fd8 100644 --- a/ui/src/main.ts +++ b/ui/src/main.ts @@ -21,6 +21,16 @@ import DateRangeInput from './components/stepforms/widgets/DateComponents/DateRa import NewDateInput from './components/stepforms/widgets/DateComponents/NewDateInput.vue'; import Vqb from './components/Vqb.vue'; +// export steps constants to be able to migrate dataviewer +export { + STEP_LABELS, + ACTION_CATEGORIES, + CATEGORY_BUTTONS, + COLUMN_MAIN_ACTIONS, + COLUMN_OTHER_ACTIONS, + COLUMN_TYPES, +} from './components/constants'; + export { // All-in-one component Vqb, From a764f35d23c452f7746e06c45f2bc31a071aca4a Mon Sep 17 00:00:00 2001 From: Alice Date: Wed, 25 Sep 2024 10:17:12 +0200 Subject: [PATCH 2/6] feat(steps): remove store dependency from store widgets --- ui/src/components/FilterEditor.vue | 1 + ui/src/components/stepforms/ColumnPicker.vue | 12 +-- .../stepforms/widgets/Aggregation.vue | 5 +- .../components/stepforms/widgets/CumSum.vue | 11 ++- .../widgets/FilterSimpleCondition.vue | 24 +----- .../stepforms/widgets/JoinColumns.vue | 5 +- ui/src/components/stepforms/widgets/List.vue | 9 ++ .../components/stepforms/widgets/Rename.vue | 11 ++- .../stepforms/widgets/SortColumn.vue | 8 +- .../stepforms/widgets/TotalDimensions.vue | 5 +- ui/stories/ColumnPicker.stories.ts | 63 +++++++------- ui/stories/FilterEditor.stories.ts | 6 -- ui/stories/Multiselect.stories.ts | 8 +- ui/tests/unit/aggregation-widget.spec.ts | 25 ++---- ui/tests/unit/column-picker.spec.ts | 62 ++++--------- ui/tests/unit/cumsum-widget.spec.ts | 25 ++---- .../filter-simple-condition-widget.spec.ts | 86 +++---------------- ui/tests/unit/join-columns.spec.ts | 29 ++----- ui/tests/unit/rename-widget.spec.ts | 35 ++++---- ui/tests/unit/replace-widget.spec.ts | 15 +--- ui/tests/unit/sort-column-widget.spec.ts | 39 +++++---- ui/tests/unit/total-dimensions.spec.ts | 25 ++---- 22 files changed, 175 insertions(+), 334 deletions(-) diff --git a/ui/src/components/FilterEditor.vue b/ui/src/components/FilterEditor.vue index d8aae355d2..fbca3602a9 100644 --- a/ui/src/components/FilterEditor.vue +++ b/ui/src/components/FilterEditor.vue @@ -18,6 +18,7 @@ :errors="errors" :multi-variable="multiVariable" :columnTypes="columnTypes" + @setSelectedColumns="$emit('setSelectColumns', $event)" /> diff --git a/ui/src/components/stepforms/ColumnPicker.vue b/ui/src/components/stepforms/ColumnPicker.vue index dc0a51c044..1949ca4e90 100644 --- a/ui/src/components/stepforms/ColumnPicker.vue +++ b/ui/src/components/stepforms/ColumnPicker.vue @@ -21,8 +21,6 @@ import { Component, Prop, Watch } from 'vue-property-decorator'; import AutocompleteWidget from '@/components/stepforms/widgets/Autocomplete.vue'; import type { VariableDelimiters, VariablesBucket } from '@/lib/variables'; -import { Action, Getter, State } from 'pinia-class'; -import { VQBModule, type VQBActions } from '@/store'; @Component({ components: { AutocompleteWidget } }) export default class ColumnPicker extends Vue { @@ -55,9 +53,11 @@ export default class ColumnPicker extends Vue { @Prop({ default: true }) syncWithSelectedColumn!: boolean; - @Action(VQBModule) setSelectedColumns!: VQBActions['setSelectedColumns']; - @State(VQBModule) selectedColumns!: string[]; - @Getter(VQBModule) columnNames!: string[]; + @Prop({ default: () => [] }) + selectedColumns!: string[]; + + @Prop({ default: () => [] }) + columnNames!: string[]; created() { if (this.syncWithSelectedColumn && this.selectedColumns[0] && !this.value) { @@ -79,7 +79,7 @@ export default class ColumnPicker extends Vue { valueChanged(newColumn: string) { this.$emit('input', newColumn); if (this.syncWithSelectedColumn) { - this.setSelectedColumns({ column: newColumn }); + this.$emit('setSelectedColumns', { column: newColumn }); } } } diff --git a/ui/src/components/stepforms/widgets/Aggregation.vue b/ui/src/components/stepforms/widgets/Aggregation.vue index bc7b59feec..3b1a5b814a 100644 --- a/ui/src/components/stepforms/widgets/Aggregation.vue +++ b/ui/src/components/stepforms/widgets/Aggregation.vue @@ -31,8 +31,6 @@ import { Component, Prop, Vue } from 'vue-property-decorator'; import type { Aggregation } from '@/lib/steps'; import type { VariableDelimiters, VariablesBucket } from '@/lib/variables'; -import { VQBModule } from '@/store'; -import { Getter } from 'pinia-class'; import AutocompleteWidget from './Autocomplete.vue'; import MultiselectWidget from './Multiselect.vue'; @@ -63,7 +61,8 @@ export default class AggregationWidget extends Vue { @Prop() trustedVariableDelimiters?: VariableDelimiters; - @Getter(VQBModule) columnNames!: string[]; + @Prop({ type: Array, default: () => [] }) + columnNames!: string[]; get aggregationColumns() { return this.value.columns; diff --git a/ui/src/components/stepforms/widgets/CumSum.vue b/ui/src/components/stepforms/widgets/CumSum.vue index 29f03d567f..964cf59965 100644 --- a/ui/src/components/stepforms/widgets/CumSum.vue +++ b/ui/src/components/stepforms/widgets/CumSum.vue @@ -11,6 +11,9 @@ :available-variables="availableVariables" :variable-delimiters="variableDelimiters" :trusted-variable-delimiters="trustedVariableDelimiters" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="$emit('setSelectedColumns', $event)" /> [] }) + selectedColumns!: string[]; + + @Prop({ type: Array, default: () => [] }) + columnNames!: string[]; created() { if (isEqual(this.value, ['', ''])) { diff --git a/ui/src/components/stepforms/widgets/FilterSimpleCondition.vue b/ui/src/components/stepforms/widgets/FilterSimpleCondition.vue index 71a31482c7..80eb1b1b2d 100644 --- a/ui/src/components/stepforms/widgets/FilterSimpleCondition.vue +++ b/ui/src/components/stepforms/widgets/FilterSimpleCondition.vue @@ -61,13 +61,11 @@ import InputTextWidget from '@/components/stepforms/widgets/InputText.vue'; import type { ColumnTypeMapping } from '@/lib/dataset'; import { keepCurrentValueIfArrayType, - keepCurrentValueIfCompatibleDate, keepCurrentValueIfCompatibleRelativeDate, keepCurrentValueIfCompatibleType, } from '@/lib/helpers'; import type { FilterSimpleCondition } from '@/lib/steps'; import type { VariableDelimiters, VariablesBucket } from '@/lib/variables'; -import { useVQBStore } from '@/store'; import InputDateWidget from './InputDate.vue'; import MultiInputTextWidget from './MultiInputText.vue'; @@ -136,6 +134,7 @@ export default defineComponent({ emits: { input: (_val: FilterSimpleCondition) => true, + setSelectedColumns: (_: { column: string }) => true, }, props: { @@ -188,27 +187,10 @@ export default defineComponent({ }, computed: { - store() { - return useVQBStore(); - }, - columnNamesFromStore(): string[] { - return this.store.columnNames; - }, - - featureFlags(): Record { - return this.store.featureFlags ?? {}; - }, - // Column names can be provided either in the store or via a prop // The prop takes priority over the store columnNames() { - if (this.columnNamesProp && this.columnNamesProp.length > 0) { - return this.columnNamesProp; - } else if (this.columnNamesFromStore && this.columnNamesFromStore.length > 0) { - return this.columnNamesFromStore; - } else { - return []; - } + return this.columnNamesProp ?? []; }, availableVariablesForInputWidget(): VariablesBucket | undefined { @@ -307,7 +289,7 @@ export default defineComponent({ updateStepColumn(newValue: string) { const updatedValue = { ...this.value }; updatedValue.column = newValue; - this.store.setSelectedColumns({ column: updatedValue.column }); + this.$emit('setSelectedColumns', { column: updatedValue.column }); this.$emit('input', updatedValue); }, }, diff --git a/ui/src/components/stepforms/widgets/JoinColumns.vue b/ui/src/components/stepforms/widgets/JoinColumns.vue index 874d24e90f..1381b8b060 100644 --- a/ui/src/components/stepforms/widgets/JoinColumns.vue +++ b/ui/src/components/stepforms/widgets/JoinColumns.vue @@ -46,8 +46,6 @@ import { Component, Prop, Vue } from 'vue-property-decorator'; import AutocompleteWidget from '@/components/stepforms/widgets/Autocomplete.vue'; import type { VariableDelimiters, VariablesBucket } from '@/lib/variables'; -import { VQBModule } from '@/store'; -import { Getter } from 'pinia-class'; import InputTextWidget from './InputText.vue'; @@ -80,7 +78,8 @@ export default class JoinColumns extends Vue { @Prop() trustedVariableDelimiters?: VariableDelimiters; - @Getter(VQBModule) columnNames!: string[]; + @Prop({ default: () => [] }) + columnNames!: string[]; @Prop() rightColumnNames?: string[] | null; // because initializing to undefined won't make it reactive diff --git a/ui/src/components/stepforms/widgets/List.vue b/ui/src/components/stepforms/widgets/List.vue index ba90d96f43..f6d2fc3585 100644 --- a/ui/src/components/stepforms/widgets/List.vue +++ b/ui/src/components/stepforms/widgets/List.vue @@ -21,6 +21,9 @@ @input="updateChildValue($event, index)" :data-path="`${dataPath}.${index}`" :errors="errors" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="$emit('setSelectedColumns', $event)" />
@@ -116,6 +119,12 @@ export default class ListWidget extends FormWidget { @Prop({ type: Boolean, default: false }) unstyledItems!: boolean; + @Prop({ type: Array, default: () => [] }) + columnNames!: string[]; + + @Prop({ type: Array, default: () => [] }) + selectedColumns!: string[]; + get children() { const valueCopy = [...this.value]; if (this.automaticNewField) { diff --git a/ui/src/components/stepforms/widgets/Rename.vue b/ui/src/components/stepforms/widgets/Rename.vue index ebcfe9acce..5a730568a0 100644 --- a/ui/src/components/stepforms/widgets/Rename.vue +++ b/ui/src/components/stepforms/widgets/Rename.vue @@ -11,6 +11,9 @@ :available-variables="availableVariables" :variable-delimiters="variableDelimiters" :trusted-variable-delimiters="trustedVariableDelimiters" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="$emit('setSelectedColumns', $event)" /> [] }) + selectedColumns!: string[]; + + @Prop({ default: () => [] }) + columnNames!: string[]; created() { if (isEqual(this.value, ['', ''])) { diff --git a/ui/src/components/stepforms/widgets/SortColumn.vue b/ui/src/components/stepforms/widgets/SortColumn.vue index cbc8bd1f51..fe80cca1fe 100644 --- a/ui/src/components/stepforms/widgets/SortColumn.vue +++ b/ui/src/components/stepforms/widgets/SortColumn.vue @@ -27,8 +27,6 @@ import type { ErrorObject } from 'ajv'; import { Component, Prop, Vue } from 'vue-property-decorator'; import type { SortColumnType } from '@/lib/steps'; -import { Action, Getter } from 'pinia-class'; -import { VQBModule, type VQBActions } from '@/store'; import AutocompleteWidget from './Autocomplete.vue'; @@ -54,15 +52,15 @@ export default class SortColumnWidget extends Vue { @Prop({ type: Array, default: () => [] }) errors!: ErrorObject[]; - @Getter(VQBModule) columnNames!: string[]; - @Action(VQBModule) setSelectedColumns!: VQBActions['setSelectedColumns']; + @Prop({ default: () => [] }) + columnNames!: string[]; get sortColumn() { return this.value.column; } set sortColumn(newValue) { - this.setSelectedColumns({ column: newValue }); + this.$emit('setSelectedColumns', { column: newValue }); this.update({ column: newValue, order: this.sortOrder, diff --git a/ui/src/components/stepforms/widgets/TotalDimensions.vue b/ui/src/components/stepforms/widgets/TotalDimensions.vue index 948e1455c9..9369c0f2d9 100644 --- a/ui/src/components/stepforms/widgets/TotalDimensions.vue +++ b/ui/src/components/stepforms/widgets/TotalDimensions.vue @@ -31,8 +31,6 @@ import { Component, Prop, Vue } from 'vue-property-decorator'; import AutocompleteWidget from '@/components/stepforms/widgets/Autocomplete.vue'; import type { TotalDimension } from '@/lib/steps'; import type { VariableDelimiters, VariablesBucket } from '@/lib/variables'; -import { VQBModule } from '@/store'; -import { Getter } from 'pinia-class'; import InputTextWidget from './InputText.vue'; @@ -65,7 +63,8 @@ export default class TotalDimensionsWidget extends Vue { @Prop() trustedVariableDelimiters?: VariableDelimiters; - @Getter(VQBModule) columnNames!: string[]; + @Prop({ default: () => [] }) + columnNames!: string[]; get totalColumn() { return this.value.totalColumn; diff --git a/ui/stories/ColumnPicker.stories.ts b/ui/stories/ColumnPicker.stories.ts index 45116e7a0e..5f4f248175 100644 --- a/ui/stories/ColumnPicker.stories.ts +++ b/ui/stories/ColumnPicker.stories.ts @@ -1,39 +1,38 @@ -import { action } from '@storybook/addon-actions'; -import type { Meta, StoryFn } from '@storybook/vue'; -import { createPinia, PiniaVuePlugin } from 'pinia'; -import Vue from 'vue'; +import type { Meta, StoryObj } from '@storybook/vue'; import ColumnPicker from '@/components/stepforms/ColumnPicker.vue'; -import { setupVQBStore } from '@/store'; - -Vue.use(PiniaVuePlugin); export default { component: ColumnPicker, -} as Meta; - -export const Empty: StoryFn = () => ({ - pinia: createPinia(), - - components: { - ColumnPicker, - }, - - template: ` - ; + +export const Default: StoryObj = { + render: (args, { argTypes }) => ({ + components: { ColumnPicker }, + props: Object.keys(argTypes), + template: ` - `, - - created: function () { - setupVQBStore({ - backendMessages: [], - dataset: { headers: [{ name: 'label' }, { name: 'value' }], data: [] }, - }); - }, - - methods: { - onInput: action('input'), + @setSelectedColumns="onSetSelectedColumns" + />`, + data(): { value?: string; selectedColumns: string[] } { + return { + value: undefined, + selectedColumns: [], + }; + }, + methods: { + onInput(value) { + this.value = value; + }, + onSetSelectedColumns({ column }) { + this.selectedColumns = [column]; + }, + }, + }), + args: { + columnNames: ['label', 'value'], }, -}); +}; diff --git a/ui/stories/FilterEditor.stories.ts b/ui/stories/FilterEditor.stories.ts index 06f7050df8..0774928ce8 100644 --- a/ui/stories/FilterEditor.stories.ts +++ b/ui/stories/FilterEditor.stories.ts @@ -1,20 +1,15 @@ import type { Meta, StoryFn } from '@storybook/vue'; -import { createPinia, PiniaVuePlugin } from 'pinia'; -import Vue from 'vue'; import FilterEditor from '@/components/FilterEditor.vue'; import type { ColumnTypeMapping } from '@/lib/dataset'; import type { FilterCondition } from '@/lib/steps'; import type { AvailableVariable, VariableDelimiters } from '@/lib/variables'; -Vue.use(PiniaVuePlugin); - export default { component: FilterEditor, } as Meta; export const Default: StoryFn = () => ({ - pinia: createPinia(), template: `
= () => ({ }); export const WithVariables: StoryFn = () => ({ - pinia: createPinia(), template: `
; export const Default: StoryFn = () => ({ - pinia: createPinia(), template: `
{{ filterTreeStringify }}
@@ -69,11 +65,11 @@ export const Default: StoryFn = () => ({ }); export const WithVariables: StoryFn = () => ({ - pinia: createPinia(), template: `
{ it('should instantiate', () => { - const wrapper = shallowMount(AggregationWidget, { pinia, localVue }); + const wrapper = shallowMount(AggregationWidget, { localVue }); expect(wrapper.exists()).toBeTruthy(); }); it('should have exactly two AutocompleteWidget components', () => { - const wrapper = shallowMount(AggregationWidget, { pinia, localVue }); + const wrapper = shallowMount(AggregationWidget, { localVue }); const autocompletetWrappers = wrapper.findAll('autocompletewidget-stub'); const multiselectWrappers = wrapper.findAll('multiselectwidget-stub'); expect(autocompletetWrappers.length).toEqual(1); @@ -26,20 +20,18 @@ describe('Widget AggregationWidget', () => { }); it('should instantiate a MultiselectWidget widget with proper options from the store', () => { - setupMockStore({ - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = shallowMount(AggregationWidget, { + localVue, + propsData: { + columnNames: ['columnA', 'columnB', 'columnC'], }, }); - const wrapper = shallowMount(AggregationWidget, { pinia, localVue }); const widgetMultiselect = wrapper.find('multiselectwidget-stub'); expect(widgetMultiselect.attributes('options')).toEqual('columnA,columnB,columnC'); }); it('should pass down the props to the MultiselectWidget value prop', async () => { const wrapper = shallowMount(AggregationWidget, { - pinia, localVue, propsData: { value: { columns: ['foo', 'bar'], newcolumns: [''], aggfunction: 'sum' } }, }); @@ -49,7 +41,6 @@ describe('Widget AggregationWidget', () => { it('should pass down the "aggfunction" prop to the second AutocompleteWidget value prop', () => { const wrapper = shallowMount(AggregationWidget, { - pinia, localVue, propsData: { value: { column: 'foo', newcolumn: '', aggfunction: 'avg' } }, }); @@ -59,7 +50,6 @@ describe('Widget AggregationWidget', () => { it('should emit "input" event on aggregation column update', async () => { const wrapper = shallowMount(AggregationWidget, { - pinia, localVue, propsData: { value: { columns: ['foo'], newcolumns: [''], aggfunction: 'sum' } }, }); @@ -72,7 +62,6 @@ describe('Widget AggregationWidget', () => { it('should emit "input" event on aggregation function update', async () => { const wrapper = shallowMount(AggregationWidget, { - pinia, localVue, propsData: { value: { columns: ['foo'], newcolumns: [''], aggfunction: 'sum' } }, }); diff --git a/ui/tests/unit/column-picker.spec.ts b/ui/tests/unit/column-picker.spec.ts index 76e574fa95..ff8900c9b7 100644 --- a/ui/tests/unit/column-picker.spec.ts +++ b/ui/tests/unit/column-picker.spec.ts @@ -1,75 +1,58 @@ -import { createTestingPinia } from '@pinia/testing'; import { createLocalVue, shallowMount } from '@vue/test-utils'; -import { PiniaVuePlugin } from 'pinia'; -import { describe, expect, it, vi } from 'vitest'; +import { describe, expect, it } from 'vitest'; import ColumnPicker from '@/components/stepforms/ColumnPicker.vue'; -import { setupMockStore } from './utils'; - const localVue = createLocalVue(); -localVue.use(PiniaVuePlugin); -const pinia = createTestingPinia({ createSpy: vi.fn, stubActions: false }); describe('Column Picker', () => { it('should instantiate', () => { - const wrapper = shallowMount(ColumnPicker, { pinia, localVue }); + const wrapper = shallowMount(ColumnPicker, { localVue }); expect(wrapper.exists()).toBeTruthy(); }); it('should have a widget autocomplete', () => { - const wrapper = shallowMount(ColumnPicker, { pinia, localVue }); + const wrapper = shallowMount(ColumnPicker, { localVue }); expect(wrapper.find('autocompletewidget-stub').exists()).toBeTruthy(); }); it('should instantiate an autocomplete widget with proper options from the store', () => { - setupMockStore({ - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = shallowMount(ColumnPicker, { + localVue, + propsData: { + columnNames: ['columnA', 'columnB', 'columnC'], }, }); - const wrapper = shallowMount(ColumnPicker, { pinia, localVue }); const selectWrapper = wrapper.find('autocompletewidget-stub'); expect(selectWrapper.attributes('options')).toEqual('columnA,columnB,columnC'); }); it('should set column when initial column value is set', () => { - setupMockStore({ - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], - }, - }); const wrapper = shallowMount(ColumnPicker, { - pinia, localVue, propsData: { value: 'columnA', + selectedColumns: ['columnA'], + columnNames: ['columnA', 'columnB', 'columnC'], }, }); expect(wrapper.find('autocompletewidget-stub').props().value).toEqual('columnA'); }); it('should update the column when a column is selected in the data table', async () => { - const store = setupMockStore({ - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], - }, - selectedColumns: ['columnA'], - }); const wrapper = shallowMount(ColumnPicker, { - pinia, localVue, + propsData: { + selectedColumns: ['columnA'], + columnNames: ['columnA', 'columnB', 'columnC'], + }, }); // On created, the selected column must be the one selected in the table expect(wrapper.emitted('input')[0][0]).toEqual('columnA'); // When selecting another column, the form should update - store.setSelectedColumns({ column: 'columnB' }); - expect(store.selectedColumns).toEqual(['columnB']); + wrapper.setProps({ selectedColumns: ['columnB'] }); await wrapper.vm.$nextTick(); expect(wrapper.emitted('input')[1][0]).toEqual('columnB'); @@ -77,21 +60,15 @@ describe('Column Picker', () => { // Note: we can't directly call wrapper.find('AutocompleteWidget-stub') because vue-test-utils would return the same vm as it's parent, because it's an only child, and therefore ties to the same HTML element wrapper.vm.$children[0].$emit('input', 'columnC'); expect(wrapper.emitted('input')[2][0]).toEqual('columnC'); - expect(store.selectedColumns).toEqual(['columnC']); + expect(wrapper.emitted().setSelectedColumns).toEqual([[{ column: 'columnC' }]]); }); it('should update the column when a column is selected in the data table when `syncWithSelectedColumn` is disabled', async () => { - const store = setupMockStore({ - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], - }, - selectedColumns: ['columnA'], - }); const wrapper = shallowMount(ColumnPicker, { - pinia, localVue, propsData: { + selectedColumns: ['columnA'], + columnNames: ['columnA', 'columnB', 'columnC'], syncWithSelectedColumn: false, }, }); @@ -101,13 +78,12 @@ describe('Column Picker', () => { expect(wrapper.emitted('input')).toBeUndefined(); // Nor on subsequent selections in the data table - store.setSelectedColumns({ column: 'columnB' }); - expect(store.selectedColumns).toEqual(['columnB']); + wrapper.setProps({ selectedColumns: ['columnB'] }); expect(wrapper.emitted('input')).toBeUndefined(); // When the form updates, the selection in the table should not change wrapper.vm.$children[0].$emit('input', 'columnC'); expect(wrapper.emitted('input')[0][0]).toEqual('columnC'); - expect(store.selectedColumns).toEqual(['columnB']); + expect(wrapper.emitted().setSelectedColumns).toBeUndefined(); }); }); diff --git a/ui/tests/unit/cumsum-widget.spec.ts b/ui/tests/unit/cumsum-widget.spec.ts index 3c5c247ae5..894a9404b8 100644 --- a/ui/tests/unit/cumsum-widget.spec.ts +++ b/ui/tests/unit/cumsum-widget.spec.ts @@ -1,24 +1,18 @@ -import { createTestingPinia } from '@pinia/testing'; import { createLocalVue, shallowMount } from '@vue/test-utils'; -import { PiniaVuePlugin } from 'pinia'; -import { describe, expect, it, vi } from 'vitest'; +import { describe, expect, it } from 'vitest'; import CumSumWidget from '@/components/stepforms/widgets/CumSum.vue'; -import { setupMockStore } from './utils'; - const localVue = createLocalVue(); -localVue.use(PiniaVuePlugin); -const pinia = createTestingPinia({ createSpy: vi.fn, stubActions: false }); describe('Widget CumSumWidget', () => { it('should instantiate', () => { - const wrapper = shallowMount(CumSumWidget, { pinia, localVue, sync: false }); + const wrapper = shallowMount(CumSumWidget, { localVue, sync: false }); expect(wrapper.exists()).toBeTruthy(); }); it('should have exactly 1 ColumnPicker and 1 InputTextWidget components', () => { - const wrapper = shallowMount(CumSumWidget, { pinia, localVue, sync: false }); + const wrapper = shallowMount(CumSumWidget, { localVue, sync: false }); const columnPickerWrappers = wrapper.findAll('ColumnPicker-stub'); const inputTextWidgetWrappers = wrapper.findAll('InputTextWidget-stub'); expect(columnPickerWrappers.length).toEqual(1); @@ -27,7 +21,6 @@ describe('Widget CumSumWidget', () => { it('should pass down the properties to the input components', () => { const wrapper = shallowMount(CumSumWidget, { - pinia, localVue, sync: false, propsData: { @@ -42,7 +35,6 @@ describe('Widget CumSumWidget', () => { it('should emit value on created if values are empty', () => { const wrapper = shallowMount(CumSumWidget, { - pinia, localVue, sync: false, }); @@ -54,7 +46,6 @@ describe('Widget CumSumWidget', () => { propsData: { value: ['lolilol', 'yolo'], }, - pinia, localVue, sync: false, }); @@ -66,7 +57,6 @@ describe('Widget CumSumWidget', () => { propsData: { value: ['yolo', 'bim'], }, - pinia, localVue, sync: false, }); @@ -79,7 +69,6 @@ describe('Widget CumSumWidget', () => { propsData: { value: ['yolo', 'bim'], }, - pinia, localVue, sync: false, }); @@ -89,10 +78,8 @@ describe('Widget CumSumWidget', () => { describe('Warning', () => { it('should report a warning when newColumn is an already existing column name', () => { - setupMockStore({ dataset: { headers: [{ name: 'columnA' }], data: [] } }); const wrapper = shallowMount(CumSumWidget, { - propsData: { value: ['yolo', 'columnA'] }, - pinia, + propsData: { value: ['yolo', 'columnA'], columnNames: ['columnA'] }, localVue, sync: false, }); @@ -102,10 +89,8 @@ describe('Widget CumSumWidget', () => { }); it('should not report any warning if newColumn is not an already existing column name', () => { - setupMockStore({ dataset: { headers: [{ name: 'columnA' }], data: [] } }); const wrapper = shallowMount(CumSumWidget, { - propsData: { value: ['yolo', 'columnB'] }, - pinia, + propsData: { value: ['yolo', 'columnB'], columnNames: ['columnA'] }, localVue, sync: false, }); diff --git a/ui/tests/unit/filter-simple-condition-widget.spec.ts b/ui/tests/unit/filter-simple-condition-widget.spec.ts index f8b480d32a..b8955a10c7 100644 --- a/ui/tests/unit/filter-simple-condition-widget.spec.ts +++ b/ui/tests/unit/filter-simple-condition-widget.spec.ts @@ -1,7 +1,5 @@ -import { createTestingPinia } from '@pinia/testing'; import type { Wrapper } from '@vue/test-utils'; import { createLocalVue, mount, shallowMount } from '@vue/test-utils'; -import { PiniaVuePlugin } from 'pinia'; import { describe, expect, it, vi } from 'vitest'; import AutocompleteWidget from '@/components/stepforms/widgets/Autocomplete.vue'; @@ -9,11 +7,7 @@ import FilterSimpleConditionWidget from '@/components/stepforms/widgets/FilterSi import InputTextWidget from '@/components/stepforms/widgets/InputText.vue'; import MultiInputTextWidget from '@/components/stepforms/widgets/MultiInputText.vue'; -import { setupMockStore } from './utils'; - const localVue = createLocalVue(); -localVue.use(PiniaVuePlugin); -const pinia = createTestingPinia({ createSpy: vi.fn, stubActions: false }); const AVAILABLE_VARIABLES_SAMPLE = [ { @@ -40,12 +34,12 @@ const AVAILABLE_VARIABLES_SAMPLE = [ describe('Widget FilterSimpleCondition', () => { it('should instantiate', () => { - const wrapper = shallowMount(FilterSimpleConditionWidget, { pinia, localVue }); + const wrapper = shallowMount(FilterSimpleConditionWidget, { localVue }); expect(wrapper.exists()).toBeTruthy(); }); it('should have exactly 3 input components', () => { - const wrapper = shallowMount(FilterSimpleConditionWidget, { pinia, localVue }); + const wrapper = shallowMount(FilterSimpleConditionWidget, { localVue }); const autocompleteWrappers = wrapper.findAll('autocompletewidget-stub'); expect(autocompleteWrappers.length).toEqual(2); const inputtextWrappers = wrapper.findAll('inputtextwidget-stub'); @@ -54,7 +48,6 @@ describe('Widget FilterSimpleCondition', () => { it('should have exactly have a MultiInputTextWidget if operator is "in" or "nin"', async () => { const wrapper = shallowMount(FilterSimpleConditionWidget, { - pinia, localVue, propsData: { value: { column: 'foo', value: [], operator: 'in' }, @@ -67,7 +60,6 @@ describe('Widget FilterSimpleCondition', () => { it('should not have any input component if operator is "isnull" or "not null"', async () => { const wrapper = shallowMount(FilterSimpleConditionWidget, { - pinia, localVue, propsData: { value: { column: 'foo', value: [], operator: 'isnull' }, @@ -80,22 +72,8 @@ describe('Widget FilterSimpleCondition', () => { expect(multinnputtextWrappers.exists()).toBeFalsy(); }); - it('should instantiate a widgetAutocomplete widget with column names from the store', () => { - setupMockStore({ - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], - }, - }); - const wrapper = shallowMount(FilterSimpleConditionWidget, { pinia, localVue }); - const widgetWrappers = wrapper.findAll('autocompletewidget-stub'); - expect(widgetWrappers.at(0).attributes('options')).toEqual('columnA,columnB,columnC'); - }); - it('should instantiate a widgetAutocomplete widget with column names from the prop', () => { - setupMockStore({}); const wrapper = shallowMount(FilterSimpleConditionWidget, { - pinia, localVue, propsData: { columnNamesProp: ['columnA', 'columnB', 'columnC'], @@ -106,9 +84,7 @@ describe('Widget FilterSimpleCondition', () => { }); it('should instantiate a widgetAutocomplete widget with nothing', () => { - setupMockStore({}); const wrapper = shallowMount(FilterSimpleConditionWidget, { - pinia, localVue, }); const widgetWrappers = wrapper.findAll('autocompletewidget-stub'); @@ -117,7 +93,6 @@ describe('Widget FilterSimpleCondition', () => { it('should pass down the "column" prop to the first AutocompleteWidget value prop', async () => { const wrapper = shallowMount(FilterSimpleConditionWidget, { - pinia, localVue, propsData: { value: { column: 'foo', value: '', operator: 'eq' }, @@ -130,7 +105,6 @@ describe('Widget FilterSimpleCondition', () => { it('should pass down the "operator" prop to the second AutocompleteWidget value prop', async () => { const wrapper = shallowMount(FilterSimpleConditionWidget, { - pinia, localVue, propsData: { value: { column: 'foo', value: [], operator: 'nin' }, @@ -147,7 +121,6 @@ describe('Widget FilterSimpleCondition', () => { it('should emit a new condition with the correct type of value when changing the operator', () => { const wrapper = shallowMount(FilterSimpleConditionWidget, { - pinia, localVue, propsData: { dataPath: '.condition' }, sync: false, @@ -171,7 +144,6 @@ describe('Widget FilterSimpleCondition', () => { it('should the widget accordingly when changing the operator', async () => { const wrapper = shallowMount(FilterSimpleConditionWidget, { - pinia, localVue, propsData: { dataPath: '.condition' }, sync: false, @@ -207,7 +179,6 @@ describe('Widget FilterSimpleCondition', () => { it('should emit input when changing the column', async () => { const wrapper = shallowMount(FilterSimpleConditionWidget, { - pinia, localVue, propsData: { dataPath: '.condition' }, sync: false, @@ -222,7 +193,6 @@ describe('Widget FilterSimpleCondition', () => { it('should emit input when changing the value', async () => { const wrapper = shallowMount(FilterSimpleConditionWidget, { - pinia, localVue, propsData: { dataPath: '.condition' }, sync: false, @@ -236,39 +206,27 @@ describe('Widget FilterSimpleCondition', () => { }); it('should update selectedColumn when column is changed', async () => { - const store = setupMockStore({ - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], - }, - selectedColumns: ['columnA'], - }); const wrapper = mount(FilterSimpleConditionWidget, { propsData: { + columnNamesProp: ['columnA', 'columnB', 'columnC'], + selectedColumns: ['columnA'], value: { column: 'columnA', value: 'bar', operator: 'eq' }, }, - pinia, localVue, sync: false, }); wrapper.find(AutocompleteWidget).vm.$emit('input', 'columnB'); await wrapper.vm.$nextTick(); - expect(store.selectedColumns).toEqual(['columnB']); + expect(wrapper.emitted().setSelectedColumns).toEqual([[{ column: 'columnB' }]]); }); it('should keep value when operator is changed and types match', async () => { - setupMockStore({ - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], - }, - selectedColumns: ['columnA'], - }); const wrapper = mount(FilterSimpleConditionWidget, { propsData: { value: { column: 'columnA', value: 'bar', operator: 'eq' }, + columnNamesProp: ['columnA', 'columnB', 'columnC'], + selectedColumns: ['columnA'], }, - pinia, localVue, sync: false, }); @@ -280,18 +238,12 @@ describe('Widget FilterSimpleCondition', () => { }); it("should replace value with default when operator is changed and types don't match", async () => { - setupMockStore({ - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], - }, - selectedColumns: ['columnA'], - }); const wrapper = mount(FilterSimpleConditionWidget, { propsData: { value: { column: 'columnA', value: 'bar', operator: 'eq' }, + columnNamesProp: ['columnA', 'columnB', 'columnC'], + selectedColumns: ['columnA'], }, - pinia, localVue, sync: false, }); @@ -306,21 +258,15 @@ describe('Widget FilterSimpleCondition', () => { mountType: typeof mount | typeof shallowMount, customProps: any = {}, ) => { - setupMockStore({ - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], - }, - selectedColumns: ['columnA'], - }); wrapper = mountType(FilterSimpleConditionWidget, { propsData: { value: { column: 'columnA', value: new Date('2021-01-01'), operator: 'from' }, columnTypes: { columnA: 'date' }, availableVariables: AVAILABLE_VARIABLES_SAMPLE, + columnNamesProp: ['columnA', 'columnB', 'columnC'], + selectedColumns: ['columnA'], ...customProps, }, - pinia, localVue, sync: false, }); @@ -412,20 +358,14 @@ describe('Widget FilterSimpleCondition', () => { describe('date column and date (using an invalid operator)', () => { let wrapper: Wrapper; const createWrapper = (operator: string) => { - setupMockStore({ - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], - }, - selectedColumns: ['columnA'], - }); wrapper = shallowMount(FilterSimpleConditionWidget, { propsData: { value: { column: 'columnA', value: '', operator }, columnTypes: { columnA: 'date' }, + columnNamesProp: ['columnA', 'columnB', 'columnC'], + selectedColumns: ['columnA'], availableVariables: AVAILABLE_VARIABLES_SAMPLE, }, - pinia, localVue, sync: false, }); diff --git a/ui/tests/unit/join-columns.spec.ts b/ui/tests/unit/join-columns.spec.ts index a7805c5086..4f3ff315bc 100644 --- a/ui/tests/unit/join-columns.spec.ts +++ b/ui/tests/unit/join-columns.spec.ts @@ -1,24 +1,18 @@ -import { createTestingPinia } from '@pinia/testing'; import { createLocalVue, shallowMount } from '@vue/test-utils'; -import { PiniaVuePlugin } from 'pinia'; -import { describe, expect, it, vi } from 'vitest'; +import { describe, expect, it } from 'vitest'; import JoinColumns from '@/components/stepforms/widgets/JoinColumns.vue'; -import { setupMockStore } from './utils'; - const localVue = createLocalVue(); -localVue.use(PiniaVuePlugin); -const pinia = createTestingPinia({ createSpy: vi.fn, stubActions: false }); describe('Widget JoinColumnsWidget', () => { it('should instantiate', () => { - const wrapper = shallowMount(JoinColumns, { pinia, localVue }); + const wrapper = shallowMount(JoinColumns, { localVue }); expect(wrapper.exists()).toBeTruthy(); }); it('should have exactly 2 input components', () => { - const wrapper = shallowMount(JoinColumns, { pinia, localVue }); + const wrapper = shallowMount(JoinColumns, { localVue }); const rightComponentWrappers = wrapper.findAll('.rightOn'); const leftComponentWrappers = wrapper.findAll('.leftOn'); expect(rightComponentWrappers.length).toEqual(1); @@ -26,13 +20,12 @@ describe('Widget JoinColumnsWidget', () => { }); it('should suggest the columns of the actual dataset in the left widget', () => { - setupMockStore({ - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = shallowMount(JoinColumns, { + localVue, + propsData: { + columnNames: ['columnA', 'columnB', 'columnC'], }, }); - const wrapper = shallowMount(JoinColumns, { pinia, localVue }); const leftWidgetWrapper = wrapper.find('.leftOn'); expect(leftWidgetWrapper.props().options).toEqual(['columnA', 'columnB', 'columnC']); }); @@ -42,7 +35,6 @@ describe('Widget JoinColumnsWidget', () => { propsData: { value: ['toto', 'tata'], }, - pinia, localVue, sync: false, }); @@ -55,7 +47,6 @@ describe('Widget JoinColumnsWidget', () => { propsData: { value: ['toto', 'tata'], }, - pinia, localVue, sync: false, }); @@ -68,7 +59,6 @@ describe('Widget JoinColumnsWidget', () => { propsData: { rightColumnNames: ['meow', 'plop'], }, - pinia, localVue, sync: false, }); @@ -78,7 +68,7 @@ describe('Widget JoinColumnsWidget', () => { }); it('should let user freely input if right dataset column names are not provided', () => { - const wrapper = shallowMount(JoinColumns, { pinia, localVue, sync: false }); + const wrapper = shallowMount(JoinColumns, { localVue, sync: false }); const rightWidgetWrapper = wrapper.find('.rightOn'); expect(rightWidgetWrapper.is('InputTextWidget-stub')).toBe(true); }); @@ -88,7 +78,6 @@ describe('Widget JoinColumnsWidget', () => { propsData: { value: ['toto', 'tata'], }, - pinia, localVue, sync: false, }); @@ -105,7 +94,6 @@ describe('Widget JoinColumnsWidget', () => { propsData: { value: ['toto', 'tata'], }, - pinia, localVue, sync: false, }); @@ -122,7 +110,6 @@ describe('Widget JoinColumnsWidget', () => { propsData: { value: ['toto', ''], }, - pinia, localVue, sync: false, }); diff --git a/ui/tests/unit/rename-widget.spec.ts b/ui/tests/unit/rename-widget.spec.ts index c69e6469b1..1f1435f2b6 100644 --- a/ui/tests/unit/rename-widget.spec.ts +++ b/ui/tests/unit/rename-widget.spec.ts @@ -1,24 +1,18 @@ -import { createTestingPinia } from '@pinia/testing'; import { createLocalVue, shallowMount } from '@vue/test-utils'; -import { PiniaVuePlugin } from 'pinia'; -import { describe, expect, it, vi } from 'vitest'; +import { describe, expect, it } from 'vitest'; import RenameWidget from '@/components/stepforms/widgets/Rename.vue'; -import { setupMockStore } from './utils'; - const localVue = createLocalVue(); -localVue.use(PiniaVuePlugin); -const pinia = createTestingPinia({ createSpy: vi.fn, stubActions: false }); describe('Widget RenameWidget', () => { it('should instantiate', () => { - const wrapper = shallowMount(RenameWidget, { pinia, localVue, sync: false }); + const wrapper = shallowMount(RenameWidget, { localVue, sync: false }); expect(wrapper.exists()).toBeTruthy(); }); it('should have exactly 1 ColumnPicker and 1 InputTextWidget components', () => { - const wrapper = shallowMount(RenameWidget, { pinia, localVue, sync: false }); + const wrapper = shallowMount(RenameWidget, { localVue, sync: false }); const columnPickerWrappers = wrapper.findAll('ColumnPicker-stub'); const inputTextWidgetWrappers = wrapper.findAll('InputTextWidget-stub'); expect(columnPickerWrappers.length).toEqual(1); @@ -27,10 +21,10 @@ describe('Widget RenameWidget', () => { it('should pass down the properties to the input components', () => { const wrapper = shallowMount(RenameWidget, { - pinia, localVue, sync: false, propsData: { + columnNames: ['foo'], value: ['foo', 'bar'], }, }); @@ -42,7 +36,6 @@ describe('Widget RenameWidget', () => { it('should emit value on created if values are empty', () => { const wrapper = shallowMount(RenameWidget, { - pinia, localVue, sync: false, }); @@ -52,9 +45,9 @@ describe('Widget RenameWidget', () => { it('should not emit value on created if there is some value', () => { const wrapper = shallowMount(RenameWidget, { propsData: { + columnNames: ['lolilol'], value: ['lolilol', 'yolo'], }, - pinia, localVue, sync: false, }); @@ -64,9 +57,9 @@ describe('Widget RenameWidget', () => { it('should emit "input" event with correct updated values when input columnToRename is updated', () => { const wrapper = shallowMount(RenameWidget, { propsData: { + columnNames: ['yolo'], value: ['yolo', 'bim'], }, - pinia, localVue, sync: false, }); @@ -77,9 +70,9 @@ describe('Widget RenameWidget', () => { it('should emit "input" event with correct updated values when input newColumnToRename is updated', () => { const wrapper = shallowMount(RenameWidget, { propsData: { + columnNames: ['yolo'], value: ['yolo', 'bim'], }, - pinia, localVue, sync: false, }); @@ -89,10 +82,11 @@ describe('Widget RenameWidget', () => { describe('Warning', () => { it('should report a warning when newColumn is an already existing column name', () => { - setupMockStore({ dataset: { headers: [{ name: 'columnA' }], data: [] } }); const wrapper = shallowMount(RenameWidget, { - propsData: { value: ['yolo', 'columnA'] }, - pinia, + propsData: { + columnNames: ['columnA'], + value: ['yolo', 'columnA'], + }, localVue, sync: false, }); @@ -102,10 +96,11 @@ describe('Widget RenameWidget', () => { }); it('should not report any warning if newColumn is not an already existing column name', () => { - setupMockStore({ dataset: { headers: [{ name: 'columnA' }], data: [] } }); const wrapper = shallowMount(RenameWidget, { - propsData: { value: ['yolo', 'columnB'] }, - pinia, + propsData: { + columnNames: ['columnA'], + value: ['yolo', 'columnB'], + }, localVue, sync: false, }); diff --git a/ui/tests/unit/replace-widget.spec.ts b/ui/tests/unit/replace-widget.spec.ts index 532fc0741d..abd6b605f8 100644 --- a/ui/tests/unit/replace-widget.spec.ts +++ b/ui/tests/unit/replace-widget.spec.ts @@ -1,29 +1,24 @@ -import { createTestingPinia } from '@pinia/testing'; import { createLocalVue, shallowMount } from '@vue/test-utils'; -import { PiniaVuePlugin } from 'pinia'; -import { describe, expect, it, vi } from 'vitest'; +import { describe, expect, it } from 'vitest'; import ReplaceWidget from '@/components/stepforms/widgets/Replace.vue'; const localVue = createLocalVue(); -localVue.use(PiniaVuePlugin); -const pinia = createTestingPinia({ createSpy: vi.fn, stubActions: false }); describe('Widget ReplaceWidget', () => { it('should instantiate', () => { - const wrapper = shallowMount(ReplaceWidget, { pinia, localVue, sync: false }); + const wrapper = shallowMount(ReplaceWidget, { localVue, sync: false }); expect(wrapper.exists()).toBeTruthy(); }); it('should have exactly two InputTextWidget components', () => { - const wrapper = shallowMount(ReplaceWidget, { pinia, localVue, sync: false }); + const wrapper = shallowMount(ReplaceWidget, { localVue, sync: false }); const widgetWrappers = wrapper.findAll('inputtextwidget-stub'); expect(widgetWrappers.length).toEqual(2); }); it('should pass down the properties to the input components', () => { const wrapper = shallowMount(ReplaceWidget, { - pinia, localVue, sync: false, propsData: { @@ -37,7 +32,6 @@ describe('Widget ReplaceWidget', () => { it('should emit value on created if values are empty', () => { const wrapper = shallowMount(ReplaceWidget, { - pinia, localVue, sync: false, }); @@ -49,7 +43,6 @@ describe('Widget ReplaceWidget', () => { propsData: { value: ['lolilol', 'yolo'], }, - pinia, localVue, sync: false, }); @@ -61,7 +54,6 @@ describe('Widget ReplaceWidget', () => { propsData: { value: ['yolo', 'bim'], }, - pinia, localVue, sync: false, }); @@ -74,7 +66,6 @@ describe('Widget ReplaceWidget', () => { propsData: { value: ['yolo', 'bim'], }, - pinia, localVue, sync: false, }); diff --git a/ui/tests/unit/sort-column-widget.spec.ts b/ui/tests/unit/sort-column-widget.spec.ts index f7565e7082..aaa3e0bbe1 100644 --- a/ui/tests/unit/sort-column-widget.spec.ts +++ b/ui/tests/unit/sort-column-widget.spec.ts @@ -1,42 +1,40 @@ -import { createTestingPinia } from '@pinia/testing'; import { createLocalVue, shallowMount } from '@vue/test-utils'; -import { PiniaVuePlugin } from 'pinia'; -import { describe, expect, it, vi } from 'vitest'; +import { describe, expect, it } from 'vitest'; import SortColumnWidget from '@/components/stepforms/widgets/SortColumn.vue'; -import { setupMockStore } from './utils'; - const localVue = createLocalVue(); -localVue.use(PiniaVuePlugin); -const pinia = createTestingPinia({ createSpy: vi.fn, stubActions: false }); describe('Widget sort column', () => { it('should instantiate', () => { - const wrapper = shallowMount(SortColumnWidget, { pinia, localVue }); + const wrapper = shallowMount(SortColumnWidget, { localVue }); expect(wrapper.exists()).toBeTruthy(); }); it('should have exactly two AutocompleteWidget components', () => { - const wrapper = shallowMount(SortColumnWidget, { pinia, localVue }); + const wrapper = shallowMount(SortColumnWidget, { localVue }); const widgetWrappers = wrapper.findAll('autocompletewidget-stub'); expect(widgetWrappers.length).toEqual(2); }); it('should instantiate an widgetAutocomplete with proper options from the store', () => { - setupMockStore({ - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = shallowMount(SortColumnWidget, { + localVue, + propsData: { + columnNames: ['columnA', 'columnB', 'columnC'], }, }); - const wrapper = shallowMount(SortColumnWidget, { pinia, localVue }); const widgetWrappers = wrapper.findAll('autocompletewidget-stub'); expect(widgetWrappers.at(0).attributes('options')).toEqual('columnA,columnB,columnC'); }); it('should pass down the "column" prop to the first AutocompleteWidget value prop', async () => { - const wrapper = shallowMount(SortColumnWidget, { pinia, localVue }); + const wrapper = shallowMount(SortColumnWidget, { + localVue, + propsData: { + columnNames: ['foo'], + }, + }); wrapper.setProps({ value: { column: 'foo', order: 'asc' } }); await localVue.nextTick(); const widgetWrappers = wrapper.findAll('AutocompleteWidget-stub'); @@ -44,7 +42,12 @@ describe('Widget sort column', () => { }); it('should pass down the "order" prop to the second AutocompleteWidget value prop', async () => { - const wrapper = shallowMount(SortColumnWidget, { pinia, localVue }); + const wrapper = shallowMount(SortColumnWidget, { + localVue, + propsData: { + columnNames: ['foo'], + }, + }); wrapper.setProps({ value: { column: 'foo', order: 'desc' } }); await localVue.nextTick(); const widgetWrappers = wrapper.findAll('AutocompleteWidget-stub'); @@ -53,10 +56,10 @@ describe('Widget sort column', () => { it('should emit "input" event on "sortColumn" update with correct properties', () => { const wrapper = shallowMount(SortColumnWidget, { - pinia, localVue, sync: false, propsData: { + columnNames: ['bar'], value: { column: 'bar', order: 'desc' }, }, }); @@ -67,10 +70,10 @@ describe('Widget sort column', () => { it('should emit "input" event on "sortOrder" update with correct properties', () => { const wrapper = shallowMount(SortColumnWidget, { - pinia, localVue, sync: false, propsData: { + columnNames: ['bar'], value: { column: 'bar', order: 'desc' }, }, }); diff --git a/ui/tests/unit/total-dimensions.spec.ts b/ui/tests/unit/total-dimensions.spec.ts index 2d6d28b48f..a61e0ba1b8 100644 --- a/ui/tests/unit/total-dimensions.spec.ts +++ b/ui/tests/unit/total-dimensions.spec.ts @@ -1,24 +1,18 @@ -import { createTestingPinia } from '@pinia/testing'; import { createLocalVue, shallowMount } from '@vue/test-utils'; -import { PiniaVuePlugin } from 'pinia'; -import { describe, expect, it, vi } from 'vitest'; +import { describe, expect, it } from 'vitest'; import TotalDimensions from '@/components/stepforms/widgets/TotalDimensions.vue'; -import { setupMockStore } from './utils'; - const localVue = createLocalVue(); -localVue.use(PiniaVuePlugin); -const pinia = createTestingPinia({ createSpy: vi.fn, stubActions: false }); describe('Widget AggregationWidget', () => { it('should instantiate', () => { - const wrapper = shallowMount(TotalDimensions, { pinia, localVue }); + const wrapper = shallowMount(TotalDimensions, { localVue }); expect(wrapper.exists()).toBeTruthy(); }); it('should have exactly 2 input components', () => { - const wrapper = shallowMount(TotalDimensions, { pinia, localVue }); + const wrapper = shallowMount(TotalDimensions, { localVue }); const autocompleteWrappers = wrapper.findAll('autocompletewidget-stub'); expect(autocompleteWrappers.length).toEqual(1); const inputtextWrappers = wrapper.findAll('inputtextwidget-stub'); @@ -26,13 +20,12 @@ describe('Widget AggregationWidget', () => { }); it('should instantiate a widgetAutocomplete widget with proper options from the store', () => { - setupMockStore({ - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = shallowMount(TotalDimensions, { + localVue, + propsData: { + columnNames: ['columnA', 'columnB', 'columnC'], }, }); - const wrapper = shallowMount(TotalDimensions, { pinia, localVue }); const autocompleteWrapper = wrapper.find('autocompletewidget-stub'); expect(autocompleteWrapper.attributes('options')).toEqual('columnA,columnB,columnC'); }); @@ -42,7 +35,6 @@ describe('Widget AggregationWidget', () => { propsData: { value: { totalColumn: 'toto', totalRowsLabel: 'tata' }, }, - pinia, localVue, sync: false, }); @@ -55,7 +47,6 @@ describe('Widget AggregationWidget', () => { propsData: { value: { totalColumn: 'toto', totalRowsLabel: 'tata' }, }, - pinia, localVue, sync: false, }); @@ -68,7 +59,6 @@ describe('Widget AggregationWidget', () => { propsData: { value: { totalColumn: 'toto', totalRowsLabel: 'tata' }, }, - pinia, localVue, sync: false, }); @@ -85,7 +75,6 @@ describe('Widget AggregationWidget', () => { propsData: { value: { totalColumn: 'toto', totalRowsLabel: 'tata' }, }, - pinia, localVue, sync: false, }); From b17fe36339337ecd186dfb4d4134e4d256ad6829 Mon Sep 17 00:00:00 2001 From: Alice Date: Wed, 25 Sep 2024 10:21:06 +0200 Subject: [PATCH 3/6] feat(steps): remove store dependency from store steps --- .../stepforms/AbsoluteValueStepForm.vue | 12 +- .../stepforms/AddMissingDatesStepForm.vue | 11 +- .../stepforms/AddTextColumnStepForm.vue | 8 - .../stepforms/AddTotalRowsStepForm.vue | 6 + .../stepforms/AggregateStepForm.vue | 12 +- .../components/stepforms/AppendStepForm.vue | 5 - .../components/stepforms/ArgmaxStepForm.vue | 11 +- .../components/stepforms/ArgminStepForm.vue | 11 +- .../stepforms/CompareTextStepForm.vue | 14 +- .../stepforms/ComputeDurationStepForm.vue | 14 +- .../stepforms/ConcatenateStepForm.vue | 11 +- .../components/stepforms/CumSumStepForm.vue | 14 +- .../components/stepforms/CustomStepForm.vue | 3 - .../stepforms/DateExtractStepForm.vue | 5 +- .../components/stepforms/DissolveStepForm.vue | 11 +- .../components/stepforms/DomainStepForm.vue | 6 +- .../stepforms/DuplicateColumnStepForm.vue | 3 + .../stepforms/EvolutionStepForm.vue | 14 +- .../components/stepforms/FillnaStepForm.vue | 5 - .../components/stepforms/FilterStepForm.vue | 11 +- .../components/stepforms/FormulaStepForm.vue | 8 - .../components/stepforms/FromDateStepForm.vue | 7 +- .../stepforms/HierarchyStepForm.vue | 3 + .../stepforms/IfThenElseStepForm.vue | 10 -- ui/src/components/stepforms/JoinStepForm.vue | 10 +- .../stepforms/MovingAverageStepForm.vue | 14 +- .../stepforms/PercentageStepForm.vue | 3 + ui/src/components/stepforms/PivotStepForm.vue | 11 +- ui/src/components/stepforms/RankStepForm.vue | 11 +- .../components/stepforms/RenameStepForm.vue | 11 +- .../components/stepforms/ReplaceStepForm.vue | 17 +- .../stepforms/ReplaceTextStepForm.vue | 13 +- .../components/stepforms/RollupStepForm.vue | 3 + ui/src/components/stepforms/SortStepForm.vue | 3 + ui/src/components/stepforms/SplitStepForm.vue | 11 +- .../stepforms/StatisticsStepForm.vue | 3 + ui/src/components/stepforms/StepForm.vue | 64 +++++--- .../stepforms/SubstringStepForm.vue | 3 + .../components/stepforms/ToDateStepForm.vue | 7 +- .../components/stepforms/ToLowerStepForm.vue | 3 + .../components/stepforms/ToUpperStepForm.vue | 3 + ui/src/components/stepforms/TopStepForm.vue | 11 +- .../components/stepforms/UnpivotStepForm.vue | 9 - .../stepforms/WaterfallStepForm.vue | 20 ++- ui/stories/AddTotalRowsStepForm.stories.ts | 25 +-- ui/stories/AggregateStepForm.stories.ts | 22 +-- ui/stories/JoinStepForm.stories.ts | 65 +++----- .../unit/add-missing-dates-step-form.spec.ts | 2 +- ui/tests/unit/add-text-column.spec.ts | 47 ++---- ui/tests/unit/aggregate-step-form.spec.ts | 76 ++++----- ui/tests/unit/append-step-form.spec.ts | 46 ++---- ui/tests/unit/compare-text.spec.ts | 47 ++---- ui/tests/unit/compute-duration.spec.ts | 47 ++---- ui/tests/unit/concatenate-step-form.spec.ts | 58 ++----- ui/tests/unit/convert-step.spec.ts | 8 +- ui/tests/unit/cumsum-step-form.spec.ts | 55 +++---- ui/tests/unit/custom-step-form.spec.ts | 1 + ui/tests/unit/dateextract-step-form.spec.ts | 67 +++----- ui/tests/unit/delete-column-step-form.spec.ts | 35 +--- ui/tests/unit/dissolve-step-form.spec.ts | 22 ++- ui/tests/unit/domain-step-form.spec.ts | 9 +- .../unit/duplicate-column-step-form.spec.ts | 11 +- ui/tests/unit/evolution-step-form.spec.ts | 15 +- ui/tests/unit/fillna-step-form.spec.ts | 155 ++++++------------ ui/tests/unit/filter-step-form.spec.ts | 104 ++++-------- ui/tests/unit/formula-step-form.spec.ts | 43 ++--- ui/tests/unit/fromdate-step-form.spec.ts | 29 +--- ui/tests/unit/hierarchy-step-form.spec.ts | 7 +- ui/tests/unit/ifthenelse-step-form.spec.ts | 41 ++--- ui/tests/unit/join-step-form.spec.ts | 43 +++-- .../unit/moving-average-step-form.spec.ts | 52 +++--- ui/tests/unit/percentage-step-form.spec.ts | 22 +-- ui/tests/unit/pivot-step-form.spec.ts | 56 +++---- ui/tests/unit/rank-step-form.spec.ts | 26 +-- ui/tests/unit/rename-step-form.spec.ts | 90 ++++------ ui/tests/unit/replace-step-form.spec.ts | 106 +++++------- ui/tests/unit/replace-text-step-form.spec.ts | 65 +++----- ui/tests/unit/rollup-step-form.spec.ts | 41 ++--- ui/tests/unit/select-column-step-form.spec.ts | 24 +-- ui/tests/unit/simplify-step-form.spec.ts | 7 +- ui/tests/unit/sort-step-form.spec.ts | 63 +++---- ui/tests/unit/split-step-form.spec.ts | 2 +- ui/tests/unit/statistics-step-form.spec.ts | 78 +++------ ui/tests/unit/substring-step-form.spec.ts | 9 +- ui/tests/unit/todate-step-form.spec.ts | 31 +--- ui/tests/unit/tolower-step-form.spec.ts | 11 +- ui/tests/unit/top-step-form.spec.ts | 34 ++-- ui/tests/unit/totals-step-form.spec.ts | 22 ++- ui/tests/unit/toupper-step-form.spec.ts | 11 +- ui/tests/unit/trim-step-form.spec.ts | 35 +--- ui/tests/unit/uniquegroups-step-form.spec.ts | 24 ++- ui/tests/unit/unpivot-step-form.spec.ts | 25 +-- ui/tests/unit/utils.ts | 84 ++++------ ui/tests/unit/waterfall-step-form.spec.ts | 19 +-- 94 files changed, 907 insertions(+), 1555 deletions(-) diff --git a/ui/src/components/stepforms/AbsoluteValueStepForm.vue b/ui/src/components/stepforms/AbsoluteValueStepForm.vue index 14cae000c3..74ed454ed9 100644 --- a/ui/src/components/stepforms/AbsoluteValueStepForm.vue +++ b/ui/src/components/stepforms/AbsoluteValueStepForm.vue @@ -13,6 +13,9 @@ placeholder="Select a column" data-path=".column" :errors="errors" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> { stepname: PipelineStepName = 'absolutevalue'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ name: 'absolutevalue', column: '', newColumn: '' }) }) declare initialStepValue: AbsoluteValueStep; diff --git a/ui/src/components/stepforms/AddMissingDatesStepForm.vue b/ui/src/components/stepforms/AddMissingDatesStepForm.vue index 0787b35879..2d47615c28 100644 --- a/ui/src/components/stepforms/AddMissingDatesStepForm.vue +++ b/ui/src/components/stepforms/AddMissingDatesStepForm.vue @@ -16,6 +16,9 @@ :available-variables="availableVariables" :variable-delimiters="variableDelimiters" :trusted-variable-delimiters="trustedVariableDelimiters" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> { stepname: PipelineStepName = 'addmissingdates'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ diff --git a/ui/src/components/stepforms/AddTextColumnStepForm.vue b/ui/src/components/stepforms/AddTextColumnStepForm.vue index c9ef568ecf..a6f8a9ebde 100644 --- a/ui/src/components/stepforms/AddTextColumnStepForm.vue +++ b/ui/src/components/stepforms/AddTextColumnStepForm.vue @@ -39,9 +39,6 @@ import { Prop } from 'vue-property-decorator'; import InputTextWidget from '@/components/stepforms/widgets/InputText.vue'; import type { AddTextColumnStep, PipelineStepName } from '@/lib/steps'; -import type { VariableDelimiters, VariablesBucket } from '@/lib/variables'; -import { State } from 'pinia-class'; -import { VQBModule } from '@/store'; import BaseStepForm from './StepForm.vue'; @@ -54,11 +51,6 @@ import BaseStepForm from './StepForm.vue'; export default class AddTextColumnStepForm extends BaseStepForm { stepname: PipelineStepName = 'text'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ name: 'text', newColumn: '', text: '' }) }) declare initialStepValue: AddTextColumnStep; diff --git a/ui/src/components/stepforms/AddTotalRowsStepForm.vue b/ui/src/components/stepforms/AddTotalRowsStepForm.vue index e98d580184..643821958c 100644 --- a/ui/src/components/stepforms/AddTotalRowsStepForm.vue +++ b/ui/src/components/stepforms/AddTotalRowsStepForm.vue @@ -17,6 +17,9 @@ data-path=".totalDimensions" :errors="errors" unstyled-items + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> { stepname: PipelineStepName = 'aggregate'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ diff --git a/ui/src/components/stepforms/AppendStepForm.vue b/ui/src/components/stepforms/AppendStepForm.vue index 5540e0fb4b..5fdecd43ad 100644 --- a/ui/src/components/stepforms/AppendStepForm.vue +++ b/ui/src/components/stepforms/AppendStepForm.vue @@ -28,8 +28,6 @@ import { Prop } from 'vue-property-decorator'; import type { AppendStep, PipelineStepName, ReferenceToExternalQuery } from '@/lib/steps'; import { isReferenceToExternalQuery } from '@/lib/steps'; -import { State } from 'pinia-class'; -import { VQBModule } from '@/store'; import BaseStepForm from './StepForm.vue'; import MultiselectWidget from './widgets/Multiselect.vue'; @@ -53,9 +51,6 @@ export default class AppendStepForm extends BaseStepForm { @Prop({ type: Object, default: () => ({ name: 'append', pipelines: [] }) }) declare initialStepValue: AppendStep; - @State(VQBModule) availableDomains!: { name: string; uid: string }[]; - @State(VQBModule) unjoinableDomains!: { name: string; uid: string }[]; - readonly title: string = 'Append datasets'; get pipelines(): DropdownOption[] { diff --git a/ui/src/components/stepforms/ArgmaxStepForm.vue b/ui/src/components/stepforms/ArgmaxStepForm.vue index 0ec18c47f2..ba8ed3d356 100644 --- a/ui/src/components/stepforms/ArgmaxStepForm.vue +++ b/ui/src/components/stepforms/ArgmaxStepForm.vue @@ -16,6 +16,9 @@ :available-variables="availableVariables" :variable-delimiters="variableDelimiters" :trusted-variable-delimiters="trustedVariableDelimiters" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> { stepname: PipelineStepName = 'argmax'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ name: 'argmax', column: '' }) }) declare initialStepValue: ArgmaxStep; diff --git a/ui/src/components/stepforms/ArgminStepForm.vue b/ui/src/components/stepforms/ArgminStepForm.vue index d5db7a648b..ea091cfdb2 100644 --- a/ui/src/components/stepforms/ArgminStepForm.vue +++ b/ui/src/components/stepforms/ArgminStepForm.vue @@ -16,6 +16,9 @@ :available-variables="availableVariables" :variable-delimiters="variableDelimiters" :trusted-variable-delimiters="trustedVariableDelimiters" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> { stepname: PipelineStepName = 'argmin'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ name: 'argmin', column: '' }) }) declare initialStepValue: ArgminStep; diff --git a/ui/src/components/stepforms/CompareTextStepForm.vue b/ui/src/components/stepforms/CompareTextStepForm.vue index e4bb8a041d..6762f32936 100644 --- a/ui/src/components/stepforms/CompareTextStepForm.vue +++ b/ui/src/components/stepforms/CompareTextStepForm.vue @@ -26,6 +26,9 @@ :available-variables="availableVariables" :variable-delimiters="variableDelimiters" :trusted-variable-delimiters="trustedVariableDelimiters" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" />
@@ -50,9 +56,6 @@ import { Prop } from 'vue-property-decorator'; import ColumnPicker from '@/components/stepforms/ColumnPicker.vue'; import InputTextWidget from '@/components/stepforms/widgets/InputText.vue'; import type { CompareTextStep, PipelineStepName } from '@/lib/steps'; -import type { VariableDelimiters, VariablesBucket } from '@/lib/variables'; -import { VQBModule } from '@/store'; -import { State } from 'pinia-class'; import BaseStepForm from './StepForm.vue'; @@ -66,11 +69,6 @@ import BaseStepForm from './StepForm.vue'; export default class CompareTextStepForm extends BaseStepForm { stepname: PipelineStepName = 'comparetext'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ diff --git a/ui/src/components/stepforms/ComputeDurationStepForm.vue b/ui/src/components/stepforms/ComputeDurationStepForm.vue index d4ad2956d6..02de4010e0 100644 --- a/ui/src/components/stepforms/ComputeDurationStepForm.vue +++ b/ui/src/components/stepforms/ComputeDurationStepForm.vue @@ -26,6 +26,9 @@ :available-variables="availableVariables" :variable-delimiters="variableDelimiters" :trusted-variable-delimiters="trustedVariableDelimiters" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> { stepname: PipelineStepName = 'duration'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ diff --git a/ui/src/components/stepforms/ConcatenateStepForm.vue b/ui/src/components/stepforms/ConcatenateStepForm.vue index d5b0818de7..8debe095cd 100644 --- a/ui/src/components/stepforms/ConcatenateStepForm.vue +++ b/ui/src/components/stepforms/ConcatenateStepForm.vue @@ -20,6 +20,9 @@ :available-variables="availableVariables" :variable-delimiters="variableDelimiters" :trusted-variable-delimiters="trustedVariableDelimiters" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> { stepname: PipelineStepName = 'concatenate'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ name: 'concatenate', columns: [''], separator: '', newColumnName: '' }), diff --git a/ui/src/components/stepforms/CumSumStepForm.vue b/ui/src/components/stepforms/CumSumStepForm.vue index ef44ce8508..cb98703ddb 100644 --- a/ui/src/components/stepforms/CumSumStepForm.vue +++ b/ui/src/components/stepforms/CumSumStepForm.vue @@ -19,6 +19,9 @@ :available-variables="availableVariables" :variable-delimiters="variableDelimiters" :trusted-variable-delimiters="trustedVariableDelimiters" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" unstyled-items /> { stepname: PipelineStepName = 'cumsum'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ name: 'cumsum', toCumSum: [['', '']], referenceColumn: '' }), diff --git a/ui/src/components/stepforms/CustomStepForm.vue b/ui/src/components/stepforms/CustomStepForm.vue index 2d625899c2..4395fa19d4 100644 --- a/ui/src/components/stepforms/CustomStepForm.vue +++ b/ui/src/components/stepforms/CustomStepForm.vue @@ -23,8 +23,6 @@ import { Prop } from 'vue-property-decorator'; import type { CustomStep, PipelineStepName } from '@/lib/steps'; import { getTranslator } from '@/lib/translators'; -import { VQBModule } from '@/store'; -import { State } from 'pinia-class'; import BaseStepForm from './StepForm.vue'; import CodeEditorWidget from './widgets/CodeEditorWidget.vue'; @@ -36,7 +34,6 @@ import CodeEditorWidget from './widgets/CodeEditorWidget.vue'; export default class CustomStepForm extends BaseStepForm { stepname: PipelineStepName = 'custom'; - @State(VQBModule) translator!: string; @Prop({ type: Object, default: () => ({ name: 'custom', query: '[{"$match": {"domain": "test"}}]' }), diff --git a/ui/src/components/stepforms/DateExtractStepForm.vue b/ui/src/components/stepforms/DateExtractStepForm.vue index 5481642734..d7bebb262b 100644 --- a/ui/src/components/stepforms/DateExtractStepForm.vue +++ b/ui/src/components/stepforms/DateExtractStepForm.vue @@ -14,6 +14,9 @@ placeholder="Pick a column" data-path=".column" :errors="errors" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> { stepname: PipelineStepName = 'dissolve'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ name: 'dissolve', groups: [], includeNulls: false, aggregations: [] }), diff --git a/ui/src/components/stepforms/DomainStepForm.vue b/ui/src/components/stepforms/DomainStepForm.vue index 8368f07d69..28a1f65a0b 100644 --- a/ui/src/components/stepforms/DomainStepForm.vue +++ b/ui/src/components/stepforms/DomainStepForm.vue @@ -23,8 +23,6 @@ import { Prop } from 'vue-property-decorator'; import AutocompleteWidget from '@/components/stepforms/widgets/Autocomplete.vue'; import type { DomainStep, PipelineStepName } from '@/lib/steps'; -import { VQBModule } from '@/store'; -import { Getter } from 'pinia-class'; import BaseStepForm from './StepForm.vue'; @@ -46,7 +44,9 @@ export default class DomainStepForm extends BaseStepForm { }) declare initialStepValue: DomainStep; - @Getter(VQBModule) availableDatasetNames!: string[]; + get availableDatasetNames() { + return this.availableDomains.map((d) => d.name); + } readonly title: string = 'Select a dataset'; } diff --git a/ui/src/components/stepforms/DuplicateColumnStepForm.vue b/ui/src/components/stepforms/DuplicateColumnStepForm.vue index 56cc0e3ef3..8dea594458 100644 --- a/ui/src/components/stepforms/DuplicateColumnStepForm.vue +++ b/ui/src/components/stepforms/DuplicateColumnStepForm.vue @@ -13,6 +13,9 @@ placeholder="Enter a column" data-path=".column" :errors="errors" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> { stepname: PipelineStepName = 'evolution'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ diff --git a/ui/src/components/stepforms/FillnaStepForm.vue b/ui/src/components/stepforms/FillnaStepForm.vue index 068dd452e3..7552ddc28c 100644 --- a/ui/src/components/stepforms/FillnaStepForm.vue +++ b/ui/src/components/stepforms/FillnaStepForm.vue @@ -33,11 +33,8 @@ import Component from 'vue-class-component'; import { Prop } from 'vue-property-decorator'; import InputTextWidget from '@/components/stepforms/widgets/InputText.vue'; -import type { ColumnTypeMapping } from '@/lib/dataset'; import { castFromString } from '@/lib/helpers'; import type { FillnaStep, PipelineStepName } from '@/lib/steps'; -import { VQBModule } from '@/store'; -import { Getter } from 'pinia-class'; import BaseStepForm from './StepForm.vue'; import MultiselectWidget from './widgets/Multiselect.vue'; @@ -58,8 +55,6 @@ export default class FillnaStepForm extends BaseStepForm { }) declare initialStepValue: FillnaStep; - @Getter(VQBModule) columnTypes!: ColumnTypeMapping; - readonly title: string = 'Fill null values'; /** Overload the definition of editedStep in BaseStepForm to guarantee retrocompatibility, diff --git a/ui/src/components/stepforms/FilterStepForm.vue b/ui/src/components/stepforms/FilterStepForm.vue index 5f5518e369..16604f6206 100644 --- a/ui/src/components/stepforms/FilterStepForm.vue +++ b/ui/src/components/stepforms/FilterStepForm.vue @@ -15,6 +15,7 @@ :trusted-variable-delimiters="trustedVariableDelimiters" :columnTypes="columnTypes" @filterTreeUpdated="updateFilterTree" + @setSelectedColumns="setSelectedColumns" />
@@ -25,16 +26,12 @@ import Component from 'vue-class-component'; import { Prop } from 'vue-property-decorator'; import FilterEditor from '@/components/FilterEditor.vue'; -import type { ColumnTypeMapping } from '@/lib/dataset'; import type { FilterCondition, FilterSimpleCondition, FilterStep, PipelineStepName, } from '@/lib/steps'; -import type { VariableDelimiters, VariablesBucket } from '@/lib/variables'; -import { VQBModule } from '@/store'; -import { State, Getter } from 'pinia-class'; import BaseStepForm from './StepForm.vue'; @@ -56,12 +53,6 @@ export default class FilterStepForm extends BaseStepForm { }) declare initialStepValue: FilterStep; - @State(VQBModule) availableVariables?: VariablesBucket; - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - - @Getter(VQBModule) columnTypes!: ColumnTypeMapping; - readonly title: string = 'Filter'; created() { diff --git a/ui/src/components/stepforms/FormulaStepForm.vue b/ui/src/components/stepforms/FormulaStepForm.vue index b2efb8990e..89781df6c7 100644 --- a/ui/src/components/stepforms/FormulaStepForm.vue +++ b/ui/src/components/stepforms/FormulaStepForm.vue @@ -39,9 +39,6 @@ import { Prop } from 'vue-property-decorator'; import InputTextWidget from '@/components/stepforms/widgets/InputText.vue'; import { escapeForUseInRegExp } from '@/lib/helpers'; import type { Formula, FormulaStep, PipelineStepName } from '@/lib/steps'; -import type { VariableDelimiters, VariablesBucket } from '@/lib/variables'; -import { VQBModule } from '@/store'; -import { State } from 'pinia-class'; import BaseStepForm from './StepForm.vue'; @@ -54,11 +51,6 @@ import BaseStepForm from './StepForm.vue'; export default class FormulaStepForm extends BaseStepForm { stepname: PipelineStepName = 'formula'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ name: 'formula', newColumn: '', formula: '' }) }) declare initialStepValue: FormulaStep; diff --git a/ui/src/components/stepforms/FromDateStepForm.vue b/ui/src/components/stepforms/FromDateStepForm.vue index 6cf73d8277..8e3fbcb3c6 100644 --- a/ui/src/components/stepforms/FromDateStepForm.vue +++ b/ui/src/components/stepforms/FromDateStepForm.vue @@ -14,6 +14,9 @@ placeholder="Add columns" data-path=".column" :errors="errors" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> { @Prop({ type: Object, default: () => ({ name: 'fromdate', column: '', format: '%Y-%m-%d' }) }) declare initialStepValue: FromDateStep; - @State(VQBModule) translator!: string; - readonly title: string = 'Convert Column From Date to Text'; readonly formatOptions: FormatOption[] = [ { format: 'custom', label: 'Custom', example: '' }, diff --git a/ui/src/components/stepforms/HierarchyStepForm.vue b/ui/src/components/stepforms/HierarchyStepForm.vue index c5dcf78175..f81251b0a0 100644 --- a/ui/src/components/stepforms/HierarchyStepForm.vue +++ b/ui/src/components/stepforms/HierarchyStepForm.vue @@ -23,6 +23,9 @@ data-path=".hierarchy" :errors="errors" :componentProps="{ allowCustom: true }" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> diff --git a/ui/src/components/stepforms/IfThenElseStepForm.vue b/ui/src/components/stepforms/IfThenElseStepForm.vue index 2ccf0da2cc..df088d622a 100644 --- a/ui/src/components/stepforms/IfThenElseStepForm.vue +++ b/ui/src/components/stepforms/IfThenElseStepForm.vue @@ -36,11 +36,7 @@ import { Prop } from 'vue-property-decorator'; import IfThenElseWidget from '@/components/stepforms/widgets/IfThenElseWidget.vue'; import InputTextWidget from '@/components/stepforms/widgets/InputText.vue'; -import type { ColumnTypeMapping } from '@/lib/dataset'; import type { IfThenElseStep, PipelineStepName } from '@/lib/steps'; -import type { VariableDelimiters, VariablesBucket } from '@/lib/variables'; -import { VQBModule } from '@/store'; -import { State, Getter } from 'pinia-class'; import BaseStepForm from './StepForm.vue'; @@ -54,12 +50,6 @@ import BaseStepForm from './StepForm.vue'; export default class IfThenElseStepForm extends BaseStepForm { stepname: PipelineStepName = 'ifthenelse'; - @State(VQBModule) availableVariables?: VariablesBucket; - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - - @Getter(VQBModule) columnTypes!: ColumnTypeMapping; - @Prop({ type: Object, default: () => ({ diff --git a/ui/src/components/stepforms/JoinStepForm.vue b/ui/src/components/stepforms/JoinStepForm.vue index 861adc1fcf..77c3e3c1b9 100644 --- a/ui/src/components/stepforms/JoinStepForm.vue +++ b/ui/src/components/stepforms/JoinStepForm.vue @@ -40,6 +40,9 @@ data-path=".on" :errors="errors" unstyled-items + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" />
@@ -59,8 +62,6 @@ import { type PipelineStepName, type ReferenceToExternalQuery, } from '@/lib/steps'; -import { Action, State } from 'pinia-class'; -import { VQBModule, type VQBActions } from '@/store'; import BaseStepForm from './StepForm.vue'; import Multiselect from './widgets/Multiselect.vue'; @@ -91,9 +92,6 @@ export default class JoinStepForm extends BaseStepForm { }) declare initialStepValue: JoinStep; - @State(VQBModule) availableDomains!: { name: string; uid: string }[]; - @State(VQBModule) unjoinableDomains!: { name: string; uid: string }[]; - readonly title: string = 'Join datasets'; joinColumns = JoinColumns; joinTypes: JoinStep['type'][] = joinTypes; @@ -146,8 +144,6 @@ export default class JoinStepForm extends BaseStepForm { rightColumnNames: string[] | null | undefined = null; - @Action(VQBModule) getColumnNamesFromPipeline!: VQBActions['getColumnNamesFromPipeline']; - async updateRightColumnNames(pipelineNameOrDomain: string | ReferenceToExternalQuery) { this.rightColumnNames = await this.getColumnNamesFromPipeline(pipelineNameOrDomain); } diff --git a/ui/src/components/stepforms/MovingAverageStepForm.vue b/ui/src/components/stepforms/MovingAverageStepForm.vue index 5db99f57f8..16c4643a2f 100644 --- a/ui/src/components/stepforms/MovingAverageStepForm.vue +++ b/ui/src/components/stepforms/MovingAverageStepForm.vue @@ -17,6 +17,9 @@ :available-variables="availableVariables" :variable-delimiters="variableDelimiters" :trusted-variable-delimiters="trustedVariableDelimiters" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> { stepname: PipelineStepName = 'movingaverage'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ diff --git a/ui/src/components/stepforms/PercentageStepForm.vue b/ui/src/components/stepforms/PercentageStepForm.vue index 13aa8a5b39..ded275723d 100644 --- a/ui/src/components/stepforms/PercentageStepForm.vue +++ b/ui/src/components/stepforms/PercentageStepForm.vue @@ -13,6 +13,9 @@ placeholder="Enter a column" data-path=".column" :errors="errors" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> { stepname: PipelineStepName = 'pivot'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ diff --git a/ui/src/components/stepforms/RankStepForm.vue b/ui/src/components/stepforms/RankStepForm.vue index c2e3c067aa..17ee9690e8 100644 --- a/ui/src/components/stepforms/RankStepForm.vue +++ b/ui/src/components/stepforms/RankStepForm.vue @@ -17,6 +17,9 @@ :available-variables="availableVariables" :variable-delimiters="variableDelimiters" :trusted-variable-delimiters="trustedVariableDelimiters" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> { stepname: PipelineStepName = 'rank'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ name: 'rank', valueCol: '', order: 'desc', method: 'standard' }), diff --git a/ui/src/components/stepforms/RenameStepForm.vue b/ui/src/components/stepforms/RenameStepForm.vue index b582a79792..8bbea4f8f7 100644 --- a/ui/src/components/stepforms/RenameStepForm.vue +++ b/ui/src/components/stepforms/RenameStepForm.vue @@ -22,6 +22,9 @@ :variable-delimiters="variableDelimiters" :trusted-variable-delimiters="trustedVariableDelimiters" unstyled-items + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" />
@@ -34,9 +37,6 @@ import { Prop } from 'vue-property-decorator'; import ListWidget from '@/components/stepforms/widgets/List.vue'; import RenameWidget from '@/components/stepforms/widgets/Rename.vue'; import type { PipelineStepName, RenameStep } from '@/lib/steps'; -import type { VariableDelimiters, VariablesBucket } from '@/lib/variables'; -import { VQBModule } from '@/store'; -import { State } from 'pinia-class'; import BaseStepForm from './StepForm.vue'; @@ -49,11 +49,6 @@ import BaseStepForm from './StepForm.vue'; export default class RenameStepForm extends BaseStepForm { stepname: PipelineStepName = 'rename'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ name: 'rename', toRename: [['', '']] }) }) declare initialStepValue: RenameStep; diff --git a/ui/src/components/stepforms/ReplaceStepForm.vue b/ui/src/components/stepforms/ReplaceStepForm.vue index 493b16e019..4c833ab16f 100644 --- a/ui/src/components/stepforms/ReplaceStepForm.vue +++ b/ui/src/components/stepforms/ReplaceStepForm.vue @@ -13,6 +13,9 @@ placeholder="Enter a column" data-path=".searchColumn" :errors="errors" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" />
@@ -40,12 +46,8 @@ import { Prop } from 'vue-property-decorator'; import ColumnPicker from '@/components/stepforms/ColumnPicker.vue'; import ListWidget from '@/components/stepforms/widgets/List.vue'; import ReplaceWidget from '@/components/stepforms/widgets/Replace.vue'; -import type { ColumnTypeMapping } from '@/lib/dataset'; import { castFromString } from '@/lib/helpers'; import type { PipelineStepName, ReplaceStep } from '@/lib/steps'; -import type { VariableDelimiters, VariablesBucket } from '@/lib/variables'; -import { VQBModule } from '@/store'; -import { State, Getter } from 'pinia-class'; import BaseStepForm from './StepForm.vue'; @@ -59,16 +61,9 @@ import BaseStepForm from './StepForm.vue'; export default class ReplaceStepForm extends BaseStepForm { stepname: PipelineStepName = 'replace'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ name: 'replace', searchColumn: '', toReplace: [[]] }) }) declare initialStepValue: ReplaceStep; - @Getter(VQBModule) columnTypes!: ColumnTypeMapping; - readonly title: string = 'Replace values'; replaceWidget = ReplaceWidget; diff --git a/ui/src/components/stepforms/ReplaceTextStepForm.vue b/ui/src/components/stepforms/ReplaceTextStepForm.vue index 9ceba69e51..6863eb44cf 100644 --- a/ui/src/components/stepforms/ReplaceTextStepForm.vue +++ b/ui/src/components/stepforms/ReplaceTextStepForm.vue @@ -13,6 +13,9 @@ placeholder="Enter a column" data-path=".column" :errors="errors" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> { stepname: PipelineStepName = 'replacetext'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ name: 'replacetext', searchColumn: '', oldStr: '', newStr: '' }), }) declare initialStepValue: ReplaceTextStep; - @Getter(VQBModule) columnTypes!: ColumnTypeMapping; - readonly title: string = 'Replace text'; get stepSelectedColumn() { diff --git a/ui/src/components/stepforms/RollupStepForm.vue b/ui/src/components/stepforms/RollupStepForm.vue index 1517aeb9c7..7a6c76b3af 100644 --- a/ui/src/components/stepforms/RollupStepForm.vue +++ b/ui/src/components/stepforms/RollupStepForm.vue @@ -27,6 +27,9 @@ :automatic-new-field="false" data-path=".aggregations" :errors="errors" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> diff --git a/ui/src/components/stepforms/SplitStepForm.vue b/ui/src/components/stepforms/SplitStepForm.vue index 57421e3c16..40a4f9dcc0 100644 --- a/ui/src/components/stepforms/SplitStepForm.vue +++ b/ui/src/components/stepforms/SplitStepForm.vue @@ -16,6 +16,9 @@ :available-variables="availableVariables" :variable-delimiters="variableDelimiters" :trusted-variable-delimiters="trustedVariableDelimiters" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> { stepname: PipelineStepName = 'split'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ name: 'split', column: '', delimiter: '' }), diff --git a/ui/src/components/stepforms/StatisticsStepForm.vue b/ui/src/components/stepforms/StatisticsStepForm.vue index 0952b8b002..d32f53783c 100644 --- a/ui/src/components/stepforms/StatisticsStepForm.vue +++ b/ui/src/components/stepforms/StatisticsStepForm.vue @@ -9,6 +9,9 @@ data-path=".column" :errors="errors" :types="['integer', 'float']" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> extends Vue { version = version; // display the current version of the package + @Prop({ type: String, default: 'pandas' }) + translator!: string; + @Prop({ type: Boolean, default: true }) isStepCreation!: boolean; @@ -99,17 +98,37 @@ export default class BaseStepForm extends Vue { @Prop({ type: String, default: undefined }) backendError?: string; - @State(VQBModule) interpolateFunc!: InterpolateFunction; - @State(VQBModule) selectedStepIndex!: number; - @State(VQBModule) variables!: ScopeContext; + @Prop({ type: Object, default: () => ({}) }) + columnTypes!: ColumnTypeMapping; + + @Prop({ type: Array, default: () => [] }) + selectedColumns!: string[]; + + @Prop() + availableVariables?: VariablesBucket; + + @Prop() + variableDelimiters?: VariableDelimiters; + + @Prop() + trustedVariableDelimiters?: VariableDelimiters; + + @Prop({ type: Object, default: () => ({}) }) + variables!: ScopeContext; - @Action(VQBModule) selectStep!: VQBActions['selectStep']; - @Action(VQBModule) setSelectedColumns!: VQBActions['setSelectedColumns']; + @Prop({ type: Array, default: () => [] }) + availableDomains!: { name: string; uid: string }[]; - @Getter(VQBModule) columnNames!: string[]; - @Getter(VQBModule) computedActiveStepIndex!: number; - @Getter(VQBModule) pipeline!: Pipeline; - @State(VQBModule) selectedColumns!: string[]; + @Prop({ type: Array, default: () => [] }) + unjoinableDomains!: { name: string; uid: string }[]; + + @Prop({ type: Function, default: (e: any) => e }) + interpolateFunc!: InterpolateFunction; + + @Prop({ type: Function, default: () => Promise.resolve([]) }) + getColumnNamesFromPipeline!: ( + pipelineNameOrDomain: string | ReferenceToExternalQuery, + ) => Promise; readonly selectedColumnAttrName: string | null = null; readonly title: string = ''; @@ -142,6 +161,10 @@ export default class BaseStepForm extends Vue { }) as EventListener); } + get columnNames(): string[] { + return Object.keys(this.columnTypes); + } + /** * The `$$super` property will return a javascript proxy that should bind * the current `this` instance on the method implentation found on the baseclass. @@ -197,6 +220,11 @@ export default class BaseStepForm extends Vue { // the new selected column. } + setSelectedColumns({ column }: { column: string | undefined }) { + // we emit the selected columns because behaviour is different if we use store or props + this.$emit('setSelectedColumns', { column }); + } + /** * `validate` calls `Ajv`. If there are some errors, return them, otherwise * return `null`. @@ -215,8 +243,6 @@ export default class BaseStepForm extends Vue { */ cancelEdition() { this.$emit('back'); - const idx = this.isStepCreation ? this.computedActiveStepIndex : this.selectedStepIndex + 1; - this.selectStep({ index: idx }); } /** diff --git a/ui/src/components/stepforms/SubstringStepForm.vue b/ui/src/components/stepforms/SubstringStepForm.vue index 68c1968925..d7b26a16a0 100644 --- a/ui/src/components/stepforms/SubstringStepForm.vue +++ b/ui/src/components/stepforms/SubstringStepForm.vue @@ -13,6 +13,9 @@ placeholder="Enter a column" data-path=".column" :errors="errors" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> { @Prop({ type: Object, default: () => ({ name: 'todate', column: '', format: undefined }) }) declare initialStepValue: ToDateStep; - @State(VQBModule) translator!: string; - readonly title: string = 'Convert Column From Text to Date'; readonly formatOptions: FormatOption[] = [ { format: 'guess', label: 'Try to guess', example: '' }, diff --git a/ui/src/components/stepforms/ToLowerStepForm.vue b/ui/src/components/stepforms/ToLowerStepForm.vue index 7b215129e3..7a1693eab4 100644 --- a/ui/src/components/stepforms/ToLowerStepForm.vue +++ b/ui/src/components/stepforms/ToLowerStepForm.vue @@ -13,6 +13,9 @@ placeholder="Enter a column" data-path=".column" :errors="errors" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> diff --git a/ui/src/components/stepforms/ToUpperStepForm.vue b/ui/src/components/stepforms/ToUpperStepForm.vue index 3e7736744b..9f4f6c5cc9 100644 --- a/ui/src/components/stepforms/ToUpperStepForm.vue +++ b/ui/src/components/stepforms/ToUpperStepForm.vue @@ -13,6 +13,9 @@ placeholder="Enter a column" data-path=".column" :errors="errors" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> diff --git a/ui/src/components/stepforms/TopStepForm.vue b/ui/src/components/stepforms/TopStepForm.vue index a7c110c43d..061f6b401a 100644 --- a/ui/src/components/stepforms/TopStepForm.vue +++ b/ui/src/components/stepforms/TopStepForm.vue @@ -26,6 +26,9 @@ :available-variables="availableVariables" :variable-delimiters="variableDelimiters" :trusted-variable-delimiters="trustedVariableDelimiters" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> { stepname: PipelineStepName = 'top'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ name: 'top', rankOn: '', sort: 'desc' }) }) declare initialStepValue: TopStep; diff --git a/ui/src/components/stepforms/UnpivotStepForm.vue b/ui/src/components/stepforms/UnpivotStepForm.vue index 7f24445261..6ee4bd180d 100644 --- a/ui/src/components/stepforms/UnpivotStepForm.vue +++ b/ui/src/components/stepforms/UnpivotStepForm.vue @@ -52,9 +52,6 @@ import CheckboxWidget from '@/components/stepforms/widgets/Checkbox.vue'; import MultiselectWidget from '@/components/stepforms/widgets/Multiselect.vue'; import { generateNewColumnName } from '@/lib/helpers'; import type { PipelineStepName, UnpivotStep } from '@/lib/steps'; -import type { VariableDelimiters, VariablesBucket } from '@/lib/variables'; -import { VQBModule } from '@/store'; -import { State } from 'pinia-class'; import BaseStepForm from './StepForm.vue'; @@ -68,11 +65,6 @@ import BaseStepForm from './StepForm.vue'; export default class UnpivotStepForm extends BaseStepForm { stepname: PipelineStepName = 'unpivot'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ @@ -85,7 +77,6 @@ export default class UnpivotStepForm extends BaseStepForm { }), }) declare initialStepValue: UnpivotStep; - @State(VQBModule) translator!: string; readonly title: string = 'Unpivot columns'; readonly checkboxLabel: string = 'Drop null values'; diff --git a/ui/src/components/stepforms/WaterfallStepForm.vue b/ui/src/components/stepforms/WaterfallStepForm.vue index a05c300362..2c2f2c2e82 100644 --- a/ui/src/components/stepforms/WaterfallStepForm.vue +++ b/ui/src/components/stepforms/WaterfallStepForm.vue @@ -17,6 +17,9 @@ :available-variables="availableVariables" :variable-delimiters="variableDelimiters" :trusted-variable-delimiters="trustedVariableDelimiters" + :columnNames="columnNames" + :selectedColumns="selectedColumns" + @setSelectedColumns="setSelectedColumns" /> { stepname: PipelineStepName = 'waterfall'; - @State(VQBModule) availableVariables?: VariablesBucket; - - @State(VQBModule) variableDelimiters?: VariableDelimiters; - @State(VQBModule) trustedVariableDelimiters?: VariableDelimiters; - @Prop({ type: Object, default: () => ({ diff --git a/ui/stories/AddTotalRowsStepForm.stories.ts b/ui/stories/AddTotalRowsStepForm.stories.ts index 707066dbbb..282b42b5ad 100644 --- a/ui/stories/AddTotalRowsStepForm.stories.ts +++ b/ui/stories/AddTotalRowsStepForm.stories.ts @@ -1,17 +1,12 @@ import { action } from '@storybook/addon-actions'; import type { Meta, StoryObj } from '@storybook/vue'; -import { createPinia, PiniaVuePlugin } from 'pinia'; -import Vue from 'vue'; import AddTotalRowsStepForm from '@/components/stepforms/AddTotalRowsStepForm.vue'; -import { setupVQBStore } from '@/store'; export default { component: AddTotalRowsStepForm, } as Meta; -Vue.use(PiniaVuePlugin); - export const Empty: StoryObj = { render: (args, { argTypes }) => ({ components: { AddTotalRowsStepForm }, @@ -20,18 +15,12 @@ export const Empty: StoryObj = { methods: { onFormSaved: action('formSaved'), }, - pinia: createPinia(), - created: function () { - setupVQBStore({ - backendMessages: [], - dataset: { - headers: [ - { name: 'label', type: 'string' }, - { name: 'value', type: 'string' }, - ], - data: [], - }, - }); - }, }), + args: { + columnTypes: { 'column A': 'string', 'column B': 'string', 'column C': 'string' }, + interpolateFunc: (a: any) => a, + availableDomains: [], + unjoinableDomains: [], + getColumnNamesFromPipeline: () => Promise.resolve([]), + }, }; diff --git a/ui/stories/AggregateStepForm.stories.ts b/ui/stories/AggregateStepForm.stories.ts index 8f057cbd5d..488aeb3583 100644 --- a/ui/stories/AggregateStepForm.stories.ts +++ b/ui/stories/AggregateStepForm.stories.ts @@ -1,34 +1,26 @@ import { action } from '@storybook/addon-actions'; import type { Meta, StoryObj } from '@storybook/vue'; -import { createPinia, PiniaVuePlugin } from 'pinia'; -import Vue from 'vue'; import AggregateStepForm from '@/components/stepforms/AggregateStepForm.vue'; -import { setupVQBStore } from '@/store'; export default { component: AggregateStepForm, } as Meta; -Vue.use(PiniaVuePlugin); - export const Default: StoryObj = { render: (args, { argTypes }) => ({ components: { AggregateStepForm }, props: Object.keys(argTypes), template: '', - pinia: createPinia(), - created: function () { - setupVQBStore({ - backendMessages: [], - dataset: { - headers: [{ name: 'column A' }, { name: 'column B' }, { name: 'column C' }], - data: [], - }, - }); - }, methods: { onFormSaved: action('formSaved'), }, }), + args: { + columnTypes: { 'column A': 'string', 'column B': 'string', 'column C': 'string' }, + interpolateFunc: (a: any) => a, + availableDomains: [], + unjoinableDomains: [], + getColumnNamesFromPipeline: () => Promise.resolve([]), + }, }; diff --git a/ui/stories/JoinStepForm.stories.ts b/ui/stories/JoinStepForm.stories.ts index 5d89febd36..d39096f9ce 100644 --- a/ui/stories/JoinStepForm.stories.ts +++ b/ui/stories/JoinStepForm.stories.ts @@ -1,40 +1,32 @@ import type { Meta, StoryObj } from '@storybook/vue'; -import { createPinia, PiniaVuePlugin } from 'pinia'; -import Vue from 'vue'; import JoinStepForm from '@/components/stepforms/JoinStepForm.vue'; -import { setupVQBStore } from '@/store'; export default { component: JoinStepForm, } as Meta; -Vue.use(PiniaVuePlugin); - export const Default: StoryObj = { render: (args, { argTypes }) => ({ components: { JoinStepForm }, props: Object.keys(argTypes), template: '', - pinia: createPinia(), - created: function () { - setupVQBStore({ - backendMessages: [], - dataset: { headers: [], data: [] }, - availableDomains: [ - { name: 'Dataset 1', uid: '1' }, - { name: 'Dataset 2', uid: '2' }, - { name: 'Dataset 3', uid: '3' }, - ], - unjoinableDomains: [ - { name: 'Dataset 1', uid: '1' }, - { name: 'Dataset 2', uid: '2' }, - ], - }); - }, }), args: { initialStepValue: { name: 'join', rightPipeline: '', type: 'left', on: [['', '']] }, + availableDomains: [ + { name: 'Dataset 1', uid: '1' }, + { name: 'Dataset 2', uid: '2' }, + { name: 'Dataset 3', uid: '3' }, + ], + unjoinableDomains: [ + { name: 'Dataset 1', uid: '1' }, + { name: 'Dataset 2', uid: '2' }, + ], + columnTypes: { + name: 'string', + }, + getColumnNamesFromPipeline: () => Promise.resolve(['name', 'other']), }, }; @@ -43,29 +35,26 @@ export const Edition: StoryObj = { components: { JoinStepForm }, props: Object.keys(argTypes), template: '', - pinia: createPinia(), - created: function () { - setupVQBStore({ - backendMessages: [], - dataset: { headers: [], data: [] }, - availableDomains: [ - { name: 'Dataset 1', uid: '1' }, - { name: 'Dataset 2', uid: '2' }, - { name: 'Dataset 3', uid: '3' }, - ], - unjoinableDomains: [ - { name: 'Dataset 1', uid: '1' }, - { name: 'Dataset 2', uid: '2' }, - ], - }); - }, }), args: { initialStepValue: { name: 'join', - rightPipeline: { type: 'ref', uid: '2' }, + rightPipeline: { type: 'ref', uid: '3' }, type: 'left', on: [['name', 'name']], }, + availableDomains: [ + { name: 'Dataset 1', uid: '1' }, + { name: 'Dataset 2', uid: '2' }, + { name: 'Dataset 3', uid: '3' }, + ], + unjoinableDomains: [ + { name: 'Dataset 1', uid: '1' }, + { name: 'Dataset 2', uid: '2' }, + ], + columnTypes: { + name: 'string', + }, + getColumnNamesFromPipeline: () => Promise.resolve(['name', 'other']), }, }; diff --git a/ui/tests/unit/add-missing-dates-step-form.spec.ts b/ui/tests/unit/add-missing-dates-step-form.spec.ts index fdc14f097f..7182c51756 100644 --- a/ui/tests/unit/add-missing-dates-step-form.spec.ts +++ b/ui/tests/unit/add-missing-dates-step-form.spec.ts @@ -45,7 +45,7 @@ describe('Add missing dates Step Form', () => { ]); it('should pass down props to widgets', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'addmissingdates', diff --git a/ui/tests/unit/add-text-column.spec.ts b/ui/tests/unit/add-text-column.spec.ts index bdb1542cbc..f4f8fcc73d 100644 --- a/ui/tests/unit/add-text-column.spec.ts +++ b/ui/tests/unit/add-text-column.spec.ts @@ -22,46 +22,35 @@ describe('Add Text Column Step Form', () => { }); it('should make the focus on the column added after validation', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], - }, - }; - const wrapper = runner.mount(initialState); - const store = runner.getStore(); + const wrapper = runner.mount({ + propsData: { columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' } }, + }); wrapper.setData({ editedStep: { name: 'text', text: 'some text', newColumn: 'foo' } }); wrapper.find('.widget-form-action__button--validate').trigger('click'); - expect(store.selectedColumns).toEqual(['foo']); + expect(wrapper.emitted().setSelectedColumns).toEqual([[{ column: 'foo' }]]); }); it('should not change the column focus if validation fails', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = runner.mount({ + propsData: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, + selectedColumns: ['columnA'], }, - selectedColumns: ['columnA'], - }; - const wrapper = runner.mount(initialState, { data: { editedStep: { name: 'text', text: '', newColumn: 'columnB' }, }, }); - const store = runner.getStore(); wrapper.find('.widget-form-action__button--validate').trigger('click'); - expect(store.selectedColumns).toEqual(['columnA']); + expect(wrapper.emitted().setSelectedColumns).toBeUndefined(); }); describe('Warning', () => { it('should report a warning when newColumn is an already existing column name', async () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); wrapper.setData({ editedStep: { text: '', newColumn: 'columnA' } }); await wrapper.vm.$nextTick(); expect(wrapper.find('.newColumnInput').props().warning).toEqual( @@ -70,13 +59,11 @@ describe('Add Text Column Step Form', () => { }); it('should not report any warning if newColumn is not an already existing column name', async () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); wrapper.setData({ editedStep: { text: '', newColumn: 'columnB' } }); await wrapper.vm.$nextTick(); expect(wrapper.find('.newColumnInput').props().warning).toBeNull(); diff --git a/ui/tests/unit/aggregate-step-form.spec.ts b/ui/tests/unit/aggregate-step-form.spec.ts index 76f844c755..759fb97ff9 100644 --- a/ui/tests/unit/aggregate-step-form.spec.ts +++ b/ui/tests/unit/aggregate-step-form.spec.ts @@ -17,19 +17,15 @@ describe('Aggregate Step Form', () => { describe('MultiselectWidget', () => { it('should instantiate an MultiselectWidget widget with proper options from the store', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], - }, - }; - const wrapper = runner.shallowMount(initialState); + const wrapper = runner.shallowMount({ + propsData: { columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' } }, + }); const widgetMultiselect = wrapper.find('multiselectwidget-stub'); expect(widgetMultiselect.attributes('options')).toEqual('columnA,columnB,columnC'); }); it('keepOriginalGranularity should be set properly if defined in inititalStepValue', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ propsData: { initialStepValue: { name: 'aggregate', @@ -44,7 +40,7 @@ describe('Aggregate Step Form', () => { }); it('keepOriginalGranularity should be set to false if undefined in inititalValue', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ propsData: { initialStepValue: { name: 'aggregate', @@ -59,7 +55,7 @@ describe('Aggregate Step Form', () => { }); it('should pass down the "on" prop to the MultiselectWidget value prop', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'aggregate', @@ -73,18 +69,16 @@ describe('Aggregate Step Form', () => { }); it('should call the setColumnMutation on input', async () => { - const wrapper = runner.mount(undefined, { - data: { - editedStep: { - name: 'aggregate', - on: ['foo'], - aggregations: [], - }, + const wrapper = runner.mount(); + wrapper.setData({ + editedStep: { + name: 'aggregate', + on: ['foo'], + aggregations: [], }, }); - const store = runner.getStore(); await wrapper.vm.$nextTick(); - expect(store.selectedColumns).toEqual(['foo']); + expect(wrapper.emitted().setSelectedColumns).toEqual([[{ column: 'foo' }]]); }); }); @@ -96,7 +90,7 @@ describe('Aggregate Step Form', () => { }); it('should pass down the "aggregations" prop to the ListWidget value prop', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'aggregate', @@ -194,7 +188,7 @@ describe('Aggregate Step Form', () => { }); it('should keep the same column name as newcolumn if only one aggregation is performed', () => { - const wrapper = runner.mount(undefined, { + const wrapper = runner.mount({ data: { editedStep: { name: 'aggregate', @@ -209,7 +203,7 @@ describe('Aggregate Step Form', () => { }); it('should set newcolumn cleverly if several aggregations are performed on the same column', () => { - const wrapper = runner.mount(undefined, { + const wrapper = runner.mount({ data: { editedStep: { name: 'aggregate', @@ -230,7 +224,7 @@ describe('Aggregate Step Form', () => { }); it('should set newcolumn cleverly if the an aggregation is perform on an id column', () => { - const wrapper = runner.mount(undefined, { + const wrapper = runner.mount({ data: { editedStep: { name: 'aggregate', @@ -245,7 +239,7 @@ describe('Aggregate Step Form', () => { }); it('should set newcolumn cleverly if we keep the original granularity', () => { - const wrapper = runner.mount(undefined, { + const wrapper = runner.mount({ data: { editedStep: { name: 'aggregate', @@ -264,33 +258,27 @@ describe('Aggregate Step Form', () => { runner.testResetSelectedIndex(); it('should change the column focus after input in multiselect', async () => { - const initialState = { selectedColumns: [] }; - const wrapper = runner.mount(initialState, { - data: { editedStep: { name: 'aggregate', on: ['foo'], aggregations: [] } }, - }); - const store = runner.getStore(); + const wrapper = runner.mount({ propsData: { selectedColumns: [] } }); + wrapper.setData({ editedStep: { name: 'aggregate', on: ['foo'], aggregations: [] } }); wrapper.find(MultiselectWidget).trigger('input'); await wrapper.vm.$nextTick(); - expect(store.selectedColumns).toEqual(['foo']); + expect(wrapper.emitted().setSelectedColumns).toEqual([[{ column: 'foo' }]]); }); it('should convert editedStep from old configurations to new configuration', async () => { - const wrapper = runner.shallowMount( - {}, - { - propsData: { - initialStepValue: { - name: 'aggregate', - on: ['index'], - aggregations: [ - { column: 'foo', newcolumn: 'foo', aggregation: 'sum' }, - { column: 'bar', newcolumn: 'bar', aggregation: 'sum' }, - { columns: ['foo', 'bar'], newcolumns: ['foo', 'bar'], aggregation: 'sum' }, - ], - }, + const wrapper = runner.shallowMount({ + propsData: { + initialStepValue: { + name: 'aggregate', + on: ['index'], + aggregations: [ + { column: 'foo', newcolumn: 'foo', aggregation: 'sum' }, + { column: 'bar', newcolumn: 'bar', aggregation: 'sum' }, + { columns: ['foo', 'bar'], newcolumns: ['foo', 'bar'], aggregation: 'sum' }, + ], }, }, - ); + }); await wrapper.vm.$nextTick(); expect(wrapper.vm.$data.editedStep.aggregations).toEqual([ { columns: ['foo'], newcolumns: ['foo'], aggregation: 'sum' }, diff --git a/ui/tests/unit/append-step-form.spec.ts b/ui/tests/unit/append-step-form.spec.ts index 88c834d339..f0efbd1deb 100644 --- a/ui/tests/unit/append-step-form.spec.ts +++ b/ui/tests/unit/append-step-form.spec.ts @@ -39,29 +39,20 @@ describe('Append Step Form', () => { }, }); - runner.testCancel({ - currentPipelineName: 'default_pipeline', - pipelines: { - default_pipeline: [ - { name: 'domain', domain: 'foo' }, - { name: 'rename', toRename: [['foo', 'bar']] }, - ], - }, - selectedStepIndex: 1, - }); + runner.testCancel(); runner.testResetSelectedIndex(); it('should instantiate a multiselect widget with proper options from the store', () => { - const initialState = { - currentPipelineName: 'my_dataset', - availableDomains: [ - { name: 'dataset1', uid: '1' }, - { name: 'dataset2', uid: '2' }, - ], - unjoinableDomains: [{ name: 'dataset2', uid: '2' }], - }; - const wrapper = runner.shallowMount(initialState); + const wrapper = runner.shallowMount({ + propsData: { + availableDomains: [ + { name: 'dataset1', uid: '1' }, + { name: 'dataset2', uid: '2' }, + ], + unjoinableDomains: [{ name: 'dataset2', uid: '2' }], + }, + }); const widgetMultiselect = wrapper.find('multiselectwidget-stub'); expect(widgetMultiselect.props('options')).toEqual([ { trackBy: { type: 'ref', uid: '1' }, label: 'dataset1' }, @@ -77,15 +68,14 @@ describe('Append Step Form', () => { }); it('should handle dataset references', async () => { - const initialState = { - currentPipelineName: 'my_dataset', - availableDomains: [ - { name: 'dataset1', uid: '1' }, - { name: 'dataset2', uid: '2' }, - ], - unjoinableDomains: [], - }; - const wrapper = runner.shallowMount(initialState, { + const wrapper = runner.shallowMount({ + propsData: { + availableDomains: [ + { name: 'dataset1', uid: '1' }, + { name: 'dataset2', uid: '2' }, + ], + unjoinableDomains: [], + }, data: { editedStep: { name: 'append', diff --git a/ui/tests/unit/compare-text.spec.ts b/ui/tests/unit/compare-text.spec.ts index fc49775d74..0b899e07b6 100644 --- a/ui/tests/unit/compare-text.spec.ts +++ b/ui/tests/unit/compare-text.spec.ts @@ -57,14 +57,11 @@ describe('Compute Text Columns Step Form', () => { }); it('should make the focus on the column added after validation', () => { - const initialState = { - dataset: { - headers: [{ name: 'start' }, { name: 'end' }], - data: [], + const wrapper = runner.mount({ + propsData: { + columnTypes: { start: 'string', end: 'string' }, }, - }; - const wrapper = runner.mount(initialState); - const store = runner.getStore(); + }); wrapper.setData({ editedStep: { name: 'comparetext', @@ -74,18 +71,15 @@ describe('Compute Text Columns Step Form', () => { }, }); wrapper.find('.widget-form-action__button--validate').trigger('click'); - expect(store.selectedColumns).toEqual(['NEW']); + expect(wrapper.emitted().setSelectedColumns).toEqual([[{ column: 'NEW' }]]); }); it('should not change the column focus if validation fails', () => { - const initialState = { - dataset: { - headers: [{ name: 'C1' }, { name: 'C2' }], - data: [], + const wrapper = runner.mount({ + propsData: { + columnTypes: { C1: 'string', C2: 'string' }, + selectedColumns: ['C1'], }, - selectedColumns: ['C1'], - }; - const wrapper = runner.mount(initialState, { data: { editedStep: { name: 'comparetext', @@ -95,20 +89,17 @@ describe('Compute Text Columns Step Form', () => { }, }, }); - const store = runner.getStore(); wrapper.find('.widget-form-action__button--validate').trigger('click'); - expect(store.selectedColumns).toEqual(['C1']); + expect(wrapper.emitted().setSelectedColumns).toBeUndefined(); }); describe('Warning', () => { it('should report a warning when newColumnName is an already existing column name', async () => { - const initialState = { - dataset: { - headers: [{ name: 'NEW' }, { name: 'C1' }, { name: 'C2' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { NEW: 'string', C1: 'string', C2: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); wrapper.setData({ editedStep: { name: 'comparetext', @@ -124,13 +115,11 @@ describe('Compute Text Columns Step Form', () => { }); it('should not report any warning if newColumnName is not an already existing column name', async () => { - const initialState = { - dataset: { - headers: [{ name: 'NEW' }, { name: 'C1' }, { name: 'C2' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { NEW: 'string', C1: 'string', C2: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); wrapper.setData({ editedStep: { name: 'comparetext', diff --git a/ui/tests/unit/compute-duration.spec.ts b/ui/tests/unit/compute-duration.spec.ts index b756a12a67..5ee02c2544 100644 --- a/ui/tests/unit/compute-duration.spec.ts +++ b/ui/tests/unit/compute-duration.spec.ts @@ -61,14 +61,11 @@ describe('Compute Duration Step Form', () => { }); it('should make the focus on the column added after validation', () => { - const initialState = { - dataset: { - headers: [{ name: 'start' }, { name: 'end' }], - data: [], + const wrapper = runner.mount({ + propsData: { + columnTypes: { start: 'string', end: 'string' }, }, - }; - const wrapper = runner.mount(initialState); - const store = runner.getStore(); + }); wrapper.setData({ editedStep: { name: 'duration', @@ -79,18 +76,15 @@ describe('Compute Duration Step Form', () => { }, }); wrapper.find('.widget-form-action__button--validate').trigger('click'); - expect(store.selectedColumns).toEqual(['test']); + expect(wrapper.emitted().setSelectedColumns).toEqual([[{ column: 'test' }]]); }); it('should not change the column focus if validation fails', () => { - const initialState = { - dataset: { - headers: [{ name: 'start' }, { name: 'end' }], - data: [], + const wrapper = runner.mount({ + propsData: { + columnTypes: { start: 'string', end: 'string' }, + selectedColumns: ['start'], }, - selectedColumns: ['start'], - }; - const wrapper = runner.mount(initialState, { data: { editedStep: { name: 'duration', @@ -101,20 +95,17 @@ describe('Compute Duration Step Form', () => { }, }, }); - const store = runner.getStore(); wrapper.find('.widget-form-action__button--validate').trigger('click'); - expect(store.selectedColumns).toEqual(['start']); + expect(wrapper.emitted().setSelectedColumns).toBeUndefined(); }); describe('Warning', () => { it('should report a warning when newColumnName is an already existing column name', async () => { - const initialState = { - dataset: { - headers: [{ name: 'foo' }, { name: 'strat' }, { name: 'end' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { foo: 'string', start: 'string', end: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); wrapper.setData({ editedStep: { name: 'duration', @@ -131,13 +122,11 @@ describe('Compute Duration Step Form', () => { }); it('should not report any warning if newColumnName is not an already existing column name', async () => { - const initialState = { - dataset: { - headers: [{ name: 'foo' }, { name: 'strat' }, { name: 'end' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { foo: 'string', start: 'string', end: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); wrapper.setData({ editedStep: { name: 'duration', diff --git a/ui/tests/unit/concatenate-step-form.spec.ts b/ui/tests/unit/concatenate-step-form.spec.ts index 86e5897545..c5eff6e69c 100644 --- a/ui/tests/unit/concatenate-step-form.spec.ts +++ b/ui/tests/unit/concatenate-step-form.spec.ts @@ -17,11 +17,8 @@ describe('Concatenate Step Form', () => { runner.testValidationErrors([ { testlabel: 'submitted data is not valid', - store: { - dataset: { - headers: [{ name: 'foo', type: 'string' }], - data: [[null]], - }, + props: { + columnTypes: { foo: 'string' }, }, errors: [ { dataPath: '.columns.0', keyword: 'minLength' }, @@ -32,16 +29,8 @@ describe('Concatenate Step Form', () => { runner.testValidate({ testlabel: 'submitted data is valid', - store: { - dataset: { - headers: [ - { name: 'foo', type: 'string' }, - { name: 'bar', type: 'string' }, - ], - data: [[null], [null]], - }, - }, props: { + columnTypes: { foo: 'string', bar: 'string' }, initialStepValue: { name: 'concatenate', columns: ['foo', 'bar'], @@ -51,48 +40,31 @@ describe('Concatenate Step Form', () => { }, }); - runner.testCancel({ - currentPipelineName: 'default_pipeline', - pipelines: { - default_pipeline: [ - { name: 'domain', domain: 'foo' }, - { name: 'rename', toRename: [['foo', 'bar']] }, - { name: 'rename', toRename: [['baz', 'spam']] }, - { name: 'rename', toRename: [['tic', 'tac']] }, - ], - }, - selectedStepIndex: 2, - }); + runner.testCancel(); runner.testResetSelectedIndex(); describe('ListWidget', () => { it('should pass down the "toConcatenate" prop to the ListWidget value prop', async () => { - const wrapper = runner.shallowMount( - {}, - { - data: { - editedStep: { - name: 'concatenate', - columns: ['foo', 'bar'], - separator: '-', - newColumnName: 'new', - }, + const wrapper = runner.shallowMount({ + data: { + editedStep: { + name: 'concatenate', + columns: ['foo', 'bar'], + separator: '-', + newColumnName: 'new', }, }, - ); + }); await wrapper.vm.$nextTick(); expect(wrapper.find('listwidget-stub').props().value).toEqual(['foo', 'bar']); }); }); it('should not sync selected columns on edition', async () => { - const initialState = { - selectedStepIndex: 1, - selectedColumns: ['spam'], - }; - const wrapper = runner.mount(initialState, { + const wrapper = runner.mount({ propsData: { + selectedColumns: ['spam'], initialStepValue: { name: 'concatenate', columns: ['foo', 'bar'], @@ -102,9 +74,7 @@ describe('Concatenate Step Form', () => { isStepCreation: false, }, }); - const store = runner.getStore(); await wrapper.vm.$nextTick(); - expect(store.selectedStepIndex).toEqual(1); const columnPickers = wrapper.findAll(ColumnPicker); expect(columnPickers.length).toEqual(2); const [picker1, picker2] = columnPickers.wrappers; diff --git a/ui/tests/unit/convert-step.spec.ts b/ui/tests/unit/convert-step.spec.ts index 2dd73d1174..d6ca2909e5 100644 --- a/ui/tests/unit/convert-step.spec.ts +++ b/ui/tests/unit/convert-step.spec.ts @@ -1,6 +1,4 @@ -import { createTestingPinia } from '@pinia/testing'; import { createLocalVue, shallowMount } from '@vue/test-utils'; -import { PiniaVuePlugin } from 'pinia'; import { describe, expect, it, vi } from 'vitest'; import ConvertStepForm from '@/components/stepforms/ConvertStepForm.vue'; @@ -8,17 +6,15 @@ import ConvertStepForm from '@/components/stepforms/ConvertStepForm.vue'; vi.mock('@/components/FAIcon.vue'); const localVue = createLocalVue(); -localVue.use(PiniaVuePlugin); -const pinia = createTestingPinia({ createSpy: vi.fn, stubActions: false }); describe('Convert Data Type Step Form', () => { it('should instantiate', () => { - const wrapper = shallowMount(ConvertStepForm, { pinia, localVue }); + const wrapper = shallowMount(ConvertStepForm, { localVue }); expect(wrapper.exists()).toBeTruthy(); }); it('should have exactly 2 input components', () => { - const wrapper = shallowMount(ConvertStepForm, { pinia, localVue }); + const wrapper = shallowMount(ConvertStepForm, { localVue }); expect(wrapper.findAll('multiselectwidget-stub').length).toEqual(1); expect(wrapper.findAll('autocompletewidget-stub').length).toEqual(1); }); diff --git a/ui/tests/unit/cumsum-step-form.spec.ts b/ui/tests/unit/cumsum-step-form.spec.ts index e5440b2886..eebb289941 100644 --- a/ui/tests/unit/cumsum-step-form.spec.ts +++ b/ui/tests/unit/cumsum-step-form.spec.ts @@ -17,19 +17,17 @@ describe('Cumsum Step Form', () => { describe('MultiselectWidgets', () => { it('should instantiate a MultiselectWidget widget with proper options from the store', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); const widgetMultiselect = wrapper.find('multiselectwidget-stub'); expect(widgetMultiselect.attributes('options')).toEqual('columnA,columnB,columnC'); }); it('should pass down the props to the MultiselectWidget value prop', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'cumsum', @@ -74,13 +72,8 @@ describe('Cumsum Step Form', () => { runner.testValidate({ testlabel: 'submitted data is valid', - store: { - dataset: { - headers: [{ name: 'columnA' }], - data: [], - }, - }, props: { + columnTypes: { columnA: 'string' }, initialStepValue: { name: 'cumsum', toCumSum: [['myValues', 'myNewColumn']], @@ -95,19 +88,16 @@ describe('Cumsum Step Form', () => { runner.testResetSelectedIndex(); it('should convert editedStep from old configurations to new configuration', async () => { - const wrapper = runner.shallowMount( - {}, - { - propsData: { - initialStepValue: { - name: 'cumsum', - valueColumn: 'foo', - newColumn: 'bar', - referenceColumn: 'toto', - }, + const wrapper = runner.shallowMount({ + propsData: { + initialStepValue: { + name: 'cumsum', + valueColumn: 'foo', + newColumn: 'bar', + referenceColumn: 'toto', }, }, - ); + }); await wrapper.vm.$nextTick(); expect(wrapper.vm.$data.editedStep.toCumSum).toBeDefined(); expect(wrapper.vm.$data.editedStep.toCumSum).toEqual([['foo', 'bar']]); @@ -118,18 +108,15 @@ describe('Cumsum Step Form', () => { }); it('should pass down "toCumSum" to ListWidget', async () => { - const wrapper = runner.shallowMount( - {}, - { - data: { - editedStep: { - name: 'cumsum', - toCumSum: [['foo', 'bar']], - referenceColumn: 'toto', - }, + const wrapper = runner.shallowMount({ + data: { + editedStep: { + name: 'cumsum', + toCumSum: [['foo', 'bar']], + referenceColumn: 'toto', }, }, - ); + }); await wrapper.vm.$nextTick(); expect(wrapper.find('listwidget-stub').props().value).toEqual([['foo', 'bar']]); }); diff --git a/ui/tests/unit/custom-step-form.spec.ts b/ui/tests/unit/custom-step-form.spec.ts index ae1cf685f9..298d6b699b 100644 --- a/ui/tests/unit/custom-step-form.spec.ts +++ b/ui/tests/unit/custom-step-form.spec.ts @@ -26,6 +26,7 @@ describe('Custom Step Form', () => { { testlabel: 'submitted query is not json', // only for translator: mongo40 (which is default translator) props: { + translator: 'mongo40', initialStepValue: { name: 'custom', query: 'a', diff --git a/ui/tests/unit/dateextract-step-form.spec.ts b/ui/tests/unit/dateextract-step-form.spec.ts index c4fb808a6e..b52cf1dd73 100644 --- a/ui/tests/unit/dateextract-step-form.spec.ts +++ b/ui/tests/unit/dateextract-step-form.spec.ts @@ -40,16 +40,8 @@ describe('DateExtract Step Form', () => { runner.testValidate({ testlabel: 'submitted data is valid', - store: { - dataset: { - headers: [ - { name: 'foo', type: 'date' }, - { name: 'bar', type: 'string' }, - ], - data: [[null], [null]], - }, - }, props: { + columnTypes: { foo: 'date', bar: 'string' }, initialStepValue: { name: 'dateextract', column: 'foo', @@ -59,35 +51,21 @@ describe('DateExtract Step Form', () => { }, }); - runner.testCancel({ - currentPipelineName: 'default_pipeline', - pipelines: { - default_pipeline: [ - { name: 'domain', domain: 'foo' }, - { name: 'rename', toRename: [['foo', 'bar']] }, - { name: 'rename', toRename: [['baz', 'spam']] }, - { name: 'rename', toRename: [['tic', 'tac']] }, - ], - }, - selectedStepIndex: 2, - }); + runner.testCancel(); runner.testResetSelectedIndex(); it('should pass down the right value to Multiselect', async () => { - const wrapper = runner.shallowMount( - {}, - { - data: { - editedStep: { - name: 'dateextract', - column: 'foo', - dateInfo: ['year', 'month', 'day'], - newColumns: ['foo_year', 'foo_month', 'foo_day'], - }, + const wrapper = runner.shallowMount({ + data: { + editedStep: { + name: 'dateextract', + column: 'foo', + dateInfo: ['year', 'month', 'day'], + newColumns: ['foo_year', 'foo_month', 'foo_day'], }, }, - ); + }); await wrapper.vm.$nextTick(); expect(wrapper.find('multiselectwidget-stub').props('value')).toEqual([ { info: 'year', label: 'year' }, @@ -109,19 +87,16 @@ describe('DateExtract Step Form', () => { }); it('should convert editedStep from old configurations to new configuration', () => { - const wrapper = runner.shallowMount( - {}, - { - propsData: { - initialStepValue: { - name: 'dateextract', - column: 'foo', - operation: 'day', - newColumnName: 'bar', - }, + const wrapper = runner.shallowMount({ + propsData: { + initialStepValue: { + name: 'dateextract', + column: 'foo', + operation: 'day', + newColumnName: 'bar', }, }, - ); + }); expect(wrapper.vm.$data.editedStep.dateInfo).toEqual(['day']); expect(wrapper.vm.$data.editedStep.newColumns).toEqual(['bar']); expect(wrapper.vm.$data.editedStep.operation).toBeUndefined(); @@ -129,8 +104,10 @@ describe('DateExtract Step Form', () => { }); it('should set newColumns automatically at submit', () => { - const initialState = { dataset: { headers: [{ name: 'foo_day', type: 'number' }] } }; - const wrapper = runner.mount(initialState, { + const wrapper = runner.mount({ + propsData: { + columnTypes: { foo_day: 'number' }, + }, data: { editedStep: { name: 'dateextract', diff --git a/ui/tests/unit/delete-column-step-form.spec.ts b/ui/tests/unit/delete-column-step-form.spec.ts index 87735b4e9d..8ff5d69512 100644 --- a/ui/tests/unit/delete-column-step-form.spec.ts +++ b/ui/tests/unit/delete-column-step-form.spec.ts @@ -27,51 +27,34 @@ describe('Delete Column Step Form', () => { }, }); - runner.testCancel({ - currentPipelineName: 'default_pipeline', - pipelines: { - default_pipeline: [ - { name: 'domain', domain: 'foo' }, - { name: 'rename', toRename: [['foo', 'bar']] }, - ], - }, - selectedStepIndex: 1, - }); + runner.testCancel(); runner.testResetSelectedIndex(); it('should instantiate a multiselect widget with proper options from the store', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); const widgetAutocomplete = wrapper.find('multiselectwidget-stub'); expect(widgetAutocomplete.attributes('options')).toEqual('columnA,columnB,columnC'); }); it('should update selectedColumn when column is changed', async () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], - }, - selectedColumns: ['columnA'], - }; - const wrapper = runner.mount(initialState, { + const wrapper = runner.mount({ propsData: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, + selectedColumns: ['columnA'], initialValue: { columns: ['columnA'], }, }, data: { editedStep: { columns: ['columnB'] } }, }); - const store = runner.getStore(); wrapper.find(MultiselectWidget).trigger('input'); await wrapper.vm.$nextTick(); - expect(store.selectedColumns).toEqual(['columnB']); + expect(wrapper.emitted().setSelectedColumns).toEqual([[{ column: 'columnB' }]]); }); }); diff --git a/ui/tests/unit/dissolve-step-form.spec.ts b/ui/tests/unit/dissolve-step-form.spec.ts index ccd839e173..256e8e46df 100644 --- a/ui/tests/unit/dissolve-step-form.spec.ts +++ b/ui/tests/unit/dissolve-step-form.spec.ts @@ -15,19 +15,17 @@ describe('Dissolve Step Form', () => { describe('MultiselectWidget', () => { it('should instantiate an MultiselectWidget widget with proper options from the store', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); const widgetMultiselect = wrapper.find('multiselectwidget-stub'); expect(widgetMultiselect.attributes('options')).toEqual('columnA,columnB,columnC'); }); it('includeNulls should be set properly if defined in inititalStepValue', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ propsData: { initialStepValue: { name: 'dissolve', @@ -42,7 +40,7 @@ describe('Dissolve Step Form', () => { }); it('should pass down the "on" prop to the MultiselectWidget value prop', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'dissolve', @@ -64,7 +62,7 @@ describe('Dissolve Step Form', () => { }); it('should pass down the "aggregations" prop to the ListWidget value prop', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'dissolve', @@ -154,7 +152,7 @@ describe('Dissolve Step Form', () => { }); it('should keep the same column name as newcolumn if only one aggregation is performed', () => { - const wrapper = runner.mount(undefined, { + const wrapper = runner.mount({ data: { editedStep: { name: 'dissolve', @@ -169,7 +167,7 @@ describe('Dissolve Step Form', () => { }); it('should set newcolumn cleverly if several aggregations are performed on the same column', () => { - const wrapper = runner.mount(undefined, { + const wrapper = runner.mount({ data: { editedStep: { name: 'dissolve', @@ -190,7 +188,7 @@ describe('Dissolve Step Form', () => { }); it('should set newcolumn cleverly if the an aggregation is perform on an id column', () => { - const wrapper = runner.mount(undefined, { + const wrapper = runner.mount({ data: { editedStep: { name: 'dissolve', diff --git a/ui/tests/unit/domain-step-form.spec.ts b/ui/tests/unit/domain-step-form.spec.ts index 0b4a53c43f..d9227960ff 100644 --- a/ui/tests/unit/domain-step-form.spec.ts +++ b/ui/tests/unit/domain-step-form.spec.ts @@ -30,7 +30,14 @@ describe('Domain Step Form', () => { runner.testCancel(); it('should instantiate an autocomplete widget with proper options from the store', () => { - const wrapper = runner.shallowMount({ domains: ['foo', 'bar'] }); + const wrapper = runner.shallowMount({ + propsData: { + availableDomains: [ + { name: 'bar', uid: 'bar' }, + { name: 'foo', uid: 'foo' }, + ], + }, + }); const widgetAutocomplete = wrapper.find('autocompletewidget-stub'); expect(widgetAutocomplete.attributes('options')).toEqual('bar,foo'); diff --git a/ui/tests/unit/duplicate-column-step-form.spec.ts b/ui/tests/unit/duplicate-column-step-form.spec.ts index 2c5236793e..c3fa998895 100644 --- a/ui/tests/unit/duplicate-column-step-form.spec.ts +++ b/ui/tests/unit/duplicate-column-step-form.spec.ts @@ -17,7 +17,10 @@ describe('Duplicate Column Step Form', () => { runner.testValidationErrors([ { testlabel: 'no submitted data', - props: { initialStepValue: { name: 'duplicate', column: '', newColumnName: '' } }, + props: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, + initialStepValue: { name: 'duplicate', column: '', newColumnName: '' }, + }, errors: [ { keyword: 'minLength', dataPath: '.column' }, { keyword: 'minLength', dataPath: '.newColumnName' }, @@ -25,12 +28,6 @@ describe('Duplicate Column Step Form', () => { }, { testlabel: 'existing column name', - store: { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], - }, - }, data: { editedStep: { name: 'duplicate', column: 'foo', newColumnName: 'columnA' } }, errors: [{ keyword: 'columnNameAlreadyUsed', dataPath: '.newColumnName' }], }, diff --git a/ui/tests/unit/evolution-step-form.spec.ts b/ui/tests/unit/evolution-step-form.spec.ts index 0a3167e081..80bbbe9faa 100644 --- a/ui/tests/unit/evolution-step-form.spec.ts +++ b/ui/tests/unit/evolution-step-form.spec.ts @@ -38,12 +38,6 @@ describe('Evolution Step Form', () => { }, { testlabel: 'existing column name', - store: { - dataset: { - headers: [{ name: 'foo' }], - data: [], - }, - }, data: { editedStep: { name: 'evolution', @@ -54,12 +48,15 @@ describe('Evolution Step Form', () => { newColumn: 'foo', }, }, + props: { + columnTypes: { foo: 'string' }, + }, errors: [{ keyword: 'columnNameAlreadyUsed', dataPath: '.newColumn' }], }, ]); it('should pass down props to widgets', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'evolution', @@ -82,7 +79,7 @@ describe('Evolution Step Form', () => { }); it('should pass set evolutionFormat properly', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'evolution', @@ -101,7 +98,7 @@ describe('Evolution Step Form', () => { }); it('should pass set evolutionType properly', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'evolution', diff --git a/ui/tests/unit/fillna-step-form.spec.ts b/ui/tests/unit/fillna-step-form.spec.ts index dc40e52afd..9dce6da211 100644 --- a/ui/tests/unit/fillna-step-form.spec.ts +++ b/ui/tests/unit/fillna-step-form.spec.ts @@ -17,11 +17,8 @@ describe('Fillna Step Form', () => { runner.testValidationErrors([ { testlabel: 'submitted data is not valid', - store: { - dataset: { - headers: [{ name: 'columnA' }], - data: [[null]], - }, + props: { + columnTypes: { columnA: 'string' }, }, data: { editedStep: { name: 'fillna', columns: ['columnA'], value: { foo: 'bar' } }, @@ -33,11 +30,8 @@ describe('Fillna Step Form', () => { runner.testValidationErrors([ { testlabel: 'should NOT have fewer than 1 items', - store: { - dataset: { - headers: [{ name: 'columnA' }], - data: [[null]], - }, + props: { + columnTypes: { columnA: 'string' }, }, data: { editedStep: { name: 'fillna', columns: [], value: 'bar' }, @@ -47,13 +41,8 @@ describe('Fillna Step Form', () => { ]); runner.testValidate({ - store: { - dataset: { - headers: [{ name: 'foo' }], - data: [[null]], - }, - }, props: { + columnTypes: { foo: 'string' }, initialStepValue: { name: 'fillna', columns: ['foo', 'toto'], value: 'bar' }, }, }); @@ -62,15 +51,10 @@ describe('Fillna Step Form', () => { runner.testResetSelectedIndex(); it('should update editedStep at creation depending on the selected column', async () => { - const initialState = { - dataset: { - headers: [{ name: 'toto' }, { name: 'foo' }], - data: [], - }, - selectedColumns: ['toto'], - }; - const wrapper = runner.shallowMount(initialState, { + const wrapper = runner.shallowMount({ propsData: { + columnTypes: { toto: 'string', foo: 'string' }, + selectedColumns: ['toto'], initialStepValue: { name: 'fillna', columns: [''], @@ -82,16 +66,11 @@ describe('Fillna Step Form', () => { }); it('should return an error if trying to set a null column', async () => { - const initialState = { - dataset: { - headers: [{ name: 'toto' }, { name: 'foo' }], - data: [], - }, - selectedColumns: [null], - }; try { - const wrapper = runner.shallowMount(initialState, { + const wrapper = runner.shallowMount({ propsData: { + selectedColumns: [null], + columnTypes: { toto: 'string', foo: 'string' }, initialStepValue: { name: 'fillna', columns: [''], @@ -105,18 +84,15 @@ describe('Fillna Step Form', () => { }); it('should convert editedStep from old configurations to new configuration', async () => { - const wrapper = runner.shallowMount( - {}, - { - propsData: { - initialStepValue: { - name: 'fillna', - column: 'hello', - value: 0, - }, + const wrapper = runner.shallowMount({ + propsData: { + initialStepValue: { + name: 'fillna', + column: 'hello', + value: 0, }, }, - ); + }); await wrapper.vm.$nextTick(); expect(wrapper.vm.$data.editedStep.column).toBeUndefined; expect(wrapper.vm.$data.editedStep.columns).toBeDefined; @@ -137,92 +113,67 @@ describe('Fillna Step Form', () => { }); it('should convert input value to integer when the column data type is integer', () => { - const wrapper = runner.mount( - { - dataset: { - headers: [{ name: 'columnA', type: 'integer' }], - data: [[null]], - }, + const wrapper = runner.mount({ + propsData: { + columnTypes: { columnA: 'integer' }, }, - { - data: { - editedStep: { name: 'fillna', columns: ['columnA'], value: '42' }, - }, + data: { + editedStep: { name: 'fillna', columns: ['columnA'], value: '42' }, }, - ); + }); wrapper.find('.widget-form-action__button--validate').trigger('click'); expect(wrapper.vm.$data.errors).toBeNull(); - expect(wrapper.emitted()).toEqual({ - formSaved: [[{ name: 'fillna', columns: ['columnA'], value: 42 }]], - }); + expect(wrapper.emitted().formSaved).toEqual([ + [{ name: 'fillna', columns: ['columnA'], value: 42 }], + ]); }); it('should convert input value to float when the column data type is float', () => { - const wrapper = runner.mount( - { - dataset: { - headers: [{ name: 'columnA', type: 'float' }], - data: [[null]], - }, + const wrapper = runner.mount({ + propsData: { + columnTypes: { columnA: 'float' }, }, - { - data: { - editedStep: { name: 'fillna', columns: ['columnA'], value: '42.3' }, - }, + data: { + editedStep: { name: 'fillna', columns: ['columnA'], value: '42.3' }, }, - ); + }); wrapper.find('.widget-form-action__button--validate').trigger('click'); expect(wrapper.vm.$data.errors).toBeNull(); - expect(wrapper.emitted()).toEqual({ - formSaved: [[{ name: 'fillna', columns: ['columnA'], value: 42.3 }]], - }); + expect(wrapper.emitted().formSaved).toEqual([ + [{ name: 'fillna', columns: ['columnA'], value: 42.3 }], + ]); }); it('should convert input value to boolean when the column data type is boolean', () => { - const wrapper = runner.mount( - { - dataset: { - headers: [{ name: 'columnA', type: 'boolean' }], - data: [[null]], - }, + const wrapper = runner.mount({ + propsData: { + columnTypes: { columnA: 'boolean' }, }, - { - data: { - editedStep: { name: 'fillna', columns: ['columnA'], value: 'true' }, - }, + data: { + editedStep: { name: 'fillna', columns: ['columnA'], value: 'true' }, }, - ); - wrapper.find('.widget-form-action__button--validate').trigger('click'); - wrapper.setData({ editedStep: { name: 'fillna', columns: ['columnA'], value: 'false' } }); + }); wrapper.find('.widget-form-action__button--validate').trigger('click'); expect(wrapper.vm.$data.errors).toBeNull(); - expect(wrapper.emitted()).toEqual({ - formSaved: [ - [{ name: 'fillna', columns: ['columnA'], value: true }], - [{ name: 'fillna', columns: ['columnA'], value: false }], - ], - }); + expect(wrapper.emitted().formSaved).toEqual([ + [{ name: 'fillna', column: undefined, columns: ['columnA'], value: true }], + ]); }); it('should accept templatable values', () => { - const wrapper = runner.mount( - { - dataset: { - headers: [{ name: 'foo', type: 'integer' }], - data: [[null]], - }, + const wrapper = runner.mount({ + propsData: { + columnTypes: { foo: 'integer' }, variables: { foo: 'bla', }, }, - { - data: { editedStep: { name: 'fillna', columns: ['foo'], value: '<%= foo %>' } }, - }, - ); + data: { editedStep: { name: 'fillna', columns: ['foo'], value: '<%= foo %>' } }, + }); wrapper.find('.widget-form-action__button--validate').trigger('click'); expect(wrapper.vm.$data.errors).toBeNull(); - expect(wrapper.emitted()).toEqual({ - formSaved: [[{ name: 'fillna', columns: ['foo'], value: '<%= foo %>' }]], - }); + expect(wrapper.emitted().formSaved).toEqual([ + [{ name: 'fillna', columns: ['foo'], value: '<%= foo %>' }], + ]); }); }); diff --git a/ui/tests/unit/filter-step-form.spec.ts b/ui/tests/unit/filter-step-form.spec.ts index cb44c97319..6d8bf08e24 100644 --- a/ui/tests/unit/filter-step-form.spec.ts +++ b/ui/tests/unit/filter-step-form.spec.ts @@ -16,10 +16,9 @@ describe('Filter Step Form', () => { runner.testValidationErrors([ { testlabel: 'submitted data is not valid', - store: { - dataset: { - headers: [{ name: 'foo', type: 'string' }], - data: [[null]], + props: { + propsData: { + columnTypes: { foo: 'string' }, }, }, data: { @@ -36,13 +35,8 @@ describe('Filter Step Form', () => { ]); runner.testValidate({ - store: { - dataset: { - headers: [{ name: 'foo', type: 'string' }], - data: [[null]], - }, - }, props: { + columnTypes: { foo: 'string' }, initialStepValue: { name: 'filter', condition: { @@ -62,22 +56,17 @@ describe('Filter Step Form', () => { let wrapper: Wrapper; beforeEach(async () => { - wrapper = runner.shallowMount( - { - dataset: { - headers: [{ name: 'foo', type: 'string' }], - data: [[null]], - }, + wrapper = runner.shallowMount({ + propsData: { + columnTypes: { foo: 'string' }, }, - { - data: { - editedStep: { - name: 'filter', - condition: { column: 'foo', value: 'bar', operator: 'gt' }, - }, + data: { + editedStep: { + name: 'filter', + condition: { column: 'foo', value: 'bar', operator: 'gt' }, }, }, - ); + }); await wrapper.vm.$nextTick(); }); @@ -97,7 +86,7 @@ describe('Filter Step Form', () => { }); it('should update editedStep with the new filter tree', () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'filter', @@ -123,47 +112,29 @@ describe('Filter Step Form', () => { }); it('should use selected column at creation', () => { - const initialState = { - dataset: { - headers: [ - { name: 'foo', type: 'string' }, - { name: 'bar', type: 'string' }, - ], - data: [[null]], + const wrapper = runner.mount({ + propsData: { + columnTypes: { foo: 'string', bar: 'string' }, + selectedColumns: ['bar'], }, - selectedColumns: ['bar'], - }; - const wrapper = runner.mount(initialState); + }); expect(wrapper.vm.$data.editedStep.condition.column).toEqual('bar'); }); it('should have no default column if no selected column', () => { - const initialState = { - dataset: { - headers: [ - { name: 'foo', type: 'string' }, - { name: 'bar', type: 'string' }, - ], - data: [[null]], + const wrapper = runner.mount({ + propsData: { + columnTypes: { foo: 'string', bar: 'string' }, }, - }; - const wrapper = runner.mount(initialState); + }); expect(wrapper.vm.$data.editedStep.condition.column).toEqual(''); }); it('should not use selected column on edition', () => { - const initialState = { - dataset: { - headers: [ - { name: 'foo', type: 'string' }, - { name: 'bar', type: 'string' }, - ], - data: [[null]], - }, - selectedColumns: ['bar'], - }; - const wrapper = runner.mount(initialState, { + const wrapper = runner.mount({ propsData: { + columnTypes: { foo: 'string', bar: 'string' }, + selectedColumns: ['bar'], isStepCreation: false, initialStepValue: { name: 'filter', @@ -178,14 +149,9 @@ describe('Filter Step Form', () => { }); it('should not raise errors with undefined or empty value', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA', type: 'boolean' }], - data: [[null]], - }, - }; - const wrapper = runner.mount(initialState, { + const wrapper = runner.mount({ propsData: { + columnTypes: { columnA: 'boolean' }, initialStepValue: { name: 'filter', condition: { column: 'columnA', operator: 'eq', value: '' }, @@ -194,15 +160,13 @@ describe('Filter Step Form', () => { }); wrapper.find('.widget-form-action__button--validate').trigger('click'); expect(wrapper.vm.$data.errors).toBeNull(); - expect(wrapper.emitted()).toEqual({ - formSaved: [ - [ - { - name: 'filter', - condition: { column: 'columnA', operator: 'eq', value: '' }, - }, - ], + expect(wrapper.emitted().formSaved).toEqual([ + [ + { + name: 'filter', + condition: { column: 'columnA', operator: 'eq', value: '' }, + }, ], - }); + ]); }); }); diff --git a/ui/tests/unit/formula-step-form.spec.ts b/ui/tests/unit/formula-step-form.spec.ts index b12b3762ae..a04bc7c776 100644 --- a/ui/tests/unit/formula-step-form.spec.ts +++ b/ui/tests/unit/formula-step-form.spec.ts @@ -49,13 +49,11 @@ describe('Formula Step Form', () => { runner.testValidate({ testlabel: 'submitted formula contains variables', props: { - initialStepValue: { name: 'formula', formula: '<%= some_var %>', newColumn: 'foo' }, - }, - store: { variableDelimiters: { start: '<%=', end: '%>', }, + initialStepValue: { name: 'formula', formula: '<%= some_var %>', newColumn: 'foo' }, }, }); @@ -63,12 +61,9 @@ describe('Formula Step Form', () => { runner.testResetSelectedIndex(); it('should pass down properties', async () => { - const wrapper = runner.shallowMount( - {}, - { - data: { editedStep: { name: 'formula', formula: 'ColumnA * 2', newColumn: 'foo' } }, - }, - ); + const wrapper = runner.shallowMount({ + data: { editedStep: { name: 'formula', formula: 'ColumnA * 2', newColumn: 'foo' } }, + }); await wrapper.vm.$nextTick(); expect(wrapper.find('.newColumnInput').props('value')).toEqual('foo'); expect(wrapper.find('.formulaInput').props('value')).toEqual('ColumnA * 2'); @@ -76,13 +71,10 @@ describe('Formula Step Form', () => { describe('Warning', () => { it('should report a warning when newColumn is an already existing column name', async () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState, { data: { editedStep: { formula: '', newColumn: 'columnA' } }, }); await wrapper.vm.$nextTick(); @@ -92,13 +84,10 @@ describe('Formula Step Form', () => { }); it('should not report any warning if newColumn is not an already existing column name', async () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState, { data: { editedStep: { formula: '', newColumn: 'columnB' } }, }); await wrapper.vm.$nextTick(); @@ -107,17 +96,13 @@ describe('Formula Step Form', () => { }); it('should make the focus on the column modified after validation', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = runner.mount({ + propsData: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, }, - }; - const wrapper = runner.mount(initialState, { data: { editedStep: { name: 'formula', formula: 'ColumnA * 2', newColumn: 'foo' } }, }); - const store = runner.getStore(); wrapper.find('.widget-form-action__button--validate').trigger('click'); - expect(store.selectedColumns).toEqual(['foo']); + expect(wrapper.emitted().setSelectedColumns).toEqual([[{ column: 'foo' }]]); }); }); diff --git a/ui/tests/unit/fromdate-step-form.spec.ts b/ui/tests/unit/fromdate-step-form.spec.ts index 7501469768..6475a2afa6 100644 --- a/ui/tests/unit/fromdate-step-form.spec.ts +++ b/ui/tests/unit/fromdate-step-form.spec.ts @@ -1,18 +1,14 @@ -import { createTestingPinia } from '@pinia/testing'; import type { Wrapper } from '@vue/test-utils'; import { createLocalVue, shallowMount } from '@vue/test-utils'; -import { PiniaVuePlugin } from 'pinia'; import { describe, expect, it, vi } from 'vitest'; import FromDateStepForm from '@/components/stepforms/FromDateStepForm.vue'; -import { BasicStepFormTestRunner, setupMockStore } from './utils'; +import { BasicStepFormTestRunner } from './utils'; vi.mock('@/components/FAIcon.vue'); const localVue = createLocalVue(); -localVue.use(PiniaVuePlugin); -const pinia = createTestingPinia({ createSpy: vi.fn, stubActions: false }); describe('Convert Date to String Step Form', () => { const runner = new BasicStepFormTestRunner(FromDateStepForm, 'fromdate'); @@ -24,9 +20,7 @@ describe('Convert Date to String Step Form', () => { }); it('should have 1 inputtext when custom format is selected', () => { - setupMockStore({}); const wrapper = shallowMount(FromDateStepForm, { - pinia, localVue, propsData: { initialStepValue: { name: 'fromdate', column: '', format: '' }, @@ -37,22 +31,17 @@ describe('Convert Date to String Step Form', () => { }); it('should update editedStep with the selected column at creation', () => { - setupMockStore({}); - const initialState = { - dataset: { - headers: [{ name: 'foo', type: 'string' }], - data: [[null]], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { foo: 'string' }, + selectedColumns: ['foo'], }, - selectedColumns: ['foo'], - }; - const wrapper = runner.shallowMount(initialState); + }); expect(wrapper.vm.$data.editedStep.column).toEqual('foo'); }); it('should update editedStep.format properly when a new format is selected', () => { - setupMockStore({}); const wrapper = shallowMount(FromDateStepForm, { - pinia, localVue, }); wrapper @@ -65,9 +54,7 @@ describe('Convert Date to String Step Form', () => { expect(wrapper.vm.$data.editedStep.format).toEqual('%Y-%m'); }); it('should toggle custom format input correctly when switching selected format', () => { - setupMockStore({}); const wrapper = shallowMount(FromDateStepForm, { - pinia, localVue, }); wrapper @@ -85,10 +72,8 @@ describe('Convert Date to String Step Form', () => { }); describe('when user delete content of custom format input', () => { - setupMockStore({}); it('should return empty string as format', () => { const wrapper = shallowMount(FromDateStepForm, { - pinia, localVue, propsData: { initialStepValue: { name: 'todate', format: '%Y %m %d %d', column: 'wdc' }, @@ -104,9 +89,7 @@ describe('Convert Date to String Step Form', () => { let wrapper: Wrapper; const createWrapper = (format: string) => { if (wrapper) wrapper.destroy(); - setupMockStore({}); wrapper = shallowMount(FromDateStepForm, { - pinia, localVue, propsData: { initialStepValue: { name: 'fromdate', column: '', format }, diff --git a/ui/tests/unit/hierarchy-step-form.spec.ts b/ui/tests/unit/hierarchy-step-form.spec.ts index d4c00840fc..fdb6977374 100644 --- a/ui/tests/unit/hierarchy-step-form.spec.ts +++ b/ui/tests/unit/hierarchy-step-form.spec.ts @@ -18,13 +18,8 @@ describe('Hierarchy Step Form', () => { runner.testValidate({ testlabel: 'submitted data is valid', - store: { - dataset: { - headers: [{ name: 'columnA' }], - data: [], - }, - }, props: { + columnTypes: { columnA: 'string' }, initialStepValue: { name: 'hierarchy', hierarchyLevelColumn: 'type', diff --git a/ui/tests/unit/ifthenelse-step-form.spec.ts b/ui/tests/unit/ifthenelse-step-form.spec.ts index fbf9334744..af5495dc82 100644 --- a/ui/tests/unit/ifthenelse-step-form.spec.ts +++ b/ui/tests/unit/ifthenelse-step-form.spec.ts @@ -17,11 +17,8 @@ describe('If...Then...Else Step Form', () => { runner.testValidationErrors([ { testlabel: 'submitted data is not valid', - store: { - dataset: { - headers: [{ name: 'foo', type: 'string' }], - data: [[null]], - }, + props: { + columnTypes: { foo: 'string' }, }, data: { editedStep: { @@ -70,13 +67,8 @@ describe('If...Then...Else Step Form', () => { ]); runner.testValidate({ - store: { - dataset: { - headers: [{ name: 'foo', type: 'string' }], - data: [[null]], - }, - }, props: { + columnTypes: { foo: 'string' }, initialStepValue: { name: 'ifthenelse', newColumn: 'new', @@ -92,13 +84,11 @@ describe('If...Then...Else Step Form', () => { describe('Warning new column name', () => { it('should report a warning when newColumn is an already existing column name', async () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); wrapper.setData({ editedStep: { name: 'ifthenelse', @@ -115,13 +105,11 @@ describe('If...Then...Else Step Form', () => { }); it('should not report any warning if newColumn is not an already existing column name', async () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); wrapper.setData({ editedStep: { name: 'ifthenelse', @@ -138,9 +126,8 @@ describe('If...Then...Else Step Form', () => { it('should pass the column types to the IfThenElse widget', () => { const wrapper = runner.shallowMount({ - dataset: { - headers: [{ name: 'foo', type: 'string' }], - data: [], + propsData: { + columnTypes: { foo: 'string' }, }, }); expect(wrapper.find('IfThenElseWidget-stub').props().columnTypes).toStrictEqual({ @@ -149,7 +136,7 @@ describe('If...Then...Else Step Form', () => { }); it('should update editedStep with the if...then...else object', () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'ifthenelse', diff --git a/ui/tests/unit/join-step-form.spec.ts b/ui/tests/unit/join-step-form.spec.ts index 91a9761434..c16009d2dd 100644 --- a/ui/tests/unit/join-step-form.spec.ts +++ b/ui/tests/unit/join-step-form.spec.ts @@ -31,15 +31,15 @@ describe('join Step Form', () => { describe('right dataset', () => { it('should instantiate an autocomplete widget with proper options from the store', () => { - const initialState = { - currentPipelineName: 'my_dataset', - availableDomains: [ - { name: 'dataset1', uid: '1' }, - { name: 'dataset2', uid: '2' }, - ], - unjoinableDomains: [{ name: 'dataset2', uid: '2' }], - }; - const wrapper = runner.shallowMount(initialState); + const wrapper = runner.shallowMount({ + propsData: { + availableDomains: [ + { name: 'dataset1', uid: '1' }, + { name: 'dataset2', uid: '2' }, + ], + unjoinableDomains: [{ name: 'dataset2', uid: '2' }], + }, + }); const widgetMultiselect = wrapper.find('autocompletewidget-stub'); expect(widgetMultiselect.props('options')).toEqual([ { trackBy: { type: 'ref', uid: '1' }, label: 'dataset1' }, @@ -57,15 +57,14 @@ describe('join Step Form', () => { }); it('should handle dataset references', async () => { - const initialState = { - currentPipelineName: 'my_dataset', - availableDomains: [ - { name: 'dataset1', uid: '1' }, - { name: 'dataset2', uid: '2' }, - ], - unjoinableDomains: [], - }; - const wrapper = runner.shallowMount(initialState, { + const wrapper = runner.shallowMount({ + propsData: { + availableDomains: [ + { name: 'dataset1', uid: '1' }, + { name: 'dataset2', uid: '2' }, + ], + unjoinableDomains: [], + }, data: { editedStep: { name: 'join', @@ -84,7 +83,7 @@ describe('join Step Form', () => { describe('column names', () => { it('should pass down the "joinColumns" prop to the ListWidget value prop', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'join', @@ -99,7 +98,7 @@ describe('join Step Form', () => { }); it('should get the right data "on" when editedStep.on is empty', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'join', @@ -114,7 +113,7 @@ describe('join Step Form', () => { }); it('should update the edited step when one of the subcomponents emits an updated value', () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'join', @@ -129,7 +128,7 @@ describe('join Step Form', () => { }); it('should fetch the right dataset columns when editing an existing step', () => { - runner.shallowMount(undefined, { + runner.shallowMount({ propsData: { initialStepValue: { name: 'join', diff --git a/ui/tests/unit/moving-average-step-form.spec.ts b/ui/tests/unit/moving-average-step-form.spec.ts index 5808df112f..f7d38385c9 100644 --- a/ui/tests/unit/moving-average-step-form.spec.ts +++ b/ui/tests/unit/moving-average-step-form.spec.ts @@ -44,7 +44,7 @@ describe('Moving Average Step Form', () => { runner.testResetSelectedIndex(); it('should pass down the properties to the input components', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'movingaverage', @@ -69,42 +69,36 @@ describe('Moving Average Step Form', () => { const compiled = _.template(s); return compiled(context); } - const wrapper = runner.mount( - { + const wrapper = runner.mount({ + propsData: { + initialStepValue: { + name: 'movingaverage', + valueColumn: 'foo', + columnToSort: 'bar', + movingWindow: '<%= movedWidow %>', + groups: ['test'], + newColumnName: 'toto', + }, variables: { movedWidow: 42, }, interpolateFunc: interpolate, }, - { - propsData: { - initialStepValue: { - name: 'movingaverage', - valueColumn: 'foo', - columnToSort: 'bar', - movingWindow: '<%= movedWidow %>', - groups: ['test'], - newColumnName: 'toto', - }, - }, - }, - ); + }); wrapper.find('.widget-form-action__button--validate').trigger('click'); await wrapper.vm.$nextTick(); expect(wrapper.vm.$data.errors).toBeNull(); - expect(wrapper.emitted()).toEqual({ - formSaved: [ - [ - { - name: 'movingaverage', - valueColumn: 'foo', - columnToSort: 'bar', - movingWindow: '<%= movedWidow %>', - groups: ['test'], - newColumnName: 'toto', - }, - ], + expect(wrapper.emitted().formSaved).toEqual([ + [ + { + name: 'movingaverage', + valueColumn: 'foo', + columnToSort: 'bar', + movingWindow: '<%= movedWidow %>', + groups: ['test'], + newColumnName: 'toto', + }, ], - }); + ]); }); }); diff --git a/ui/tests/unit/percentage-step-form.spec.ts b/ui/tests/unit/percentage-step-form.spec.ts index b513aa55c2..56f5f782c8 100644 --- a/ui/tests/unit/percentage-step-form.spec.ts +++ b/ui/tests/unit/percentage-step-form.spec.ts @@ -21,11 +21,8 @@ describe('Percentage Step Form', () => { }, { testlabel: 'existing column name', - store: { - dataset: { - headers: [{ name: 'bar' }], - data: [], - }, + props: { + columnTypes: { bar: 'string' }, }, data: { editedStep: { name: 'percentage', column: 'foo', newColumnName: 'bar' } }, errors: [{ keyword: 'columnNameAlreadyUsed', dataPath: '.newColumnName' }], @@ -43,7 +40,7 @@ describe('Percentage Step Form', () => { runner.testResetSelectedIndex(); it('should pass down the properties to the input components', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'percentage', column: 'foo', group: ['test'] }, }, @@ -53,16 +50,13 @@ describe('Percentage Step Form', () => { }); it('should update step when selectedColumn is changed', async () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); - const store = runner.getStore(); + }); expect(wrapper.vm.$data.editedStep.column).toEqual(''); - store.toggleColumnSelection({ column: 'columnB' }); + wrapper.setProps({ selectedColumns: ['columnB'] }); await wrapper.vm.$nextTick(); expect(wrapper.vm.$data.editedStep.column).toEqual('columnB'); }); diff --git a/ui/tests/unit/pivot-step-form.spec.ts b/ui/tests/unit/pivot-step-form.spec.ts index 9264b682af..0934e69642 100644 --- a/ui/tests/unit/pivot-step-form.spec.ts +++ b/ui/tests/unit/pivot-step-form.spec.ts @@ -36,11 +36,8 @@ describe('Pivot Step Form', () => { }, { testlabel: 'index and columnToPivot column names overlap', - store: { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], - }, + props: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, }, data: { editedStep: { @@ -60,11 +57,8 @@ describe('Pivot Step Form', () => { }, { testlabel: 'index and valueColumn column names overlap', - store: { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], - }, + props: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, }, data: { editedStep: { @@ -84,11 +78,8 @@ describe('Pivot Step Form', () => { }, { testlabel: 'columnToPivot and valueColumn are equal', - store: { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], - }, + props: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, }, data: { editedStep: { @@ -109,7 +100,7 @@ describe('Pivot Step Form', () => { ]); it('should pass down props to widgets', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'pivot', @@ -127,24 +118,20 @@ describe('Pivot Step Form', () => { }); it('should instantiate indexInput widget multiselect with column names', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); expect(wrapper.find('.indexInput').attributes('options')).toEqual('columnA,columnB,columnC'); }); it('should instantiate valueColumnInput widget autocomplete with column names', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); expect(wrapper.find('.valueColumnInput').attributes('options')).toEqual( 'columnA,columnB,columnC', ); @@ -158,16 +145,13 @@ describe('Pivot Step Form', () => { }); it('should update step when selectedColumn is changed', async () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); - const store = runner.getStore(); + }); expect(wrapper.vm.$data.editedStep.columnToPivot).toEqual(''); - store.toggleColumnSelection({ column: 'columnB' }); + wrapper.setProps({ selectedColumns: ['columnB'] }); await wrapper.vm.$nextTick(); expect(wrapper.vm.$data.editedStep.columnToPivot).toEqual('columnB'); }); diff --git a/ui/tests/unit/rank-step-form.spec.ts b/ui/tests/unit/rank-step-form.spec.ts index 54ff4d5b6f..5c5c89beec 100644 --- a/ui/tests/unit/rank-step-form.spec.ts +++ b/ui/tests/unit/rank-step-form.spec.ts @@ -18,19 +18,17 @@ describe('Cumsum Step Form', () => { describe('MultiselectWidget', () => { it('should instantiate a MultiselectWidget widget with proper options from the store', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); const widgetMultiselect = wrapper.find('multiselectwidget-stub'); expect(widgetMultiselect.attributes('options')).toEqual('columnA,columnB,columnC'); }); it('should pass down the props to the MultiselectWidget value prop', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'rank', @@ -77,11 +75,8 @@ describe('Cumsum Step Form', () => { }, { testlabel: 'existing column name', - store: { - dataset: { - headers: [{ name: 'columnA' }], - data: [], - }, + props: { + columnTypes: { columnA: 'string' }, }, data: { editedStep: { @@ -98,13 +93,8 @@ describe('Cumsum Step Form', () => { runner.testValidate({ testlabel: 'submitted data is valid', - store: { - dataset: { - headers: [{ name: 'columnA' }], - data: [], - }, - }, props: { + columnTypes: { columnA: 'string' }, initialStepValue: { name: 'rank', valueCol: 'VALUE', diff --git a/ui/tests/unit/rename-step-form.spec.ts b/ui/tests/unit/rename-step-form.spec.ts index 75b6d05eb1..0e4b3dfa1a 100644 --- a/ui/tests/unit/rename-step-form.spec.ts +++ b/ui/tests/unit/rename-step-form.spec.ts @@ -25,16 +25,8 @@ describe('Rename Step Form', () => { runner.testValidate({ testlabel: 'submitted data is valid', - store: { - dataset: { - headers: [ - { name: 'foo', type: 'string' }, - { name: 'hello', type: 'string' }, - ], - data: [], - }, - }, props: { + columnTypes: { toto: 'string', foo: 'string' }, initialStepValue: { name: 'rename', toRename: [['foo', 'bar']] }, }, }); @@ -44,15 +36,10 @@ describe('Rename Step Form', () => { runner.testResetSelectedIndex(); it('should update editedStep at creation depending on the selected column', async () => { - const initialState = { - dataset: { - headers: [{ name: 'toto' }, { name: 'foo' }], - data: [], - }, - selectedColumns: ['toto'], - }; - const wrapper = runner.shallowMount(initialState, { + const wrapper = runner.shallowMount({ propsData: { + columnTypes: { toto: 'string', foo: 'string' }, + selectedColumns: ['toto'], initialStepValue: { name: 'rename', toRename: [['', '']], @@ -64,16 +51,11 @@ describe('Rename Step Form', () => { }); it('should return an error if trying to set a null column', async () => { - const initialState = { - dataset: { - headers: [{ name: 'toto' }, { name: 'foo' }], - data: [], - }, - selectedColumns: [null], - }; try { - const wrapper = runner.shallowMount(initialState, { + const wrapper = runner.shallowMount({ propsData: { + columnTypes: { toto: 'string', foo: 'string' }, + selectedColumns: [null], initialStepValue: { name: 'rename', toRename: [['', '']], @@ -87,35 +69,29 @@ describe('Rename Step Form', () => { }); it('should convert editedStep from old configurations to new configuration', async () => { - const wrapper = runner.shallowMount( - {}, - { - propsData: { - initialStepValue: { - name: 'rename', - oldname: 'foo', - newname: 'bar', - }, + const wrapper = runner.shallowMount({ + propsData: { + initialStepValue: { + name: 'rename', + oldname: 'foo', + newname: 'bar', }, }, - ); + }); await wrapper.vm.$nextTick(); expect(wrapper.vm.$data.editedStep.toRename).toBeDefined(); expect(wrapper.vm.$data.editedStep.toRename).toEqual([['foo', 'bar']]); }); it('should pass down "toRename" to ListWidget', async () => { - const wrapper = runner.shallowMount( - {}, - { - data: { - editedStep: { - name: 'rename', - toRename: [['foo', 'bar']], - }, + const wrapper = runner.shallowMount({ + data: { + editedStep: { + name: 'rename', + toRename: [['foo', 'bar']], }, }, - ); + }); await wrapper.vm.$nextTick(); expect(wrapper.find('listwidget-stub').props().value).toEqual([['foo', 'bar']]); }); @@ -129,13 +105,10 @@ describe('Rename Step Form', () => { }); it('should make the focus on the last column modified at submit', () => { - const initialState = { - dataset: { - headers: [{ name: 'toto' }, { name: 'foo' }], - data: [], + const wrapper = runner.mount({ + propsData: { + columnTypes: { toto: 'string', foo: 'string' }, }, - }; - const wrapper = runner.mount(initialState, { data: { editedStep: { name: 'rename', @@ -146,20 +119,16 @@ describe('Rename Step Form', () => { }, }, }); - const store = runner.getStore(); wrapper.find('.widget-form-action__button--validate').trigger('click'); - expect(store.selectedColumns).toEqual(['bar']); + expect(wrapper.emitted().setSelectedColumns).toEqual([[{ column: 'bar' }]]); }); it('should not change the column focus if validation fails', () => { - const initialState = { - dataset: { - headers: [{ name: 'toto' }, { name: 'foo' }], - data: [], + const wrapper = runner.mount({ + propsData: { + columnTypes: { toto: 'string', foo: 'string' }, + selectedColumns: ['toto'], }, - selectedColumns: ['toto'], - }; - const wrapper = runner.mount(initialState, { data: { editedStep: { name: 'rename', @@ -170,8 +139,7 @@ describe('Rename Step Form', () => { }, }, }); - const store = runner.getStore(); wrapper.find('.widget-form-action__button--validate').trigger('click'); - expect(store.selectedColumns).toEqual(['toto']); + expect(wrapper.emitted().setSelectedColumns).toBeUndefined(); }); }); diff --git a/ui/tests/unit/replace-step-form.spec.ts b/ui/tests/unit/replace-step-form.spec.ts index 4e35409f97..51a76870ea 100644 --- a/ui/tests/unit/replace-step-form.spec.ts +++ b/ui/tests/unit/replace-step-form.spec.ts @@ -15,16 +15,8 @@ describe('Replace Step Form', () => { }); runner.testValidate({ testlabel: 'submitted data is valid', - store: { - dataset: { - headers: [ - { name: 'foo', type: 'string' }, - { name: 'bar', type: 'string' }, - ], - data: [], - }, - }, props: { + columnTypes: { foo: 'string', bar: 'string' }, initialStepValue: { name: 'replace', searchColumn: 'foo', toReplace: [['hello', 'hi']] }, }, }); @@ -33,63 +25,51 @@ describe('Replace Step Form', () => { runner.testResetSelectedIndex(); it('should pass down "searchColumn" to ColumnPicker', async () => { - const wrapper = runner.shallowMount( - {}, - { - data: { - editedStep: { - name: 'replace', - searchColumn: 'test', - toReplace: [['foo', 'bar']], - }, + const wrapper = runner.shallowMount({ + data: { + editedStep: { + name: 'replace', + searchColumn: 'test', + toReplace: [['foo', 'bar']], }, }, - ); + }); await wrapper.vm.$nextTick(); expect(wrapper.find('columnpicker-stub').attributes().value).toEqual('test'); }); it('should pass down "toReplace" to ListWidget', async () => { - const wrapper = runner.shallowMount( - {}, - { - data: { - editedStep: { - name: 'replace', - searchColumn: 'test', - toReplace: [['foo', 'bar']], - }, + const wrapper = runner.shallowMount({ + data: { + editedStep: { + name: 'replace', + searchColumn: 'test', + toReplace: [['foo', 'bar']], }, }, - ); + }); await wrapper.vm.$nextTick(); expect(wrapper.find('listwidget-stub').props().value).toEqual([['foo', 'bar']]); }); it('should pass down the default "toReplace" to ListWidget', () => { - const wrapper = runner.shallowMount( - {}, - { - data: { - editedStep: { - name: 'replace', - searchColumn: 'test', - toReplace: [], - }, + const wrapper = runner.shallowMount({ + data: { + editedStep: { + name: 'replace', + searchColumn: 'test', + toReplace: [], }, }, - ); + }); expect(wrapper.find('listwidget-stub').props().value).toEqual([[]]); }); it('should convert input value to integer when the column data type is integer', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA', type: 'integer' }], - data: [[null]], + const wrapper = runner.mount({ + propsData: { + columnTypes: { columnA: 'integer' }, }, - }; - const wrapper = runner.mount(initialState, { data: { editedStep: { name: 'replace', @@ -100,19 +80,16 @@ describe('Replace Step Form', () => { }); wrapper.find('.widget-form-action__button--validate').trigger('click'); expect(wrapper.vm.$data.errors).toBeNull(); - expect(wrapper.emitted()).toEqual({ - formSaved: [[{ name: 'replace', searchColumn: 'columnA', toReplace: [[0, 42]] }]], - }); + expect(wrapper.emitted().formSaved).toEqual([ + [{ name: 'replace', searchColumn: 'columnA', toReplace: [[0, 42]] }], + ]); }); it('should convert input value to float when the column data type is float', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA', type: 'float' }], - data: [[null]], + const wrapper = runner.mount({ + propsData: { + columnTypes: { columnA: 'float' }, }, - }; - const wrapper = runner.mount(initialState, { data: { editedStep: { name: 'replace', @@ -123,19 +100,16 @@ describe('Replace Step Form', () => { }); wrapper.find('.widget-form-action__button--validate').trigger('click'); expect(wrapper.vm.$data.errors).toBeNull(); - expect(wrapper.emitted()).toEqual({ - formSaved: [[{ name: 'replace', searchColumn: 'columnA', toReplace: [[0, 42.3]] }]], - }); + expect(wrapper.emitted().formSaved).toEqual([ + [{ name: 'replace', searchColumn: 'columnA', toReplace: [[0, 42.3]] }], + ]); }); it('should convert input value to boolean when the column data type is boolean', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA', type: 'boolean' }], - data: [[null]], + const wrapper = runner.mount({ + propsData: { + columnTypes: { columnA: 'boolean' }, }, - }; - const wrapper = runner.mount(initialState, { data: { editedStep: { name: 'replace', @@ -146,8 +120,8 @@ describe('Replace Step Form', () => { }); wrapper.find('.widget-form-action__button--validate').trigger('click'); expect(wrapper.vm.$data.errors).toBeNull(); - expect(wrapper.emitted()).toEqual({ - formSaved: [[{ name: 'replace', searchColumn: 'columnA', toReplace: [[false, true]] }]], - }); + expect(wrapper.emitted().formSaved).toEqual([ + [{ name: 'replace', searchColumn: 'columnA', toReplace: [[false, true]] }], + ]); }); }); diff --git a/ui/tests/unit/replace-text-step-form.spec.ts b/ui/tests/unit/replace-text-step-form.spec.ts index ff74dc9404..cf80256e12 100644 --- a/ui/tests/unit/replace-text-step-form.spec.ts +++ b/ui/tests/unit/replace-text-step-form.spec.ts @@ -15,16 +15,8 @@ describe('Replace Text Step Form', () => { }); runner.testValidate({ testlabel: 'submitted data is valid', - store: { - dataset: { - headers: [ - { name: 'foo', type: 'string' }, - { name: 'bar', type: 'string' }, - ], - data: [], - }, - }, props: { + columnTypes: { toto: 'string', foo: 'string' }, initialStepValue: { name: 'replacetext', searchColumn: 'foo', oldStr: 'old', newStr: 'new' }, }, }); @@ -33,54 +25,45 @@ describe('Replace Text Step Form', () => { runner.testResetSelectedIndex(); it('should pass down "searchColumn" to ColumnPicker', async () => { - const wrapper = runner.shallowMount( - {}, - { - data: { - editedStep: { - name: 'replacetext', - searchColumn: 'test', - oldStr: 'old', - newStr: 'new', - }, + const wrapper = runner.shallowMount({ + data: { + editedStep: { + name: 'replacetext', + searchColumn: 'test', + oldStr: 'old', + newStr: 'new', }, }, - ); + }); await wrapper.vm.$nextTick(); expect(wrapper.find('columnpicker-stub').attributes().value).toEqual('test'); }); it('should pass down "oldStr" to TextInputWidget', async () => { - const wrapper = runner.shallowMount( - {}, - { - data: { - editedStep: { - name: 'replacetext', - searchColumn: 'test', - oldStr: 'coucou', - }, + const wrapper = runner.shallowMount({ + data: { + editedStep: { + name: 'replacetext', + searchColumn: 'test', + oldStr: 'coucou', }, }, - ); + }); await wrapper.vm.$nextTick(); expect(wrapper.find('inputtextwidget-stub').props().value).toEqual('coucou'); }); it('should pass down "newStr" to TextInputWidget', async () => { - const wrapper = runner.shallowMount( - {}, - { - data: { - editedStep: { - name: 'replacetext', - searchColumn: 'test', - oldStr: 'coucou', - newStr: 'hello', - }, + const wrapper = runner.shallowMount({ + data: { + editedStep: { + name: 'replacetext', + searchColumn: 'test', + oldStr: 'coucou', + newStr: 'hello', }, }, - ); + }); await wrapper.vm.$nextTick(); expect(wrapper.findAll('inputtextwidget-stub').at(1).props().value).toEqual('hello'); }); diff --git a/ui/tests/unit/rollup-step-form.spec.ts b/ui/tests/unit/rollup-step-form.spec.ts index b0b30fed7d..5bafe7851a 100644 --- a/ui/tests/unit/rollup-step-form.spec.ts +++ b/ui/tests/unit/rollup-step-form.spec.ts @@ -21,20 +21,18 @@ describe('Rollup Step Form', () => { describe('MultiselectWidgets', () => { it('should instantiate a MultiselectWidget widget with proper options from the store', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); const widgetMultiselects = wrapper.findAll('multiselectwidget-stub'); expect(widgetMultiselects.at(0).attributes('options')).toEqual('columnA,columnB,columnC'); expect(widgetMultiselects.at(1).attributes('options')).toEqual('columnA,columnB,columnC'); }); it('should pass down the props to the MultiselectWidget value prop', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'rollup', @@ -59,7 +57,7 @@ describe('Rollup Step Form', () => { }); it('should pass down the "aggregations" prop to the ListWidget value prop', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'rollup', @@ -262,7 +260,7 @@ describe('Rollup Step Form', () => { { columns: ['bar', 'test'], newcolumns: [''], aggfunction: 'avg' }, ], }; - const wrapper = runner.mount(undefined, { data: { editedStep } }); + const wrapper = runner.mount({ data: { editedStep } }); wrapper.find('.widget-form-action__button--validate').trigger('click'); expect(setAggregationsNewColumnsInStep).toHaveBeenCalled(); expect(setAggregationsNewColumnsInStep).toHaveBeenCalledWith(editedStep); @@ -273,22 +271,19 @@ describe('Rollup Step Form', () => { runner.testResetSelectedIndex(); it('should convert editedStep from old configurations to new configuration', async () => { - const wrapper = runner.shallowMount( - {}, - { - propsData: { - initialStepValue: { - name: 'rollup', - hierarchy: ['foo'], - aggregations: [ - { column: 'foo', newcolumn: 'foo', aggregation: 'sum' }, - { column: 'bar', newcolumn: 'bar', aggregation: 'sum' }, - { columns: ['foo', 'bar'], newcolumns: ['foo', 'bar'], aggregation: 'sum' }, - ], - }, + const wrapper = runner.shallowMount({ + propsData: { + initialStepValue: { + name: 'rollup', + hierarchy: ['foo'], + aggregations: [ + { column: 'foo', newcolumn: 'foo', aggregation: 'sum' }, + { column: 'bar', newcolumn: 'bar', aggregation: 'sum' }, + { columns: ['foo', 'bar'], newcolumns: ['foo', 'bar'], aggregation: 'sum' }, + ], }, }, - ); + }); await wrapper.vm.$nextTick(); expect(wrapper.vm.$data.editedStep.aggregations).toEqual([ { columns: ['foo'], newcolumns: ['foo'], aggregation: 'sum' }, diff --git a/ui/tests/unit/select-column-step-form.spec.ts b/ui/tests/unit/select-column-step-form.spec.ts index f2303b67f7..71baf58b06 100644 --- a/ui/tests/unit/select-column-step-form.spec.ts +++ b/ui/tests/unit/select-column-step-form.spec.ts @@ -31,37 +31,29 @@ describe('Select Column Step Form', () => { runner.testResetSelectedIndex(); it('should instantiate a multiselect widget with proper options from the store', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); const widgetAutocomplete = wrapper.find('multiselectwidget-stub'); expect(widgetAutocomplete.attributes('options')).toEqual('columnA,columnB,columnC'); }); it('should update selectedColumn when column is changed', async () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], - }, - selectedColumns: ['columnA'], - }; - const wrapper = runner.mount(initialState, { + const wrapper = runner.mount({ propsData: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, + selectedColumns: ['columnA'], initialValue: { columns: ['columnA'], }, }, }); - const store = runner.getStore(); wrapper.setData({ editedStep: { columns: ['columnB'] } }); wrapper.find(MultiselectWidget).trigger('input'); await wrapper.vm.$nextTick(); - expect(store.selectedColumns).toEqual(['columnB']); + expect(wrapper.emitted().setSelectedColumns).toEqual([[{ column: 'columnB' }]]); }); }); diff --git a/ui/tests/unit/simplify-step-form.spec.ts b/ui/tests/unit/simplify-step-form.spec.ts index 5028500be3..6749054ffa 100644 --- a/ui/tests/unit/simplify-step-form.spec.ts +++ b/ui/tests/unit/simplify-step-form.spec.ts @@ -17,13 +17,8 @@ describe('Simplify Step Form', () => { runner.testValidate({ testlabel: 'submitted data is valid', - store: { - dataset: { - headers: [{ name: 'columnA' }], - data: [], - }, - }, props: { + columnTypes: { columnA: 'string' }, initialStepValue: { name: 'simplify', tolerance: 1, diff --git a/ui/tests/unit/sort-step-form.spec.ts b/ui/tests/unit/sort-step-form.spec.ts index 6f41b0209a..0b974859f7 100644 --- a/ui/tests/unit/sort-step-form.spec.ts +++ b/ui/tests/unit/sort-step-form.spec.ts @@ -40,24 +40,15 @@ describe('Sort Step Form', () => { }, ); - runner.testCancel({ - currentPipelineName: 'default_pipeline', - pipelines: { - default_pipeline: [ - { name: 'domain', domain: 'foo' }, - { name: 'rename', toRename: [['foo', 'bar']] }, - { name: 'rename', toRename: [['baz', 'spam']] }, - { name: 'rename', toRename: [['tic', 'tac']] }, - ], - }, - selectedStepIndex: 2, - }); + runner.testCancel(); runner.testResetSelectedIndex(); it('should suggest the selected column as the column to be sorted', function () { const wrapper = runner.shallowMount({ - selectedColumns: ['selectedColumn'], + propsData: { + selectedColumns: ['selectedColumn'], + }, }); expect(wrapper.find('listwidget-stub').props().value).toEqual([ { column: 'selectedColumn', order: 'asc' }, @@ -70,34 +61,29 @@ describe('Sort Step Form', () => { }); it('should not suggest a column to be sorted if the step has already been edited', function () { - const wrapper = runner.shallowMount( - { selectedColumns: ['selectedColumn'] }, - { - propsData: { - initialStepValue: { - name: 'sort', - columns: [{ column: 'amazing', order: 'desc' }], - }, + const wrapper = runner.shallowMount({ + propsData: { + selectedColumns: ['selectedColumn'], + initialStepValue: { + name: 'sort', + columns: [{ column: 'amazing', order: 'desc' }], }, }, - ); + }); expect(wrapper.find('listwidget-stub').props().value).toEqual([ { column: 'amazing', order: 'desc' }, ]); }); it('should pass right sort props to widgetList sort column', async () => { - const wrapper = runner.shallowMount( - {}, - { - data: { - editedStep: { - name: 'sort', - columns: [{ column: 'amazing', order: 'desc' }], - }, + const wrapper = runner.shallowMount({ + data: { + editedStep: { + name: 'sort', + columns: [{ column: 'amazing', order: 'desc' }], }, }, - ); + }); await wrapper.vm.$nextTick(); expect(wrapper.find('listwidget-stub').props().value).toEqual([ { column: 'amazing', order: 'desc' }, @@ -105,17 +91,14 @@ describe('Sort Step Form', () => { }); it('should update the editedStep when the list is updated', async () => { - const wrapper = runner.shallowMount( - {}, - { - data: { - editedStep: { - name: 'sort', - columns: [{ column: 'amazing', order: 'desc' }], - }, + const wrapper = runner.shallowMount({ + data: { + editedStep: { + name: 'sort', + columns: [{ column: 'amazing', order: 'desc' }], }, }, - ); + }); wrapper.find('listwidget-stub').vm.$emit('input', [{ column: 'amazing', order: 'desc' }]); expect(wrapper.vm.$data.editedStep.columns).toEqual([{ column: 'amazing', order: 'desc' }]); }); diff --git a/ui/tests/unit/split-step-form.spec.ts b/ui/tests/unit/split-step-form.spec.ts index 0a04d4c5fa..dda645807a 100644 --- a/ui/tests/unit/split-step-form.spec.ts +++ b/ui/tests/unit/split-step-form.spec.ts @@ -35,7 +35,7 @@ describe('Split Step Form', () => { runner.testResetSelectedIndex(); it('should pass down the properties to the input components', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'split', column: 'foo', delimiter: '-', numberColsToKeep: 3 }, }, diff --git a/ui/tests/unit/statistics-step-form.spec.ts b/ui/tests/unit/statistics-step-form.spec.ts index 45d6c2eb1c..ef42a84473 100644 --- a/ui/tests/unit/statistics-step-form.spec.ts +++ b/ui/tests/unit/statistics-step-form.spec.ts @@ -35,40 +35,22 @@ describe('statistics Step Form', () => { }, }); - runner.testCancel({ - currentPipelineName: 'default_pipeline', - pipelines: { - default_pipeline: [ - { name: 'domain', domain: 'foo' }, - { + runner.testCancel(); + + runner.testResetSelectedIndex(); + + it('should pass down the parameters properly to widgets', async () => { + const wrapper = runner.shallowMount({ + data: { + editedStep: { name: 'statistics', column: 'jjg', groupbyColumns: ['plop'], statistics: ['average'], quantiles: [{ label: 'median', nth: 1, order: 2 }], }, - ], - }, - selectedStepIndex: 1, - }); - - runner.testResetSelectedIndex(); - - it('should pass down the parameters properly to widgets', async () => { - const wrapper = runner.shallowMount( - {}, - { - data: { - editedStep: { - name: 'statistics', - column: 'jjg', - groupbyColumns: ['plop'], - statistics: ['average'], - quantiles: [{ label: 'median', nth: 1, order: 2 }], - }, - }, }, - ); + }); await wrapper.vm.$nextTick(); expect(wrapper.find('ColumnPicker-stub').props('value')).toEqual('jjg'); expect(wrapper.find('MultiselectWidget-stub').props('value')).toEqual(['plop']); @@ -87,20 +69,17 @@ describe('statistics Step Form', () => { }); it('should open and close section correcly', async () => { - const wrapper = runner.shallowMount( - {}, - { - data: { - editedStep: { - name: 'statistics', - column: 'jjg', - groupbyColumns: ['plop'], - statistics: ['average'], - quantiles: [{ label: 'median', nth: 1, order: 2 }], - }, + const wrapper = runner.shallowMount({ + data: { + editedStep: { + name: 'statistics', + column: 'jjg', + groupbyColumns: ['plop'], + statistics: ['average'], + quantiles: [{ label: 'median', nth: 1, order: 2 }], }, }, - ); + }); await wrapper.vm.$nextTick(); const basicSection: any = wrapper.findAll('.statistic-section-header').at(0); const advancedSection: any = wrapper.findAll('.statistic-section-header').at(1); @@ -124,20 +103,17 @@ describe('statistics Step Form', () => { }); it('should toogle quantiles and statistics correlty', async () => { - const wrapper = runner.shallowMount( - {}, - { - data: { - editedStep: { - name: 'statistics', - column: 'jjg', - groupbyColumns: ['plop'], - statistics: ['average'], - quantiles: [{ label: 'median', nth: 1, order: 2 }], - }, + const wrapper = runner.shallowMount({ + data: { + editedStep: { + name: 'statistics', + column: 'jjg', + groupbyColumns: ['plop'], + statistics: ['average'], + quantiles: [{ label: 'median', nth: 1, order: 2 }], }, }, - ); + }); await wrapper.vm.$nextTick(); wrapper.findAll('Checkbox-stub').at(0).vm.$emit('input', true); // checking count diff --git a/ui/tests/unit/substring-step-form.spec.ts b/ui/tests/unit/substring-step-form.spec.ts index fa34ef3506..120b40de27 100644 --- a/ui/tests/unit/substring-step-form.spec.ts +++ b/ui/tests/unit/substring-step-form.spec.ts @@ -20,11 +20,8 @@ describe('Substring Step Form', () => { }, { testlabel: 'existing column name', - store: { - dataset: { - headers: [{ name: 'bar' }], - data: [], - }, + props: { + columnTypes: { bar: 'string' }, }, data: { editedStep: { @@ -55,7 +52,7 @@ describe('Substring Step Form', () => { runner.testResetSelectedIndex(); it('should pass down the properties to the input components', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'Substring', column: 'foo', startIndex: 1, endIndex: 3 }, }, diff --git a/ui/tests/unit/todate-step-form.spec.ts b/ui/tests/unit/todate-step-form.spec.ts index 337dd2dbe1..883ae51d44 100644 --- a/ui/tests/unit/todate-step-form.spec.ts +++ b/ui/tests/unit/todate-step-form.spec.ts @@ -1,18 +1,14 @@ -import { createTestingPinia } from '@pinia/testing'; import type { Wrapper } from '@vue/test-utils'; import { createLocalVue, shallowMount } from '@vue/test-utils'; -import { PiniaVuePlugin } from 'pinia'; import { describe, expect, it, vi } from 'vitest'; import ToDateStepForm from '@/components/stepforms/ToDateStepForm.vue'; -import { BasicStepFormTestRunner, setupMockStore } from './utils'; +import { BasicStepFormTestRunner } from './utils'; vi.mock('@/components/FAIcon.vue'); const localVue = createLocalVue(); -localVue.use(PiniaVuePlugin); -const pinia = createTestingPinia({ createSpy: vi.fn, stubActions: false }); describe('Convert String to Date Step Form', () => { const runner = new BasicStepFormTestRunner(ToDateStepForm, 'todate'); @@ -35,9 +31,7 @@ describe('Convert String to Date Step Form', () => { ); it('should have 1 inputtext when custom format is selected', () => { - setupMockStore({}); const wrapper = shallowMount(ToDateStepForm, { - pinia, localVue, propsData: { initialStepValue: { name: 'todate', column: '', format: '' }, @@ -48,21 +42,17 @@ describe('Convert String to Date Step Form', () => { }); it('should update editedStep with the selected column at creation', () => { - setupMockStore({}); - const initialState = { - dataset: { - headers: [{ name: 'foo', type: 'string' }], - data: [[null]], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { foo: 'string' }, + selectedColumns: ['foo'], }, - selectedColumns: ['foo'], - }; - const wrapper = runner.shallowMount(initialState); + }); expect(wrapper.vm.$data.editedStep.column).toEqual('foo'); }); it('should update editedStep.format properly when a new format is selected', () => { - setupMockStore({}); - const wrapper = shallowMount(ToDateStepForm, { pinia, localVue }); + const wrapper = shallowMount(ToDateStepForm, { localVue }); wrapper .find('autocompletewidget-stub') .vm.$emit('input', { format: 'guess', label: '%Y-%m', example: '' }); @@ -78,8 +68,7 @@ describe('Convert String to Date Step Form', () => { }); it('should toggle custom format input correctly when switching selected format', () => { - setupMockStore({}); - const wrapper = shallowMount(ToDateStepForm, { pinia, localVue }); + const wrapper = shallowMount(ToDateStepForm, { localVue }); wrapper .find('autocompletewidget-stub') .vm.$emit('input', { format: 'guess', label: '%Y-%m', example: '' }); @@ -96,9 +85,7 @@ describe('Convert String to Date Step Form', () => { describe('when user delete content of custom format input', () => { it('should return empty string as format', () => { - setupMockStore({}); const wrapper = shallowMount(ToDateStepForm, { - pinia, localVue, propsData: { initialStepValue: { name: 'todate', format: '%Y %m %d %d', column: 'wdc' }, @@ -113,10 +100,8 @@ describe('Convert String to Date Step Form', () => { describe('on init', () => { let wrapper: Wrapper; const createWrapper = (format?: string) => { - setupMockStore({}); if (wrapper) wrapper.destroy(); wrapper = shallowMount(ToDateStepForm, { - pinia, localVue, propsData: { initialStepValue: { name: 'todate', column: '', format }, diff --git a/ui/tests/unit/tolower-step-form.spec.ts b/ui/tests/unit/tolower-step-form.spec.ts index 4f145f8449..2e0ee0536f 100644 --- a/ui/tests/unit/tolower-step-form.spec.ts +++ b/ui/tests/unit/tolower-step-form.spec.ts @@ -14,14 +14,11 @@ describe('To Lowercase Step Form', () => { }); it('should display step column on edition', () => { - const wrapper = runner.shallowMount( - {}, - { - propsData: { - initialStepValue: { name: 'lowercase', column: 'foo' }, - }, + const wrapper = runner.shallowMount({ + propsData: { + initialStepValue: { name: 'lowercase', column: 'foo' }, }, - ); + }); const columnPicker = wrapper.find('columnpicker-stub'); expect(columnPicker.attributes('value')).toEqual('foo'); }); diff --git a/ui/tests/unit/top-step-form.spec.ts b/ui/tests/unit/top-step-form.spec.ts index b747921e87..7647ba7cec 100644 --- a/ui/tests/unit/top-step-form.spec.ts +++ b/ui/tests/unit/top-step-form.spec.ts @@ -38,7 +38,7 @@ describe('Top Step Form', () => { runner.testResetSelectedIndex(); it('should pass down default properties to the input components', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'top', rankOn: 'foo', limit: 3 }, }, @@ -50,7 +50,7 @@ describe('Top Step Form', () => { }); it('should pass down the properties to the input components', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'top', rankOn: 'foo', sort: 'asc', limit: 10, groups: ['test'] }, }, @@ -66,32 +66,26 @@ describe('Top Step Form', () => { const compiled = _.template(s); return compiled(context); } - const wrapper = runner.mount( - { + const wrapper = runner.mount({ + propsData: { variables: { leemeat: 42, }, interpolateFunc: interpolate, - }, - { - propsData: { - initialStepValue: { - name: 'top', - rankOn: 'foo', - sort: 'asc', - limit: '<%= leemeat %>', - groups: ['test'], - }, + initialStepValue: { + name: 'top', + rankOn: 'foo', + sort: 'asc', + limit: '<%= leemeat %>', + groups: ['test'], }, }, - ); + }); wrapper.find('.widget-form-action__button--validate').trigger('click'); await wrapper.vm.$nextTick(); expect(wrapper.vm.$data.errors).toBeNull(); - expect(wrapper.emitted()).toEqual({ - formSaved: [ - [{ name: 'top', rankOn: 'foo', sort: 'asc', limit: '<%= leemeat %>', groups: ['test'] }], - ], - }); + expect(wrapper.emitted().formSaved).toEqual([ + [{ name: 'top', rankOn: 'foo', sort: 'asc', limit: '<%= leemeat %>', groups: ['test'] }], + ]); }); }); diff --git a/ui/tests/unit/totals-step-form.spec.ts b/ui/tests/unit/totals-step-form.spec.ts index f2d102365e..774e8bdfa6 100644 --- a/ui/tests/unit/totals-step-form.spec.ts +++ b/ui/tests/unit/totals-step-form.spec.ts @@ -24,7 +24,7 @@ describe('Add Total Rows Step Form', () => { describe('ListWidget "totalDimensions"', () => { it('should pass down the "totalDimensions" prop to the first ListWidget value prop', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'totals', @@ -40,7 +40,7 @@ describe('Add Total Rows Step Form', () => { }); it('should get the right data "totalDimensions" when editedStep.totals is empty', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'totals', @@ -56,7 +56,7 @@ describe('Add Total Rows Step Form', () => { }); it('should update the edited step when one of the subcomponents emits an updated value', () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'totals', @@ -85,7 +85,7 @@ describe('Add Total Rows Step Form', () => { describe('ListWidget "aggregations"', () => { it('should pass down the "aggregations" prop to the ListWidget value prop', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'totals', @@ -108,19 +108,17 @@ describe('Add Total Rows Step Form', () => { describe('MultiselectWidget', () => { it('should instantiate an MultiselectWidget widget with proper options from the store', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); const widgetMultiselect = wrapper.find('multiselectwidget-stub'); expect(widgetMultiselect.attributes('options')).toEqual('columnA,columnB,columnC'); }); it('should pass down the "groups" prop to the MultiselectWidget value prop', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'totals', @@ -241,7 +239,7 @@ describe('Add Total Rows Step Form', () => { { columns: ['bar', 'test'], newcolumns: ['', ''], aggfunction: 'avg' }, ], }; - const wrapper = runner.mount(undefined, { data: { editedStep } }); + const wrapper = runner.mount({ data: { editedStep } }); wrapper.find('.widget-form-action__button--validate').trigger('click'); expect(setAggregationsNewColumnsInStep).toHaveBeenCalled(); expect(setAggregationsNewColumnsInStep).toHaveBeenCalledWith(editedStep); diff --git a/ui/tests/unit/toupper-step-form.spec.ts b/ui/tests/unit/toupper-step-form.spec.ts index 9ef39be628..45107a82e4 100644 --- a/ui/tests/unit/toupper-step-form.spec.ts +++ b/ui/tests/unit/toupper-step-form.spec.ts @@ -14,14 +14,11 @@ describe('To Uppercase Step Form', () => { }); it('should display step column on edition', () => { - const wrapper = runner.shallowMount( - {}, - { - propsData: { - initialStepValue: { name: 'uppercase', column: 'foo' }, - }, + const wrapper = runner.shallowMount({ + propsData: { + initialStepValue: { name: 'uppercase', column: 'foo' }, }, - ); + }); const columnPicker = wrapper.find('columnpicker-stub'); expect(columnPicker.attributes('value')).toEqual('foo'); }); diff --git a/ui/tests/unit/trim-step-form.spec.ts b/ui/tests/unit/trim-step-form.spec.ts index 33985c3ba4..74452e1cde 100644 --- a/ui/tests/unit/trim-step-form.spec.ts +++ b/ui/tests/unit/trim-step-form.spec.ts @@ -27,51 +27,34 @@ describe('Trim Column Step Form', () => { }, }); - runner.testCancel({ - currentPipelineName: 'default_pipeline', - pipelines: { - default_pipeline: [ - { name: 'domain', domain: 'foo' }, - { name: 'rename', toRename: [['foo', 'bar']] }, - ], - }, - selectedStepIndex: 1, - }); + runner.testCancel(); runner.testResetSelectedIndex(); it('should instantiate a multiselect widget with proper options from the store', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); const widgetAutocomplete = wrapper.find('multiselectwidget-stub'); expect(widgetAutocomplete.attributes('options')).toEqual('columnA,columnB,columnC'); }); it('should update selectedColumn when column is changed', async () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], - }, - selectedColumns: ['columnA'], - }; - const wrapper = runner.mount(initialState, { + const wrapper = runner.mount({ propsData: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, + selectedColumns: ['columnA'], initialValue: { columns: ['columnA'], }, }, data: { editedStep: { columns: ['columnB'] } }, }); - const store = runner.getStore(); wrapper.find(MultiselectWidget).trigger('input'); await wrapper.vm.$nextTick(); - expect(store.selectedColumns).toEqual(['columnB']); + expect(wrapper.emitted().setSelectedColumns).toEqual([[{ column: 'columnB' }]]); }); }); diff --git a/ui/tests/unit/uniquegroups-step-form.spec.ts b/ui/tests/unit/uniquegroups-step-form.spec.ts index 6d7e53748c..bc7d9f90cf 100644 --- a/ui/tests/unit/uniquegroups-step-form.spec.ts +++ b/ui/tests/unit/uniquegroups-step-form.spec.ts @@ -16,19 +16,17 @@ describe('UniqueGroups Step Form', () => { describe('MultiselectWidget', () => { it('should instantiate an MultiselectWidget widget with proper options from the store', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); const widgetMultiselect = wrapper.find('multiselectwidget-stub'); expect(widgetMultiselect.attributes('options')).toEqual('columnA,columnB,columnC'); }); it('should pass down the "on" prop to the MultiselectWidget value prop', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'uniquegroups', on: ['foo', 'bar'] } }, }); await wrapper.vm.$nextTick(); @@ -36,12 +34,11 @@ describe('UniqueGroups Step Form', () => { }); it('should call the setColumnMutation on input', async () => { - const wrapper = runner.mount(undefined, { + const wrapper = runner.mount({ data: { editedStep: { name: 'uniquegroups', on: ['foo'] } }, }); - const store = runner.getStore(); await wrapper.vm.$nextTick(); - expect(store.selectedColumns).toEqual(['foo']); + expect(wrapper.emitted().setSelectedColumns).toEqual([[{ column: 'foo' }]]); }); }); @@ -74,13 +71,12 @@ describe('UniqueGroups Step Form', () => { runner.testResetSelectedIndex(); it('should change the column focus after input in multiselect', async () => { - const initialState = { selectedColumns: [] }; - const wrapper = runner.mount(initialState, { + const wrapper = runner.mount({ + propsData: { selectedColumns: [] }, data: { editedStep: { name: 'uniquegroups', on: ['foo'] } }, }); - const store = runner.getStore(); wrapper.find(MultiselectWidget).trigger('input'); await wrapper.vm.$nextTick(); - expect(store.selectedColumns).toEqual(['foo']); + expect(wrapper.emitted().setSelectedColumns).toEqual([[{ column: 'foo' }]]); }); }); diff --git a/ui/tests/unit/unpivot-step-form.spec.ts b/ui/tests/unit/unpivot-step-form.spec.ts index 158ebb9c60..746d1abf2d 100644 --- a/ui/tests/unit/unpivot-step-form.spec.ts +++ b/ui/tests/unit/unpivot-step-form.spec.ts @@ -47,23 +47,12 @@ describe('Unpivot Step Form', () => { }, ); - runner.testCancel({ - currentPipelineName: 'default_pipeline', - pipelines: { - default_pipeline: [ - { name: 'domain', domain: 'foo' }, - { name: 'rename', toRename: [['foo', 'bar']] }, - { name: 'rename', toRename: [['baz', 'spam']] }, - { name: 'rename', toRename: [['tic', 'tac']] }, - ], - }, - selectedStepIndex: 2, - }); + runner.testCancel(); runner.testResetSelectedIndex(); it('should pass down props to widgets', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'unpivot', @@ -83,13 +72,11 @@ describe('Unpivot Step Form', () => { }); it('should instantiate an autocomplete widget with proper options from the store', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); expect(wrapper.find('.keepColumnInput').attributes('options')).toEqual( 'columnA,columnB,columnC', ); diff --git a/ui/tests/unit/utils.ts b/ui/tests/unit/utils.ts index d705c56131..07f62b3166 100644 --- a/ui/tests/unit/utils.ts +++ b/ui/tests/unit/utils.ts @@ -65,6 +65,12 @@ export class BasicStepFormTestRunner { store: Store<'vqb', any>; pinia: Pinia; + requiredStepProps = { + columnTypes: {}, + interpolateFunc: (a: any) => a, + getColumnNamesFromPipeline: () => Promise.resolve([]), + }; + constructor(componentType: ComponentType, stepname: string, vue?: VueConstructor) { this.componentType = componentType; this.stepname = stepname; @@ -73,13 +79,14 @@ export class BasicStepFormTestRunner { this.pinia = pinia; } - _mount(shallow: boolean, initialState: object = {}, optional: MountOptions = {}) { - setupMockStore(initialState); + _mount(shallow: boolean, optional: MountOptions = {}) { const mountfunc = shallow ? shallowMount : mount; const { propsData, data } = optional; const wrapper = mountfunc(this.componentType, { - propsData, - pinia: this.pinia, + propsData: { + ...this.requiredStepProps, + ...propsData, + }, localVue: this.vue, sync: false, }); @@ -89,12 +96,12 @@ export class BasicStepFormTestRunner { return wrapper; } - mount(initialState: object = {}, optional: MountOptions = {}) { - return this._mount(false, initialState, optional); + mount(optional: MountOptions = {}) { + return this._mount(false, optional); } - shallowMount(initialState: object = {}, optional: MountOptions = {}) { - return this._mount(true, initialState, optional); + shallowMount(optional: MountOptions = {}) { + return this._mount(true, optional); } getStore() { @@ -109,12 +116,12 @@ export class BasicStepFormTestRunner { }); } - testExpectedComponents(componentSpec: { [prop: string]: number }, initialState: object = {}) { + testExpectedComponents(componentSpec: { [prop: string]: number }, propsData: object = {}) { const specStr = Object.entries(componentSpec) .map(([k, v]) => `${v} ${k}`) .join(', '); it(`should generate ${specStr} components`, () => { - const wrapper = this.shallowMount(initialState); + const wrapper = this.shallowMount({ propsData }); for (const [componentName, count] of Object.entries(componentSpec)) { const compWrappers = wrapper.findAll(componentName); expect(compWrappers.length).toEqual(count); @@ -122,18 +129,13 @@ export class BasicStepFormTestRunner { }); } - async checkValidationError( - _testlabel: any, - propsData: any, - data: any, - expectedErrors: any, - initialState: Partial = buildStateWithOnePipeline([]), - ) { - setupMockStore(initialState); + async checkValidationError(_testlabel: any, propsData: any, data: any, expectedErrors: any) { const wrapper = mount(this.componentType, { - propsData, + propsData: { + ...this.requiredStepProps, + ...propsData, + }, localVue: this.vue, - pinia: this.pinia, }); if (data) { wrapper.setData(data); @@ -151,12 +153,11 @@ export class BasicStepFormTestRunner { } testValidationErrors(configurations: ValidationErrorConfiguration[]) { - const cases = configurations.map(({ testlabel, props, data, errors, store }) => [ + const cases = configurations.map(({ testlabel, props, data, errors }) => [ testlabel, props ?? {}, data, errors, - store, ]); test.each(cases)( 'should generate validation error if %s (#%#)', @@ -165,19 +166,18 @@ export class BasicStepFormTestRunner { } testValidate(testConfiguration: TestCaseConfiguration, expectedEmit?: object) { - const { testlabel, store, props, data } = testConfiguration; + const { testlabel, props, data } = testConfiguration; // assume by default that the expected output is the initial input expectedEmit = expectedEmit ?? props?.initialStepValue; describe(`should validate and emit "formSaved" when ${testlabel}`, () => { - beforeEach(() => { - setupMockStore(store ?? buildStateWithOnePipeline([])); - }); - it(`click version`, async () => { const wrapper = mount(this.componentType, { localVue: this.vue, - propsData: props ?? {}, + propsData: { + ...this.requiredStepProps, + ...(props ?? {}), + }, sync: false, }); if (data) { @@ -186,15 +186,13 @@ export class BasicStepFormTestRunner { wrapper.find('.widget-form-action__button--validate').trigger('click'); await this.vue.nextTick(); expect(wrapper.vm.$data.errors).toBeNull(); - expect(wrapper.emitted()).toEqual({ - formSaved: [[expectedEmit]], - }); + expect(wrapper.emitted().formSaved).toEqual([[expectedEmit]]); }); it(`shortcut ctrl+enter version`, async () => { const wrapper = mount(this.componentType, { localVue: this.vue, - propsData: props ?? {}, + propsData: { ...this.requiredStepProps, ...(props ?? {}) }, sync: false, }); if (data) { @@ -205,16 +203,13 @@ export class BasicStepFormTestRunner { ); await this.vue.nextTick(); expect(wrapper.vm.$data.errors).toBeNull(); - expect(wrapper.emitted()).toEqual({ - formSaved: [[expectedEmit]], - }); + expect(wrapper.emitted().formSaved).toEqual([[expectedEmit]]); }); it(`shortcut command+enter version`, async () => { const wrapper = mount(this.componentType, { - pinia: this.pinia, localVue: this.vue, - propsData: props ?? {}, + propsData: { ...this.requiredStepProps, ...(props ?? {}) }, sync: false, }); if (data) { @@ -225,35 +220,28 @@ export class BasicStepFormTestRunner { ); await this.vue.nextTick(); expect(wrapper.vm.$data.errors).toBeNull(); - expect(wrapper.emitted()).toEqual({ - formSaved: [[expectedEmit]], - }); + expect(wrapper.emitted().formSaved).toEqual([[expectedEmit]]); }); }); } - testCancel(initialState: Partial = buildStateWithOnePipeline([])) { + testCancel() { it('should emit "back" event when back button is clicked', () => { - setupMockStore(initialState); - const initialPipeline = [...(this.store.pipeline ?? [])]; - const initialStepIndex = this.store.selectedStepIndex; const wrapper = mount(this.componentType, { - pinia: this.pinia, localVue: this.vue, + propsData: this.requiredStepProps, sync: false, }); wrapper.find('.step-edit-form__back-button').trigger('click'); expect(wrapper.emitted()).toEqual({ back: [[]] }); - expect(this.store.selectedStepIndex).toEqual(initialStepIndex); - expect(this.store.pipeline).toEqual(initialPipeline); }); it('should overwrite cancelEdition function', () => { const cancelEditionCustomMock = vi.fn(); const methods = { cancelEdition: cancelEditionCustomMock }; const wrapper = mount(this.componentType, { - pinia: this.pinia, localVue: this.vue, + propsData: this.requiredStepProps, sync: false, methods, }); diff --git a/ui/tests/unit/waterfall-step-form.spec.ts b/ui/tests/unit/waterfall-step-form.spec.ts index dc74932cb7..0dc2be8f8c 100644 --- a/ui/tests/unit/waterfall-step-form.spec.ts +++ b/ui/tests/unit/waterfall-step-form.spec.ts @@ -18,19 +18,17 @@ describe('Waterfall Step Form', () => { describe('MultiselectWidget', () => { it('should instantiate a MultiselectWidget widget with proper options from the store', () => { - const initialState = { - dataset: { - headers: [{ name: 'columnA' }, { name: 'columnB' }, { name: 'columnC' }], - data: [], + const wrapper = runner.shallowMount({ + propsData: { + columnTypes: { columnA: 'string', columnB: 'string', columnC: 'string' }, }, - }; - const wrapper = runner.shallowMount(initialState); + }); const widgetMultiselect = wrapper.find('multiselectwidget-stub'); expect(widgetMultiselect.attributes('options')).toEqual('columnA,columnB,columnC'); }); it('should pass down the props to the MultiselectWidget value prop', async () => { - const wrapper = runner.shallowMount(undefined, { + const wrapper = runner.shallowMount({ data: { editedStep: { name: 'waterfall', @@ -109,13 +107,8 @@ describe('Waterfall Step Form', () => { runner.testValidate({ testlabel: 'submitted data is valid', - store: { - dataset: { - headers: [{ name: 'columnA' }], - data: [], - }, - }, props: { + columnTypes: { columnA: 'string' }, initialStepValue: { name: 'waterfall', valueColumn: 'VALUE', From f56a53169a5a70b85ded560ecea66c7999f6dcf1 Mon Sep 17 00:00:00 2001 From: Alice Date: Wed, 25 Sep 2024 10:21:49 +0200 Subject: [PATCH 4/6] feat(step-form): enable to use form component alone or with query builder and store --- ui/src/components/QueryBuilder.vue | 12 +- .../stepforms/StepFormComponent.vue | 116 ++++++++++++++++++ .../stepforms/StoreStepFormComponent.vue | 91 ++++++++++++++ ui/src/main.ts | 2 + ui/stories/StepForm.stories.ts | 107 ++++++++++++++++ .../filter-simple-condition-widget.spec.ts | 2 +- ui/tests/unit/query-builder.spec.ts | 78 +----------- ui/tests/unit/utils.ts | 9 +- 8 files changed, 332 insertions(+), 85 deletions(-) create mode 100644 ui/src/components/stepforms/StepFormComponent.vue create mode 100644 ui/src/components/stepforms/StoreStepFormComponent.vue create mode 100644 ui/stories/StepForm.stories.ts diff --git a/ui/src/components/QueryBuilder.vue b/ui/src/components/QueryBuilder.vue index 6520e856a1..68513a70bc 100644 --- a/ui/src/components/QueryBuilder.vue +++ b/ui/src/components/QueryBuilder.vue @@ -1,13 +1,12 @@ + diff --git a/ui/src/components/stepforms/StoreStepFormComponent.vue b/ui/src/components/stepforms/StoreStepFormComponent.vue new file mode 100644 index 0000000000..6ab5adb822 --- /dev/null +++ b/ui/src/components/stepforms/StoreStepFormComponent.vue @@ -0,0 +1,91 @@ + + + diff --git a/ui/src/main.ts b/ui/src/main.ts index aa94b25fd8..ede0ecb343 100644 --- a/ui/src/main.ts +++ b/ui/src/main.ts @@ -20,6 +20,7 @@ import QueryBuilder from './components/QueryBuilder.vue'; import DateRangeInput from './components/stepforms/widgets/DateComponents/DateRangeInput.vue'; import NewDateInput from './components/stepforms/widgets/DateComponents/NewDateInput.vue'; import Vqb from './components/Vqb.vue'; +import StepFormComponent from './components/stepforms/StepFormComponent.vue'; // export steps constants to be able to migrate dataviewer export { @@ -43,6 +44,7 @@ export { NewDateInput, DateRangeInput, Pagination, + StepFormComponent, }; // export helpers/utils diff --git a/ui/stories/StepForm.stories.ts b/ui/stories/StepForm.stories.ts new file mode 100644 index 0000000000..b6e2c7a521 --- /dev/null +++ b/ui/stories/StepForm.stories.ts @@ -0,0 +1,107 @@ +import { action } from '@storybook/addon-actions'; +import type { Meta, StoryObj } from '@storybook/vue'; + +import StepFormComponent from '@/components/stepforms/StepFormComponent.vue'; +import { STEP_LABELS } from '@/types'; + +const RELATIVE_SAMPLE_VARIABLES = [ + { + label: 'Today', + identifier: 'today', + value: new Date('1/12/2021'), + }, + { + label: 'Last month', + identifier: 'last_month', + value: new Date('11/12/2021'), + }, + { + label: 'Last year', + identifier: 'last_year', + + value: new Date('1/12/2020'), + }, +]; + +const SAMPLE_VARIABLES = [ + { + identifier: 'dates.last_7_days', + trusted: true, + label: 'Last 7 days', + }, + { + identifier: 'dates.last_14_days', + trusted: true, + label: 'Last 14 days', + }, + { + identifier: 'dates.last_30_days', + trusted: true, + label: 'Last 30 days', + }, + { + identifier: 'dates.last_3_months', + trusted: true, + label: 'Last 3 Months', + }, + { + identifier: 'dates.last_12_months', + trusted: true, + label: 'Last 12 Months', + }, + { + identifier: 'dates.month_to_date', + trusted: true, + label: 'Month to date', + }, + { + identifier: 'dates.quarter_to_date', + trusted: true, + label: 'Quarter to date', + }, + { + identifier: 'dates.all_time', + trusted: true, + label: 'All time', + }, + ...RELATIVE_SAMPLE_VARIABLES, +]; + +const VARIABLES = SAMPLE_VARIABLES.reduce((vars, item) => { + vars[item.identifier] = 'value' in item ? item.value : item.identifier; + return vars; +}, {} as Record); + +export default { + component: StepFormComponent, +} as Meta; + +export const Default: StoryObj = { + render: (args, { argTypes }) => ({ + components: { StepFormComponent }, + props: Object.keys(argTypes), + template: '', + methods: { + onFormSaved: action('formSaved'), + onBack: action('back'), + }, + }), + args: { + name: 'text', + availableDomains: [{ name: 'other_domain', uid: 'other_domain' }], + unjoinableDomains: [], + columnTypes: { a: 'string', b: 'boolean' }, + availableVariables: SAMPLE_VARIABLES, + variableDelimiters: { start: '<%=', end: '%>' }, + trustedVariableDelimiters: { start: '{{', end: '}}' }, + variables: VARIABLES, + interpolateFunc: (a) => a, + getColumnNamesFromPipeline: () => Promise.resolve(['c', 'd']), + }, + argTypes: { + name: { + options: Object.keys(STEP_LABELS), + control: { type: 'select' }, + }, + }, +}; diff --git a/ui/tests/unit/filter-simple-condition-widget.spec.ts b/ui/tests/unit/filter-simple-condition-widget.spec.ts index b8955a10c7..f65df6b131 100644 --- a/ui/tests/unit/filter-simple-condition-widget.spec.ts +++ b/ui/tests/unit/filter-simple-condition-widget.spec.ts @@ -1,6 +1,6 @@ import type { Wrapper } from '@vue/test-utils'; import { createLocalVue, mount, shallowMount } from '@vue/test-utils'; -import { describe, expect, it, vi } from 'vitest'; +import { describe, expect, it } from 'vitest'; import AutocompleteWidget from '@/components/stepforms/widgets/Autocomplete.vue'; import FilterSimpleConditionWidget from '@/components/stepforms/widgets/FilterSimpleCondition.vue'; diff --git a/ui/tests/unit/query-builder.spec.ts b/ui/tests/unit/query-builder.spec.ts index c9e5341c81..3f1c73c077 100644 --- a/ui/tests/unit/query-builder.spec.ts +++ b/ui/tests/unit/query-builder.spec.ts @@ -43,85 +43,17 @@ describe('Query Builder', () => { expect(wrapper.find('Pipeline-stub').exists()).toBeFalsy(); }); - it('should instantiate a AggregateStepForm component', () => { + it('should instantiate a step form component', () => { setupMockStore(buildStateWithOnePipeline([], { currentStepFormName: 'aggregate' })); wrapper = shallowMount(QueryBuilder, { pinia, localVue, }); - const form = wrapper.find('aggregatestepform-stub'); - expect(form.exists()).toBeTruthy(); - }); - - it('should instantiate a FormRenameStep component', () => { - setupMockStore(buildStateWithOnePipeline([], { currentStepFormName: 'rename' })); - wrapper = shallowMount(QueryBuilder, { - pinia, - localVue, - }); - const form = wrapper.find('renamestepform-stub'); - expect(form.exists()).toBeTruthy(); - }); - - it('should instantiate a DeleteColumnStep component', () => { - setupMockStore(buildStateWithOnePipeline([], { currentStepFormName: 'delete' })); - wrapper = shallowMount(QueryBuilder, { - pinia, - localVue, - }); - const form = wrapper.find('deletestepform-stub'); - expect(form.exists()).toBeTruthy(); - }); - - it('should instantiate a FillnaStep component', () => { - setupMockStore(buildStateWithOnePipeline([], { currentStepFormName: 'fillna' })); - wrapper = shallowMount(QueryBuilder, { - pinia, - localVue, - }); - const form = wrapper.find('fillnastepform-stub'); - expect(form.exists()).toBeTruthy(); - }); - - it('should instantiate a DomainStep component', () => { - setupMockStore(buildStateWithOnePipeline([], { currentStepFormName: 'domain' })); - wrapper = shallowMount(QueryBuilder, { - pinia, - localVue, - }); - const form = wrapper.find('domainstepform-stub'); + const form = wrapper.find('stepform-stub'); expect(form.exists()).toBeTruthy(); }); describe('save step', () => { - describe('when editing domain step', () => { - beforeEach(async () => { - store = setupMockStore( - buildStateWithOnePipeline([{ name: 'domain', domain: 'foo' }], { - currentStepFormName: 'domain', - stepFormInitialValue: { name: 'domain', domain: 'foo' }, - }), - ); - wrapper = shallowMount(QueryBuilder, { - pinia, - localVue, - stubs: { - transition: true, - }, - }); - await localVue.nextTick(); - }); - - it('should update the pipeline', () => { - wrapper.find('domainstepform-stub').vm.$emit('formSaved', { - name: 'domain', - domain: 'bar', - }); - expect(store.isEditingStep).toBeFalsy(); - expect(store.pipeline).toEqual([{ name: 'domain', domain: 'bar' }]); - }); - }); - describe('when editing a step', () => { beforeEach(async () => { store = setupMockStore( @@ -173,7 +105,7 @@ describe('Query Builder', () => { it('should set pipeline when form is saved', async () => { wrapper - .find('renamestepform-stub') + .find('stepform-stub') .vm.$emit('formSaved', { name: 'rename', oldname: 'columnA', newname: 'columnAA' }); expect(store.isEditingStep).toBeFalsy(); expect(store.pipeline).toEqual([ @@ -184,7 +116,7 @@ describe('Query Builder', () => { it('should compute the right computedActiveStepIndex', () => { expect(store.computedActiveStepIndex).toEqual(0); - wrapper.find('renamestepform-stub').vm.$emit('formSaved', { + wrapper.find('stepform-stub').vm.$emit('formSaved', { name: 'rename', oldname: 'columnA', newname: 'columnAA', @@ -208,7 +140,7 @@ describe('Query Builder', () => { }, }); await localVue.nextTick(); - wrapper.find('renamestepform-stub').vm.$emit('back'); + wrapper.find('stepform-stub').vm.$emit('back'); expect(store.isEditingStep).toBeFalsy(); expect(store.pipeline).toEqual([{ name: 'domain', domain: 'foo' }]); }); diff --git a/ui/tests/unit/utils.ts b/ui/tests/unit/utils.ts index 07f62b3166..75cd3cf441 100644 --- a/ui/tests/unit/utils.ts +++ b/ui/tests/unit/utils.ts @@ -1,10 +1,11 @@ import { createTestingPinia } from '@pinia/testing'; import { createLocalVue, mount, shallowMount } from '@vue/test-utils'; import { type Pinia, type Store, PiniaVuePlugin } from 'pinia'; -import { beforeEach, describe, expect, it, test, vi } from 'vitest'; +import { describe, expect, it, test, vi } from 'vitest'; import type { VueConstructor } from 'vue'; import type BaseStepForm from '@/components/stepforms/StepForm.vue'; +import StoreStepFormComponent from '@/components/stepforms/StoreStepFormComponent.vue'; import type { Pipeline } from '@/lib/steps'; import type { ValidationError } from '@/lib/translators/base'; import { setupVQBStore, useVQBStore } from '@/store'; @@ -266,15 +267,17 @@ export class BasicStepFormTestRunner { it('should reset selectedStepIndex correctly on cancel depending on isStepCreation', () => { setupMockStore(initialState); const initialStepIndex = this.store.selectedStepIndex; - const wrapper = mount(this.componentType, { + // selectedStepIndex is only available with store component + const wrapper = mount(StoreStepFormComponent, { pinia: this.pinia, localVue: this.vue, + propsData: { name: this.stepname }, sync: false, }); wrapper.find('.step-edit-form__back-button').trigger('click'); expect(this.store.selectedStepIndex).toEqual(initialStepIndex); - wrapper.setProps({ isStepCreation: false }); + wrapper.setProps({ initialStepValue: {} }); wrapper.find('.step-edit-form__back-button').trigger('click'); expect(this.store.selectedStepIndex).toEqual(initialStepIndex + 1); }); From a512936527e3400184e540aca30ea1fff84fdf47 Mon Sep 17 00:00:00 2001 From: Alice Date: Wed, 25 Sep 2024 10:42:03 +0200 Subject: [PATCH 5/6] chore: update changelog --- ui/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/CHANGELOG.md b/ui/CHANGELOG.md index 41cdda1716..d8778fca42 100644 --- a/ui/CHANGELOG.md +++ b/ui/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Changed + +- Stepform: remove store dependency from step form component + ## [0.114.1] - 2024-09-10 ### Fixed From 6b9c17206d58903b54349fd545912d33f8e9e3bd Mon Sep 17 00:00:00 2001 From: Alice Date: Wed, 25 Sep 2024 15:37:20 +0200 Subject: [PATCH 6/6] fix: lint --- ui/src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/main.ts b/ui/src/main.ts index ede0ecb343..d47346e2f2 100644 --- a/ui/src/main.ts +++ b/ui/src/main.ts @@ -17,10 +17,10 @@ import FilterEditor from './components/FilterEditor.vue'; import Pagination from './components/Pagination.vue'; import PipelineSelector from './components/PipelineSelector.vue'; import QueryBuilder from './components/QueryBuilder.vue'; +import StepFormComponent from './components/stepforms/StepFormComponent.vue'; import DateRangeInput from './components/stepforms/widgets/DateComponents/DateRangeInput.vue'; import NewDateInput from './components/stepforms/widgets/DateComponents/NewDateInput.vue'; import Vqb from './components/Vqb.vue'; -import StepFormComponent from './components/stepforms/StepFormComponent.vue'; // export steps constants to be able to migrate dataviewer export {