Skip to content

Commit

Permalink
Instructions, refactoring, selenium tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrej33 committed Dec 13, 2024
1 parent 7e734a1 commit 60e352b
Show file tree
Hide file tree
Showing 10 changed files with 211 additions and 112 deletions.
21 changes: 16 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,17 @@ Sketchbook presents a way to design all these components and more.

Once you finish designing your sketch, you can run the state-of-the-art synthesis algorithms and symbolically compute all BNs consistent with your requirements. You can then sample individual BNs, or export the results for further analysis with libraries like [AEON.py](https://pypi.org/project/biodivine-aeon/).

### Citation
#### Manual

In the provided `manual.pdf`, we discuss the details regarding
- installation,
- editing BN sketches in Sketchbook,
- running BN inference in Sketchbook,
- format and syntax used.

The installation is also summarized below, with an additional development guide.

#### Citation

If you used Sketchbook for some academic work, we'd be very happy if you could cite it using the following publication:

Expand All @@ -33,7 +43,7 @@ Alternatively, if you want to build the tool locally, the instructions are provi

The following instructions describe the local installation of the application and relevant frameworks. We recommend using the pre-built binaries described in the previous section.

For a summary of all technologies and detailed project structure, see `project-docs/ARCHITECTURE.md`. The directory `project-docs` also contains other documents relevant to the design/development.
For a summary of all technologies and detailed project structure, see `project-docs/architecture.md`. The directory `project-docs` also contains other documents relevant to the design/development.

We also provide web-based Rust documentation (including internal modules), currently hosted on [these GitHub pages](https://ondrej33.github.io/biodivine_sketchbook/). Instructions to generate Rust documentation locally are given below.

Expand Down Expand Up @@ -77,10 +87,11 @@ cargo doc --no-deps --document-private-items
```

#### End-to-end tests
We also utilize an end-to-end Selenium-based testing framework. Note that these tests require additional dependencies, and they are limited for Linux and Windows (due to MacOS issues with WebDriver).
We also utilize an end-to-end Selenium-based testing framework. Note that these tests require additional dependencies, and they are limited for Linux and Windows (due to MacOS issues with WebDriver). You should also update the test configs based on your system.

You can follow this [detailed tutorial](https://jonaskruckenberg.github.io/tauri-docs-wip/development/testing.html) for setup. In short, you should install `tauri-driver` (with `cargo install tauri-driver`), and then you will need either `WebKitWebDriver` on Linux or `Microsoft Edge Driver` on Windows (make sure that you have updated Microsoft Edge too). The mocha test runner can be installed with `npm install mocha chai selenium-webdriver`. You might need to update the configuration at the top of the testing script `test/test.js`, mainly the path to your Sketchbook binary and to your webdriver.

You can follow this [detailed tutorial](https://jonaskruckenberg.github.io/tauri-docs-wip/development/testing.html) for setup. In short, you should install `tauri-driver` (with `cargo install tauri-driver`), and then you will need either `WebKitWebDriver` on Linux or `Microsoft Edge Driver` on Windows (make sure that you have updated Microsoft Edge too). The mocha test runner can be installed with `npm install mocha chai selenium-webdriver`.
To run the tests, first build the app with `cargo tauri build` and then use `npx mocha` (you might need a longer timeout, like `npx mocha --timeout 20000`).
To run the tests, first build the app with `cargo tauri build` and then use `npx mocha` (you might need a longer timeout, like `npx mocha --timeout 20000`).
The framework was tested on Windows with `Microsoft Edge WebDriver` version `130.0.2849.89`.
However, note that we found the testing framework a bit unstable when the testing machine is overloaded with other tasks. Sometimes, the tests do not go through due to internal WebDriver issues, and we are investigating this.

Expand Down
30 changes: 18 additions & 12 deletions project-docs/ARCHITECTURE.md → project-docs/architecture.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
# Sketchbook Architecture

This document gives a general rationale behind the chosen architecture and technologies.

## Technologies

- Overall, we rely primarily on [Rust](https://www.rust-lang.org/), [TypeScript](https://www.typescriptlang.org/) and HTML/CSS. We use [less](https://lesscss.org/usage/) as a CSS pre-processor and [posthtml](https://posthtml.org/#/) as a HTML pre-processor.
- Dependencies for Rust are managed through `cargo` (obviously), while the JS part is managed by `npm`, because it's the default choice almost everywhere.
- The connection between the Rust back-end and the TypeScript front-end is facilitated using [tauri](https://tauri.app/).
- To build TypeScript and less, we use [Vite](https://vitejs.dev/). It is not a particularly mainstream choice, but it is officially recommended by Tauri, so hopefully it will give us the best compatibility.
- To help with the UI, we use [UIkit](https://getuikit.com/). It seems to be reasonably popular, stable, and above all simple (i.e. just sensible widgets, no special framework logic, templates, etc.).

Overall, you should be able to work with the source code comfortably from Visual Studio Code, although IntelliJ IDEA may be preferable for the Rust portion.

We use standard `cargo` utilities for Rust testing and linting. For TypeScript static analysis, we use [ESLint](https://eslint.org/). For some further TypeScript unit-testing, we use [vitest](https://vitest.dev/) that is recommended by Tauri. For some limited end-to-end testing, we utilize [WebDriver](https://www.w3.org/TR/webdriver/) based approach recommended by Tauri. We go with `selenium-webdriver` framework and `mocha` test runner. More details are in the main README, or you can see this [Tauri testing tutorial](https://jonaskruckenberg.github.io/tauri-docs-wip/development/testing.html)
It is divided into sections describing:
- structure of the project repository
- details on structure of Rust modules
- details on structure of data folder
- technologies used
- early architecture notes

## Project structure

We first list the most important components of the project repository, mainly various source folders and configuration files. After that, we add more details on how the Rust back-end code is structured.

- `manual.pdf` | PDF manual describing tool's functionality, sessions, and various syntax/format details.
- `vite.config.ts` | Configuration for the Vite build system (HTML/JS/CSS processing). Most stuff is generated by Tauri, there's just some extra code related to properly building UIKit and to declaring multiple entry points for different windows.
- `tsconfig.json` | Configuration for the TypeScript compiler. Generated by Tauri for now. Later we might want to make it a bit more restrictive.
- `package.json` and `package-lock.json` | List of `npm` dependencies (and its frozen variant). Mostly just Tauri, UIkit, Less, PostHTML, some packages with types declarations, and testing frameworks.
Expand Down Expand Up @@ -86,6 +81,17 @@ Directory `data` contains various models, benchmarks, and datasets. The structur
- `test_data` | Sketches and datasets for testing purposes. Used to test importing and inference.
- `load-results-aeon-py.py` | Python script to load results archive exported by Sketchbook and load it into `aeon-py` library. You need to install python and biodivine_aeon library first (`https://pypi.org/project/biodivine-aeon/`).

## Technologies

- Overall, we rely primarily on [Rust](https://www.rust-lang.org/), [TypeScript](https://www.typescriptlang.org/) and HTML/CSS. We use [less](https://lesscss.org/usage/) as a CSS pre-processor and [posthtml](https://posthtml.org/#/) as a HTML pre-processor.
- Dependencies for Rust are managed through `cargo` (obviously), while the JS part is managed by `npm`, because it's the default choice almost everywhere.
- The connection between the Rust back-end and the TypeScript front-end is facilitated using [tauri](https://tauri.app/).
- To build TypeScript and less, we use [Vite](https://vitejs.dev/). It is not a particularly mainstream choice, but it is officially recommended by Tauri, so hopefully it will give us the best compatibility.
- To help with the UI, we use [UIkit](https://getuikit.com/). It seems to be reasonably popular, stable, and above all simple (i.e. just sensible widgets, no special framework logic, templates, etc.).

Overall, you should be able to work with the source code comfortably from Visual Studio Code, although IntelliJ IDEA may be preferable for the Rust portion.

We use standard `cargo` utilities for Rust testing and linting. For TypeScript static analysis, we use [ESLint](https://eslint.org/). For some further TypeScript unit-testing, we use [vitest](https://vitest.dev/) that is recommended by Tauri. For some limited end-to-end testing, we utilize [WebDriver](https://www.w3.org/TR/webdriver/) based approach recommended by Tauri. We go with `selenium-webdriver` framework and `mocha` test runner. More details are in the main README, or you can see this [Tauri testing tutorial](https://jonaskruckenberg.github.io/tauri-docs-wip/development/testing.html)

## Architecture notes (early stage)

Expand Down
2 changes: 1 addition & 1 deletion src-tauri/src/algorithms/eval_dynamic/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub fn eval_dyn_prop(
encode_dataset_hctl_str(&prop.dataset, None, DataEncodingType::TrapSpace)?;
let mut sat_colors = model_check_colors_universal(graph, &trap_space_formula)?;

// TODO: if needed, restrict colors to only a set where the TSs are minimal or non-percolable
// if needed, restrict colors to only a set where the TSs are minimal or non-percolable
if prop.minimal || prop.nonpercolable {
// compute new trap-space context
let bn = graph.as_network().unwrap();
Expand Down
1 change: 0 additions & 1 deletion src-tauri/src/app/state/editor/_state_editor_session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ impl StackSession for EditorSession {
// If the state changed due to message processing, we'll have to reset the undo-redo stack
// (but we do not use messages that make these changes often)

// todo: make this `mut` when we have some cases here that could mutate state
let reset_stack = false;

// request from new Inference session for sending a sketch
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ fn get_payload_or_panic(event: tauri::Event, event_type: &str) -> String {
let Some(payload) = event.payload() else {
let message = format!("No payload in {event_type}.");
error!("{message}");
// TODO: This could be an error.
// TODO: think about whether this could be a normal error
panic!("{message}");
};
payload.to_string()
Expand Down
4 changes: 0 additions & 4 deletions src-tauri/src/sketchbook/_tests_events/_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use crate::sketchbook::JsonSerde;

#[test]
/// Test adding variable via events.
/// TODO - add tests for more complex scenarios
fn test_add_var() {
let variables = vec![("a", "a")];
let mut model = ModelState::new_from_vars(variables).unwrap();
Expand Down Expand Up @@ -173,7 +172,6 @@ fn test_invalid_var_events() {

#[test]
/// Test adding regulation via (raw) event.
/// TODO: add tests for more complex scenarios which requires changes in static properties
fn test_add_reg_simple() {
let variables = vec![("a", "a"), ("b", "b")];
let mut model = ModelState::new_from_vars(variables).unwrap();
Expand All @@ -193,7 +191,6 @@ fn test_add_reg_simple() {

#[test]
/// Test changing regulation's monotonicity and essentiality via event.
/// TODO: add tests for more complex scenarios which requires changes in static properties
fn test_change_reg_sign_essentiality() {
let variables = vec![("a", "a_name"), ("b", "b_name")];
let mut model = ModelState::new_from_vars(variables).unwrap();
Expand Down Expand Up @@ -226,7 +223,6 @@ fn test_change_reg_sign_essentiality() {

#[test]
/// Test removing regulation via (raw) event.
/// TODO: add tests for more complex scenarios which requires changes in static properties
fn test_remove_reg_simple() {
let variables = vec![("a", "a_name"), ("b", "b_name")];
let mut model = ModelState::new_from_vars(variables).unwrap();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ export class FunctionsEditor extends LitElement {
<div class="header uk-background-primary uk-margin-bottom">
<h3 class="uk-heading-bullet uk-margin-remove-bottom">Supplementary functions</h3>
<div class="uk-text-center">
<button @click="${this.addFunction}" class="uk-button uk-button-small uk-button-primary"> + add </button>
<button id="add-fn-button" @click="${this.addFunction}" class="uk-button uk-button-small uk-button-primary"> + add </button>
</div>
</div>
${this.contentData?.functions.length === 0 ? html`<div class="uk-text-center uk-margin-bottom"><span class="uk-label">No functions defined</span></div>` : ''}
Expand Down
2 changes: 1 addition & 1 deletion src/html/component-editor/tab-bar/tab-bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default class TabBar extends LitElement {
return html`
<div class="tab-bar uk-button-group uk-flex uk-flex-row">
${map(this.tabs, (tab) => html`
<button class="tab uk-button uk-padding-remove-vertical ${tab.active ? 'active uk-button-primary' : 'inactive uk-button-secondary'}"
<button id="${tab.name}-tab-button" class="tab uk-button uk-padding-remove-vertical ${tab.active ? 'active uk-button-primary' : 'inactive uk-button-secondary'}"
@click=${this.switchTab(tab.id)}>
${tab.pinned ? icon(faLock).node : ''}
${icon(findIconDefinition({ prefix: 'fas', iconName: `${tab.icon as IconName}` })).node}
Expand Down
Binary file modified test/example-output.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 60e352b

Please sign in to comment.