Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions lightly_studio_view/e2e/general/export-annotations.e2e-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,6 @@ test.describe('Export Annotations', () => {
// Switch to the correct export type
await page.getByTestId('export-type-select').click();
await page.getByRole('option', { name: 'Image Object Detections (COCO)' }).click();
await expect(page.getByTestId('submit-button-annotations-coco')).toHaveAttribute(
'href',
/\/api\/collections\/.*\/export\/annotations\?ts=\d+/
);

// Remove target to avoid popup and keep navigation in the same page context
await page
.getByTestId('submit-button-annotations-coco')
.evaluate((el: HTMLAnchorElement) => el.removeAttribute('target'));

// Click and wait for the download event deterministically
const [download] = await Promise.all([
Expand Down Expand Up @@ -76,15 +67,6 @@ test.describe('Export Annotations', () => {
// Switch to the YOLO export type
await page.getByTestId('export-type-select').click();
await page.getByRole('option', { name: 'Image Object Detections (YOLO)' }).click();
await expect(page.getByTestId('submit-button-annotations-yolo')).toHaveAttribute(
'href',
/\/api\/collections\/.*\/export\/annotations\?ts=\d+&export_format=object_detection_yolo/
);

// Remove target to avoid popup and keep navigation in the same page context
await page
.getByTestId('submit-button-annotations-yolo')
.evaluate((el: HTMLAnchorElement) => el.removeAttribute('target'));

// Click and wait for the download event deterministically
const [download] = await Promise.all([
Expand Down
9 changes: 0 additions & 9 deletions lightly_studio_view/e2e/general/export-captions.e2e-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,6 @@ test.describe('Export Captions', () => {
// Switch to the correct export type
await page.getByTestId('export-type-select').click();
await page.getByRole('option', { name: 'Image Captions' }).click();
await expect(page.getByTestId('submit-button-captions')).toHaveAttribute(
'href',
/\/api\/collections\/.*\/export\/captions\?ts=\d+/
);

// Remove target to avoid popup and keep navigation in the same page context
await page
.getByTestId('submit-button-captions')
.evaluate((el: HTMLAnchorElement) => el.removeAttribute('target'));

// Click and wait for the download event deterministically
const [download] = await Promise.all([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,6 @@ test.describe('Export Segmentation Masks', () => {
// Switch to the correct export type
await page.getByTestId('export-type-select').click();
await page.getByRole('option', { name: 'Image Segmentation Mask (COCO)' }).click();
await expect(page.getByTestId('submit-button-instance-segmentations')).toHaveAttribute(
'href',
/\/api\/collections\/.*\/export\/annotations\?ts=\d+&export_format=segmentation_mask_coco/
);

// Remove target to avoid popup and keep navigation in the same page context
await page
.getByTestId('submit-button-instance-segmentations')
.evaluate((el: HTMLAnchorElement) => el.removeAttribute('target'));

// Click and wait for the download event deterministically
const [download] = await Promise.all([
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<script lang="ts">
import * as Alert from '$lib/components/ui/alert/index.js';
import { fade } from 'svelte/transition';

interface Props {
/** Error message to display. When empty, the component renders nothing. */
error: string;
}

let { error }: Props = $props();
</script>

{#if error}
<div transition:fade>
<Alert.Root
variant="destructive"
class="border text-foreground"
data-testid="alert-destructive"
>
<div class="flex items-center gap-2">
<span class="text-destructive-foreground">{error}</span>
</div>
</Alert.Root>
</div>
{/if}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { describe, it, expect } from 'vitest';
import { render } from '@testing-library/svelte';
import '@testing-library/jest-dom';
import ExportAnnotationError from './ExportAnnotationError.svelte';

describe('ExportAnnotationError', () => {
it('renders nothing when error is empty', () => {
const { container } = render(ExportAnnotationError, { props: { error: '' } });

expect(container.querySelector('[data-testid="alert-destructive"]')).toBeNull();
});

it('renders the error alert when error is provided', () => {
const { container } = render(ExportAnnotationError, {
props: { error: 'Export failed: something went wrong' }
});

expect(container.querySelector('[data-testid="alert-destructive"]')).toBeInTheDocument();
expect(container.textContent).toContain('Export failed: something went wrong');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script lang="ts">
import { Button } from '$lib/components/ui';
import { Loader2 } from '@lucide/svelte';

interface Props {
/** Called when the button is clicked. */
onclick: () => void;
/** When true, the button is non-interactive. */
disabled?: boolean;
/** When true, a spinner overlay is shown on the button. */
isLoading?: boolean;
/** Value for the data-testid attribute. */
testId: string;
}

let { onclick, disabled = false, isLoading = false, testId }: Props = $props();
</script>

<Button class="relative my-4 w-full" {disabled} {onclick} data-testid={testId}>
Download
{#if isLoading}
<div
class="absolute inset-0 flex items-center justify-center backdrop-blur-sm"
data-testid="loading-spinner"
>
<Loader2 class="animate-spin" />
</div>
{/if}
</Button>
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { describe, it, expect, vi } from 'vitest';
import { fireEvent, render, screen } from '@testing-library/svelte';
import '@testing-library/jest-dom';
import ExportDownloadButton from './ExportDownloadButton.svelte';

describe('ExportDownloadButton', () => {
it('renders the Download button with the given testId', () => {
render(ExportDownloadButton, { props: { onclick: vi.fn(), testId: 'test-btn' } });

expect(screen.getByTestId('test-btn')).toBeInTheDocument();
expect(screen.getByTestId('test-btn')).toHaveTextContent('Download');
});

it('does not show loading spinner by default', () => {
const { container } = render(ExportDownloadButton, {
props: { onclick: vi.fn(), testId: 'test-btn' }
});

expect(container.querySelector('[data-testid="loading-spinner"]')).toBeNull();
});

it('shows loading spinner when isLoading is true', () => {
const { container } = render(ExportDownloadButton, {
props: { onclick: vi.fn(), testId: 'test-btn', isLoading: true }
});

expect(container.querySelector('[data-testid="loading-spinner"]')).toBeInTheDocument();
});

it('disables the button when disabled is true', () => {
render(ExportDownloadButton, {
props: { onclick: vi.fn(), testId: 'test-btn', disabled: true }
});

expect(screen.getByTestId('test-btn')).toBeDisabled();
});

it('calls onclick when clicked', async () => {
const onclick = vi.fn();
render(ExportDownloadButton, { props: { onclick, testId: 'test-btn' } });

await fireEvent.click(screen.getByTestId('test-btn'));

expect(onclick).toHaveBeenCalledOnce();
});
});
Loading
Loading