| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425 | use crate::database::block_test::script::RowScript::{AssertCell, CreateRow};use crate::database::block_test::util::DatabaseRowTestBuilder;use crate::database::database_editor::DatabaseEditorTest;use database_model::{  DatabaseBlockMetaRevision, DatabaseBlockMetaRevisionChangeset, RowChangeset, RowRevision,};use flowy_database::entities::{CellIdParams, CreateRowParams, FieldType, RowPB};use flowy_database::services::field::*;use flowy_database::services::row::DatabaseBlockRow;use std::collections::HashMap;use std::sync::Arc;use strum::IntoEnumIterator;pub enum RowScript {  CreateEmptyRow,  CreateRow {    row_rev: RowRevision,  },  UpdateRow {    changeset: RowChangeset,  },  AssertRow {    expected_row: RowRevision,  },  DeleteRows {    row_ids: Vec<String>,  },  AssertCell {    row_id: String,    field_id: String,    field_type: FieldType,    expected: String,  },  AssertRowCount(usize),  CreateBlock {    block: DatabaseBlockMetaRevision,  },  UpdateBlock {    changeset: DatabaseBlockMetaRevisionChangeset,  },  AssertBlockCount(usize),  AssertBlock {    block_index: usize,    row_count: i32,    start_row_index: i32,  },  AssertBlockEqual {    block_index: usize,    block: DatabaseBlockMetaRevision,  },}pub struct DatabaseRowTest {  inner: DatabaseEditorTest,}impl DatabaseRowTest {  pub async fn new() -> Self {    let editor_test = DatabaseEditorTest::new_grid().await;    Self { inner: editor_test }  }  pub fn last_row(&self) -> Option<RowRevision> {    self.row_revs.last().map(|a| a.clone().as_ref().clone())  }  pub async fn run_scripts(&mut self, scripts: Vec<RowScript>) {    for script in scripts {      self.run_script(script).await;    }  }  pub fn row_builder(&self) -> DatabaseRowTestBuilder {    DatabaseRowTestBuilder::new(self.block_id().to_string(), self.field_revs.clone())  }  pub async fn run_script(&mut self, script: RowScript) {    match script {      RowScript::CreateEmptyRow => {        let params = CreateRowParams {          view_id: self.editor.database_id.clone(),          start_row_id: None,          group_id: None,          cell_data_by_field_id: None,        };        let row_order = self.editor.create_row(params).await.unwrap();        self          .row_by_row_id          .insert(row_order.row_id().to_owned(), row_order);        self.row_revs = self.get_row_revs().await;        self.block_meta_revs = self.editor.get_block_meta_revs().await.unwrap();      },      RowScript::CreateRow { row_rev } => {        let row_orders = self.editor.insert_rows(vec![row_rev]).await.unwrap();        for row_order in row_orders {          self            .row_by_row_id            .insert(row_order.row_id().to_owned(), row_order);        }        self.row_revs = self.get_row_revs().await;        self.block_meta_revs = self.editor.get_block_meta_revs().await.unwrap();      },      RowScript::UpdateRow { changeset: change } => self.editor.update_row(change).await.unwrap(),      RowScript::DeleteRows { row_ids } => {        let row_pbs = row_ids          .into_iter()          .map(|row_id| self.row_by_row_id.get(&row_id).unwrap().clone())          .collect::<Vec<RowPB>>();        let block_rows = block_from_row_pbs(row_pbs);        self.editor.delete_rows(block_rows).await.unwrap();        self.row_revs = self.get_row_revs().await;        self.block_meta_revs = self.editor.get_block_meta_revs().await.unwrap();      },      RowScript::AssertCell {        row_id,        field_id,        field_type,        expected,      } => {        let id = CellIdParams {          view_id: self.view_id.clone(),          field_id,          row_id,        };        self.compare_cell_content(id, field_type, expected).await;      },      RowScript::AssertRow { expected_row } => {        let row = &*self          .row_revs          .iter()          .find(|row| row.id == expected_row.id)          .cloned()          .unwrap();        assert_eq!(&expected_row, row);      },      RowScript::AssertRowCount(expected_row_count) => {        assert_eq!(expected_row_count, self.row_revs.len());      },      RowScript::CreateBlock { block } => {        self.editor.create_block(block).await.unwrap();        self.block_meta_revs = self.editor.get_block_meta_revs().await.unwrap();      },      RowScript::UpdateBlock { changeset: change } => {        self.editor.update_block(change).await.unwrap();      },      RowScript::AssertBlockCount(count) => {        assert_eq!(          self.editor.get_block_meta_revs().await.unwrap().len(),          count        );      },      RowScript::AssertBlock {        block_index,        row_count,        start_row_index,      } => {        assert_eq!(self.block_meta_revs[block_index].row_count, row_count);        assert_eq!(          self.block_meta_revs[block_index].start_row_index,          start_row_index        );      },      RowScript::AssertBlockEqual { block_index, block } => {        let blocks = self.editor.get_block_meta_revs().await.unwrap();        let compared_block = blocks[block_index].clone();        assert_eq!(compared_block, Arc::new(block));      },    }  }  async fn compare_cell_content(    &self,    cell_id: CellIdParams,    field_type: FieldType,    expected: String,  ) {    match field_type {      FieldType::RichText => {        let cell_data = self          .editor          .get_cell_protobuf(&cell_id)          .await          .unwrap()          .parser::<TextCellDataParser>()          .unwrap();        assert_eq!(cell_data.as_ref(), &expected);      },      FieldType::Number => {        let field_rev = self.editor.get_field_rev(&cell_id.field_id).await.unwrap();        let number_type_option = field_rev          .get_type_option::<NumberTypeOptionPB>(FieldType::Number.into())          .unwrap();        let cell_data = self          .editor          .get_cell_protobuf(&cell_id)          .await          .unwrap()          .custom_parser(NumberCellCustomDataParser(number_type_option.format))          .unwrap();        assert_eq!(cell_data.to_string(), expected);      },      FieldType::DateTime => {        let cell_data = self          .editor          .get_cell_protobuf(&cell_id)          .await          .unwrap()          .parser::<DateCellDataParser>()          .unwrap();        assert_eq!(cell_data.date, expected);      },      FieldType::SingleSelect => {        let cell_data = self          .editor          .get_cell_protobuf(&cell_id)          .await          .unwrap()          .parser::<SelectOptionCellDataParser>()          .unwrap();        let select_option = cell_data.select_options.first().unwrap();        assert_eq!(select_option.name, expected);      },      FieldType::MultiSelect => {        let cell_data = self          .editor          .get_cell_protobuf(&cell_id)          .await          .unwrap()          .parser::<SelectOptionCellDataParser>()          .unwrap();        let s = cell_data          .select_options          .into_iter()          .map(|option| option.name)          .collect::<Vec<String>>()          .join(SELECTION_IDS_SEPARATOR);        assert_eq!(s, expected);      },      FieldType::Checklist => {        let cell_data = self          .editor          .get_cell_protobuf(&cell_id)          .await          .unwrap()          .parser::<SelectOptionCellDataParser>()          .unwrap();        let s = cell_data          .select_options          .into_iter()          .map(|option| option.name)          .collect::<Vec<String>>()          .join(SELECTION_IDS_SEPARATOR);        assert_eq!(s, expected);      },      FieldType::Checkbox => {        let cell_data = self          .editor          .get_cell_protobuf(&cell_id)          .await          .unwrap()          .parser::<CheckboxCellDataParser>()          .unwrap();        assert_eq!(cell_data.to_string(), expected);      },      FieldType::URL => {        let cell_data = self          .editor          .get_cell_protobuf(&cell_id)          .await          .unwrap()          .parser::<URLCellDataParser>()          .unwrap();        assert_eq!(cell_data.content, expected);        // assert_eq!(cell_data.url, expected);      },    }  }}fn block_from_row_pbs(row_orders: Vec<RowPB>) -> Vec<DatabaseBlockRow> {  let mut map: HashMap<String, DatabaseBlockRow> = HashMap::new();  row_orders.into_iter().for_each(|row_pb| {    let block_id = row_pb.block_id().to_owned();    let cloned_block_id = block_id.clone();    map      .entry(block_id)      .or_insert_with(|| DatabaseBlockRow::new(cloned_block_id, vec![]))      .row_ids      .push(row_pb.id);  });  map.into_values().collect::<Vec<_>>()}impl std::ops::Deref for DatabaseRowTest {  type Target = DatabaseEditorTest;  fn deref(&self) -> &Self::Target {    &self.inner  }}impl std::ops::DerefMut for DatabaseRowTest {  fn deref_mut(&mut self) -> &mut Self::Target {    &mut self.inner  }}pub struct CreateRowScriptBuilder {  builder: DatabaseRowTestBuilder,  data_by_field_type: HashMap<FieldType, CellTestData>,  output_by_field_type: HashMap<FieldType, CellTestOutput>,}impl CreateRowScriptBuilder {  pub fn new(test: &DatabaseRowTest) -> Self {    Self {      builder: test.row_builder(),      data_by_field_type: HashMap::new(),      output_by_field_type: HashMap::new(),    }  }  pub fn insert(&mut self, field_type: FieldType, input: &str, expected: &str) {    self.data_by_field_type.insert(      field_type,      CellTestData {        input: input.to_string(),        expected: expected.to_owned(),      },    );  }  pub fn insert_single_select_cell<F>(&mut self, f: F, expected: &str)  where    F: Fn(Vec<SelectOptionPB>) -> SelectOptionPB,  {    let field_id = self.builder.insert_single_select_cell(f);    self.output_by_field_type.insert(      FieldType::SingleSelect,      CellTestOutput {        field_id,        expected: expected.to_owned(),      },    );  }  pub fn insert_multi_select_cell<F>(&mut self, f: F, expected: &str)  where    F: Fn(Vec<SelectOptionPB>) -> Vec<SelectOptionPB>,  {    let field_id = self.builder.insert_multi_select_cell(f);    self.output_by_field_type.insert(      FieldType::MultiSelect,      CellTestOutput {        field_id,        expected: expected.to_owned(),      },    );  }  pub fn build(mut self) -> Vec<RowScript> {    let mut scripts = vec![];    let output_by_field_type = &mut self.output_by_field_type;    for field_type in FieldType::iter() {      let field_type: FieldType = field_type;      if let Some(data) = self.data_by_field_type.get(&field_type) {        let field_id = match field_type {          FieldType::RichText => self.builder.insert_text_cell(&data.input),          FieldType::Number => self.builder.insert_number_cell(&data.input),          FieldType::DateTime => self.builder.insert_date_cell(&data.input),          FieldType::Checkbox => self.builder.insert_checkbox_cell(&data.input),          FieldType::URL => self.builder.insert_url_cell(&data.input),          _ => "".to_owned(),        };        if !field_id.is_empty() {          output_by_field_type.insert(            field_type,            CellTestOutput {              field_id,              expected: data.expected.clone(),            },          );        }      }    }    let row_rev = self.builder.build();    let row_id = row_rev.id.clone();    scripts.push(CreateRow { row_rev });    for field_type in FieldType::iter() {      if let Some(data) = output_by_field_type.get(&field_type) {        let script = AssertCell {          row_id: row_id.clone(),          field_id: data.field_id.clone(),          field_type,          expected: data.expected.clone(),        };        scripts.push(script);      }    }    scripts  }}pub struct CellTestData {  pub input: String,  pub expected: String,}struct CellTestOutput {  field_id: String,  expected: String,}
 |