Skip to content

Commit a56d52e

Browse files
committed
fix typing errors and add CSV import tests
1 parent 3c44f43 commit a56d52e

71 files changed

Lines changed: 901 additions & 608 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import {test, expect} from '@playwright/test';
2+
import {openApp} from './utils';
3+
import {tpGetData} from './utilsTestPanel';
4+
import {
5+
expandImportOptions,
6+
openCsvImportDialog,
7+
setColumnPath,
8+
setCsvTablePath,
9+
submitCsvImport,
10+
uploadCsvFile,
11+
} from './utilsCsvImport';
12+
import {SessionMode} from '../src/store/sessionMode';
13+
14+
test('Import CSV as standalone table with default paths', async ({page}) => {
15+
await openApp(page, 'settings_testpanel.json');
16+
17+
await openCsvImportDialog(page);
18+
await uploadCsvFile(page, 'data_people.csv');
19+
20+
// submit without changing any options — default table path comes from the filename
21+
await submitCsvImport(page);
22+
23+
// filename "data_people.csv" → stringToIdentifier strips underscores → key is "datapeople"
24+
const data = await tpGetData(page, SessionMode.DataEditor);
25+
expect(data).toHaveProperty('datapeople');
26+
expect(data.datapeople).toHaveLength(2);
27+
expect(data.datapeople[0]).toMatchObject({name: 'Alice', city: 'Berlin', role: 'Engineer'});
28+
expect(data.datapeople[1]).toMatchObject({name: 'Bob', city: 'Munich', role: 'Designer'});
29+
});
30+
31+
test('Import CSV with custom table path and renamed column', async ({page}) => {
32+
await openApp(page, 'settings_testpanel.json');
33+
34+
await openCsvImportDialog(page);
35+
await uploadCsvFile(page, 'data_people.csv');
36+
37+
await expandImportOptions(page);
38+
await setCsvTablePath(page, 'people');
39+
await setColumnPath(page, 'city', 'location');
40+
41+
await submitCsvImport(page);
42+
43+
const data = await tpGetData(page, SessionMode.DataEditor);
44+
expect(data).toEqual({
45+
people: [
46+
{name: 'Alice', location: 'Berlin', role: 'Engineer'},
47+
{name: 'Bob', location: 'Munich', role: 'Designer'},
48+
],
49+
});
50+
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
name,city,role
2+
Alice,Berlin,Engineer
3+
Bob,Munich,Designer
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import {Page} from 'playwright';
2+
import {expect} from '@playwright/test';
3+
import path from 'node:path';
4+
5+
const fixturesDir = path.resolve(process.cwd(), 'e2e/test-fixtures');
6+
7+
export async function openCsvImportDialog(page: Page) {
8+
await page.locator('#import-data').click();
9+
await page.getByRole('menuitem', {name: 'Import CSV Data'}).click();
10+
await expect(page.getByRole('dialog', {name: 'Import CSV'})).toBeVisible();
11+
}
12+
13+
export async function uploadCsvFile(page: Page, filename: string) {
14+
const fileChooserPromise = page.waitForEvent('filechooser');
15+
await page.getByTestId('csv-select-file').click();
16+
const fileChooser = await fileChooserPromise;
17+
await fileChooser.setFiles(path.join(fixturesDir, filename));
18+
// wait for the Import button to appear, confirming the CSV was parsed
19+
await expect(page.getByTestId('csv-submit-import')).toBeVisible();
20+
}
21+
22+
export async function expandImportOptions(page: Page) {
23+
await page.getByTestId('csv-import-options-toggle').click();
24+
}
25+
26+
export async function setCsvTablePath(page: Page, tablePath: string) {
27+
const input = page.getByTestId('csv-table-path-input');
28+
await input.clear();
29+
await input.fill(tablePath);
30+
}
31+
32+
export async function setColumnPath(page: Page, columnName: string, newPath: string) {
33+
const input = page.getByTestId(`csv-column-path-${columnName}`);
34+
await input.clear();
35+
await input.fill(newPath);
36+
}
37+
38+
export async function submitCsvImport(page: Page) {
39+
await page.getByTestId('csv-submit-import').click();
40+
await expect(page.getByRole('dialog', {name: 'Import CSV'})).not.toBeVisible();
41+
}

meta_configurator/src/components/CombinedEditorComponent.vue

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Main component of the application.
33
Combines the code editor and the gui editor.
44
-->
55
<script lang="ts" setup>
6-
import {computed, onMounted, onUnmounted, type Ref, ref, watch} from 'vue';
6+
import {computed, onMounted, onUnmounted, ref, watch} from 'vue';
77
import 'primeicons/primeicons.css';
88
import SplitterPanel from 'primevue/splitterpanel';
99
import Splitter from 'primevue/splitter';
@@ -15,13 +15,13 @@ import {useConfirm} from 'primevue/useconfirm';
1515
import {confirmationService} from '@/utility/confirmationService';
1616
import {toastService} from '@/utility/toastService';
1717
import {useAppRouter} from '@/router/router';
18-
import {useDropZone, useWindowSize, watchImmediate} from '@vueuse/core/index';
18+
import {useDropZone, useWindowSize, watchImmediate} from '@vueuse/core';
1919
import {readFileContentToDataLink} from '@/utility/readFileContent';
2020
import {getDataForMode} from '@/data/useDataLink';
2121
import {useSettings} from '@/settings/useSettings';
2222
import {modeToRoute, SessionMode} from '@/store/sessionMode';
2323
import {useSessionStore} from '@/store/sessionStore';
24-
import type {SettingsInterfacePanels, SettingsInterfaceRoot} from '@/settings/settingsTypes';
24+
import type {SettingsInterfacePanels} from '@/settings/settingsTypes';
2525
import {SETTINGS_DATA_DEFAULT} from '@/settings/defaultSettingsData';
2626
import {updateSettingsWithDefaults} from '@/settings/settingsUpdater';
2727
import {panelTypeRegistry} from '@/components/panels/panelTypeRegistry';
@@ -37,16 +37,18 @@ let panelsDefinition: SettingsInterfacePanels = settings.value.panels;
3737
// any setting is changed, which is not necessary and leads to Ace Editor becoming blank if settings were modified via
3838
// Ace Editor
3939
watchImmediate(
40-
() => settings,
41-
(settings: Ref<SettingsInterfaceRoot>) => {
42-
let panels = settings.value.panels;
40+
() => settings.value,
41+
newSettings => {
42+
const panels = newSettings.panels;
4343
if (JSON.stringify(panels) !== JSON.stringify(panelsDefinition)) {
4444
panelsDefinition = panels;
4545
}
4646
// fix panels if they are not defined
4747
for (let mode of Object.values(SessionMode)) {
4848
if (!panels[mode]) {
49-
panels[mode] = structuredClone(SETTINGS_DATA_DEFAULT.panels[mode]);
49+
panels[mode] = structuredClone(
50+
SETTINGS_DATA_DEFAULT.panels[mode]
51+
) as SettingsInterfacePanels[typeof mode];
5052
}
5153
}
5254
}
@@ -164,10 +166,10 @@ onUnmounted(() => {
164166
class="h-full"
165167
style="min-width: 0"
166168
:layout="width < 600 ? 'vertical' : 'horizontal'"
167-
:key="panels">
169+
:key="props.sessionMode">
168170
<SplitterPanel
169171
v-for="(panel, index) in panels"
170-
:key="index + panel"
172+
:key="`${panel.sessionMode}-${index}`"
171173
:min-size="10"
172174
:size="panel.size"
173175
:resizable="true">

meta_configurator/src/components/panels/ai-prompts/AiPromptsTemplate.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,10 @@ async function submitPromptExportDocument() {
261261
// if the schema defines export formats, the user prompt is ignored and the selected export format is used
262262
if (documentExportFormatNames.value.length > 0) {
263263
const exportFormatName = selectedExportFormat.value;
264-
const exportFormatDef = documentExportFormats.value![exportFormatName];
264+
const exportFormatDef = documentExportFormats.value?.[exportFormatName];
265+
if (!exportFormatDef) {
266+
throw new Error(`Unknown export format "${exportFormatName}".`);
267+
}
265268
// if export format is just a string, it is the URL
266269
if (typeof exportFormatDef === 'string') {
267270
userPrompt = await fetchExternalContentText(exportFormatDef);

meta_configurator/src/components/panels/code-editor/setupAnnotations.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,12 @@ function validationErrorsToAnnotations(editor: Editor, errors: ErrorObject[]): A
7777
}
7878

7979
const index = positions[instancePathKey];
80-
let position;
80+
if (index === undefined) {
81+
continue;
82+
}
83+
let position: {row: number; column: number};
8184
if (index in cachedPositionsForIndices) {
82-
position = cachedPositionsForIndices[index];
85+
position = cachedPositionsForIndices[index]!;
8386
} else {
8487
position = editor.session.doc.indexToPosition(index, 0);
8588
cachedPositionsForIndices[index] = position;

meta_configurator/src/components/panels/code-editor/setupLinkToSelectionAndData.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
} from '@/components/panels/code-editor/aceUtility';
1010
import type {SessionMode} from '@/store/sessionMode';
1111
import {getDataForMode, getSessionForMode} from '@/data/useDataLink';
12-
import {watchImmediate} from '@vueuse/core/index';
12+
import {watchImmediate} from '@vueuse/core';
1313
import {useSettings} from '@/settings/useSettings';
1414
import {sizeOf} from '@/utility/sizeOf';
1515

meta_configurator/src/components/panels/gui-editor/PropertiesPanel.vue

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -507,27 +507,27 @@ const schemaInfoOverlay = ref<InstanceType<typeof SchemaInfoOverlay> | undefined
507507
const allowShowOverlay = ref(true);
508508
const overlayShowScheduled = ref(false);
509509
510-
const showInfoOverlayPanelInstantly = (nodeData: ConfigTreeNodeData, event: MouseEvent) => {
510+
const showInfoOverlayPanelInstantly = (nodeData: ConfigTreeNodeData, event: Event) => {
511511
const relevantErrors = getValidationResults(nodeData.absolutePath).errors;
512512
// @ts-ignore
513513
schemaInfoOverlay.value?.showPanel(
514514
nodeData.schema,
515-
nodeData.name,
515+
String(nodeData.name),
516516
nodeData.parentSchema,
517517
relevantErrors,
518518
event
519519
);
520520
};
521521
const showInfoOverlayPanelDebounced = useDebounceFn(
522-
(nodeData: ConfigTreeNodeData, event: MouseEvent) => {
522+
(nodeData: ConfigTreeNodeData, event: Event) => {
523523
if (allowShowOverlay.value && overlayShowScheduled.value) {
524524
showInfoOverlayPanelInstantly(nodeData, event);
525525
}
526526
},
527527
1000
528528
);
529529
530-
function showInfoOverlayPanel(nodeData: ConfigTreeNodeData, event: MouseEvent) {
530+
function showInfoOverlayPanel(nodeData: ConfigTreeNodeData, event: Event) {
531531
overlayShowScheduled.value = true;
532532
showInfoOverlayPanelDebounced(nodeData, event);
533533
}
@@ -608,7 +608,9 @@ function zoomIntoPath(path: Path) {
608608
@update_tree="updateTree"
609609
@click="() => clickedPropertyData(slotProps.node.data)"
610610
bodyClass="w-full"
611-
@keydown.ctrl.i="event => showInfoOverlayPanelInstantly(slotProps.node.data, event)"
611+
@keydown.ctrl.i="
612+
(event: KeyboardEvent) => showInfoOverlayPanelInstantly(slotProps.node.data, event)
613+
"
612614
:data-testid="'property-data-' + pathToString(slotProps.node.data.absolutePath)" />
613615
</span>
614616

meta_configurator/src/components/panels/gui-editor/PropertyMetadata.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ function zoomIntoPath() {
9393
}
9494
}
9595
96-
function updatePropertyName(event) {
96+
function updatePropertyName(event: KeyboardEvent | FocusEvent) {
9797
const target = event.target as HTMLElement;
9898
let text = target.innerText;
9999
@@ -103,12 +103,12 @@ function updatePropertyName(event) {
103103
if (isPropertyNameEditable(props.type)) {
104104
emit('update_property_name', props.node.data.name as string, text);
105105
} else {
106-
event.target.innerText = props.node.data.name;
106+
target.innerText = String(props.node.data.name);
107107
}
108108
109109
isEditingPropertyName.value = false;
110110
emit('stop_editing_property_name');
111-
event.target.contenteditable = false;
111+
target.contentEditable = 'false';
112112
showPencil.value = true;
113113
}
114114

meta_configurator/src/components/panels/gui-editor/SchemaInfoOverlay.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import type {ErrorObject} from 'ajv';
1818
import {useSessionStore} from '@/store/sessionStore';
1919
2020
const schemaRef: Ref<JsonSchemaWrapper | undefined> = ref();
21-
const propertyNameRef: Ref<String> = ref('');
21+
const propertyNameRef: Ref<string> = ref('');
2222
const parentSchemaRef: Ref<JsonSchemaWrapper | undefined> = ref();
2323
const validationErrorsRef: Ref<ErrorObject[]> = ref([]);
2424
@@ -46,7 +46,7 @@ const showPanel = (
4646
propertyName: string,
4747
parentSchema: JsonSchemaWrapper,
4848
validationErrors: ErrorObject[],
49-
event
49+
event: Event
5050
) => {
5151
schemaRef.value = schema;
5252
propertyNameRef.value = propertyName;

0 commit comments

Comments
 (0)