mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[6.4] Fix bug caused by importing saved objects with missing index patterns (#20379, #20379, #22068, #22029) (#22432)
* Add detection of invalid JSON searchSource to saved_object and dashboard (#20379) * Reenable import objects tests (#21250) * Reenable import objects tests. Refine their assertions. Add primary callout to indicate completion of import process when the user has opted to not import anything. * fixing importing saved objects when there's a missing index pattern (#22068) * fixing issue with importing vis with missing saved search (#22029)
This commit is contained in:
parent
4114120a70
commit
11e2fa1b6f
12 changed files with 2897 additions and 54 deletions
|
@ -28,7 +28,7 @@ import dashboardTemplate from './dashboard_app.html';
|
|||
import dashboardListingTemplate from './listing/dashboard_listing_ng_wrapper.html';
|
||||
|
||||
import { DashboardConstants, createDashboardEditUrl } from './dashboard_constants';
|
||||
import { SavedObjectNotFound } from 'ui/errors';
|
||||
import { InvalidJSONProperty, SavedObjectNotFound } from 'ui/errors';
|
||||
import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';
|
||||
import { SavedObjectsClientProvider } from 'ui/saved_objects';
|
||||
import { recentlyAccessed } from 'ui/persisted_log';
|
||||
|
@ -114,6 +114,13 @@ uiRoutes
|
|||
return savedDashboard;
|
||||
})
|
||||
.catch((error) => {
|
||||
// A corrupt dashboard was detected (e.g. with invalid JSON properties)
|
||||
if (error instanceof InvalidJSONProperty) {
|
||||
toastNotifications.addDanger(error.message);
|
||||
kbnUrl.redirect(DashboardConstants.LANDING_PAGE_PATH);
|
||||
return;
|
||||
}
|
||||
|
||||
// Preserve BWC of v5.3.0 links for new, unsaved dashboards.
|
||||
// See https://github.com/elastic/kibana/issues/10951 for more context.
|
||||
if (error instanceof SavedObjectNotFound && id === 'create') {
|
||||
|
|
1268
src/core_plugins/kibana/public/index.css
Normal file
1268
src/core_plugins/kibana/public/index.css
Normal file
File diff suppressed because one or more lines are too long
|
@ -136,6 +136,7 @@ export class Flyout extends Component {
|
|||
conflictedSavedObjectsLinkedToSavedSearches,
|
||||
conflictedSearchDocs,
|
||||
importedObjectCount,
|
||||
failedImports,
|
||||
} = await resolveSavedObjects(
|
||||
contents,
|
||||
isOverwriteAllChecked,
|
||||
|
@ -166,6 +167,7 @@ export class Flyout extends Component {
|
|||
conflictedIndexPatterns,
|
||||
conflictedSavedObjectsLinkedToSavedSearches,
|
||||
conflictedSearchDocs,
|
||||
failedImports,
|
||||
conflicts,
|
||||
importCount: importedObjectCount,
|
||||
isLoading: false,
|
||||
|
@ -198,6 +200,7 @@ export class Flyout extends Component {
|
|||
isOverwriteAllChecked,
|
||||
conflictedSavedObjectsLinkedToSavedSearches,
|
||||
conflictedSearchDocs,
|
||||
failedImports
|
||||
} = this.state;
|
||||
|
||||
const { services, indexPatterns } = this.props;
|
||||
|
@ -237,6 +240,13 @@ export class Flyout extends Component {
|
|||
indexPatterns,
|
||||
isOverwriteAllChecked
|
||||
);
|
||||
this.setState({
|
||||
loadingMessage: 'Retrying failed objects...',
|
||||
});
|
||||
importCount += await saveObjects(
|
||||
failedImports.map(({ obj }) => obj),
|
||||
isOverwriteAllChecked
|
||||
);
|
||||
} catch (e) {
|
||||
this.setState({
|
||||
error: e.message,
|
||||
|
@ -373,6 +383,7 @@ export class Flyout extends Component {
|
|||
isOverwriteAllChecked,
|
||||
wasImportSuccessful,
|
||||
importCount,
|
||||
failedImports = [],
|
||||
} = this.state;
|
||||
|
||||
if (isLoading) {
|
||||
|
@ -389,9 +400,41 @@ export class Flyout extends Component {
|
|||
);
|
||||
}
|
||||
|
||||
if (wasImportSuccessful) {
|
||||
if (failedImports.length && !this.hasConflicts) {
|
||||
return (
|
||||
<EuiCallOut title="Import successful" color="success" iconType="check">
|
||||
<EuiCallOut
|
||||
title="Import failed"
|
||||
color="warning"
|
||||
iconType="help"
|
||||
>
|
||||
<p>
|
||||
Failed to import {failedImports.length} of {importCount + failedImports.length} objects.
|
||||
</p>
|
||||
<p>
|
||||
{failedImports.map(({ error }) => error.message || '').join(' ')}
|
||||
</p>
|
||||
</EuiCallOut>
|
||||
);
|
||||
}
|
||||
|
||||
if (wasImportSuccessful) {
|
||||
if (importCount === 0) {
|
||||
return (
|
||||
<EuiCallOut
|
||||
data-test-subj="importSavedObjectsSuccessNoneImported"
|
||||
title="No objects imported"
|
||||
color="primary"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiCallOut
|
||||
data-test-subj="importSavedObjectsSuccess"
|
||||
title="Import successful"
|
||||
color="success"
|
||||
iconType="check"
|
||||
>
|
||||
<p>Successfully imported {importCount} objects.</p>
|
||||
</EuiCallOut>
|
||||
);
|
||||
|
|
|
@ -163,6 +163,7 @@ export async function resolveSavedObjects(
|
|||
// Keep track of how many we actually import because the user
|
||||
// can cancel an override
|
||||
let importedObjectCount = 0;
|
||||
// Keep a record of any objects which fail to import for unknown reasons.
|
||||
const failedImports = [];
|
||||
// Start with the index patterns since everything is dependent on them
|
||||
await awaitEachItemInParallel(
|
||||
|
@ -199,13 +200,15 @@ export async function resolveSavedObjects(
|
|||
if (await importDocument(obj, searchDoc, overwriteAll)) {
|
||||
importedObjectCount++;
|
||||
}
|
||||
} catch (err) {
|
||||
if (err instanceof SavedObjectNotFound) {
|
||||
if (err.savedObjectType === 'index-pattern') {
|
||||
} catch (error) {
|
||||
if (error instanceof SavedObjectNotFound) {
|
||||
if (error.savedObjectType === 'index-pattern') {
|
||||
conflictedIndexPatterns.push({ obj, doc: searchDoc });
|
||||
} else {
|
||||
conflictedSearchDocs.push(searchDoc);
|
||||
}
|
||||
} else {
|
||||
failedImports.push({ obj, error });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -217,15 +220,20 @@ export async function resolveSavedObjects(
|
|||
if (await importDocument(obj, otherDoc, overwriteAll)) {
|
||||
importedObjectCount++;
|
||||
}
|
||||
} catch (err) {
|
||||
if (err instanceof SavedObjectNotFound) {
|
||||
if (err.savedObjectType === 'index-pattern') {
|
||||
} catch (error) {
|
||||
if (error instanceof SavedObjectNotFound) {
|
||||
if (error.savedObjectType === 'search') {
|
||||
failedImports.push({ obj, error });
|
||||
}
|
||||
if (error.savedObjectType === 'index-pattern') {
|
||||
if (obj.savedSearchId) {
|
||||
conflictedSavedObjectsLinkedToSavedSearches.push(obj);
|
||||
} else {
|
||||
conflictedIndexPatterns.push({ obj, doc: otherDoc });
|
||||
}
|
||||
}
|
||||
} else {
|
||||
failedImports.push({ obj, error });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -235,5 +243,6 @@ export async function resolveSavedObjects(
|
|||
conflictedSavedObjectsLinkedToSavedSearches,
|
||||
conflictedSearchDocs,
|
||||
importedObjectCount,
|
||||
failedImports,
|
||||
};
|
||||
}
|
||||
|
|
87
src/core_plugins/status_page/public/index.css
Normal file
87
src/core_plugins/status_page/public/index.css
Normal file
|
@ -0,0 +1,87 @@
|
|||
@-webkit-keyframes euiAnimFadeIn {
|
||||
0% {
|
||||
opacity: 0; }
|
||||
100% {
|
||||
opacity: 1; } }
|
||||
|
||||
@keyframes euiAnimFadeIn {
|
||||
0% {
|
||||
opacity: 0; }
|
||||
100% {
|
||||
opacity: 1; } }
|
||||
|
||||
@-webkit-keyframes euiGrow {
|
||||
0% {
|
||||
opacity: 0; }
|
||||
1% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0); }
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1); } }
|
||||
|
||||
@keyframes euiGrow {
|
||||
0% {
|
||||
opacity: 0; }
|
||||
1% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0); }
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1); } }
|
||||
|
||||
/**
|
||||
* Text truncation
|
||||
*
|
||||
* Prevent text from wrapping onto multiple lines, and truncate with an
|
||||
* ellipsis.
|
||||
*
|
||||
* 1. Ensure that the node has a maximum width after which truncation can
|
||||
* occur.
|
||||
* 2. Fix for IE 8/9 if `word-wrap: break-word` is in effect on ancestor
|
||||
* nodes.
|
||||
*/
|
||||
/**
|
||||
* Set scroll bar appearance on Chrome.
|
||||
*/
|
||||
/**
|
||||
* Specifically target IE11, but not Edge.
|
||||
*/
|
||||
@-webkit-keyframes focusRingAnimate {
|
||||
0% {
|
||||
-webkit-box-shadow: 0 0 0 6px rgba(0, 121, 165, 0);
|
||||
box-shadow: 0 0 0 6px rgba(0, 121, 165, 0); }
|
||||
100% {
|
||||
-webkit-box-shadow: 0 0 0 2px rgba(0, 121, 165, 0.3);
|
||||
box-shadow: 0 0 0 2px rgba(0, 121, 165, 0.3); } }
|
||||
@keyframes focusRingAnimate {
|
||||
0% {
|
||||
-webkit-box-shadow: 0 0 0 6px rgba(0, 121, 165, 0);
|
||||
box-shadow: 0 0 0 6px rgba(0, 121, 165, 0); }
|
||||
100% {
|
||||
-webkit-box-shadow: 0 0 0 2px rgba(0, 121, 165, 0.3);
|
||||
box-shadow: 0 0 0 2px rgba(0, 121, 165, 0.3); } }
|
||||
|
||||
@-webkit-keyframes focusRingAnimateLarge {
|
||||
0% {
|
||||
-webkit-box-shadow: 0 0 0 10px rgba(0, 121, 165, 0);
|
||||
box-shadow: 0 0 0 10px rgba(0, 121, 165, 0); }
|
||||
100% {
|
||||
-webkit-box-shadow: 0 0 0 4px rgba(0, 121, 165, 0.3);
|
||||
box-shadow: 0 0 0 4px rgba(0, 121, 165, 0.3); } }
|
||||
|
||||
@keyframes focusRingAnimateLarge {
|
||||
0% {
|
||||
-webkit-box-shadow: 0 0 0 10px rgba(0, 121, 165, 0);
|
||||
box-shadow: 0 0 0 10px rgba(0, 121, 165, 0); }
|
||||
100% {
|
||||
-webkit-box-shadow: 0 0 0 4px rgba(0, 121, 165, 0.3);
|
||||
box-shadow: 0 0 0 4px rgba(0, 121, 165, 0.3); } }
|
||||
|
||||
.stsPage {
|
||||
min-height: 100vh; }
|
||||
/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9AZWxhc3RpYy9ldWkvc3JjL2dsb2JhbF9zdHlsaW5nL3ZhcmlhYmxlcy9fYW5pbWF0aW9ucy5zY3NzIiwiLi4vLi4vLi4vLi4vbm9kZV9tb2R1bGVzL0BlbGFzdGljL2V1aS9zcmMvZ2xvYmFsX3N0eWxpbmcvbWl4aW5zL190eXBvZ3JhcGh5LnNjc3MiLCIuLi8uLi8uLi8uLi9ub2RlX21vZHVsZXMvQGVsYXN0aWMvZXVpL3NyYy9nbG9iYWxfc3R5bGluZy9taXhpbnMvX2hlbHBlcnMuc2NzcyIsIi4uLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9AZWxhc3RpYy9ldWkvc3JjL2dsb2JhbF9zdHlsaW5nL21peGlucy9fc3RhdGVzLnNjc3MiLCIuLi8uLi8uLi8uLi9ub2RlX21vZHVsZXMvQGVsYXN0aWMvZXVpL3NyYy9nbG9iYWxfc3R5bGluZy92YXJpYWJsZXMvX2NvbG9ycy5zY3NzIiwiaW5kZXguc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFXQTtFQUNFO0lBQ0UsV0FBVSxFQUFBO0VBRVo7SUFDRSxXQUFVLEVBQUEsRUFBQTs7QUFMZDtFQUNFO0lBQ0UsV0FBVSxFQUFBO0VBRVo7SUFDRSxXQUFVLEVBQUEsRUFBQTs7QUFJZDtFQUNFO0lBQ0UsV0FBVSxFQUFBO0VBRVo7SUFDRSxXQUFVO0lBQ1YsNEJBQW1CO1lBQW5CLG9CQUFtQixFQUFBO0VBRXJCO0lBQ0UsV0FBVTtJQUNWLDRCQUFtQjtZQUFuQixvQkFBbUIsRUFBQSxFQUFBOztBQVZ2QjtFQUNFO0lBQ0UsV0FBVSxFQUFBO0VBRVo7SUFDRSxXQUFVO0lBQ1YsNEJBQW1CO1lBQW5CLG9CQUFtQixFQUFBO0VBRXJCO0lBQ0UsV0FBVTtJQUNWLDRCQUFtQjtZQUFuQixvQkFBbUIsRUFBQSxFQUFBOztBQ3lEdkI7Ozs7Ozs7Ozs7R0FVRztBQ2xFSDs7R0FFRztBQW9CSDs7R0FFRztBQ3ZDSDtFQUNFO0lBQ0UsbURDaEJxQjtZRGdCckIsMkNDaEJxQixFQUFBO0VEa0J2QjtJQUNFLHFEQ25CcUI7WURtQnJCLDZDQ25CcUIsRUFBQSxFQUFBO0FEY3pCO0VBQ0U7SUFDRSxtRENoQnFCO1lEZ0JyQiwyQ0NoQnFCLEVBQUE7RURrQnZCO0lBQ0UscURDbkJxQjtZRG1CckIsNkNDbkJxQixFQUFBLEVBQUE7O0FEdUJ6QjtFQUNFO0lBQ0Usb0RDekJxQjtZRHlCckIsNENDekJxQixFQUFBO0VEMkJ2QjtJQUNFLHFEQzVCcUI7WUQ0QnJCLDZDQzVCcUIsRUFBQSxFQUFBOztBRHVCekI7RUFDRTtJQUNFLG9EQ3pCcUI7WUR5QnJCLDRDQ3pCcUIsRUFBQTtFRDJCdkI7SUFDRSxxREM1QnFCO1lENEJyQiw2Q0M1QnFCLEVBQUEsRUFBQTs7QUNDekI7RUFDRSxrQkFBaUIsRUFDbEIiLCJmaWxlIjoidG8uY3NzIn0= */
|
|
@ -25,8 +25,8 @@ import BluebirdPromise from 'bluebird';
|
|||
import { SavedObjectProvider } from '../saved_object';
|
||||
import { IndexPatternProvider } from '../../../index_patterns/_index_pattern';
|
||||
import { SavedObjectsClientProvider } from '../../../saved_objects';
|
||||
|
||||
import { StubIndexPatternsApiClientModule } from '../../../index_patterns/__tests__/stub_index_patterns_api_client';
|
||||
import { InvalidJSONProperty } from '../../../errors';
|
||||
|
||||
describe('Saved Object', function () {
|
||||
require('test_utils/no_digest_promises').activateForSuite();
|
||||
|
@ -300,6 +300,25 @@ describe('Saved Object', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('throws error invalid JSON is detected', async function () {
|
||||
const savedObject = await createInitializedSavedObject({ type: 'dashboard', searchSource: true });
|
||||
const response = {
|
||||
found: true,
|
||||
_source: {
|
||||
kibanaSavedObjectMeta: {
|
||||
searchSourceJSON: '\"{\\n \\\"filter\\\": []\\n}\"'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
await savedObject.applyESResp(response);
|
||||
throw new Error('applyESResp should have failed, but did not.');
|
||||
} catch (err) {
|
||||
expect(err instanceof InvalidJSONProperty).to.be(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('preserves original defaults if not overridden', function () {
|
||||
const id = 'anid';
|
||||
const preserveMeValue = 'here to stay!';
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
import angular from 'angular';
|
||||
import _ from 'lodash';
|
||||
|
||||
import { SavedObjectNotFound } from '../../errors';
|
||||
import { InvalidJSONProperty, SavedObjectNotFound } from '../../errors';
|
||||
import MappingSetupProvider from '../../utils/mapping_setup';
|
||||
|
||||
import { SearchSourceProvider } from '../search_source';
|
||||
|
@ -117,7 +117,15 @@ export function SavedObjectProvider(Promise, Private, Notifier, confirmModalProm
|
|||
try {
|
||||
searchSourceValues = JSON.parse(searchSourceJson);
|
||||
} catch (e) {
|
||||
searchSourceValues = {};
|
||||
throw new InvalidJSONProperty(
|
||||
`Invalid JSON in ${esType} "${this.id}". ${e.message} JSON: ${searchSourceJson}`
|
||||
);
|
||||
}
|
||||
|
||||
// This detects a scenario where documents with invalid JSON properties have been imported into the saved object index.
|
||||
// (This happened in issue #20308)
|
||||
if (!searchSourceValues || typeof searchSourceValues !== 'object') {
|
||||
throw new InvalidJSONProperty(`Invalid searchSourceJSON in ${esType} "${this.id}".`);
|
||||
}
|
||||
|
||||
const searchSourceFields = this.searchSource.getFields();
|
||||
|
|
|
@ -230,6 +230,17 @@ export class PersistedStateError extends KbnError {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This error is for scenarios where a saved object is detected that has invalid JSON properties.
|
||||
* There was a scenario where we were importing objects with double-encoded JSON, and the system
|
||||
* was silently failing. This error is now thrown in those scenarios.
|
||||
*/
|
||||
export class InvalidJSONProperty extends KbnError {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UI Errors
|
||||
*/
|
||||
|
|
|
@ -24,6 +24,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
const kibanaServer = getService('kibanaServer');
|
||||
const esArchiver = getService('esArchiver');
|
||||
const PageObjects = getPageObjects(['common', 'settings', 'header']);
|
||||
const testSubjects = getService('testSubjects');
|
||||
|
||||
describe('import objects', function describeIndexTests() {
|
||||
beforeEach(async function () {
|
||||
|
@ -53,7 +54,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects-conflicts.json'));
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.settings.setImportIndexFieldOption(2);
|
||||
await PageObjects.settings.clickConfirmConflicts();
|
||||
await PageObjects.settings.clickConfirmChanges();
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.settings.clickImportDone();
|
||||
await PageObjects.settings.waitUntilSavedObjectsTableIsNotLoading();
|
||||
|
@ -62,56 +63,40 @@ export default function ({ getService, getPageObjects }) {
|
|||
expect(isSavedObjectImported).to.be(true);
|
||||
});
|
||||
|
||||
// Test should be testing that user is warned when saved object will override another because of an id collision
|
||||
// This is not the case. Instead the test just loads a saved object with an index pattern conflict
|
||||
// Disabling until the issue is resolved since the test does not test the intended behavior
|
||||
it.skip('should allow for overrides', async function () {
|
||||
it('should allow the user to override duplicate saved objects', async function () {
|
||||
await PageObjects.settings.clickKibanaSavedObjects();
|
||||
|
||||
// Put in data which already exists
|
||||
// This data has already been loaded by the "visualize" esArchive. We'll load it again
|
||||
// so that we can override the existing visualization.
|
||||
await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects_exists.json'), false);
|
||||
// Wait for all the saves to happen
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
// Interact with the conflict modal
|
||||
await PageObjects.settings.setImportIndexFieldOption(2);
|
||||
await PageObjects.settings.clickConfirmConflicts();
|
||||
// Now confirm we want to override
|
||||
await PageObjects.common.clickConfirmOnModal();
|
||||
// Wait for all the saves to happen
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
// Finish the flyout
|
||||
await PageObjects.settings.clickImportDone();
|
||||
// Wait...
|
||||
await PageObjects.settings.waitUntilSavedObjectsTableIsNotLoading();
|
||||
|
||||
const objects = await PageObjects.settings.getSavedObjectsInTable();
|
||||
expect(objects.length).to.be(2);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.settings.setImportIndexFieldOption(2);
|
||||
await PageObjects.settings.clickConfirmChanges();
|
||||
|
||||
// Override the visualization.
|
||||
await PageObjects.common.clickConfirmOnModal();
|
||||
|
||||
const isSuccessful = await testSubjects.exists('importSavedObjectsSuccess');
|
||||
expect(isSuccessful).to.be(true);
|
||||
});
|
||||
|
||||
// Test should be testing that user is warned when saved object will overrides another because of an id collision
|
||||
// This is not the case. Instead the test just loads a saved object with an index pattern conflict
|
||||
// Disabling until the issue is resolved since the test does not test the intended behavior
|
||||
it.skip('should allow for cancelling overrides', async function () {
|
||||
it('should allow the user to cancel overriding duplicate saved objects', async function () {
|
||||
await PageObjects.settings.clickKibanaSavedObjects();
|
||||
|
||||
// Put in data which already exists
|
||||
// This data has already been loaded by the "visualize" esArchive. We'll load it again
|
||||
// so that we can be prompted to override the existing visualization.
|
||||
await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects_exists.json'), false);
|
||||
// Wait for all the saves to happen
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
// Interact with the conflict modal
|
||||
await PageObjects.settings.setImportIndexFieldOption(2);
|
||||
await PageObjects.settings.clickConfirmConflicts();
|
||||
// Now cancel the override
|
||||
await PageObjects.common.clickCancelOnModal();
|
||||
// Wait for all saves to happen
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
// Finish the flyout
|
||||
await PageObjects.settings.clickImportDone();
|
||||
// Wait for table to refresh
|
||||
await PageObjects.settings.waitUntilSavedObjectsTableIsNotLoading();
|
||||
|
||||
const objects = await PageObjects.settings.getSavedObjectsInTable();
|
||||
expect(objects.length).to.be(2);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.settings.setImportIndexFieldOption(2);
|
||||
await PageObjects.settings.clickConfirmChanges();
|
||||
|
||||
// *Don't* override the visualization.
|
||||
await PageObjects.common.clickCancelOnModal();
|
||||
|
||||
const isSuccessful = await testSubjects.exists('importSavedObjectsSuccessNoneImported');
|
||||
expect(isSuccessful).to.be(true);
|
||||
});
|
||||
|
||||
it('should import saved objects linked to saved searches', async function () {
|
||||
|
|
|
@ -578,7 +578,7 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
|
|||
await testSubjects.click('importSavedObjectsDoneBtn');
|
||||
}
|
||||
|
||||
async clickConfirmConflicts() {
|
||||
async clickConfirmChanges() {
|
||||
await testSubjects.click('importSavedObjectsConfirmBtn');
|
||||
}
|
||||
|
||||
|
|
865
x-pack/plugins/dashboard_mode/public/index.css
Normal file
865
x-pack/plugins/dashboard_mode/public/index.css
Normal file
File diff suppressed because one or more lines are too long
541
x-pack/plugins/monitoring/public/index.css
Normal file
541
x-pack/plugins/monitoring/public/index.css
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue