Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added project dir setting and other changes #634

Merged
merged 10 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

# Unreleased

* Added project dir setting (\#634);
* Made zarr_dir optional when creating dataset (\#634);
* Updated query parameters of GET /api/v2/task/ (\#634);
* Displayed task collection logs also in install phase (\#634);
* Handled missing banner file error (\#634);
* Used fractal-logos sources for README and docs (\#634);
* Added fractal logo (\#626);
* Removed usage of pip extras when installing fractal-server for testing (\#626);
* Removed usage of verbose query parameter in task collection (\#626);
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Fractal Web Client

<p align="center">
<img src="https://github.com/user-attachments/assets/984e89fe-b536-4414-8949-58029056e53c" alt="Fractal web" width="400">
<img src="https://raw.githubusercontent.com/fractal-analytics-platform/fractal-logos/refs/heads/main/projects/fractal_web.png" alt="Fractal web" width="400">
</p>

[Fractal](https://fractal-analytics-platform.github.io/) is a framework developed at the [BioVisionCenter](https://www.biovisioncenter.uzh.ch/en.html) to process bioimaging data at scale in the OME-Zarr format and prepare the images for interactive visualization.
Expand Down
138 changes: 118 additions & 20 deletions __tests__/v2/CreateDatasetModal.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { describe, it, expect, vi } from 'vitest';
import { describe, it, beforeEach, expect, vi } from 'vitest';
import { fireEvent, render } from '@testing-library/svelte';
import { readable } from 'svelte/store';

Expand Down Expand Up @@ -35,27 +35,42 @@ const defaultProps = {
props: { createDatasetCallback: vi.fn() }
};

describe('CreateDatasetModal', () => {
fetch.mockResolvedValue({
/**
* @param {string|null} project_dir
*/
function mockFetch(project_dir) {
fetch.mockImplementation((url) => ({
ok: true,
status: 200,
json: () =>
new Promise((resolve) =>
resolve({
data: {
new Promise((resolve) => {
if (url === '/api/auth/current-user/settings') {
resolve({
project_dir
});
} else {
resolve({
id: 1
}
})
)
});
}
})
}));
}

describe('CreateDatasetModal', () => {
beforeEach(() => {
fetch.mockClear();
});

it('validate missing name and zarr dir', async () => {
mockFetch(null);
const result = render(CreateDatasetModal, defaultProps);
await fireEvent.click(result.getByRole('button', { name: 'Save' }));
expect(result.queryAllByText('Required field').length).eq(2);
});

it('create dataset with string filter', async () => {
mockFetch(null);
const createDatasetCallback = vi.fn();
const result = render(CreateDatasetModal, {
props: { createDatasetCallback }
Expand All @@ -70,22 +85,23 @@ describe('CreateDatasetModal', () => {
await fireEvent.input(result.getByPlaceholderText('Key'), { target: { value: 'my-key' } });
await fireEvent.input(result.getByPlaceholderText('Value'), { target: { value: 'my-value' } });
await fireEvent.click(result.getByRole('button', { name: 'Save' }));
expect(fetch).toHaveBeenCalledWith(
expect(fetch).toHaveBeenLastCalledWith(
'/api/v2/project/1/dataset',
expect.objectContaining({
body: JSON.stringify({
name: 'my dataset',
zarr_dir: '/tmp',
filters: {
attributes: { 'my-key': 'my-value' },
types: {}
}
},
zarr_dir: '/tmp'
})
})
);
});

it('create dataset with number filter', async () => {
mockFetch(null);
const createDatasetCallback = vi.fn();
const result = render(CreateDatasetModal, {
props: { createDatasetCallback }
Expand All @@ -101,22 +117,23 @@ describe('CreateDatasetModal', () => {
await fireEvent.input(result.getByPlaceholderText('Value'), { target: { value: '123' } });
await fireEvent.change(result.getByLabelText('Type'), { target: { value: 'number' } });
await fireEvent.click(result.getByRole('button', { name: 'Save' }));
expect(fetch).toHaveBeenCalledWith(
expect(fetch).toHaveBeenLastCalledWith(
'/api/v2/project/1/dataset',
expect.objectContaining({
body: JSON.stringify({
name: 'my dataset',
zarr_dir: '/tmp',
filters: {
attributes: { 'my-key': 123 },
types: {}
}
},
zarr_dir: '/tmp'
})
})
);
});

it('create dataset with type filter set to false', async () => {
mockFetch(null);
const createDatasetCallback = vi.fn();
const result = render(CreateDatasetModal, {
props: { createDatasetCallback }
Expand All @@ -130,22 +147,23 @@ describe('CreateDatasetModal', () => {
await fireEvent.click(result.getByRole('button', { name: 'Add type filter' }));
await fireEvent.input(result.getByPlaceholderText('Key'), { target: { value: 'my-key' } });
await fireEvent.click(result.getByRole('button', { name: 'Save' }));
expect(fetch).toHaveBeenCalledWith(
expect(fetch).toHaveBeenLastCalledWith(
'/api/v2/project/1/dataset',
expect.objectContaining({
body: JSON.stringify({
name: 'my dataset',
zarr_dir: '/tmp',
filters: {
attributes: {},
types: { 'my-key': false }
}
},
zarr_dir: '/tmp'
})
})
);
});

it('create dataset with type filter set to true', async () => {
mockFetch(null);
const createDatasetCallback = vi.fn();
const result = render(CreateDatasetModal, {
props: { createDatasetCallback }
Expand All @@ -160,18 +178,98 @@ describe('CreateDatasetModal', () => {
await fireEvent.input(result.getByPlaceholderText('Key'), { target: { value: 'my-key' } });
await fireEvent.click(result.getByLabelText('Value for my-key'));
await fireEvent.click(result.getByRole('button', { name: 'Save' }));
expect(fetch).toHaveBeenCalledWith(
expect(fetch).toHaveBeenLastCalledWith(
'/api/v2/project/1/dataset',
expect.objectContaining({
body: JSON.stringify({
name: 'my dataset',
zarr_dir: '/tmp',
filters: {
attributes: {},
types: { 'my-key': true }
},
zarr_dir: '/tmp'
})
})
);
});

it('create dataset without specifying zarr dir', async () => {
mockFetch('/path/to/zarr/dir');
const createDatasetCallback = vi.fn();
const result = render(CreateDatasetModal, {
props: { createDatasetCallback }
});
await fireEvent.input(result.getByRole('textbox', { name: 'Dataset Name' }), {
target: { value: 'my dataset' }
});
await fireEvent.click(result.getByRole('button', { name: 'Save' }));
expect(fetch).toHaveBeenLastCalledWith(
'/api/v2/project/1/dataset',
expect.objectContaining({
body: JSON.stringify({
name: 'my dataset',
filters: {
attributes: {},
types: {}
}
})
})
);
});

it('validate missing dataset name', async () => {
mockFetch('/path/to/zarr/dir');
const result = render(CreateDatasetModal, defaultProps);
expect(await result.findByText('/path/to/zarr/dir')).toBeVisible();
await fireEvent.click(result.getByRole('button', { name: 'Save' }));
expect(result.queryAllByText('Required field').length).eq(1);
});

it('display invalid zarr dir error', async () => {
fetch
.mockResolvedValueOnce({
ok: true,
status: 200,
json: async () => ({ project_dir: null })
})
.mockResolvedValueOnce({
ok: false,
status: 422,
json: async () => ({
detail: [
{
loc: ['body', 'zarr_dir'],
msg: "URLs must begin with '/' or 's3'.",
type: 'value_error'
}
]
})
});

const createDatasetCallback = vi.fn();
const result = render(CreateDatasetModal, {
props: { createDatasetCallback }
});
await fireEvent.input(result.getByRole('textbox', { name: 'Dataset Name' }), {
target: { value: 'my dataset' }
});
await fireEvent.input(result.getByRole('textbox', { name: 'Zarr dir' }), {
target: { value: 'foo' }
});
await fireEvent.click(result.getByRole('button', { name: 'Save' }));
expect(fetch).toHaveBeenLastCalledWith(
'/api/v2/project/1/dataset',
expect.objectContaining({
body: JSON.stringify({
name: 'my dataset',
filters: {
attributes: {},
types: {}
},
zarr_dir: 'foo'
})
})
);
expect(await result.findByText(/URLs must begin with '\/' or 's3'/)).toBeVisible();
});
});
9 changes: 8 additions & 1 deletion __tests__/v2/UserEditor.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ describe('UserEditor', () => {
const initialSettings = {
id: 1,
slurm_accounts: [],
project_dir: null,
slurm_user: null,
cache_dir: null,
ssh_host: null,
Expand Down Expand Up @@ -79,11 +80,13 @@ describe('UserEditor', () => {
resolve({
...initialSettings,
slurm_user: 'user',
cache_dir: '/path/to/cache/dir'
cache_dir: '/path/to/cache/dir',
project_dir: '/path/to/project/dir',
})
)
});

await user.type(screen.getByRole('textbox', { name: 'Project dir' }), '/path/to/project/dir');
await user.type(screen.getByRole('textbox', { name: 'SLURM user' }), 'user');
await user.type(screen.getByRole('textbox', { name: 'Cache dir' }), '/path/to/cache/dir');
await user.click(screen.getByRole('button', { name: 'Save' }));
Expand All @@ -94,6 +97,7 @@ describe('UserEditor', () => {
expect.objectContaining({
body: JSON.stringify({
slurm_accounts: [],
project_dir: '/path/to/project/dir',
slurm_user: 'user',
cache_dir: '/path/to/cache/dir',
ssh_host: null,
Expand Down Expand Up @@ -144,6 +148,7 @@ describe('UserEditor', () => {
expect.objectContaining({
body: JSON.stringify({
slurm_accounts: [],
project_dir: null,
slurm_user: null,
cache_dir: 'xxx',
ssh_host: null,
Expand Down Expand Up @@ -197,6 +202,7 @@ describe('UserEditor', () => {
expect.objectContaining({
body: JSON.stringify({
slurm_accounts: [],
project_dir: null,
slurm_user: null,
cache_dir: null,
ssh_host: 'localhost',
Expand Down Expand Up @@ -266,6 +272,7 @@ describe('UserEditor', () => {
expect.objectContaining({
body: JSON.stringify({
slurm_accounts: [],
project_dir: null,
slurm_user: null,
cache_dir: null,
ssh_host: 'localhost',
Expand Down
Binary file removed docs/assets/fractal_favicon.png
Binary file not shown.
Binary file removed docs/assets/fractal_logo.png
Binary file not shown.
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
## Fractal

<p align="center">
<img src="https://github.com/user-attachments/assets/984e89fe-b536-4414-8949-58029056e53c" alt="Fractal web" width="400">
<img src="https://raw.githubusercontent.com/fractal-analytics-platform/fractal-logos/refs/heads/main/projects/fractal_web.png" alt="Fractal web" width="400">
</p>

Fractal is a framework developed at the [BioVisionCenter](https://www.biovisioncenter.uzh.ch/en.html) to process bioimaging data at scale in the OME-Zarr format and prepare the images for interactive visualization.
Expand Down
4 changes: 2 additions & 2 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ markdown_extensions:

theme:
name: "material"
logo: 'assets/fractal_logo.png'
favicon: 'assets/fractal_favicon.png'
logo: 'https://raw.githubusercontent.com/fractal-analytics-platform/fractal-logos/refs/heads/main/common/fractal_logo.png'
favicon: 'https://raw.githubusercontent.com/fractal-analytics-platform/fractal-logos/refs/heads/main/common/fractal_favicon.png'
custom_dir: "docs/overrides"
features:
- content.code.annotate
Expand Down
2 changes: 1 addition & 1 deletion playwright.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export default defineConfig({

webServer: [
{
command: './tests/start-test-server.sh 2.7.1',
command: './tests/start-test-server.sh 2.8.0',
port: 8000,
waitForPort: true,
stdout: 'pipe',
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/v2/admin/UserEditor.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@
{/if}
</div>

{#if settings && runnerBackend !== 'local' && runnerBackend !== 'local_experimental'}
{#if settings}
<div class="row">
<div class="mt-3 col-lg-7">
<div class="row">
Expand Down
Loading
Loading