Skip to content

Commit

Permalink
fix: handle event when loading images from archives
Browse files Browse the repository at this point in the history
fixes #5221
Signed-off-by: Florent Benoit <fbenoit@redhat.com>
  • Loading branch information
benoitf committed Dec 13, 2023
1 parent c8c3d92 commit 17d932e
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 1 deletion.
34 changes: 34 additions & 0 deletions packages/main/src/plugin/container-registry.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2351,3 +2351,37 @@ test('setupConnectionAPI with errors after machine being removed', async () => {
'Aborting reconnect due to error as connection has been removed (probably machine has been removed)',
);
});

test('check handleEvents with loadArchive', async () => {
const getEventsMock = vi.fn();
let eventsMockCallback: any;
// keep the function passed in parameter of getEventsMock
getEventsMock.mockImplementation((options: any) => {
eventsMockCallback = options;
});

const passThrough = new PassThrough();
const fakeDockerode = {
getEvents: getEventsMock,
} as unknown as Dockerode;

const errorCallback = vi.fn();

containerRegistry.handleEvents(fakeDockerode, errorCallback);

if (eventsMockCallback) {
eventsMockCallback?.(undefined, passThrough);
}

// send loadArchive event
passThrough.emit('data', JSON.stringify({ status: 'loadfromarchive', Type: 'image', id: '123456' }));

// wait 1s
await new Promise(resolve => setTimeout(resolve, 3000));

// check callback is defined
expect(eventsMockCallback).toBeDefined();

// check we send the event to notify renderer part
expect(apiSender.send).toBeCalledWith('image-loadfromarchive-event', '123456');
});
3 changes: 3 additions & 0 deletions packages/main/src/plugin/container-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ export class ContainerProviderRegistry {
} else if (jsonEvent.status === 'build' && jsonEvent?.Type === 'image') {
// need to notify that image are being pulled
this.apiSender.send('image-build-event', jsonEvent.id);
} else if (jsonEvent.status === 'loadfromarchive' && jsonEvent?.Type === 'image') {
// need to notify that image are being pulled
this.apiSender.send('image-loadfromarchive-event', jsonEvent.id);
}
});

Expand Down
88 changes: 88 additions & 0 deletions packages/renderer/src/stores/images.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**********************************************************************
* Copyright (C) 2023 Red Hat, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
***********************************************************************/

/* eslint-disable @typescript-eslint/no-explicit-any */

import { get } from 'svelte/store';
import type { Mock } from 'vitest';
import { beforeAll, expect, test, vi } from 'vitest';
import { imagesInfos, imagesEventStore } from './images';
import type { ImageInfo } from '../../../main/src/plugin/api/image-info';

// first, path window object
const callbacks = new Map<string, any>();
const eventEmitter = {
receive: (message: string, callback: any) => {
callbacks.set(message, callback);
},
};

const listImagesMock: Mock<any, Promise<ImageInfo[]>> = vi.fn();

Object.defineProperty(global, 'window', {
value: {
listImages: listImagesMock,
events: {
receive: eventEmitter.receive,
},
addEventListener: eventEmitter.receive,
},
writable: true,
});

beforeAll(() => {
vi.clearAllMocks();
});

test('images should be updated in case of a image is loaded from an archive', async () => {
// initial images
listImagesMock.mockResolvedValue([
{
Id: 1,
} as unknown as ImageInfo,
]);
const storeInfo = imagesEventStore.setup();

const callback = callbacks.get('extensions-already-started');
// send 'extensions-already-started' event
expect(callback).toBeDefined();
await callback();

// fetch
await storeInfo.fetch();

// now get list
const images = get(imagesInfos);
expect(images.length).toBe(1);
expect(images[0].Id).toBe(1);

// ok now mock the listImages function to return an empty list
listImagesMock.mockResolvedValue([]);

// call 'image-loadfromarchive-event' event
const imageLoadFromArchiveCallback = callbacks.get('image-loadfromarchive-event');
expect(imageLoadFromArchiveCallback).toBeDefined();
await imageLoadFromArchiveCallback();

// wait debounce
await new Promise(resolve => setTimeout(resolve, 2000));

// check if the images have been updated
const images2 = get(imagesInfos);
expect(images2.length).toBe(0);
});
3 changes: 2 additions & 1 deletion packages/renderer/src/stores/images.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const windowEvents = [
'image-tag-event',
'image-untag-event',
'extensions-started',
'image-loadfromarchive-event',
];
const windowListeners = ['image-build', 'extensions-already-started'];

Expand All @@ -56,7 +57,7 @@ const listImages = (): Promise<ImageInfo[]> => {
return window.listImages();
};

const imagesEventStore = new EventStore<ImageInfo[]>(
export const imagesEventStore = new EventStore<ImageInfo[]>(
'images',
imagesInfos,
checkForUpdate,
Expand Down

0 comments on commit 17d932e

Please sign in to comment.