From 2fa2649671381d2ce73f259845570c201f487084 Mon Sep 17 00:00:00 2001 From: Lukas Giger Date: Thu, 12 Dec 2024 14:44:17 +0100 Subject: [PATCH] XIVY-15648 meta data details of known variables The endpoint `knownVariables` has been adapted in the core to return the meta data details of variables of type enum (values) and file (extension). These values are now set on the overwriting variable when using the overwrite dialog. Additionally: - Added tests for `nodeIcon`. - Added tests that editing meta data details is disabled on overwriting variables. - Minor refactors here and there. --- integrations/standalone/src/mock/meta.ts | 49 +++++++++--- packages/protocol/src/editor.ts | 13 ++-- packages/protocol/src/types.ts | 13 +++- .../variables/data/metadata.test.ts | 49 +++++++++++- .../src/components/variables/data/metadata.ts | 8 +- .../test-utils/variables-with-metadata.ts | 2 +- .../variables/data/variable-utils.test.ts | 35 ++++++++- .../variables/data/variable-utils.ts | 10 +-- .../variables/detail/DetailContent.test.ts | 4 +- .../variables/detail/DetailContent.tsx | 4 +- .../components/variables/detail/Metadata.tsx | 4 +- .../variables/dialog/OverwriteDialog.tsx | 43 +++++------ .../variables/dialog/VariableBrowser.tsx | 32 ++++---- .../variables/dialog/known-variables.test.ts | 26 +++---- .../variables/dialog/known-variables.ts | 10 +-- .../tests/integration/mock/detail.spec.ts | 8 +- .../tests/integration/mock/import.spec.ts | 76 ++++++++++++++----- playwright/tests/pageobjects/EnumValues.ts | 13 +++- 18 files changed, 277 insertions(+), 122 deletions(-) diff --git a/integrations/standalone/src/mock/meta.ts b/integrations/standalone/src/mock/meta.ts index 0df488ec..1a419785 100644 --- a/integrations/standalone/src/mock/meta.ts +++ b/integrations/standalone/src/mock/meta.ts @@ -1,45 +1,70 @@ -import type { ProjectVarNode } from '@axonivy/variable-editor-protocol'; +import type { KnownVariables, MetaData } from '@axonivy/variable-editor-protocol'; -export const knownVariables: ProjectVarNode = { - key: '', +export const knownVariables: KnownVariables = { + namespace: '', name: '', value: '', - type: 'folder', + metaData: { type: 'folder' }, description: '', children: [ { - key: 'Amazon', + namespace: '', name: 'Amazon', value: '', - type: 'folder', + metaData: { type: 'folder' }, description: '', children: [ { - key: 'Amazon.Comprehend', + namespace: 'Amazon', name: 'Comprehend', value: '', - type: 'folder', + metaData: { type: 'folder' }, description: 'Amazon comprehend connector settings', children: [ { - key: 'Amazon.Comprehend.SecretKey', + namespace: 'Amazon.Comprehend', name: 'SecretKey', value: '', - type: 'password', + metaData: { type: 'password' }, description: 'Secret key to access amazon comprehend', children: [] }, { - key: 'Amazon.Comprehend.AccessKey', + namespace: 'Amazon.Comprehend', name: 'AccessKey', value: '', - type: 'string', + metaData: { type: 'string' }, description: 'Access key to access amazon comprehend', children: [] } ] } ] + }, + { + namespace: '', + name: 'Meta', + value: '', + metaData: { type: 'folder' }, + description: '', + children: [ + { + namespace: 'Meta', + name: 'Enum', + value: 'two', + metaData: { type: 'enum', values: ['one', 'two', 'three'] } as MetaData, + description: '', + children: [] + }, + { + namespace: 'Meta', + name: 'File', + value: '', + metaData: { type: 'file', extension: 'json' } as MetaData, + description: '', + children: [] + } + ] } ] }; diff --git a/packages/protocol/src/editor.ts b/packages/protocol/src/editor.ts index a352bc76..2c1fac14 100644 --- a/packages/protocol/src/editor.ts +++ b/packages/protocol/src/editor.ts @@ -9,7 +9,7 @@ export type Severity = ("INFO" | "WARNING" | "ERROR") export interface Variables { - projectVarNode: ProjectVarNode; + knownVariables: KnownVariables; validationResult: ValidationResult[]; variablesActionArgs: VariablesActionArgs; variablesData: VariablesData; @@ -18,14 +18,17 @@ export interface Variables { void: Void; [k: string]: unknown; } -export interface ProjectVarNode { - children: ProjectVarNode[]; +export interface KnownVariables { + children: KnownVariables[]; description: string; - key: string; + metaData: MetaData; name: string; - type: string; + namespace: string; value: string; } +export interface MetaData { + type: string; +} export interface ValidationResult { message: string; path: string; diff --git a/packages/protocol/src/types.ts b/packages/protocol/src/types.ts index 6bd023d1..f9f54edb 100644 --- a/packages/protocol/src/types.ts +++ b/packages/protocol/src/types.ts @@ -1,5 +1,5 @@ import type { - ProjectVarNode, + KnownVariables, ValidationResult, VariablesActionArgs, VariablesData, @@ -13,7 +13,7 @@ export type SaveArgs = VariablesSaveDataArgs & { directSave?: boolean }; export type ValidationMessages = Array; export interface MetaRequestTypes { - 'meta/knownVariables': [VariablesEditorDataContext, ProjectVarNode]; + 'meta/knownVariables': [VariablesEditorDataContext, KnownVariables]; } export interface RequestTypes extends MetaRequestTypes { @@ -51,4 +51,11 @@ export interface ClientContext { client: Client; } -export const EMPTY_PROJECT_VAR_NODE: ProjectVarNode = { children: [], description: '', key: '', name: '', type: '', value: '' }; +export const EMPTY_KNOWN_VARIABLES: KnownVariables = { + children: [], + description: '', + metaData: { type: '' }, + name: '', + namespace: '', + value: '' +}; diff --git a/packages/variable-editor/src/components/variables/data/metadata.test.ts b/packages/variable-editor/src/components/variables/data/metadata.test.ts index 1932f52b..3506583b 100644 --- a/packages/variable-editor/src/components/variables/data/metadata.test.ts +++ b/packages/variable-editor/src/components/variables/data/metadata.test.ts @@ -3,10 +3,13 @@ import { isEnumMetadata, isFileMetadata, isFileMetadataFilenameExtension, + isMetadata, isMetadataType, metadataOptions, toEnumMetadataUpdate, - toFileMetadataUpdate + toFileMetadataUpdate, + type Metadata, + type MetadataType } from './metadata'; test('metadataOptions', () => { @@ -54,6 +57,44 @@ describe('isMetadataType', () => { }); }); +describe('isMetadata', () => { + describe('true', () => { + test('empty', () => { + expect(isMetadata({ type: '' })).toBeTruthy(); + }); + + test('password', () => { + expect(isMetadata({ type: 'password' })).toBeTruthy(); + }); + + test('daytime', () => { + expect(isMetadata({ type: 'daytime' })).toBeTruthy(); + }); + + test('enum', () => { + expect(isMetadata({ type: 'enum' })).toBeTruthy(); + }); + + test('file', () => { + expect(isMetadata({ type: 'file' })).toBeTruthy(); + }); + }); + + describe('false', () => { + test('other', () => { + expect(isMetadata({ type: 'other' as MetadataType })).toBeFalsy(); + }); + + test('undefined', () => { + expect(isMetadata()).toBeFalsy(); + }); + + test('type is undefined', () => { + expect(isMetadata({} as Metadata)).toBeFalsy(); + }); + }); +}); + describe('isEnumMetadata', () => { test('true', () => { expect(isEnumMetadata({ type: 'enum' })).toBeTruthy(); @@ -108,9 +149,9 @@ test('toEnumMetadataUpdate', () => { }); test('toFileMetadataUpdate', () => { - const filenameExtension = 'txt'; - expect(toFileMetadataUpdate(filenameExtension)).toEqual({ + const extension = 'txt'; + expect(toFileMetadataUpdate(extension)).toEqual({ key: 'metadata', - value: { type: 'file', filenameExtension: filenameExtension } + value: { type: 'file', extension } }); }); diff --git a/packages/variable-editor/src/components/variables/data/metadata.ts b/packages/variable-editor/src/components/variables/data/metadata.ts index 15981f03..3d9aba49 100644 --- a/packages/variable-editor/src/components/variables/data/metadata.ts +++ b/packages/variable-editor/src/components/variables/data/metadata.ts @@ -8,7 +8,7 @@ export interface EnumMetadata extends Metadata { } export interface FileMetadata extends Metadata { - filenameExtension: FileMetadataFilenameExtension; + extension: FileMetadataFilenameExtension; } export type FileMetadataFilenameExtension = (typeof fileMetadataFilenameExtensionOptions)[number]['value']; @@ -29,6 +29,10 @@ export const isMetadataType = (metadataType: string): metadataType is MetadataTy return metadataType === '' || metadataOptions.some(option => option.value === metadataType); }; +export const isMetadata = (metadata?: Metadata): metadata is Metadata => { + return metadata !== undefined && isMetadataType(metadata.type); +}; + export const isEnumMetadata = (metadata?: Metadata): metadata is EnumMetadata => { return metadata !== undefined && metadata.type === 'enum'; }; @@ -47,6 +51,6 @@ export const toEnumMetadataUpdate = (values: Array): VariableUpdate => { }; export const toFileMetadataUpdate = (filenameExtension: FileMetadataFilenameExtension): VariableUpdate => { - const metadata: FileMetadata = { type: 'file', filenameExtension: filenameExtension }; + const metadata: FileMetadata = { type: 'file', extension: filenameExtension }; return { key: 'metadata', value: metadata }; }; diff --git a/packages/variable-editor/src/components/variables/data/test-utils/variables-with-metadata.ts b/packages/variable-editor/src/components/variables/data/test-utils/variables-with-metadata.ts index 3a7c050c..c74dd3ab 100644 --- a/packages/variable-editor/src/components/variables/data/test-utils/variables-with-metadata.ts +++ b/packages/variable-editor/src/components/variables/data/test-utils/variables-with-metadata.ts @@ -44,7 +44,7 @@ export const rootVariableWithMetadata: RootVariable = { name: 'fileKey', value: 'fileValue', description: '', - metadata: { type: 'file', filenameExtension: 'json' } as FileMetadata, + metadata: { type: 'file', extension: 'json' } as FileMetadata, children: [] } ] diff --git a/packages/variable-editor/src/components/variables/data/variable-utils.test.ts b/packages/variable-editor/src/components/variables/data/variable-utils.test.ts index 5564b096..eda7cfa2 100644 --- a/packages/variable-editor/src/components/variables/data/variable-utils.test.ts +++ b/packages/variable-editor/src/components/variables/data/variable-utils.test.ts @@ -1,4 +1,5 @@ import { IvyIcons } from '@axonivy/ui-icons'; +import type { KnownVariables } from '@axonivy/variable-editor-protocol'; import { content, contentStringsOnly, rootVariable } from './test-utils/variables'; import { contentEmpty, @@ -23,7 +24,7 @@ import { rootVariableWithMetadata } from './test-utils/variables-with-metadata'; import type { Variable } from './variable'; -import { toContent, toVariables, variableIcon } from './variable-utils'; +import { nodeIcon, toContent, toVariables, variableIcon } from './variable-utils'; describe('toVariables', () => { test('default', () => { @@ -146,3 +147,35 @@ describe('variableIcon', () => { expect(variableIcon(variable)).toEqual(IvyIcons.Note); }); }); + +describe('nodeIcon', () => { + test('default', () => { + const node = { metaData: { type: 'other' } } as KnownVariables; + expect(nodeIcon(node)).toEqual(IvyIcons.Quote); + }); + + test('mapping', () => { + const node = { metaData: { type: 'folder' } } as KnownVariables; + expect(nodeIcon(node)).toEqual(IvyIcons.FolderOpen); + }); + + test('password', () => { + const node = { metaData: { type: 'password' } } as KnownVariables; + expect(nodeIcon(node)).toEqual(IvyIcons.Password); + }); + + test('daytime', () => { + const node = { metaData: { type: 'daytime' } } as KnownVariables; + expect(nodeIcon(node)).toEqual(IvyIcons.CalendarTime); + }); + + test('enum', () => { + const node = { metaData: { type: 'enum' } } as KnownVariables; + expect(nodeIcon(node)).toEqual(IvyIcons.List); + }); + + test('file', () => { + const node = { metaData: { type: 'file' } } as KnownVariables; + expect(nodeIcon(node)).toEqual(IvyIcons.Note); + }); +}); diff --git a/packages/variable-editor/src/components/variables/data/variable-utils.ts b/packages/variable-editor/src/components/variables/data/variable-utils.ts index c2d5a38d..4805023a 100644 --- a/packages/variable-editor/src/components/variables/data/variable-utils.ts +++ b/packages/variable-editor/src/components/variables/data/variable-utils.ts @@ -1,4 +1,5 @@ import { IvyIcons } from '@axonivy/ui-icons'; +import type { KnownVariables } from '@axonivy/variable-editor-protocol'; import { Pair, Scalar, YAMLMap, isMap, isPair, isScalar, parseDocument, stringify } from 'yaml'; import { addSingleLeadingWhitespaceToEachLine, getLastLine, removeSingleLeadingWhitespaceFromEachLine } from '../../../utils/string/string'; import { hasChildren } from '../../../utils/tree/tree-data'; @@ -13,7 +14,6 @@ import { type MetadataType } from './metadata'; import type { RootVariable, Variable } from './variable'; -import type { ProjectVarNode } from '@axonivy/variable-editor-protocol'; export const toVariables = (content: string) => { const rootVariable: RootVariable = { @@ -184,7 +184,7 @@ const enrichVariableWithEnumMetadata = (variable: Variable, metadata: string) => const enrichVariableWithFileMetadata = (variable: Variable, metadata: string) => { const filenameExtension = metadata.replace(/^file:\s*/, ''); if (isFileMetadataFilenameExtension(filenameExtension)) { - const fileMetadata: FileMetadata = { type: 'file', filenameExtension: filenameExtension }; + const fileMetadata: FileMetadata = { type: 'file', extension: filenameExtension }; variable.metadata = fileMetadata; } return variable; @@ -245,7 +245,7 @@ const parseMetadataComment = (metadata: Metadata) => { break; case 'file': if (isFileMetadata(metadata)) { - metadataComment = 'file: ' + metadata.filenameExtension; + metadataComment = 'file: ' + metadata.extension; } break; default: @@ -262,8 +262,8 @@ export const variableIcon = (variable: Variable) => { return icon(variable.metadata.type); }; -export const nodeIcon = (variableNode: ProjectVarNode) => { - return icon(variableNode.type); +export const nodeIcon = (node: KnownVariables) => { + return icon(node.metaData.type); }; const icon = (type: string) => { diff --git a/packages/variable-editor/src/components/variables/detail/DetailContent.test.ts b/packages/variable-editor/src/components/variables/detail/DetailContent.test.ts index ed61851b..4d45bf52 100644 --- a/packages/variable-editor/src/components/variables/detail/DetailContent.test.ts +++ b/packages/variable-editor/src/components/variables/detail/DetailContent.test.ts @@ -1,4 +1,4 @@ -import type { Client, MetaRequestTypes, ProjectVarNode } from '@axonivy/variable-editor-protocol'; +import type { Client, MetaRequestTypes, KnownVariables } from '@axonivy/variable-editor-protocol'; import { waitFor } from '@testing-library/react'; import { customRenderHook } from '../data/test-utils/test-utils'; import type { Variable } from '../data/variable'; @@ -47,6 +47,6 @@ class ClientMock implements Partial { meta(): Promise { return Promise.resolve({ children: [{ name: 'Amazon', children: [{ name: 'Comprehend', children: [{ name: 'SecretKey' }, { name: 'AccessKey' }] }] }] - } as ProjectVarNode); + } as KnownVariables); } } diff --git a/packages/variable-editor/src/components/variables/detail/DetailContent.tsx b/packages/variable-editor/src/components/variables/detail/DetailContent.tsx index 9ff24f44..5fc82ae8 100644 --- a/packages/variable-editor/src/components/variables/detail/DetailContent.tsx +++ b/packages/variable-editor/src/components/variables/detail/DetailContent.tsx @@ -1,5 +1,5 @@ import { BasicField, BasicInput, Flex, PanelMessage, ReadonlyProvider, Textarea, useReadonly } from '@axonivy/ui-components'; -import { EMPTY_PROJECT_VAR_NODE, type ProjectVarNode } from '@axonivy/variable-editor-protocol'; +import { EMPTY_KNOWN_VARIABLES, type KnownVariables } from '@axonivy/variable-editor-protocol'; import { useMemo } from 'react'; import { useAppContext } from '../../../context/AppContext'; import { useMeta } from '../../../context/useMeta'; @@ -11,7 +11,7 @@ import { Value } from './Value'; export const useOverwrites = () => { const { context, variables, selectedVariable } = useAppContext(); - let currentNode: ProjectVarNode | undefined = useMeta('meta/knownVariables', context, EMPTY_PROJECT_VAR_NODE).data; + let currentNode: KnownVariables | undefined = useMeta('meta/knownVariables', context, EMPTY_KNOWN_VARIABLES).data; if (currentNode === undefined || currentNode.children.length === 0) { return false; } diff --git a/packages/variable-editor/src/components/variables/detail/Metadata.tsx b/packages/variable-editor/src/components/variables/detail/Metadata.tsx index b9543d58..dc18066a 100644 --- a/packages/variable-editor/src/components/variables/detail/Metadata.tsx +++ b/packages/variable-editor/src/components/variables/detail/Metadata.tsx @@ -35,7 +35,7 @@ export const Metadata = ({ variable, onChange }: MetadataProps) => { case 'file': updates.push({ key: 'value', value: '' }); if (isFileMetadata(newMetadata)) { - newMetadata.filenameExtension = 'txt'; + newMetadata.extension = 'txt'; } } updates.push({ key: 'metadata', value: newMetadata }); @@ -51,7 +51,7 @@ export const Metadata = ({ variable, onChange }: MetadataProps) => { {isFileMetadata(metadata) && ( onChange([toFileMetadataUpdate(filenameExtension)])} /> diff --git a/packages/variable-editor/src/components/variables/dialog/OverwriteDialog.tsx b/packages/variable-editor/src/components/variables/dialog/OverwriteDialog.tsx index a6122013..228b1fe1 100644 --- a/packages/variable-editor/src/components/variables/dialog/OverwriteDialog.tsx +++ b/packages/variable-editor/src/components/variables/dialog/OverwriteDialog.tsx @@ -1,13 +1,13 @@ import { Button, Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, selectRow } from '@axonivy/ui-components'; import { IvyIcons } from '@axonivy/ui-icons'; +import type { KnownVariables } from '@axonivy/variable-editor-protocol'; import { type Table } from '@tanstack/react-table'; import { useState } from 'react'; import { useAppContext } from '../../../context/AppContext'; -import type { ProjectVarNode } from '@axonivy/variable-editor-protocol'; import { toRowId } from '../../../utils/tree/tree'; import { addNode } from '../../../utils/tree/tree-data'; import type { AddNodeReturnType } from '../../../utils/tree/types'; -import { isMetadataType, type MetadataType } from '../data/metadata'; +import { isMetadata, type Metadata } from '../data/metadata'; import { createVariable, type Variable } from '../data/variable'; import { VariableBrowser } from './VariableBrowser'; @@ -18,15 +18,16 @@ type OverwriteProps = { export const OverwriteDialog = ({ table }: OverwriteProps) => { const { setVariables, setSelectedVariable } = useAppContext(); - const insertVariable = (node?: ProjectVarNode): void => { - if (node) { - setVariables(old => { - const addNodeReturnValue = addVariable(old, node); - selectRow(table, toRowId(addNodeReturnValue.newNodePath)); - setSelectedVariable(addNodeReturnValue.newNodePath); - return addNodeReturnValue.newData; - }); + const insertVariable = (node?: KnownVariables): void => { + if (!node) { + return; } + setVariables(old => { + const addNodeReturnValue = addVariable(old, node); + selectRow(table, toRowId(addNodeReturnValue.newNodePath)); + setSelectedVariable(addNodeReturnValue.newNodePath); + return addNodeReturnValue.newData; + }); }; const [dialogState, setDialogState] = useState(false); @@ -51,29 +52,27 @@ export const OverwriteDialog = ({ table }: OverwriteProps) => { ); }; -const addVariable = (variables: Array, node: ProjectVarNode): AddNodeReturnType => { - const lastDot = node.key.lastIndexOf('.'); - const namespace = node.key.substring(0, lastDot); - let metadataType: MetadataType = ''; - if (isMetadataType(node.type)) { - metadataType = node.type; +const addVariable = (variables: Array, node: KnownVariables): AddNodeReturnType => { + let metadata: Metadata = { type: '' }; + const nodeMetaData = node.metaData as Metadata; + if (isMetadata(nodeMetaData)) { + metadata = nodeMetaData; } - const returnValue = addNode(node.name, namespace, variables, name => { + let returnValue = addNode(node.name, node.namespace, variables, name => { if (name === node.name) { return { name, value: node.value, children: [], description: node.description, - metadata: { type: metadataType } + metadata: metadata }; } return createVariable(name); }); - let childReturnValue = returnValue; + const newNodePath = returnValue.newNodePath; for (const child of node.children) { - childReturnValue = addVariable(childReturnValue.newData, child); + returnValue = addVariable(returnValue.newData, child); } - returnValue.newData = childReturnValue.newData; - return returnValue; + return { newData: returnValue.newData, newNodePath }; }; diff --git a/packages/variable-editor/src/components/variables/dialog/VariableBrowser.tsx b/packages/variable-editor/src/components/variables/dialog/VariableBrowser.tsx index 4d278ef2..2e3ae94c 100644 --- a/packages/variable-editor/src/components/variables/dialog/VariableBrowser.tsx +++ b/packages/variable-editor/src/components/variables/dialog/VariableBrowser.tsx @@ -1,14 +1,14 @@ -import { useBrowser, BrowsersView } from '@axonivy/ui-components'; +import { BrowsersView, useBrowser } from '@axonivy/ui-components'; import { IvyIcons } from '@axonivy/ui-icons'; -import { EMPTY_PROJECT_VAR_NODE, type ProjectVarNode } from '@axonivy/variable-editor-protocol'; +import { EMPTY_KNOWN_VARIABLES, type KnownVariables } from '@axonivy/variable-editor-protocol'; import { useMemo } from 'react'; import { useAppContext } from '../../../context/AppContext'; import { useMeta } from '../../../context/useMeta'; import { toNodes } from './known-variables'; -export const VariableBrowser = ({ applyFn }: { applyFn: (node?: ProjectVarNode) => void }) => { +export const VariableBrowser = ({ applyFn }: { applyFn: (node?: KnownVariables) => void }) => { const { context } = useAppContext(); - const knownVariables = useMeta('meta/knownVariables', context, EMPTY_PROJECT_VAR_NODE).data; + const knownVariables = useMeta('meta/knownVariables', context, EMPTY_KNOWN_VARIABLES).data; const nodes = useMemo(() => toNodes(knownVariables), [knownVariables]); const variableBrowser = useBrowser(nodes); return ( @@ -18,30 +18,30 @@ export const VariableBrowser = ({ applyFn }: { applyFn: (node?: ProjectVarNode) name: 'Variables', icon: IvyIcons.Tool, browser: variableBrowser, - infoProvider: row => + infoProvider: row => } ]} - apply={(type, result) => { - applyFn(result?.data as ProjectVarNode); + apply={(_, result) => { + applyFn(result?.data as KnownVariables); }} applyBtn={{ label: 'Import', icon: IvyIcons.FileImport }} /> ); }; -const InfoProvider = ({ node }: { node?: ProjectVarNode }) => { - let value = node?.value; - if (value !== undefined && node?.type == 'password') { - value = '***'; +const InfoProvider = ({ node }: { node?: KnownVariables }) => { + if (!node) { + return; } - if (value !== undefined && value !== '') { - value = node?.name + ' = ' + value; + let value = node.value; + if (node.metaData.type === 'password') { + value = '***'; } return (
-
{node?.key}
-
{node?.description}
-
{value}
+
{`${node.namespace}.${node.name}`}
+
{node.description}
+ {value &&
{node.name + ' = ' + value}
}
); }; diff --git a/packages/variable-editor/src/components/variables/dialog/known-variables.test.ts b/packages/variable-editor/src/components/variables/dialog/known-variables.test.ts index 20d66129..b40cec08 100644 --- a/packages/variable-editor/src/components/variables/dialog/known-variables.test.ts +++ b/packages/variable-editor/src/components/variables/dialog/known-variables.test.ts @@ -1,40 +1,40 @@ -import { EMPTY_PROJECT_VAR_NODE, type ProjectVarNode } from '@axonivy/variable-editor-protocol'; +import { EMPTY_KNOWN_VARIABLES, type KnownVariables } from '@axonivy/variable-editor-protocol'; import { toNodes } from './known-variables'; -const knownVariables: ProjectVarNode = { - key: '', +const knownVariables: KnownVariables = { + namespace: '', name: '', value: '', - type: 'folder', + metaData: { type: 'folder' }, description: '', children: [ { - key: 'Amazon', + namespace: '', name: 'Amazon', value: '', - type: 'folder', + metaData: { type: 'folder' }, description: '', children: [ { - key: 'Amazon.Comprehend', + namespace: 'Amazon', name: 'Comprehend', value: '', - type: 'folder', + metaData: { type: 'folder' }, description: 'Amazon comprehend connector settings', children: [ { - key: 'Amazon.Comprehend.SecretKey', + namespace: 'Amazon.Comprehend', name: 'SecretKey', value: '', - type: 'password', + metaData: { type: 'password' }, description: 'Secret key to access amazon comprehend', children: [] }, { - key: 'Amazon.Comprehend.AccessKey', + namespace: 'Amazon.Comprehend', name: 'AccessKey', value: '', - type: 'string', + metaData: { type: 'string' }, description: 'Access key to access amazon comprehend', children: [] } @@ -46,7 +46,7 @@ const knownVariables: ProjectVarNode = { }; test('toNodes', () => { - expect(toNodes(EMPTY_PROJECT_VAR_NODE)).toEqual([]); + expect(toNodes(EMPTY_KNOWN_VARIABLES)).toEqual([]); const nodes = toNodes(knownVariables); expect(nodes).toHaveLength(1); diff --git a/packages/variable-editor/src/components/variables/dialog/known-variables.ts b/packages/variable-editor/src/components/variables/dialog/known-variables.ts index b637f9fc..8e5f744f 100644 --- a/packages/variable-editor/src/components/variables/dialog/known-variables.ts +++ b/packages/variable-editor/src/components/variables/dialog/known-variables.ts @@ -1,16 +1,16 @@ import type { BrowserNode } from '@axonivy/ui-components'; -import type { ProjectVarNode } from '@axonivy/variable-editor-protocol'; +import type { KnownVariables } from '@axonivy/variable-editor-protocol'; import { nodeIcon } from '../data/variable-utils'; -export const toNodes = (root?: ProjectVarNode): Array => { +export const toNodes = (root?: KnownVariables): Array => { if (!root) { return []; } return root.children.map(varNode => toNode(varNode)); }; -const toNode = (node: ProjectVarNode): BrowserNode => { - const c = node.children.map(child => toNode(child)); +const toNode = (node: KnownVariables): BrowserNode => { + const children = node.children.map(child => toNode(child)); const icon = nodeIcon(node); const info = node.description; return { @@ -18,6 +18,6 @@ const toNode = (node: ProjectVarNode): BrowserNode => { info, icon, data: node, - children: c + children }; }; diff --git a/playwright/tests/integration/mock/detail.spec.ts b/playwright/tests/integration/mock/detail.spec.ts index a8a853c5..6ee59207 100644 --- a/playwright/tests/integration/mock/detail.spec.ts +++ b/playwright/tests/integration/mock/detail.spec.ts @@ -100,7 +100,7 @@ test('new enum variable', async () => { await details.fill('myName', 'Monday', 'This is myName with a value of Monday', 'Enum'); await details.expectValues('myName', 'Monday', 'This is myName with a value of Monday', 'Enum'); - await details.listOfPossibleValues.expectValues(['Monday']); + await details.listOfPossibleValues.expectValues('Monday'); await details.expectTitle('Variables - project-name - myName'); await editor.tree.row(11).expectValues(['myName', 'Monday']); await editor.tree.row(10).click(); @@ -109,7 +109,7 @@ test('new enum variable', async () => { await details.expectTitle('Variables - project-name - myName'); await details.expectValues('myName', 'Monday', 'This is myName with a value of Monday', 'Enum'); - await details.listOfPossibleValues.expectValues(['Monday']); + await details.listOfPossibleValues.expectValues('Monday'); }); test('add/delete enum variable', async () => { @@ -122,7 +122,7 @@ test('add/delete enum variable', async () => { await details.listOfPossibleValues.addValue('Tuesday'); await details.listOfPossibleValues.addValue('Wednesday'); - await details.listOfPossibleValues.expectValues(['Monday', 'Tuesday', 'Wednesday']); + await details.listOfPossibleValues.expectValues('Monday', 'Tuesday', 'Wednesday'); await details.enumValue.choose('Tuesday'); await details.enumValue.expectValue('Tuesday'); @@ -135,7 +135,7 @@ test('add/delete enum variable', async () => { await details.listOfPossibleValues.deleteValue('Tuesday'); await details.listOfPossibleValues.deleteValue('Wednesday'); - await details.listOfPossibleValues.expectValues(['Monday']); + await details.listOfPossibleValues.expectValues('Monday'); }); test('edit name', async () => { diff --git a/playwright/tests/integration/mock/import.spec.ts b/playwright/tests/integration/mock/import.spec.ts index 2abe8562..13de691b 100644 --- a/playwright/tests/integration/mock/import.spec.ts +++ b/playwright/tests/integration/mock/import.spec.ts @@ -1,23 +1,44 @@ import { expect, test } from '@playwright/test'; +import { describe } from 'node:test'; import { VariableEditor } from '../../pageobjects/VariableEditor'; -test('importAndOverwrite', async ({ page }) => { - const editor = await VariableEditor.openMock(page); - await editor.tree.expectRowCount(11); +describe('importAndOverwrite', async () => { + test('password', async ({ page }) => { + const editor = await VariableEditor.openMock(page); + await editor.tree.expectRowCount(11); - const overwrite = editor.overwrite; - await overwrite.open(); - const variables = overwrite.variables; - await variables.cell(0, 0).expectValue('Amazon'); - await variables.cell(1, 0).expectValue('ComprehendAmazon comprehend connector settings'); - await variables.cell(1, 0).expand(); - await variables.cell(2, 0).expectValue('SecretKeySecret key to access amazon comprehend'); - await variables.row(2).click(); - await overwrite.importBtn.click(); - await overwrite.expectClosed(); + const overwrite = editor.overwrite; + await overwrite.open(); + const variables = overwrite.variables; + await variables.cell(0, 0).expectValue('Amazon'); + await variables.cell(1, 0).expectValue('ComprehendAmazon comprehend connector settings'); + await variables.cell(1, 0).expand(); + await variables.cell(2, 0).expectValue('SecretKeySecret key to access amazon comprehend'); + await variables.row(2).click(); + await overwrite.importBtn.click(); + await overwrite.expectClosed(); - const details = editor.details; - await details.expectValues('SecretKey', '', 'Secret key to access amazon comprehend', 'Password'); + const details = editor.details; + await details.expectValues('SecretKey', '', 'Secret key to access amazon comprehend', 'Password'); + }); + + test('enum has values', async ({ page }) => { + const editor = await VariableEditor.openMock(page); + await editor.overwrite.open(); + await editor.overwrite.variables.row(2).expand(); + await editor.overwrite.variables.row(3).click(); + await editor.overwrite.importBtn.click(); + await editor.details.listOfPossibleValues.expectValues('one', 'two', 'three'); + }); + + test('file has extension', async ({ page }) => { + const editor = await VariableEditor.openMock(page); + await editor.overwrite.open(); + await editor.overwrite.variables.row(2).expand(); + await editor.overwrite.variables.row(4).click(); + await editor.overwrite.importBtn.click(); + await editor.details.fileNameExtension.expectValue('json'); + }); }); test('importAndOverwriteWholeSubTree', async ({ page }) => { @@ -45,9 +66,24 @@ test('importAndOverwriteWholeSubTree', async ({ page }) => { await details.expectValues('AccessKey', '', 'Access key to access amazon comprehend', 'Default'); }); -test('disabledMetadataOfOverwrittenVariable', async ({ page }) => { - const editor = await VariableEditor.openMock(page); - await editor.addVariable('SecretKey', 'Amazon.Comprehend'); - await editor.tree.row(13).click(); - await expect(editor.details.metaData.locator).toBeDisabled(); +describe('disabledMetadataOfOverwrittenVariable', async () => { + test('enum', async ({ page }) => { + const editor = await VariableEditor.openMock(page); + await editor.overwrite.open(); + await editor.overwrite.variables.row(2).click(); + await editor.overwrite.importBtn.click(); + await editor.tree.row(12).click(); + await expect(editor.details.metaData.locator).toBeDisabled(); + await editor.details.listOfPossibleValues.expectToBeDisabled(); + }); + + test('file', async ({ page }) => { + const editor = await VariableEditor.openMock(page); + await editor.overwrite.open(); + await editor.overwrite.variables.row(2).click(); + await editor.overwrite.importBtn.click(); + await editor.tree.row(13).click(); + await expect(editor.details.metaData.locator).toBeDisabled(); + await expect(editor.details.fileNameExtension.locator).toBeDisabled(); + }); }); diff --git a/playwright/tests/pageobjects/EnumValues.ts b/playwright/tests/pageobjects/EnumValues.ts index af55c90e..67c15918 100644 --- a/playwright/tests/pageobjects/EnumValues.ts +++ b/playwright/tests/pageobjects/EnumValues.ts @@ -1,6 +1,6 @@ -import type { Locator, Page } from '@playwright/test'; -import { Table } from './Table'; +import { expect, type Locator, type Page } from '@playwright/test'; import { Button } from './Button'; +import { Table } from './Table'; export class EnumValues { private readonly table: Table; @@ -41,10 +41,17 @@ export class EnumValues { await this.table.cell(rowCount - 1, 0).fill(value); } - async expectValues(values: string[]) { + async expectValues(...values: Array) { await this.table.expectRowCount(values.length); for (let row = 0; row < values.length; row++) { await this.table.cell(row, 0).expectValue(values[row]); } } + + async expectToBeDisabled() { + const rowCount = await this.table.rowCount(); + for (let row = 0; row < rowCount; row++) { + await expect(this.table.row(row).locator.locator('.ui-input')).toBeDisabled(); + } + } }