datalens-ui/tests/suites/dataset/history.test.ts
2026-06-24 20:31:05 +05:00

749 lines
29 KiB
TypeScript

import {expect} from '@playwright/test';
import datalensTest from '../../utils/playwright/globalTestDefinition';
import {openTestPage, slct} from '../../utils';
import {
DatasetFieldsTabQa,
DatasetEditorTableSettingsItems,
EditHistoryQA,
DatasetFieldContextMenuItemsQA,
FieldEditorQa,
DatasetFieldTabBatchPanelQa,
DialogConfirmQA,
DATASET_TAB,
DialogParameterQA,
ActionPanelQA,
DialogRelatedEntitiesQA,
} from '../../../src/shared';
import DatasetPage from '../../page-objects/dataset/DatasetPage';
import FieldEditor from '../../page-objects/wizard/FieldEditor';
import {VALIDATE_DATASET_URL} from '../../page-objects/dataset/constants';
import {RobotChartsDatasetUrls} from '../../utils/constants';
import {getValidatePromise} from '../../page-objects/dataset/utils';
import {ActionPanelEntryContextMenuQa} from '../../../src/shared/constants/qa/action-panel';
datalensTest.describe('Dataset history', () => {
const url = RobotChartsDatasetUrls.DatasetWithCsvConnection;
let datasetPage: DatasetPage;
datalensTest.beforeEach(async ({page}) => {
datasetPage = new DatasetPage({page});
const validatePromise = page.waitForResponse(
(response) => response.url().includes('/validateDataset') && response.ok(),
);
await openTestPage(page, url);
await page.waitForSelector(slct(DatasetFieldsTabQa.FieldNameColumnInput));
// Wait for initial dataset validation to complete, ensuring the edit history is initialized
await validatePromise;
});
datalensTest('Undo button is disabled when no changes were made', async ({page}) => {
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeVisible();
await expect(undoBtn).toBeDisabled();
});
datalensTest('Redo button is disabled when no changes were made', async ({page}) => {
const redoBtn = page.locator(slct(EditHistoryQA.RedoBtn));
await expect(redoBtn).toBeVisible();
await expect(redoBtn).toBeDisabled();
});
datalensTest('Undo and redo reverts a field rename', async ({page}) => {
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeDisabled();
const fieldInput = datasetPage.datasetFieldsTable.getFieldNameInput();
const {newValue: changedValue, originalValue} =
(await datasetPage.renameFirstField()) ?? {};
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const undoValue = await fieldInput.inputValue();
expect(undoValue).toBe(originalValue);
const redoBtn = page.locator(slct(EditHistoryQA.RedoBtn));
await expect(redoBtn).toBeEnabled();
await redoBtn.click();
const redoValue = await fieldInput.inputValue();
expect(redoValue).toBe(changedValue);
});
datalensTest('Redo is disabled after undo and making a new change', async ({page}) => {
await datasetPage.renameFirstField();
// Undo
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const redoBtn = page.locator(slct(EditHistoryQA.RedoBtn));
await expect(redoBtn).toBeEnabled();
await datasetPage.renameFirstField({value: 'new_value'});
await expect(redoBtn).toBeDisabled();
});
datalensTest('Undo reverts field visibility toggle', async ({page}) => {
// Disable "Show hidden" so we cant observe the hidden field
const settingsBtn = page.locator(slct(DatasetFieldsTabQa.TableSettingsBtn));
await settingsBtn.click();
const showHiddenMenuItem = await page.waitForSelector(
slct(DatasetEditorTableSettingsItems.ShowHidden),
);
await showHiddenMenuItem.click();
const rowsCountBefore = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
// Hide first field
const hiddenBtn = page.locator(slct(DatasetFieldsTabQa.FieldVisibleColumnIcon)).first();
await hiddenBtn.click();
const rowsCountAfterHide = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
expect(rowsCountAfterHide).toBe(rowsCountBefore - 1);
// Undo the hide
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const rowsCountAfterUndo = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
expect(rowsCountAfterUndo).toBe(rowsCountBefore);
});
datalensTest('Redo restores field visibility toggle', async ({page}) => {
// Get the visibility state of the first field before hiding
const firstFieldVisibleIcon = page
.locator(slct(DatasetFieldsTabQa.FieldVisibleColumnIcon))
.first();
const visibleClassBefore = await firstFieldVisibleIcon.getAttribute('title');
// Hide first field
await firstFieldVisibleIcon.click();
const visibleClassAfterHide = await firstFieldVisibleIcon.getAttribute('title');
expect(visibleClassAfterHide).not.toBe(visibleClassBefore);
// Undo the hide
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
// Redo the hide
const redoBtn = page.locator(slct(EditHistoryQA.RedoBtn));
await expect(redoBtn).toBeEnabled();
await redoBtn.click();
const visibleClassAfterRedo = await firstFieldVisibleIcon.getAttribute('title');
expect(visibleClassAfterRedo).toBe(visibleClassAfterHide);
});
datalensTest('Undo and Redo restores field duplication', async ({page}) => {
const rowsCountBefore = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
const fieldInput = datasetPage.datasetFieldsTable.getFieldNameInput();
await fieldInput.hover();
// Duplicate field via context menu
const contextMenuBtn = page.locator(slct(DatasetFieldsTabQa.FieldContextMenuBtn)).first();
await contextMenuBtn.click();
const duplicateItem = page.locator(slct(DatasetFieldContextMenuItemsQA.DUPLICATE));
const duplicatePromise = datasetPage.waitForSuccessfulResponse(VALIDATE_DATASET_URL);
await duplicateItem.click();
await duplicatePromise;
const rowsCountAfterDuplicate = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
expect(rowsCountAfterDuplicate).toBe(rowsCountBefore + 1);
// Undo the duplication
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const rowsCountAfterUndo = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
expect(rowsCountAfterUndo).toBe(rowsCountBefore);
// Redo the duplication
const redoBtn = page.locator(slct(EditHistoryQA.RedoBtn));
await expect(redoBtn).toBeEnabled();
await redoBtn.click();
const rowsCountAfterRedo = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
expect(rowsCountAfterRedo).toBe(rowsCountBefore + 1);
});
datalensTest('Undo and Redo restores field removal', async ({page}) => {
const rowsCountBefore = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
const fieldInput = datasetPage.datasetFieldsTable.getFieldNameInput();
await fieldInput.hover();
// Remove field via context menu
const contextMenuBtn = page.locator(slct(DatasetFieldsTabQa.FieldContextMenuBtn)).first();
await contextMenuBtn.click();
const removeItem = page.locator(slct(DatasetFieldContextMenuItemsQA.REMOVE));
const removePromise = datasetPage.waitForSuccessfulResponse(VALIDATE_DATASET_URL);
await removeItem.click();
await removePromise;
const rowsCountAfterRemove = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
expect(rowsCountAfterRemove).toBe(rowsCountBefore - 1);
// Undo the removal
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const rowsCountAfterUndo = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
expect(rowsCountAfterUndo).toBe(rowsCountBefore);
// Redo the removal
const redoBtn = page.locator(slct(EditHistoryQA.RedoBtn));
await expect(redoBtn).toBeEnabled();
await redoBtn.click();
const rowsCountAfterRedo = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
expect(rowsCountAfterRedo).toBe(rowsCountBefore - 1);
});
datalensTest('Undo reverts field description change', async ({page}) => {
const descriptionInput = page
.locator(slct(DatasetFieldsTabQa.FieldDescriptionColumnInput))
.first()
.locator('input');
const originalValue = await descriptionInput.inputValue();
await descriptionInput.fill('test description for history');
await page.keyboard.press('Enter');
const updatedValue = await descriptionInput.inputValue();
expect(updatedValue).toBe('test description for history');
// Undo the description change
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const restoredValue = await descriptionInput.inputValue();
expect(restoredValue).toBe(originalValue);
});
datalensTest('Redo restores field description change', async ({page}) => {
const descriptionInput = page
.locator(slct(DatasetFieldsTabQa.FieldDescriptionColumnInput))
.first()
.locator('input');
const originalValue = await descriptionInput.inputValue();
const newDescription = 'test description for redo';
await descriptionInput.fill(newDescription);
await page.keyboard.press('Enter');
// Undo
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const afterUndo = await descriptionInput.inputValue();
expect(afterUndo).toBe(originalValue);
// Redo
const redoBtn = page.locator(slct(EditHistoryQA.RedoBtn));
await expect(redoBtn).toBeEnabled();
await redoBtn.click();
const afterRedo = await descriptionInput.inputValue();
expect(afterRedo).toBe(newDescription);
});
datalensTest('Undo reverts field type change', async ({page}) => {
const typeSelect = page.locator(slct(DatasetFieldsTabQa.FieldTypeColumnBtn));
const {
targetOption,
selectBtn: typeSelectBtn,
originalSelectText: originalTypeText,
} = await datasetPage.datasetFieldsTable.changeFieldSelect(typeSelect);
if (!targetOption || !typeSelectBtn) {
return;
}
const validatePromise = datasetPage.waitForSuccessfulResponse(VALIDATE_DATASET_URL);
await targetOption.click();
await validatePromise;
const changedTypeText = await typeSelectBtn.textContent();
expect(changedTypeText).not.toBe(originalTypeText);
// Undo the type change
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const restoredTypeText = await typeSelectBtn.textContent();
expect(restoredTypeText).toBe(originalTypeText);
});
datalensTest('Redo restores field type change', async ({page}) => {
const typeSelect = page.locator(slct(DatasetFieldsTabQa.FieldTypeColumnBtn));
const {
targetOption,
targetOptionText,
originalSelectText: originalTypeText,
selectBtn: typeSelectBtn,
} = await datasetPage.datasetFieldsTable.changeFieldSelect(typeSelect);
if (!targetOption || !typeSelectBtn) {
return;
}
const validatePromise = datasetPage.waitForSuccessfulResponse(VALIDATE_DATASET_URL);
await targetOption.click();
await validatePromise;
// Undo
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const afterUndo = await typeSelectBtn.textContent();
expect(afterUndo).toBe(originalTypeText);
// Redo
const redoBtn = page.locator(slct(EditHistoryQA.RedoBtn));
await expect(redoBtn).toBeEnabled();
await redoBtn.click();
const afterRedo = await typeSelectBtn.textContent();
expect(afterRedo).toBe(targetOptionText);
});
datalensTest('Undo reverts field aggregation change', async ({page}) => {
const aggregationSelectBtns = page.locator(
slct(DatasetFieldsTabQa.FieldAggregationColumnBtn),
);
const {
targetOption,
selectBtn: aggregationSelectBtn,
originalSelectText: originalAggregationText,
} = await datasetPage.datasetFieldsTable.changeFieldSelect(aggregationSelectBtns);
if (!targetOption || !aggregationSelectBtn) {
return;
}
const validatePromise = getValidatePromise(page);
await targetOption.click();
await validatePromise;
const changedAggregationText = await aggregationSelectBtn.textContent();
expect(changedAggregationText).not.toBe(originalAggregationText);
// Undo
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const restoredAggregationText = await aggregationSelectBtn.textContent();
expect(restoredAggregationText).toBe(originalAggregationText);
});
datalensTest('Redo restores field aggregation change', async ({page}) => {
const aggregationSelectBtns = page.locator(
slct(DatasetFieldsTabQa.FieldAggregationColumnBtn),
);
const {
targetOption,
targetOptionText,
originalSelectText: originalAggregationText,
selectBtn: aggregationSelectBtn,
} = await datasetPage.datasetFieldsTable.changeFieldSelect(aggregationSelectBtns);
if (!targetOption || !aggregationSelectBtn) {
return;
}
const validatePromise = getValidatePromise(page);
await targetOption.click();
await validatePromise;
// Undo
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const afterUndo = await aggregationSelectBtn.textContent();
expect(afterUndo).toBe(originalAggregationText);
// Redo
const redoBtn = page.locator(slct(EditHistoryQA.RedoBtn));
await expect(redoBtn).toBeEnabled();
await redoBtn.click();
const afterRedo = await aggregationSelectBtn.textContent();
expect(afterRedo).toBe(targetOptionText);
});
datalensTest('Undo and redo restore field edit via field editor dialog', async ({page}) => {
const fieldInput = datasetPage.datasetFieldsTable.getFieldNameInput();
const originalName = await fieldInput.inputValue();
await fieldInput.hover();
// Open field editor via context menu
const contextMenuBtn = page.locator(slct(DatasetFieldsTabQa.FieldContextMenuBtn)).first();
await contextMenuBtn.click();
const editItem = page.locator(slct(DatasetFieldContextMenuItemsQA.EDIT));
await editItem.click();
const fieldEditorDialog = page.locator(slct(FieldEditorQa.Dialog));
await expect(fieldEditorDialog).toBeVisible();
const fieldEditor = new FieldEditor(page);
const changedName = `${originalName}_edited`;
await fieldEditor.changeName(changedName);
const applyPromise = datasetPage.waitForSuccessfulResponse(VALIDATE_DATASET_URL);
await fieldEditor.clickToApplyButton();
await applyPromise;
// Undo
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const afterUndo = await fieldInput.inputValue();
expect(afterUndo).toBe(originalName);
// Redo
const redoBtn = page.locator(slct(EditHistoryQA.RedoBtn));
await expect(redoBtn).toBeEnabled();
await redoBtn.click();
const afterRedo = await fieldInput.inputValue();
expect(afterRedo).toBe(changedName);
});
datalensTest('Undo reverts batch deletion of selected fields', async ({page}) => {
const rowsCountBefore = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
await datasetPage.datasetFieldsTable.selectTwoCheckboxes();
// Click batch delete button
const actionsPanel = page.locator(slct(DatasetFieldsTabQa.BatchActionsPanel));
await expect(actionsPanel).toBeVisible();
const deleteBtn = actionsPanel.locator(slct(DatasetFieldTabBatchPanelQa.BatchDelete));
await deleteBtn.click();
const applyDelete = await page.waitForSelector(slct(DialogConfirmQA.ApplyButton));
const deletePromise = datasetPage.waitForSuccessfulResponse(VALIDATE_DATASET_URL);
await applyDelete.click();
await deletePromise;
const rowsCountAfterDelete = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
expect(rowsCountAfterDelete).toBe(rowsCountBefore - 2);
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const rowsCountAfterUndo = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
expect(rowsCountAfterUndo).toBe(rowsCountBefore);
const redoBtn = page.locator(slct(EditHistoryQA.RedoBtn));
await expect(redoBtn).toBeEnabled();
await redoBtn.click();
const rowsCountAfterRedo = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
expect(rowsCountAfterRedo).toBe(rowsCountBefore - 2);
});
datalensTest('Undo reverts batch hide of selected fields', async ({page}) => {
const settingsBtn = page.locator(slct(DatasetFieldsTabQa.TableSettingsBtn));
await settingsBtn.click();
const showHiddenMenuItem = await page.waitForSelector(
slct(DatasetEditorTableSettingsItems.ShowHidden),
);
await showHiddenMenuItem.click();
const rowsCountBefore = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
await datasetPage.datasetFieldsTable.selectTwoCheckboxes();
const actionsPanel = page.locator(slct(DatasetFieldsTabQa.BatchActionsPanel));
await expect(actionsPanel).toBeVisible();
const hideBtn = actionsPanel.locator('button').nth(1);
await hideBtn.click();
const applyHide = await page.waitForSelector(slct(DialogConfirmQA.ApplyButton));
await applyHide.click();
// After hiding, the hidden fields should disappear (Show hidden is off by default)
const rowsCountAfterHide = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
expect(rowsCountAfterHide).toBe(rowsCountBefore - 2);
// Undo the batch hide
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const rowsCountAfterUndo = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
expect(rowsCountAfterUndo).toBe(rowsCountBefore);
const redoBtn = page.locator(slct(EditHistoryQA.RedoBtn));
await expect(redoBtn).toBeEnabled();
await redoBtn.click();
const rowsCountAfterRedo = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
expect(rowsCountAfterRedo).toBe(rowsCountBefore - 2);
});
datalensTest('Multiple redo steps restore multiple changes', async ({page}) => {
const fieldInput = datasetPage.datasetFieldsTable.getFieldNameInput();
const step1Value = 'step1';
const step2Value = 'step2';
// Two changes
const {originalValue} = (await datasetPage.renameFirstField({value: step1Value})) ?? {};
await datasetPage.renameFirstField({value: step2Value});
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
const redoBtn = page.locator(slct(EditHistoryQA.RedoBtn));
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const afterFirstUndo = await fieldInput.inputValue();
expect(afterFirstUndo).toBe(step1Value);
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const afterUndoAll = await fieldInput.inputValue();
expect(afterUndoAll).toBe(originalValue);
// Redo first
await expect(redoBtn).toBeEnabled();
await redoBtn.click();
const afterFirstRedo = await fieldInput.inputValue();
expect(afterFirstRedo).toBe(step1Value);
// Redo second
await expect(redoBtn).toBeEnabled();
await redoBtn.click();
const afterSecondRedo = await fieldInput.inputValue();
expect(afterSecondRedo).toBe(step2Value);
});
datalensTest('Undo button becomes disabled at the beginning of history', async ({page}) => {
await datasetPage.renameFirstField();
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
await expect(undoBtn).toBeDisabled();
});
datalensTest('Redo button becomes disabled at the end of history', async ({page}) => {
await datasetPage.renameFirstField();
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const redoBtn = page.locator(slct(EditHistoryQA.RedoBtn));
await expect(redoBtn).toBeEnabled();
await redoBtn.click();
await expect(redoBtn).toBeDisabled();
});
datalensTest('Keyboard shortcut Cmd/Ctrl+Z triggers undo', async ({page}) => {
const fieldInput = datasetPage.datasetFieldsTable.getFieldNameInput();
const {originalValue} = (await datasetPage.renameFirstField()) ?? {};
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeEnabled();
// Click outside the input to unfocus before using hotkey
await page.locator(slct(DatasetFieldsTabQa.DatasetEditor)).click();
await page.keyboard.press(`ControlOrMeta+z`);
const restoredValue = await fieldInput.inputValue();
expect(restoredValue).toBe(originalValue);
});
datalensTest('Keyboard shortcut Cmd/Ctrl+Shift+Z triggers redo', async ({page}) => {
const fieldInput = datasetPage.datasetFieldsTable.getFieldNameInput();
const {newValue: changedValue} = (await datasetPage.renameFirstField()) ?? {};
// Undo via button
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const redoBtn = page.locator(slct(EditHistoryQA.RedoBtn));
await expect(redoBtn).toBeEnabled();
// Click outside the input to unfocus before using hotkey
await page.locator(slct(DatasetFieldsTabQa.DatasetEditor)).click();
await page.keyboard.press(`ControlOrMeta+Shift+z`);
const restoredValue = await fieldInput.inputValue();
expect(restoredValue).toBe(changedValue);
});
datalensTest('Ctrl+Z hotkey does not trigger undo when dialog is open', async ({page}) => {
const fieldInput = datasetPage.datasetFieldsTable.getFieldNameInput();
const {newValue: changedValue} = (await datasetPage.renameFirstField()) ?? {};
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
const redoBtn = page.locator(slct(EditHistoryQA.RedoBtn));
await expect(undoBtn).toBeEnabled();
await datasetPage.openTab(DATASET_TAB.PARAMETERS);
await datasetPage.datasetTabSection.clickAddButton();
await datasetPage.dialogParameter.waitForDialogParameter();
await page.waitForSelector(slct(DialogParameterQA.Dialog));
const parametersDialog = page.locator(slct(DialogParameterQA.Dialog));
await expect(parametersDialog).toBeVisible();
await expect(undoBtn).toBeHidden();
await expect(redoBtn).toBeHidden();
// Try to undo via hotkey — should have no effect
await page.keyboard.press('ControlOrMeta+z');
// Close the dialog
const cancelBtn = page.locator(slct(DialogParameterQA.Cancel));
await cancelBtn.click();
await expect(parametersDialog).toBeHidden();
await datasetPage.openTab(DATASET_TAB.DATASET);
// The field value should still be the changed value (undo was blocked)
const currentValue = await fieldInput.inputValue();
expect(currentValue).toBe(changedValue);
// Undo button should be visible and enabled again
await expect(undoBtn).toBeVisible();
await expect(undoBtn).toBeEnabled();
});
datalensTest(
'Ctrl+Shift+Z hotkey does not trigger redo when dialog is open',
async ({page}) => {
const fieldInput = datasetPage.datasetFieldsTable.getFieldNameInput();
const {originalValue} = (await datasetPage.renameFirstField()) ?? {};
// Undo the change first
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const redoBtn = page.locator(slct(EditHistoryQA.RedoBtn));
await expect(redoBtn).toBeEnabled();
const entryContextBtn = page.locator(slct(ActionPanelQA.MoreBtn));
await entryContextBtn.click();
const relatedEntitiesBtn = await page.waitForSelector(
slct(ActionPanelEntryContextMenuQa.RelatedEntities),
);
await relatedEntitiesBtn.click();
await page.waitForSelector(slct(DialogRelatedEntitiesQA.Dialog));
const relatedEntitiesDialog = page.locator(slct(DialogRelatedEntitiesQA.Dialog));
await expect(relatedEntitiesDialog).toBeVisible();
await expect(undoBtn).toBeHidden();
await expect(redoBtn).toBeHidden();
// Try to redo via hotkey — should have no effect
await page.keyboard.press('ControlOrMeta+Shift+z');
await page.keyboard.press('Escape');
await expect(relatedEntitiesDialog).toBeHidden();
// The field value should still be the original value (redo was blocked)
const currentValue = await fieldInput.inputValue();
expect(currentValue).toBe(originalValue);
// Redo button should be visible and enabled again
await expect(redoBtn).toBeVisible();
await expect(redoBtn).toBeEnabled();
},
);
datalensTest('Undo reverts mixed action types in correct order', async ({page}) => {
const rowsCountBefore = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
const fieldInput = datasetPage.datasetFieldsTable.getFieldNameInput();
// // Step 1: Rename a field
const {newValue, originalValue} = (await datasetPage.renameFirstField()) ?? {};
// Step 2: Duplicate a field via context menu
await fieldInput.hover();
const contextMenuBtn = page.locator(slct(DatasetFieldsTabQa.FieldContextMenuBtn)).first();
await contextMenuBtn.click();
const duplicateItem = page.locator(slct(DatasetFieldContextMenuItemsQA.DUPLICATE));
const dupPromise = datasetPage.waitForSuccessfulResponse(VALIDATE_DATASET_URL);
await duplicateItem.click();
await dupPromise;
const rowsCountAfterDup = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
expect(rowsCountAfterDup).toBe(rowsCountBefore + 1);
const undoBtn = page.locator(slct(EditHistoryQA.UndoBtn));
// Undo step 2 (duplicate)
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const rowsCountAfterUndoDup = await page
.locator(slct(DatasetFieldsTabQa.FieldNameColumnInput))
.count();
expect(rowsCountAfterUndoDup).toBe(rowsCountBefore);
const afterUndoFirst = await fieldInput.inputValue();
expect(afterUndoFirst).toBe(newValue);
// Undo step 1 (rename)
await expect(undoBtn).toBeEnabled();
await undoBtn.click();
const afterUndoAll = await fieldInput.inputValue();
expect(afterUndoAll).toBe(originalValue);
});
});