Use management.getTitle for import summary (#87285) (#87462)

* fix import summary title

* remove TODO
This commit is contained in:
Pierre Gayvallet 2021-01-06 14:38:31 +01:00 committed by GitHub
parent 07e96fff34
commit b6237b1cf1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 146 additions and 39 deletions

View file

@ -79,17 +79,18 @@ describe('#importSavedObjectsFromStream', () => {
let typeRegistry: jest.Mocked<ISavedObjectTypeRegistry>;
const namespace = 'some-namespace';
const setupOptions = (createNewCopies: boolean = false): SavedObjectsImportOptions => {
const setupOptions = (
createNewCopies: boolean = false,
getTypeImpl: (name: string) => any = (type: string) =>
({
// other attributes aren't needed for the purposes of injecting metadata
management: { icon: `${type}-icon` },
} as any)
): SavedObjectsImportOptions => {
readStream = new Readable();
savedObjectsClient = savedObjectsClientMock.create();
typeRegistry = typeRegistryMock.create();
typeRegistry.getType.mockImplementation(
(type: string) =>
({
// other attributes aren't needed for the purposes of injecting metadata
management: { icon: `${type}-icon` },
} as any)
);
typeRegistry.getType.mockImplementation(getTypeImpl);
return {
readStream,
objectLimit,
@ -100,14 +101,17 @@ describe('#importSavedObjectsFromStream', () => {
createNewCopies,
};
};
const createObject = (): SavedObject<{
const createObject = ({
type = 'foo-type',
title = 'some-title',
}: { type?: string; title?: string } = {}): SavedObject<{
title: string;
}> => {
return {
type: 'foo-type',
type,
id: uuidv4(),
references: [],
attributes: { title: 'some-title' },
attributes: { title },
};
};
const createError = (): SavedObjectsImportError => {
@ -419,6 +423,51 @@ describe('#importSavedObjectsFromStream', () => {
});
});
test('uses `type.management.getTitle` to resolve the titles', async () => {
const obj1 = createObject({ type: 'foo' });
const obj2 = createObject({ type: 'bar', title: 'bar-title' });
const options = setupOptions(false, (type) => {
if (type === 'foo') {
return {
management: { getTitle: () => 'getTitle-foo', icon: `${type}-icon` },
};
}
return {
management: { icon: `${type}-icon` },
};
});
getMockFn(checkConflicts).mockResolvedValue({
errors: [],
filteredObjects: [],
importIdMap: new Map(),
pendingOverwrites: new Set(),
});
getMockFn(createSavedObjects).mockResolvedValue({ errors: [], createdObjects: [obj1, obj2] });
const result = await importSavedObjectsFromStream(options);
// successResults only includes the imported object's type, id, and destinationId (if a new one was generated)
const successResults = [
{
type: obj1.type,
id: obj1.id,
meta: { title: 'getTitle-foo', icon: `${obj1.type}-icon` },
},
{
type: obj2.type,
id: obj2.id,
meta: { title: 'bar-title', icon: `${obj2.type}-icon` },
},
];
expect(result).toEqual({
success: true,
successCount: 2,
successResults,
});
});
test('accumulates multiple errors', async () => {
const options = setupOptions();
const errors = [createError(), createError(), createError(), createError(), createError()];

View file

@ -111,20 +111,23 @@ export async function importSavedObjectsFromStream({
const createSavedObjectsResult = await createSavedObjects(createSavedObjectsParams);
errorAccumulator = [...errorAccumulator, ...createSavedObjectsResult.errors];
const successResults = createSavedObjectsResult.createdObjects.map(
({ type, id, attributes: { title }, destinationId, originId }) => {
const meta = { title, icon: typeRegistry.getType(type)?.management?.icon };
const attemptedOverwrite = pendingOverwrites.has(`${type}:${id}`);
return {
type,
id,
meta,
...(attemptedOverwrite && { overwrite: true }),
...(destinationId && { destinationId }),
...(destinationId && !originId && !createNewCopies && { createNewCopy: true }),
};
}
);
const successResults = createSavedObjectsResult.createdObjects.map((createdObject) => {
const { type, id, destinationId, originId } = createdObject;
const getTitle = typeRegistry.getType(type)?.management?.getTitle;
const meta = {
title: getTitle ? getTitle(createdObject) : createdObject.attributes.title,
icon: typeRegistry.getType(type)?.management?.icon,
};
const attemptedOverwrite = pendingOverwrites.has(`${type}:${id}`);
return {
type,
id,
meta,
...(attemptedOverwrite && { overwrite: true }),
...(destinationId && { destinationId }),
...(destinationId && !originId && !createNewCopies && { createNewCopy: true }),
};
});
const errorResults = errorAccumulator.map((error) => {
const icon = typeRegistry.getType(error.type)?.management?.icon;
const attemptedOverwrite = pendingOverwrites.has(`${error.type}:${error.id}`);

View file

@ -89,18 +89,18 @@ describe('#importSavedObjectsFromStream', () => {
const setupOptions = (
retries: SavedObjectsImportRetry[] = [],
createNewCopies: boolean = false
createNewCopies: boolean = false,
getTypeImpl: (name: string) => any = (type: string) =>
({
// other attributes aren't needed for the purposes of injecting metadata
management: { icon: `${type}-icon` },
} as any)
): SavedObjectsResolveImportErrorsOptions => {
readStream = new Readable();
savedObjectsClient = savedObjectsClientMock.create();
typeRegistry = typeRegistryMock.create();
typeRegistry.getType.mockImplementation(
(type: string) =>
({
// other attributes aren't needed for the purposes of injecting metadata
management: { icon: `${type}-icon` },
} as any)
);
typeRegistry.getType.mockImplementation(getTypeImpl);
return {
readStream,
objectLimit,
@ -122,15 +122,16 @@ describe('#importSavedObjectsFromStream', () => {
return { type: 'foo-type', id, overwrite, replaceReferences };
};
const createObject = (
references?: SavedObjectReference[]
references?: SavedObjectReference[],
{ type = 'foo-type', title = 'some-title' }: { type?: string; title?: string } = {}
): SavedObject<{
title: string;
}> => {
return {
type: 'foo-type',
type,
id: uuidv4(),
references: references || [],
attributes: { title: 'some-title' },
attributes: { title },
};
};
const createError = (): SavedObjectsImportError => {
@ -267,7 +268,7 @@ describe('#importSavedObjectsFromStream', () => {
expect(getImportIdMapForRetries).toHaveBeenCalledWith(getImportIdMapForRetriesParams);
});
test('splits objects to ovewrite from those not to overwrite', async () => {
test('splits objects to overwrite from those not to overwrite', async () => {
const retries = [createRetry()];
const options = setupOptions(retries);
const collectedObjects = [createObject()];
@ -491,6 +492,55 @@ describe('#importSavedObjectsFromStream', () => {
expect(result).toEqual({ success: false, successCount: 3, successResults, errors });
});
test('uses `type.management.getTitle` to resolve the titles', async () => {
const obj1 = createObject([], { type: 'foo' });
const obj2 = createObject([], { type: 'bar', title: 'bar-title' });
const options = setupOptions([], false, (type) => {
if (type === 'foo') {
return {
management: { getTitle: () => 'getTitle-foo', icon: `${type}-icon` },
};
}
return {
management: { icon: `${type}-icon` },
};
});
getMockFn(checkConflicts).mockResolvedValue({
errors: [],
filteredObjects: [],
importIdMap: new Map(),
pendingOverwrites: new Set(),
});
getMockFn(createSavedObjects)
.mockResolvedValueOnce({ errors: [], createdObjects: [obj1, obj2] })
.mockResolvedValueOnce({ errors: [], createdObjects: [] });
const result = await resolveSavedObjectsImportErrors(options);
// successResults only includes the imported object's type, id, and destinationId (if a new one was generated)
const successResults = [
{
type: obj1.type,
id: obj1.id,
overwrite: true,
meta: { title: 'getTitle-foo', icon: `${obj1.type}-icon` },
},
{
type: obj2.type,
id: obj2.id,
overwrite: true,
meta: { title: 'bar-title', icon: `${obj2.type}-icon` },
},
];
expect(result).toEqual({
success: true,
successCount: 2,
successResults,
});
});
test('accumulates multiple errors', async () => {
const options = setupOptions();
const errors = [createError(), createError(), createError(), createError()];

View file

@ -153,8 +153,13 @@ export async function resolveSavedObjectsImportErrors({
successCount += createdObjects.length;
successResults = [
...successResults,
...createdObjects.map(({ type, id, attributes: { title }, destinationId, originId }) => {
const meta = { title, icon: typeRegistry.getType(type)?.management?.icon };
...createdObjects.map((createdObject) => {
const { type, id, destinationId, originId } = createdObject;
const getTitle = typeRegistry.getType(type)?.management?.getTitle;
const meta = {
title: getTitle ? getTitle(createdObject) : createdObject.attributes.title,
icon: typeRegistry.getType(type)?.management?.icon,
};
return {
type,
id,