Skip to content

Commit

Permalink
fix: do not use extensionInfo until it is defined
Browse files Browse the repository at this point in the history
page was using extensionInfo field but this object can be undefined

Add a check on the state

fixes #3030

Signed-off-by: Florent Benoit <fbenoit@redhat.com>
  • Loading branch information
benoitf committed Aug 9, 2023
1 parent 103bcea commit eaa8a87
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

import '@testing-library/jest-dom';
import { test, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/svelte';
import { render, screen, waitForElementToBeRemoved } from '@testing-library/svelte';
import PreferencesExtensionRendering from './PreferencesExtensionRendering.svelte';
import { extensionInfos } from '../../stores/extensions';

Expand Down Expand Up @@ -113,4 +113,27 @@ describe('PreferencesExtensionRendering', () => {
expect(remove).toBeInTheDocument();
expect(remove).toBeDisabled();
});

test('Expect empty screen if there is no matching extension (could be during providerInfos is loading)', async () => {
// clear store
extensionInfos.set([]);

// start without extension in the stores, should be empty
render(PreferencesExtensionRendering, { extensionId: 'test' });

// check empty page is displayed if we do not have matching of the extension
const emptyHeading = screen.getByRole('heading', { name: 'Extension not found', level: 1 });
expect(emptyHeading).toBeInTheDocument();

// now register the extension in the store
setup('started');

// wait empty page disappear
await waitForElementToBeRemoved(() => screen.queryByRole('heading', { name: 'Extension not found', level: 1 }));

// now check disable button is displayed as extension is started
const start = screen.getByRole('button', { name: 'Disable' });
expect(start).toBeInTheDocument();
expect(start).toBeEnabled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import type { ExtensionInfo } from '../../../../main/src/plugin/api/extension-in
import SettingsPage from './SettingsPage.svelte';
import ExtensionStatus from '../ui/ExtensionStatus.svelte';
import Button from '../ui/Button.svelte';
import { faPlay, faStop, faTrash } from '@fortawesome/free-solid-svg-icons';
import { faPlay, faPuzzlePiece, faStop, faTrash } from '@fortawesome/free-solid-svg-icons';
import { router } from 'tinro';
import EmptyScreen from '../ui/EmptyScreen.svelte';
export let extensionId: string = undefined;
let extensionInfo: ExtensionInfo;
$: extensionInfo = $extensionInfos.find(extension => extension.id === extensionId);
$: hideOnboardingButton = true;
$: hasOnboarding(extensionId).then(value => (hideOnboardingButton = value));
Expand All @@ -32,72 +34,76 @@ async function hasOnboarding(extensionId: string): Promise<boolean> {
}
</script>

<SettingsPage title="{extensionInfo.displayName} Extension">
<span slot="subtitle">
{extensionInfo.description}
</span>
<div class="flex flex-col bg-charcoal-600 rounded-md p-3">
{#if extensionInfo}
<Route path="/*" breadcrumb="{extensionInfo.displayName}">
<!-- Manage lifecycle-->
<div class="flex pb-2">
<div class="pr-2">Status</div>
<ExtensionStatus status="{extensionInfo.state}" />
</div>

<div class="py-2 flex flex-row items-center">
<!-- start is enabled only when stopped or failed -->
<div class="px-2 text-sm italic text-gray-700">
<Button
disabled="{extensionInfo.state !== 'stopped' && extensionInfo.state !== 'failed'}"
on:click="{() => startExtension()}"
icon="{faPlay}">
Enable
</Button>
</div>

<!-- stop is enabled only when started -->
<div class="px-2 text-sm italic text-gray-700">
<Button disabled="{extensionInfo.state !== 'started'}" on:click="{() => stopExtension()}" icon="{faStop}">
Disable
</Button>
{#if !extensionInfo}
<EmptyScreen title="Extension not found" icon="{faPuzzlePiece}" message="No extension found with id {extensionId}" />
{:else}
<SettingsPage title="{extensionInfo.displayName} Extension">
<span slot="subtitle">
{extensionInfo.description}
</span>
<div class="flex flex-col bg-charcoal-600 rounded-md p-3">
{#if extensionInfo}
<Route path="/*" breadcrumb="{extensionInfo.displayName}">
<!-- Manage lifecycle-->
<div class="flex pb-2">
<div class="pr-2">Status</div>
<ExtensionStatus status="{extensionInfo.state}" />
</div>

<!-- delete is enabled only when stopped or failed -->
{#if extensionInfo.removable}
<div class="py-2 flex flex-row items-center">
<!-- start is enabled only when stopped or failed -->
<div class="px-2 text-sm italic text-gray-700">
<Button
disabled="{extensionInfo.state !== 'stopped' && extensionInfo.state !== 'failed'}"
on:click="{() => removeExtension()}"
icon="{faTrash}">
Remove
on:click="{() => startExtension()}"
icon="{faPlay}">
Enable
</Button>
</div>
{:else}
<div class="text-gray-900 items-center px-2 text-sm">Default extension, cannot be removed</div>
{/if}
</div>

<div class="px-2 text-sm italic text-gray-700" class:hidden="{hideOnboardingButton}">
<button
on:click="{() => router.goto(`/preferences/onboarding/${extensionInfo.id}`)}"
class="pf-c-button pf-m-primary"
type="button">
<span class="pf-c-button__icon pf-m-start">
<i class="fas fa-play" aria-hidden="true"></i>
</span>
Onboarding
</button>
</div>
{#if extensionInfo.error}
<div class="flex flex-col">
<div class="py-2">Extension error: {extensionInfo.error.message}</div>
{#if extensionInfo.error.stack}
<div class="py-2">Stack trace</div>
<div class="py-2">{extensionInfo.error.stack}</div>
<!-- stop is enabled only when started -->
<div class="px-2 text-sm italic text-gray-700">
<Button disabled="{extensionInfo.state !== 'started'}" on:click="{() => stopExtension()}" icon="{faStop}">
Disable
</Button>
</div>

<!-- delete is enabled only when stopped or failed -->
{#if extensionInfo.removable}
<div class="px-2 text-sm italic text-gray-700">
<Button
disabled="{extensionInfo.state !== 'stopped' && extensionInfo.state !== 'failed'}"
on:click="{() => removeExtension()}"
icon="{faTrash}">
Remove
</Button>
</div>
{:else}
<div class="text-gray-900 items-center px-2 text-sm">Default extension, cannot be removed</div>
{/if}
</div>
{/if}
</Route>
{/if}
</div></SettingsPage>

<div class="px-2 text-sm italic text-gray-700" class:hidden="{hideOnboardingButton}">
<button
on:click="{() => router.goto(`/preferences/onboarding/${extensionInfo.id}`)}"
class="pf-c-button pf-m-primary"
type="button">
<span class="pf-c-button__icon pf-m-start">
<i class="fas fa-play" aria-hidden="true"></i>
</span>
Onboarding
</button>
</div>
{#if extensionInfo.error}
<div class="flex flex-col">
<div class="py-2">Extension error: {extensionInfo.error.message}</div>
{#if extensionInfo.error.stack}
<div class="py-2">Stack trace</div>
<div class="py-2">{extensionInfo.error.stack}</div>
{/if}
</div>
{/if}
</Route>
{/if}
</div></SettingsPage>
{/if}

0 comments on commit eaa8a87

Please sign in to comment.