use std::sync::Arc;
use egui::{Key, Modifiers, Vec2, accesskit::Role, mutex::RwLock};
use egui_kittest::{Harness, kittest::Queryable};
use graphannis::{model::AnnotationComponentType, update::GraphUpdate};
use insta::assert_snapshot;
use itertools::Itertools;
use crate::{
AnnatomicApp,
app::{
OPEN_LABEL,
actions::{EditorAction, GraphAction},
editors::spans::actions::DeleteSelectedNode,
messages::Notifier,
set_fonts,
tests::{
cleanup_test_project, create_app_with_corpus, create_test_harness,
create_test_harness_with_document_editor, get_text_input, open_corpus_structure,
wait_for_editor, wait_until_jobs_finished,
},
},
assert_screenshots,
};
use super::{Editor, SpanEditor};
fn create_example_ui(
graphml: &[u8],
document_node: &str,
render_spans: bool,
) -> (Harness<'static>, Arc<RwLock<SpanEditor>>) {
let (graph, _config) = graphannis_core::graph::serialization::graphml::import::<
AnnotationComponentType,
_,
_,
>(graphml, false, |_| {})
.unwrap();
let notifier = Notifier::default();
let editor = SpanEditor::create_from_graph(
document_node.to_string(),
render_spans,
Arc::new(RwLock::new(graph)),
notifier.clone(),
)
.unwrap();
let editor = Arc::new(RwLock::new(editor));
let editor_for_closure = editor.clone();
let mut harness = Harness::builder().build_ui(move |ui| {
set_fonts(ui.ctx());
let mut editor = editor_for_closure.write();
editor.show(ui);
});
harness.fit_contents();
(harness, editor)
}
#[test]
fn render_token_with_labels() {
let app = create_app_with_corpus(
"single_sentence",
&include_bytes!("../../../../tests/data/single_sentence.graphml")[..],
);
let (mut harness, _app_state) =
create_test_harness_with_document_editor(app, "single_sentence", "single_sentence/zossen");
harness.set_size(Vec2::new(800.0, 160.0));
harness.run();
harness.get_by_label("NE").hover();
harness.run();
harness.snapshot("render_token_with_labels");
}
fn get_selected_nodes(app: &RwLock<AnnatomicApp>) -> Vec<String> {
let mut app = app.write();
app.current_typed_editor::<SpanEditor>()
.unwrap()
.selected_nodes
.iter()
.cloned()
.sorted()
.collect()
}
#[test]
fn select_token_range_right() {
let app = create_app_with_corpus(
"single_sentence",
&include_bytes!("../../../../tests/data/single_sentence.graphml")[..],
);
let (mut harness, app) =
create_test_harness_with_document_editor(app, "single_sentence", "single_sentence/zossen");
harness.set_size(Vec2::new(950.0, 200.0));
harness
.get_by_label_contains("Token ranging from 1 to 1")
.click();
harness.run();
assert_eq!(1, get_selected_nodes(&app).len());
for _ in 0..5 {
harness.key_press_modifiers(Modifiers::SHIFT, egui::Key::ArrowRight);
harness.run();
}
assert_eq!(
6,
app.write()
.current_typed_editor::<SpanEditor>()
.unwrap()
.selected_nodes
.len()
);
harness.snapshot("select_token_range_right");
}
#[test]
fn select_token_range_left() {
let app = create_app_with_corpus(
"single_sentence",
&include_bytes!("../../../../tests/data/single_sentence.graphml")[..],
);
let (mut harness, app) =
create_test_harness_with_document_editor(app, "single_sentence", "single_sentence/zossen");
harness.set_size(Vec2::new(950.0, 200.0));
harness
.get_by_label_contains("Token ranging from 5 to 5")
.click();
harness.run();
assert_eq!(1, get_selected_nodes(&app).len());
for _ in 0..5 {
harness.key_press_modifiers(Modifiers::SHIFT, egui::Key::ArrowLeft);
harness.run();
}
assert_eq!(6, get_selected_nodes(&app).len());
harness.snapshot("select_token_range_left");
}
#[test]
fn select_two_token_right() {
let app = create_app_with_corpus(
"single_sentence",
&include_bytes!("../../../../tests/data/single_sentence.graphml")[..],
);
let (mut harness, app) =
create_test_harness_with_document_editor(app, "single_sentence", "single_sentence/zossen");
harness.set_size(Vec2::new(900.0, 200.0));
harness
.get_by_label_contains("Token ranging from 1 to 1")
.click();
harness.run();
assert_eq!(1, get_selected_nodes(&app).len());
harness.key_press_modifiers(Modifiers::SHIFT, egui::Key::ArrowRight);
harness.run();
assert_eq!(
2,
app.write()
.current_typed_editor::<SpanEditor>()
.unwrap()
.selected_nodes
.len()
);
harness.snapshot("select_two_token_right");
}
#[test]
fn select_two_token_left() {
let app = create_app_with_corpus(
"single_sentence",
&include_bytes!("../../../../tests/data/single_sentence.graphml")[..],
);
let (mut harness, app) =
create_test_harness_with_document_editor(app, "single_sentence", "single_sentence/zossen");
harness.set_size(Vec2::new(900.0, 200.0));
harness
.get_by_label_contains("Token ranging from 5 to 5")
.click();
harness.run();
assert_eq!(1, get_selected_nodes(&app).len());
harness.key_press_modifiers(Modifiers::SHIFT, egui::Key::ArrowLeft);
harness.run();
assert_eq!(
2,
app.write()
.current_typed_editor::<SpanEditor>()
.unwrap()
.selected_nodes
.len()
);
harness.snapshot("select_two_token_left");
}
#[test]
fn select_two_token_with_gap() {
let app = create_app_with_corpus(
"single_sentence",
&include_bytes!("../../../../tests/data/single_sentence.graphml")[..],
);
let (mut harness, app) =
create_test_harness_with_document_editor(app, "single_sentence", "single_sentence/zossen");
harness.set_size(Vec2::new(900.0, 200.0));
harness
.get_by_label_contains("Token ranging from 2 to 2")
.click();
harness.run();
assert_eq!(1, get_selected_nodes(&app).len());
}
#[test]
fn select_anno_span() {
let (mut harness, editor) = create_example_ui(
&include_bytes!("../../../../tests/data/SegmentationWithGaps.graphml")[..],
"SegmentationWithGaps/doc01",
true,
);
harness.get_by_label("All").click();
harness.run();
harness.set_size(Vec2::new(1000.0, 450.0));
harness.run();
harness.get_by_label("IN").click();
harness.run();
let editor = editor.read();
assert_eq!(1, editor.selected_nodes.len());
assert_eq!(
"SegmentationWithGaps/doc01#sSpan23",
editor.selected_nodes.iter().next().unwrap()
);
harness.snapshot("select_anno_span");
}
#[test]
fn select_anno_span_with_arrows() {
let app = create_app_with_corpus(
"SegmentationWithGaps",
&include_bytes!("../../../../tests/data/SegmentationWithGaps.graphml")[..],
);
let (mut harness, app) = create_test_harness_with_document_editor(
app,
"SegmentationWithGaps",
"SegmentationWithGaps/doc01",
);
harness.get_by_label("All").click();
harness.run();
harness.set_size(Vec2::new(1000.0, 450.0));
harness.run();
harness.get_by_label("IN").click();
harness.run();
harness.key_press_modifiers(Modifiers::NONE, egui::Key::ArrowLeft);
harness.run();
assert_eq!(
vec!["SegmentationWithGaps/doc01#sSpan22"],
get_selected_nodes(&app)
);
harness.key_press_modifiers(Modifiers::NONE, egui::Key::ArrowRight);
harness.run();
{
let mut app = app.write();
let editor = app.current_typed_editor::<SpanEditor>().unwrap();
assert_eq!(1, editor.selected_nodes.len());
assert_eq!(
"SegmentationWithGaps/doc01#sSpan23",
editor.selected_nodes.iter().next().unwrap()
);
}
}
#[test]
fn move_selection_downwards() {
let app = create_app_with_corpus(
"SegmentationWithGaps",
&include_bytes!("../../../../tests/data/SegmentationWithGaps.graphml")[..],
);
let (mut harness, app) = create_test_harness_with_document_editor(
app,
"SegmentationWithGaps",
"SegmentationWithGaps/doc01",
);
harness.set_size(Vec2::new(1000.0, 450.0));
harness.get_by_label("All").click();
harness.run();
harness.get_by_label("sub-").click();
harness.run();
assert_eq!(
vec!["SegmentationWithGaps/doc01#tok_8"],
get_selected_nodes(&app)
);
harness.key_press(Key::ArrowDown);
harness.run();
assert_eq!(
vec!["SegmentationWithGaps/doc01#sSpan35"],
get_selected_nodes(&app)
);
harness.key_press(Key::ArrowDown);
harness.run();
assert_eq!(
vec!["SegmentationWithGaps/doc01#sSpan16"],
get_selected_nodes(&app)
);
harness.key_press(Key::ArrowDown);
harness.run();
assert_eq!(
vec!["SegmentationWithGaps/doc01#sSpan7"],
get_selected_nodes(&app)
);
harness.key_press(Key::ArrowDown);
harness.run();
assert_eq!(
vec![
"SegmentationWithGaps/doc01#sSpan39",
"SegmentationWithGaps/doc01#sSpan40"
],
get_selected_nodes(&app)
);
harness.key_press(Key::ArrowDown);
harness.run();
assert_eq!(
vec!["SegmentationWithGaps/doc01#sSpan41"],
get_selected_nodes(&app)
);
harness.key_press(Key::ArrowDown);
harness.run();
assert_eq!(
vec![
"SegmentationWithGaps/doc01#sSpan19",
"SegmentationWithGaps/doc01#sSpan20",
"SegmentationWithGaps/doc01#sSpan21",
"SegmentationWithGaps/doc01#sSpan22",
"SegmentationWithGaps/doc01#sSpan23",
"SegmentationWithGaps/doc01#sSpan24",
"SegmentationWithGaps/doc01#sSpan25",
"SegmentationWithGaps/doc01#sSpan26",
"SegmentationWithGaps/doc01#sSpan27"
],
get_selected_nodes(&app)
);
harness.key_press(Key::ArrowDown);
harness.run();
assert_eq!(
vec!["SegmentationWithGaps/doc01#sSpan42"],
get_selected_nodes(&app)
);
harness.key_press(Key::ArrowDown);
harness.run();
assert_eq!(
vec!["SegmentationWithGaps/doc01#sSpan42"],
get_selected_nodes(&app)
);
}
#[test]
fn move_selection_updards() {
let app = create_app_with_corpus(
"SegmentationWithGaps",
&include_bytes!("../../../../tests/data/SegmentationWithGaps.graphml")[..],
);
let (mut harness, app) = create_test_harness_with_document_editor(
app,
"SegmentationWithGaps",
"SegmentationWithGaps/doc01",
);
harness.set_size(Vec2::new(1000.0, 450.0));
harness.get_by_label("All").click();
harness.run();
harness.get_by_label_contains("line=2").click();
harness.run();
assert_eq!(
vec!["SegmentationWithGaps/doc01#sSpan40"],
get_selected_nodes(&app)
);
harness.key_press(Key::ArrowUp);
harness.run();
assert_eq!(
vec![
"SegmentationWithGaps/doc01#sSpan7",
"SegmentationWithGaps/doc01#sSpan8",
"SegmentationWithGaps/doc01#sSpan9"
],
get_selected_nodes(&app)
);
harness.key_press(Key::ArrowUp);
harness.run();
assert_eq!(
vec![
"SegmentationWithGaps/doc01#sSpan16",
"SegmentationWithGaps/doc01#sSpan17",
"SegmentationWithGaps/doc01#sSpan18"
],
get_selected_nodes(&app)
);
harness.key_press(Key::ArrowUp);
harness.run();
assert_eq!(
vec![
"SegmentationWithGaps/doc01#sSpan35",
"SegmentationWithGaps/doc01#sSpan36",
"SegmentationWithGaps/doc01#sSpan37",
"SegmentationWithGaps/doc01#sSpan38"
],
get_selected_nodes(&app)
);
harness.key_press(Key::ArrowUp);
harness.run();
assert_eq!(
vec![
"SegmentationWithGaps/doc01#tok_10",
"SegmentationWithGaps/doc01#tok_11",
"SegmentationWithGaps/doc01#tok_8",
"SegmentationWithGaps/doc01#tok_9",
],
get_selected_nodes(&app)
);
harness.key_press(Key::ArrowUp);
harness.run();
assert_eq!(
vec![
"SegmentationWithGaps/doc01#tok_10",
"SegmentationWithGaps/doc01#tok_11",
"SegmentationWithGaps/doc01#tok_8",
"SegmentationWithGaps/doc01#tok_9",
],
get_selected_nodes(&app)
);
}
#[test]
fn render_segmentation_spans() {
let app = create_app_with_corpus(
"SegmentationWithGaps",
&include_bytes!("../../../../tests/data/SegmentationWithGaps.graphml")[..],
);
let (mut harness, _app_state) = create_test_harness_with_document_editor(
app,
"SegmentationWithGaps",
"SegmentationWithGaps/doc01",
);
harness.set_size(Vec2::new(1400.0, 450.0));
harness.get_by_label("All").click();
harness.run();
harness.snapshot("render_segmentation_spans");
}
#[test]
fn render_segmentation_spans_clipped() {
let app = create_app_with_corpus(
"SegmentationWithGaps",
&include_bytes!("../../../../tests/data/SegmentationWithGaps.graphml")[..],
);
let (mut harness, _app_state) = create_test_harness_with_document_editor(
app,
"SegmentationWithGaps",
"SegmentationWithGaps/doc01",
);
harness.set_size(Vec2::new(900.0, 450.0));
harness.get_by_label("All").click();
harness.run();
harness.get_all_by_label("DT").next().unwrap().scroll_left();
harness.run();
harness
.get_all_by_label("subtokenize")
.next()
.unwrap()
.hover();
harness.run();
harness.snapshot("render_segmentation_spans_clipped");
}
#[test]
fn select_next_and_previous_segmentation() {
let app = create_app_with_corpus(
"SegmentationWithGaps",
&include_bytes!("../../../../tests/data/SegmentationWithGaps.graphml")[..],
);
let (mut harness, app) = create_test_harness_with_document_editor(
app,
"SegmentationWithGaps",
"SegmentationWithGaps/doc01",
);
harness.set_size(Vec2::new(1500.0, 280.0));
harness.run();
harness
.get_by_label_contains("Token ranging from 7 to 8")
.click();
harness.run();
{
let mut app = app.write();
let editor = app.current_typed_editor::<SpanEditor>().unwrap();
assert_eq!(1, editor.selected_nodes.len());
}
harness.key_press_modifiers(Modifiers::NONE, egui::Key::ArrowRight);
harness.run();
let r1 = harness.try_snapshot("select_next_segmentation");
harness.key_press_modifiers(Modifiers::NONE, egui::Key::ArrowLeft);
harness.run();
harness.key_press_modifiers(Modifiers::NONE, egui::Key::ArrowLeft);
harness.run();
let r2 = harness.try_snapshot("select_previous_segmentation");
assert_screenshots!(r1, r2);
cleanup_test_project(app);
}
#[test]
fn add_first_token() {
let app_state = create_app_with_corpus(
"EmptyDocument",
&include_bytes!("../../../../tests/data/EmptyDocument.graphml")[..],
);
let (mut harness, app_state) = create_test_harness(app_state);
harness.set_size(Vec2::new(800.0, 180.0));
harness.run();
open_corpus_structure("EmptyDocument", &mut harness, app_state.clone());
harness.get_by_label("EmptyDocument/doc").click();
harness.run();
harness.get_by_label(OPEN_LABEL.as_str()).click();
wait_for_editor(&mut harness, app_state.clone());
let r1 = harness.try_snapshot("add_first_token_before");
harness
.get_all_by_label_contains("Add first token")
.next()
.unwrap()
.click();
wait_until_jobs_finished(&mut harness, app_state.clone());
let r2 = harness.try_snapshot("add_first_token_after");
harness.key_press_modifiers(Modifiers::COMMAND, Key::A);
harness.get_by(|n| n.is_focused()).type_text("Test ");
harness.run();
harness.key_press(egui::Key::Space);
wait_until_jobs_finished(&mut harness, app_state.clone());
harness.run();
let r3 = harness.try_snapshot("add_first_token_with_value");
assert_screenshots!(r1, r2, r3);
cleanup_test_project(app_state);
}
#[test]
fn navigate_to_first_and_last_token() {
let app = create_app_with_corpus(
"single_sentence",
&include_bytes!("../../../../tests/data/single_sentence.graphml")[..],
);
let (mut harness, app) =
create_test_harness_with_document_editor(app, "single_sentence", "single_sentence/zossen");
harness.set_size(Vec2::new(400.0, 160.0));
harness.key_press(Key::End);
harness.run();
let r1 = harness.try_snapshot("navigate_to_last_token");
harness.key_press(Key::Home);
harness.run();
let r2 = harness.try_snapshot("navigate_to_first_token");
assert_screenshots!(r1, r2);
cleanup_test_project(app);
}
#[test]
fn change_base_token_value() {
let app = create_app_with_corpus(
"single_sentence",
&include_bytes!("../../../../tests/data/single_sentence.graphml")[..],
);
let (mut harness, app) =
create_test_harness_with_document_editor(app, "single_sentence", "single_sentence/zossen");
harness.set_size(Vec2::new(800.0, 160.0));
harness.run();
assert_eq!(
0,
app.write()
.current_typed_editor::<SpanEditor>()
.unwrap()
.selected_nodes
.len()
);
harness
.get_by_label_contains("Token ranging from 1 to 1")
.click();
harness.run();
harness
.get_by_label_contains("Selected token ranging from 1 to 1")
.click();
harness.run();
get_text_input(&harness, "Jugendlichen").focus();
harness.key_press_modifiers(Modifiers::COMMAND, Key::A);
get_text_input(&harness, "Jugendlichen").type_text("Menschen");
harness.run();
harness.key_press(Key::Enter);
harness.run();
harness.snapshot("change_base_token_value");
}
#[test]
fn change_base_token_with_enter() {
let app = create_app_with_corpus(
"single_sentence",
&include_bytes!("../../../../tests/data/single_sentence.graphml")[..],
);
let (mut harness, app) =
create_test_harness_with_document_editor(app, "single_sentence", "single_sentence/zossen");
harness.set_size(Vec2::new(800.0, 160.0));
harness.run();
assert_eq!(
0,
app.write()
.current_typed_editor::<SpanEditor>()
.unwrap()
.selected_nodes
.len()
);
harness
.get_by_label_contains("Token ranging from 1 to 1")
.click();
harness.run();
harness.key_press(egui::Key::Enter);
harness.run();
let txt = get_text_input(&harness, "Jugendlichen");
txt.focus();
harness.key_press_modifiers(Modifiers::COMMAND, Key::A);
txt.type_text("Menschen");
harness.run();
harness.key_press(Key::Enter);
harness.run();
harness.snapshot("change_base_token_with_enter");
cleanup_test_project(app);
}
#[test]
fn change_base_token_whitespace_after() {
let app = create_app_with_corpus(
"single_sentence",
&include_bytes!("../../../../tests/data/single_sentence.graphml")[..],
);
let (mut harness, app) =
create_test_harness_with_document_editor(app, "single_sentence", "single_sentence/zossen");
harness.set_size(Vec2::new(800.0, 160.0));
harness.run();
harness
.get_by_label_contains("Token ranging from 1 to 1")
.click();
harness.run();
harness.key_press_modifiers(Modifiers::COMMAND, Key::W);
harness.run();
let txt = get_text_input(&harness, "");
txt.focus();
txt.type_text(" ");
harness.run();
harness.key_press(Key::Enter);
harness.run();
harness.snapshot("change_base_token_whitespace_after");
cleanup_test_project(app);
}
#[test]
fn change_base_token_whitespace_before() {
let app = create_app_with_corpus(
"single_sentence",
&include_bytes!("../../../../tests/data/single_sentence.graphml")[..],
);
let (mut harness, app) =
create_test_harness_with_document_editor(app, "single_sentence", "single_sentence/zossen");
harness.set_size(Vec2::new(800.0, 160.0));
harness.run();
harness
.get_by_label_contains("Token ranging from 1 to 1")
.click();
harness.run();
harness.key_press_modifiers(Modifiers::COMMAND.plus(Modifiers::SHIFT), Key::W);
harness.run();
let txt = get_text_input(&harness, " ");
txt.focus();
txt.type_text(" ");
harness.run();
harness.key_press(Key::Enter);
harness.run();
harness.snapshot("change_base_token_whitespace_before");
cleanup_test_project(app);
}
#[test]
fn change_segmentation_value() {
let app = create_app_with_corpus(
"SegmentationWithGaps",
&include_bytes!("../../../../tests/data/SegmentationWithGaps.graphml")[..],
);
let (mut harness, app) = create_test_harness_with_document_editor(
app,
"SegmentationWithGaps",
"SegmentationWithGaps/doc01",
);
harness.set_size(Vec2::new(1800.0, 280.0));
harness.run();
assert_eq!(
0,
app.write()
.current_typed_editor::<SpanEditor>()
.unwrap()
.selected_nodes
.len()
);
harness
.get_by_label_contains("Token ranging from 7 to 8")
.click();
harness.run();
harness
.get_by_label_contains("Selected token ranging from 7 to 8")
.click();
harness.run();
harness.key_press_modifiers(Modifiers::COMMAND, Key::A);
harness.run();
get_text_input(&harness, "subtokenized").type_text("tokenized");
harness.run();
let r1 = harness.try_snapshot("change_segmentation_value_during_edit");
get_text_input(&harness, "tokenized").focus();
harness.run();
harness.key_press(Key::Enter);
wait_until_jobs_finished(&mut harness, app);
let r2 = harness.try_snapshot("change_segmentation_value");
assert_screenshots![r1, r2];
}
#[test]
fn change_segmentation_whitespace_after() {
let app = create_app_with_corpus(
"SegmentationWithGaps",
&include_bytes!("../../../../tests/data/SegmentationWithGaps.graphml")[..],
);
let (mut harness, app) = create_test_harness_with_document_editor(
app,
"SegmentationWithGaps",
"SegmentationWithGaps/doc01",
);
harness.set_size(Vec2::new(800.0, 200.0));
harness.run();
harness
.get_by_label_contains("SegmentationWithGaps/doc01#sSpan34")
.click();
harness.run();
harness.key_press_modifiers(Modifiers::COMMAND, Key::W);
harness.run();
let txt = get_text_input(&harness, "");
txt.focus();
txt.type_text(" ");
harness.run();
harness.key_press(Key::Enter);
harness.run();
harness.snapshot("change_segmentation_whitespace_after");
cleanup_test_project(app);
}
#[test]
fn change_segmentation_whitespace_before() {
let app = create_app_with_corpus(
"SegmentationWithGaps",
&include_bytes!("../../../../tests/data/SegmentationWithGaps.graphml")[..],
);
let (mut harness, app) = create_test_harness_with_document_editor(
app,
"SegmentationWithGaps",
"SegmentationWithGaps/doc01",
);
harness.set_size(Vec2::new(800.0, 200.0));
harness.run();
harness
.get_by_label_contains("SegmentationWithGaps/doc01#sSpan34")
.click();
harness.run();
harness.key_press_modifiers(Modifiers::COMMAND.plus(Modifiers::SHIFT), Key::W);
harness.run();
let txt = get_text_input(&harness, "");
txt.focus();
txt.type_text(" ");
harness.run();
harness.key_press(Key::Enter);
harness.run();
harness.snapshot("change_segmentation_whitespace_before");
cleanup_test_project(app);
}
#[test]
fn change_token_label_value() {
let app = create_app_with_corpus(
"single_sentence",
&include_bytes!("../../../../tests/data/single_sentence.graphml")[..],
);
let (mut harness, app) =
create_test_harness_with_document_editor(app, "single_sentence", "single_sentence/zossen");
harness.set_size(Vec2::new(800.0, 160.0));
harness.run();
assert_eq!(
0,
app.write()
.current_typed_editor::<SpanEditor>()
.unwrap()
.selected_nodes
.len()
);
harness.get_by_label("NE").click();
harness.run();
harness.get_by_label("NE").click();
harness.run();
get_text_input(&harness, "NE").focus();
harness.run();
harness.key_press(Key::Backspace);
harness.key_press(Key::Backspace);
get_text_input(&harness, "NE").type_text("EXAMPLE");
harness.key_press(Key::Enter);
harness.run();
harness.snapshot("change_token_label_value");
}
#[test]
fn delete_token_label() {
let app = create_app_with_corpus(
"single_sentence",
&include_bytes!("../../../../tests/data/single_sentence.graphml")[..],
);
let (mut harness, app) =
create_test_harness_with_document_editor(app, "single_sentence", "single_sentence/zossen");
harness.set_size(Vec2::new(800.0, 160.0));
harness.run();
assert_eq!(
0,
app.write()
.current_typed_editor::<SpanEditor>()
.unwrap()
.selected_nodes
.len()
);
harness.get_by_label("NE").click();
harness.run();
harness.get_by_label("NE").click();
harness.run();
get_text_input(&harness, "NE").focus();
harness.run();
harness.key_press(Key::Backspace);
harness.key_press(Key::Backspace);
harness.key_press(Key::Enter);
wait_until_jobs_finished(&mut harness, app.clone());
harness.snapshot("delete_token_label");
}
#[test]
fn add_token_label() {
let app_state = create_app_with_corpus(
"single_sentence",
&include_bytes!("../../../../tests/data/single_sentence.graphml")[..],
);
let (mut harness, app_state) = create_test_harness(app_state);
harness.set_size(Vec2::new(800.0, 180.0));
harness.run();
open_corpus_structure("single_sentence", &mut harness, app_state.clone());
harness.get_by_label("single_sentence/zossen").click();
harness.run();
harness.get_by_label(OPEN_LABEL.as_str()).click();
wait_for_editor(&mut harness, app_state.clone());
harness
.get_by_label_contains("single_sentence/zossen#t2")
.click();
harness.run();
harness
.get_all_by_label(egui_phosphor::regular::PLUS_CIRCLE)
.nth(1)
.unwrap()
.click();
harness.run();
let r1 = harness.try_snapshot("add_token_label_modal");
let txt = harness.get_all_by_role(Role::TextInput).collect_vec();
txt[0].type_text("some");
txt[1].type_text("anno");
harness.run();
harness.get_by_label("Add").click();
harness.run();
let r2 = harness.try_snapshot("add_token_label");
assert_screenshots!(r1, r2);
cleanup_test_project(app_state);
}
#[test]
fn delete_and_add_segmentation() {
let app_state = create_app_with_corpus(
"SegmentationWithGaps",
&include_bytes!("../../../../tests/data/SegmentationWithGaps.graphml")[..],
);
let (mut harness, app_state) = create_test_harness(app_state);
harness.set_size(Vec2::new(1200.0, 600.0));
harness.run();
open_corpus_structure("SegmentationWithGaps", &mut harness, app_state.clone());
harness.get_by_label("SegmentationWithGaps/doc01").click();
harness.run();
harness.get_by_label(OPEN_LABEL.as_str()).click();
wait_for_editor(&mut harness, app_state.clone());
harness.get_by_label("All").click();
harness.run();
{
let mut app_state = app_state.write();
let editor = app_state.current_typed_editor::<SpanEditor>().unwrap();
editor.selected_nodes.clear();
editor
.selected_nodes
.insert("SegmentationWithGaps/doc01#sSpan32".to_string());
editor
.selected_nodes
.insert("SegmentationWithGaps/doc01#sSpan33".to_string());
editor
.selected_nodes
.insert("SegmentationWithGaps/doc01#sSpan34".to_string());
editor
.selected_nodes
.insert("SegmentationWithGaps/doc01#sSpan35".to_string());
DeleteSelectedNode::perform(editor);
}
wait_until_jobs_finished(&mut harness, app_state.clone());
{
let mut app_state = app_state.write();
let editor = app_state.current_typed_editor::<SpanEditor>().unwrap();
editor.selected_nodes.clear();
editor
.selected_nodes
.insert("SegmentationWithGaps/doc01#tok_6".to_string());
editor
.selected_nodes
.insert("SegmentationWithGaps/doc01#tok_7".to_string());
editor.add_segmentation_for_selection(0);
}
wait_until_jobs_finished(&mut harness, app_state.clone());
harness.get_by_role(Role::TextInput).type_text("ofa");
harness.key_press(Key::Enter);
harness.run();
harness.snapshot("delete_and_add_segmentation");
}
#[test]
fn delete_node_action() {
let graphml = &include_bytes!("../../../../tests/data/single_sentence.graphml")[..];
let (mut graph, _config) = graphannis_core::graph::serialization::graphml::import::<
AnnotationComponentType,
_,
_,
>(graphml, false, |_| {})
.unwrap();
let action = GraphAction::DeleteNodes {
node_names: vec!["single_sentence/zossen#t5".to_string()],
};
let mut updates = GraphUpdate::new();
let changeset = action.create_changeset(&graph).unwrap();
for u in changeset.updates {
updates.add_event(u).unwrap();
}
graph.apply_update(&mut updates, |_| {}).unwrap();
let mut output = Vec::<u8>::default();
graphannis_core::graph::serialization::graphml::export_stable_order(
&graph,
None,
&mut output,
|_| {},
)
.unwrap();
assert_snapshot!(String::from_utf8_lossy(&output));
}
#[test]
fn expand_and_shrink_segmentation() {
let app = create_app_with_corpus(
"SegmentationWithGaps",
&include_bytes!("../../../../tests/data/SegmentationWithGaps.graphml")[..],
);
let (mut harness, app) = create_test_harness_with_document_editor(
app,
"SegmentationWithGaps",
"SegmentationWithGaps/doc01",
);
harness.set_size(Vec2::new(1400.0, 300.0));
harness.run();
{
let mut app = app.write();
let editor = app.current_typed_editor::<SpanEditor>().unwrap();
editor.selected_nodes.clear();
editor
.selected_nodes
.insert("SegmentationWithGaps/doc01#norm14".to_string());
}
harness.run();
harness.key_press_modifiers(Modifiers::COMMAND, Key::ArrowLeft);
harness.run();
let r1 = harness.try_snapshot("expand_and_shrink_segmentation_1");
harness.key_press_modifiers(Modifiers::COMMAND.plus(Modifiers::SHIFT), Key::ArrowLeft);
harness.run();
let r2 = harness.try_snapshot("expand_and_shrink_segmentation_2");
harness.key_press_modifiers(Modifiers::COMMAND, Key::ArrowRight);
harness.run();
let r3 = harness.try_snapshot("expand_and_shrink_segmentation_3");
harness.key_press_modifiers(Modifiers::COMMAND.plus(Modifiers::SHIFT), Key::ArrowRight);
harness.run();
let r4 = harness.try_snapshot("expand_and_shrink_segmentation_4");
assert_screenshots!(r1, r2, r3, r4);
}
#[test]
fn expand_and_shrink_span() {
let app = create_app_with_corpus(
"SegmentationWithGaps",
&include_bytes!("../../../../tests/data/SegmentationWithGaps.graphml")[..],
);
let (mut harness, _app) = create_test_harness_with_document_editor(
app,
"SegmentationWithGaps",
"SegmentationWithGaps/doc01",
);
harness.set_size(Vec2::new(1400.0, 300.0));
harness.get_by_label_contains("grammar pos").click();
harness.run();
harness.get_by_label_contains("grammar::pos=.").click();
harness.run();
harness.key_press_modifiers(Modifiers::COMMAND, Key::ArrowRight);
harness.run();
let r1 = harness.try_snapshot("expand_and_shrink_span_1");
harness.key_press_modifiers(Modifiers::COMMAND.plus(Modifiers::SHIFT), Key::ArrowRight);
harness.run();
let r2 = harness.try_snapshot("expand_and_shrink_span_2");
harness.key_press_modifiers(Modifiers::COMMAND, Key::ArrowLeft);
harness.run();
let r3 = harness.try_snapshot("expand_and_shrink_span_3");
harness.key_press_modifiers(Modifiers::COMMAND.plus(Modifiers::SHIFT), Key::ArrowLeft);
harness.run();
let r4 = harness.try_snapshot("expand_and_shrink_span_4");
assert_screenshots!(r1, r2, r3, r4);
}
#[test]
fn apply_add_base_token_before_action() {
let graphml = &include_bytes!("../../../../tests/data/single_sentence.graphml")[..];
let (mut graph, _config) = graphannis_core::graph::serialization::graphml::import::<
AnnotationComponentType,
_,
_,
>(graphml, false, |_| {})
.unwrap();
let action = GraphAction::AddBaseTokenBefore {
parent_name: "single_sentence/zossen#text".to_string(),
reference_node: "single_sentence/zossen#t5".to_string(),
};
let mut updates = GraphUpdate::new();
let changeset = action.create_changeset(&graph).unwrap();
for u in changeset.updates {
updates.add_event(u).unwrap();
}
graph.apply_update(&mut updates, |_| {}).unwrap();
let mut output = Vec::<u8>::default();
graphannis_core::graph::serialization::graphml::export_stable_order(
&graph,
None,
&mut output,
|_| {},
)
.unwrap();
assert_snapshot!(String::from_utf8_lossy(&output));
}
#[test]
fn apply_add_base_token_after_action() {
let graphml = &include_bytes!("../../../../tests/data/single_sentence.graphml")[..];
let (mut graph, _config) = graphannis_core::graph::serialization::graphml::import::<
AnnotationComponentType,
_,
_,
>(graphml, false, |_| {})
.unwrap();
let action = GraphAction::AddBaseTokenAfter {
parent_name: "single_sentence/zossen#text".to_string(),
reference_node: "single_sentence/zossen#t5".to_string(),
};
let mut updates = GraphUpdate::new();
let changset = action.create_changeset(&graph).unwrap();
for u in changset.updates {
updates.add_event(u).unwrap();
}
graph.apply_update(&mut updates, |_| {}).unwrap();
let mut output = Vec::<u8>::default();
graphannis_core::graph::serialization::graphml::export_stable_order(
&graph,
None,
&mut output,
|_| {},
)
.unwrap();
assert_snapshot!(String::from_utf8_lossy(&output));
}
#[test]
fn update_view_after_adding_token() {
let app_state = create_app_with_corpus(
"single_sentence",
&include_bytes!("../../../../tests/data/single_sentence.graphml")[..],
);
let (mut harness, app) = create_test_harness(app_state);
harness.set_size(Vec2::new(1200.0, 600.0));
harness.run();
open_corpus_structure("single_sentence", &mut harness, app.clone());
harness.get_by_label("single_sentence/zossen").click();
harness.run();
harness.get_by_label(OPEN_LABEL.as_str()).click();
wait_for_editor(&mut harness, app.clone());
{
let mut app = app.write();
let editor = app.current_typed_editor::<SpanEditor>().unwrap();
editor
.pending_graph_actions
.push(GraphAction::AddBaseTokenBefore {
parent_name: "single_sentence/zossen#text".to_string(),
reference_node: "single_sentence/zossen#t5".to_string(),
});
app.apply_pending_updates().unwrap();
}
wait_for_editor(&mut harness, app.clone());
harness.run();
harness.snapshot("update_view_after_adding_token");
cleanup_test_project(app);
}
#[test]
fn add_span_to_existing_layer() {
let app = create_app_with_corpus(
"SegmentationWithGaps",
&include_bytes!("../../../../tests/data/SegmentationWithGaps.graphml")[..],
);
let (mut harness, app) = create_test_harness_with_document_editor(
app,
"SegmentationWithGaps",
"SegmentationWithGaps/doc01",
);
harness.set_size(Vec2::new(1500.0, 500.0));
harness.run();
harness.get_by_label("All").click();
harness.run();
{
let mut app = app.write();
let editor = app.current_typed_editor::<SpanEditor>().unwrap();
editor.selected_nodes.clear();
editor
.selected_nodes
.insert("SegmentationWithGaps/doc01#tok_12".to_string());
editor
.selected_nodes
.insert("SegmentationWithGaps/doc01#tok_13".to_string());
editor
.selected_nodes
.insert("SegmentationWithGaps/doc01#tok_14".to_string());
}
harness.input_mut().modifiers = Modifiers::COMMAND;
harness.step();
let r1 = harness.try_snapshot("add_span_command_down");
harness.get_by_label("4 - line").click();
harness.run();
let txt = get_text_input(&harness, "");
txt.type_text("PP");
harness.key_press(Key::Enter);
wait_until_jobs_finished(&mut harness, app.clone());
harness.run();
let r2 = harness.try_snapshot("add_span_final");
assert_screenshots!(r1, r2);
cleanup_test_project(app);
}
#[test]
fn add_span_to_new_layer() {
let app_state = create_app_with_corpus(
"single_sentence",
&include_bytes!("../../../../tests/data/single_sentence.graphml")[..],
);
let (mut harness, app_state) = create_test_harness_with_document_editor(
app_state,
"single_sentence",
"single_sentence/zossen",
);
harness.set_size(Vec2::new(800.0, 200.0));
{
let mut app = app_state.write();
let editor = app.current_typed_editor::<SpanEditor>().unwrap();
editor
.selected_nodes
.insert("single_sentence/zossen#t3".to_string());
editor
.selected_nodes
.insert("single_sentence/zossen#t4".to_string());
}
harness.run();
harness.key_press_modifiers(Modifiers::NONE, egui::Key::Insert);
harness.run();
let txt = harness.get_all_by_role(Role::TextInput).collect_vec();
txt[0].focus();
txt[0].type_text("some");
txt[1].focus();
txt[1].type_text("anno");
harness.run();
let r1 = harness.try_snapshot("add_span_to_new_layer_modal");
harness.get_by_label("Add").click();
harness.run();
let txt = get_text_input(&harness, "");
txt.type_text("PP");
harness.key_press(Key::Enter);
wait_until_jobs_finished(&mut harness, app_state.clone());
harness.run();
let r2 = harness.try_snapshot("add_span_to_new_layer");
assert_screenshots!(r1, r2);
cleanup_test_project(app_state);
}
#[test]
fn abort_adding_span() {
let app_state = create_app_with_corpus(
"single_sentence",
&include_bytes!("../../../../tests/data/single_sentence.graphml")[..],
);
let (mut harness, app_state) = create_test_harness_with_document_editor(
app_state,
"single_sentence",
"single_sentence/zossen",
);
harness.set_size(Vec2::new(800.0, 180.0));
{
let mut app = app_state.write();
let editor = app.current_typed_editor::<SpanEditor>().unwrap();
editor
.selected_nodes
.insert("single_sentence/zossen#t3".to_string());
editor
.selected_nodes
.insert("single_sentence/zossen#t4".to_string());
}
harness.run();
harness.key_press_modifiers(Modifiers::NONE, egui::Key::Insert);
harness.run();
harness.get_by_label("Cancel").click();
harness.run();
{
let mut app = app_state.write();
assert_eq!(
None,
app.current_typed_editor::<SpanEditor>()
.unwrap()
.active_interaction
);
}
cleanup_test_project(app_state);
}
#[test]
fn test_menu_entries() {
let app_state = create_app_with_corpus(
"single_sentence",
&include_bytes!("../../../../tests/data/single_sentence.graphml")[..],
);
let (mut harness, app_state) = create_test_harness(app_state);
harness.set_size(Vec2::new(1200.0, 600.0));
harness.run();
open_corpus_structure("single_sentence", &mut harness, app_state.clone());
harness.get_by_label("single_sentence/zossen").click();
harness.run();
harness.get_by_label(OPEN_LABEL.as_str()).click();
harness.run_steps(10);
wait_for_editor(&mut harness, app_state.clone());
harness.get_by_label("Edit").click();
harness.run();
harness.snapshot("test_menu_entries_disabled");
harness
.get_by_label_contains("Token ranging from 5 to 5")
.click();
harness.run();
harness.get_by_label("Edit").click();
harness.run();
harness.snapshot("test_menu_entries_enabled");
harness
.get_by_label_contains("Add base token after selection")
.click();
wait_until_jobs_finished(&mut harness, app_state.clone());
harness.get_by_label("Edit").click();
harness.run();
harness
.get_by_label_contains("Add base token before selection")
.click();
wait_until_jobs_finished(&mut harness, app_state.clone());
harness.get_by_label("Edit").click();
harness.run();
harness.snapshot("test_menu_entries_added");
cleanup_test_project(app_state);
}
#[test]
fn filter_spans() {
let app = create_app_with_corpus(
"SegmentationWithGaps",
&include_bytes!("../../../../tests/data/SegmentationWithGaps.graphml")[..],
);
let (mut harness, app) = create_test_harness_with_document_editor(
app,
"SegmentationWithGaps",
"SegmentationWithGaps/doc01",
);
harness.set_size(Vec2::new(1600.0, 500.0));
harness.run();
harness.get_by_label_contains("structure page").click();
harness.run();
let r1 = harness.try_snapshot("filter_spans_single_selection");
harness.get_by_label_contains("structure page").click();
harness.run();
let r2 = harness.try_snapshot("filter_spans_unselected");
harness.get_by_label("All").click();
harness.run();
let r3 = harness.try_snapshot("filter_spans_initial_all");
harness.get_by_label("None").click();
harness.run();
let r4 = harness.try_snapshot("filter_spans_initial_none");
assert_screenshots!(r1, r2, r3, r4);
cleanup_test_project(app);
}
#[test]
fn token_becomes_wider_on_edit_regression() {
let app = create_app_with_corpus(
"SegmentationWithGaps",
&include_bytes!("../../../../tests/data/SegmentationWithGaps.graphml")[..],
);
let (mut harness, app) = create_test_harness_with_document_editor(
app,
"SegmentationWithGaps",
"SegmentationWithGaps/doc01",
);
harness.set_size(Vec2::new(800.0, 300.0));
harness.run();
{
let mut app = app.write();
let editor = app.current_typed_editor::<SpanEditor>().unwrap();
editor
.selected_nodes
.insert("SegmentationWithGaps/doc01#tok_2".to_string());
}
harness.run();
let original = harness.render().unwrap();
for _ in 0..10 {
harness.key_press(Key::Enter);
harness.run_steps(10);
harness.key_press(Key::Enter);
harness.run();
}
let after_editing = harness.render().unwrap();
let result = dify::diff::get_results(original, after_editing, 0.6, true, None, &None, &None);
assert_eq!(false, result.is_some());
cleanup_test_project(app);
}