mirror of
https://github.com/Nutomic/ibis.git
synced 2024-11-22 14:01:08 +00:00
tests compiling (but failing)
This commit is contained in:
parent
573f15b293
commit
9ca2558b06
7 changed files with 162 additions and 138 deletions
17
src/api.rs
17
src/api.rs
|
@ -1,4 +1,4 @@
|
|||
use crate::database::article::{DbArticle, DbArticleForm};
|
||||
use crate::database::article::{ArticleView, DbArticle, DbArticleForm};
|
||||
use crate::database::edit::{DbEdit, EditVersion};
|
||||
use crate::database::{DbConflict, MyDataHandle};
|
||||
use crate::error::MyResult;
|
||||
|
@ -126,7 +126,7 @@ async fn edit_article(
|
|||
} else {
|
||||
// There have been other changes since this edit was initiated. Get the common ancestor
|
||||
// version and generate a diff to find out what exactly has changed.
|
||||
let edits = DbEdit::for_article(original_article.id, &data.db_connection)?;
|
||||
let edits = DbEdit::for_article(&original_article, &data.db_connection)?;
|
||||
let ancestor = generate_article_version(&edits, &edit_form.previous_version)?;
|
||||
let patch = create_patch(&ancestor, &edit_form.new_text);
|
||||
|
||||
|
@ -154,8 +154,8 @@ pub struct GetArticleData {
|
|||
async fn get_article(
|
||||
Query(query): Query<GetArticleData>,
|
||||
data: Data<MyDataHandle>,
|
||||
) -> MyResult<Json<DbArticle>> {
|
||||
Ok(Json(DbArticle::read(
|
||||
) -> MyResult<Json<ArticleView>> {
|
||||
Ok(Json(DbArticle::read_view(
|
||||
query.article_id,
|
||||
&data.db_connection,
|
||||
)?))
|
||||
|
@ -183,9 +183,10 @@ async fn resolve_instance(
|
|||
async fn resolve_article(
|
||||
Query(query): Query<ResolveObject>,
|
||||
data: Data<MyDataHandle>,
|
||||
) -> MyResult<Json<DbArticle>> {
|
||||
) -> MyResult<Json<ArticleView>> {
|
||||
let article: DbArticle = ObjectId::from(query.id).dereference(&data).await?;
|
||||
Ok(Json(article))
|
||||
let edits = DbEdit::for_article(&article, &data.db_connection)?;
|
||||
Ok(Json(ArticleView { article, edits }))
|
||||
}
|
||||
|
||||
/// Retrieve the local instance info.
|
||||
|
@ -255,7 +256,7 @@ pub struct ForkArticleData {
|
|||
async fn fork_article(
|
||||
data: Data<MyDataHandle>,
|
||||
Form(fork_form): Form<ForkArticleData>,
|
||||
) -> MyResult<Json<DbArticle>> {
|
||||
) -> MyResult<Json<ArticleView>> {
|
||||
// TODO: lots of code duplicated from create_article(), can move it into helper
|
||||
let original_article = DbArticle::read(fork_form.article_id, &data.db_connection)?;
|
||||
let existing_article =
|
||||
|
@ -286,5 +287,5 @@ async fn fork_article(
|
|||
|
||||
CreateArticle::send_to_followers(article.clone(), &data).await?;
|
||||
|
||||
Ok(Json(article))
|
||||
Ok(Json(DbArticle::read_view(article.id, &data.db_connection)?))
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::database::edit::EditVersion;
|
||||
use crate::database::edit::{DbEdit, EditVersion};
|
||||
use crate::database::schema::article;
|
||||
use crate::error::MyResult;
|
||||
use crate::federation::objects::edits_collection::DbEditCollection;
|
||||
|
@ -6,6 +6,7 @@ use crate::federation::objects::instance::DbInstance;
|
|||
use activitypub_federation::fetch::collection_id::CollectionId;
|
||||
use activitypub_federation::fetch::object_id::ObjectId;
|
||||
use diesel::pg::PgConnection;
|
||||
use diesel::BelongingToDsl;
|
||||
use diesel::ExpressionMethods;
|
||||
use diesel::{
|
||||
insert_into, AsChangeset, BoolExpressionMethods, Identifiable, Insertable,
|
||||
|
@ -23,10 +24,18 @@ pub struct DbArticle {
|
|||
pub text: String,
|
||||
pub ap_id: ObjectId<DbArticle>,
|
||||
pub instance_id: ObjectId<DbInstance>,
|
||||
// TODO: should read this from edits table instead of separate db field
|
||||
pub latest_version: EditVersion,
|
||||
pub local: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Queryable)]
|
||||
#[diesel(table_name = article, check_for_backend(diesel::pg::Pg))]
|
||||
pub struct ArticleView {
|
||||
pub article: DbArticle,
|
||||
pub edits: Vec<DbEdit>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Insertable, AsChangeset)]
|
||||
#[diesel(table_name = article, check_for_backend(diesel::pg::Pg))]
|
||||
pub struct DbArticleForm {
|
||||
|
@ -67,6 +76,13 @@ impl DbArticle {
|
|||
Ok(article::table.find(id).get_result(conn.deref_mut())?)
|
||||
}
|
||||
|
||||
pub fn read_view(id: i32, conn: &Mutex<PgConnection>) -> MyResult<ArticleView> {
|
||||
let mut conn = conn.lock().unwrap();
|
||||
let article: DbArticle = article::table.find(id).get_result(conn.deref_mut())?;
|
||||
let edits = DbEdit::belonging_to(&article).get_results(conn.deref_mut())?;
|
||||
Ok(ArticleView { article, edits })
|
||||
}
|
||||
|
||||
pub fn read_from_ap_id(
|
||||
ap_id: &ObjectId<DbArticle>,
|
||||
conn: &Mutex<PgConnection>,
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use crate::database::article::DbArticle;
|
||||
use crate::database::schema::edit;
|
||||
use crate::database::DbArticle;
|
||||
use crate::error::MyResult;
|
||||
use activitypub_federation::fetch::object_id::ObjectId;
|
||||
use diesel::ExpressionMethods;
|
||||
use diesel::{
|
||||
insert_into, AsChangeset, Identifiable, Insertable, PgConnection, QueryDsl, Queryable,
|
||||
RunQueryDsl, Selectable,
|
||||
insert_into, AsChangeset, Identifiable, Insertable, PgConnection, Queryable, RunQueryDsl,
|
||||
Selectable,
|
||||
};
|
||||
use diesel::{Associations, BelongingToDsl};
|
||||
use diesel_derive_newtype::DieselNewType;
|
||||
use diffy::create_patch;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -16,8 +16,18 @@ use std::sync::Mutex;
|
|||
use url::Url;
|
||||
|
||||
/// Represents a single change to the article.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Queryable, Selectable, Identifiable)]
|
||||
#[diesel(table_name = edit, check_for_backend(diesel::pg::Pg))]
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
PartialEq,
|
||||
Queryable,
|
||||
Selectable,
|
||||
Identifiable,
|
||||
Associations,
|
||||
)]
|
||||
#[diesel(table_name = edit, check_for_backend(diesel::pg::Pg), belongs_to(DbArticle, foreign_key = article_id))]
|
||||
pub struct DbEdit {
|
||||
pub id: i32,
|
||||
pub ap_id: ObjectId<DbEdit>,
|
||||
|
@ -66,12 +76,9 @@ impl DbEdit {
|
|||
.get_result(conn.deref_mut())?)
|
||||
}
|
||||
|
||||
pub fn for_article(id: i32, conn: &Mutex<PgConnection>) -> MyResult<Vec<Self>> {
|
||||
pub fn for_article(article: &DbArticle, conn: &Mutex<PgConnection>) -> MyResult<Vec<Self>> {
|
||||
let mut conn = conn.lock().unwrap();
|
||||
Ok(edit::table
|
||||
.filter(edit::dsl::id.eq(id))
|
||||
.order_by(edit::dsl::id.asc())
|
||||
.get_results(conn.deref_mut())?)
|
||||
Ok(DbEdit::belonging_to(&article).get_results(conn.deref_mut())?)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ impl DbConflict {
|
|||
DbArticle::read_from_ap_id(&self.article_id.clone().into(), &data.db_connection)?;
|
||||
|
||||
// create common ancestor version
|
||||
let edits = DbEdit::for_article(original_article.id, &data.db_connection)?;
|
||||
let edits = DbEdit::for_article(&original_article, &data.db_connection)?;
|
||||
let ancestor = generate_article_version(&edits, &self.previous_version)?;
|
||||
|
||||
let patch = Patch::from_str(&self.diff)?;
|
||||
|
|
|
@ -37,7 +37,7 @@ impl Collection for DbEditCollection {
|
|||
owner: &Self::Owner,
|
||||
data: &Data<Self::DataType>,
|
||||
) -> Result<Self::Kind, Self::Error> {
|
||||
let edits = DbEditCollection(DbEdit::for_article(owner.id, &data.db_connection)?);
|
||||
let edits = DbEditCollection(DbEdit::for_article(owner, &data.db_connection)?);
|
||||
|
||||
let edits = future::try_join_all(
|
||||
edits
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use fediwiki::api::{
|
||||
ApiConflict, CreateArticleData, EditArticleData, FollowInstance, GetArticleData, ResolveObject,
|
||||
};
|
||||
use fediwiki::database::article::DbArticle;
|
||||
use fediwiki::database::article::{ArticleView, DbArticle};
|
||||
use fediwiki::error::MyResult;
|
||||
use fediwiki::federation::objects::instance::DbInstance;
|
||||
use fediwiki::start;
|
||||
|
@ -68,7 +68,7 @@ impl TestData {
|
|||
|
||||
pub const TEST_ARTICLE_DEFAULT_TEXT: &str = "some\nexample\ntext\n";
|
||||
|
||||
pub async fn create_article(hostname: &str, title: String) -> MyResult<DbArticle> {
|
||||
pub async fn create_article(hostname: &str, title: String) -> MyResult<ArticleView> {
|
||||
let create_form = CreateArticleData {
|
||||
title: title.clone(),
|
||||
};
|
||||
|
@ -83,9 +83,9 @@ pub async fn create_article(hostname: &str, title: String) -> MyResult<DbArticle
|
|||
edit_article(hostname, &edit_form).await
|
||||
}
|
||||
|
||||
pub async fn get_article(hostname: &str, article_id: i32) -> MyResult<DbArticle> {
|
||||
pub async fn get_article(hostname: &str, article_id: i32) -> MyResult<ArticleView> {
|
||||
let get_article = GetArticleData { article_id };
|
||||
get_query::<DbArticle, _>(hostname, "article", Some(get_article.clone())).await
|
||||
get_query::<ArticleView, _>(hostname, "article", Some(get_article.clone())).await
|
||||
}
|
||||
|
||||
pub async fn edit_article_with_conflict(
|
||||
|
@ -101,7 +101,7 @@ pub async fn edit_article_with_conflict(
|
|||
.await?)
|
||||
}
|
||||
|
||||
pub async fn edit_article(hostname: &str, edit_form: &EditArticleData) -> MyResult<DbArticle> {
|
||||
pub async fn edit_article(hostname: &str, edit_form: &EditArticleData) -> MyResult<ArticleView> {
|
||||
let edit_res: Option<ApiConflict> = CLIENT
|
||||
.patch(format!("http://{}/api/v1/article", hostname))
|
||||
.form(&edit_form)
|
||||
|
@ -110,11 +110,7 @@ pub async fn edit_article(hostname: &str, edit_form: &EditArticleData) -> MyResu
|
|||
.json()
|
||||
.await?;
|
||||
assert!(edit_res.is_none());
|
||||
let get_article = GetArticleData {
|
||||
article_id: edit_form.article_id,
|
||||
};
|
||||
let updated_article: DbArticle = get_query(hostname, "article", Some(get_article)).await?;
|
||||
Ok(updated_article)
|
||||
get_article(hostname, edit_form.article_id).await
|
||||
}
|
||||
|
||||
pub async fn get<T>(hostname: &str, endpoint: &str) -> MyResult<T>
|
||||
|
|
216
tests/test.rs
216
tests/test.rs
|
@ -10,7 +10,7 @@ use common::get;
|
|||
use fediwiki::api::{
|
||||
ApiConflict, EditArticleData, ForkArticleData, ResolveObject, SearchArticleData,
|
||||
};
|
||||
use fediwiki::database::article::DbArticle;
|
||||
use fediwiki::database::article::{ArticleView, DbArticle};
|
||||
use fediwiki::error::MyResult;
|
||||
use fediwiki::federation::objects::edit::ApubEdit;
|
||||
use fediwiki::federation::objects::instance::DbInstance;
|
||||
|
@ -25,28 +25,28 @@ async fn test_create_read_and_edit_article() -> MyResult<()> {
|
|||
// create article
|
||||
let title = "Manu_Chao".to_string();
|
||||
let create_res = create_article(data.hostname_alpha, title.clone()).await?;
|
||||
assert_eq!(title, create_res.title);
|
||||
assert!(create_res.local);
|
||||
assert_eq!(title, create_res.article.title);
|
||||
assert!(create_res.article.local);
|
||||
|
||||
// now article can be read
|
||||
let get_res = get_article(data.hostname_alpha, create_res.id).await?;
|
||||
assert_eq!(title, get_res.title);
|
||||
assert_eq!(TEST_ARTICLE_DEFAULT_TEXT, get_res.text);
|
||||
assert!(get_res.local);
|
||||
let get_res = get_article(data.hostname_alpha, create_res.article.id).await?;
|
||||
assert_eq!(title, get_res.article.title);
|
||||
assert_eq!(TEST_ARTICLE_DEFAULT_TEXT, get_res.article.text);
|
||||
assert!(get_res.article.local);
|
||||
|
||||
// error on article which wasnt federated
|
||||
let not_found = get_article(data.hostname_beta, create_res.id).await;
|
||||
let not_found = get_article(data.hostname_beta, create_res.article.id).await;
|
||||
assert!(not_found.is_err());
|
||||
|
||||
// edit article
|
||||
let edit_form = EditArticleData {
|
||||
article_id: create_res.id,
|
||||
article_id: create_res.article.id,
|
||||
new_text: "Lorem Ipsum 2".to_string(),
|
||||
previous_version: get_res.latest_version,
|
||||
previous_version: get_res.article.latest_version,
|
||||
resolve_conflict_id: None,
|
||||
};
|
||||
let edit_res = edit_article(data.hostname_alpha, &edit_form).await?;
|
||||
assert_eq!(edit_form.new_text, edit_res.text);
|
||||
assert_eq!(edit_form.new_text, edit_res.article.text);
|
||||
assert_eq!(2, edit_res.edits.len());
|
||||
|
||||
let search_form = SearchArticleData {
|
||||
|
@ -55,7 +55,7 @@ async fn test_create_read_and_edit_article() -> MyResult<()> {
|
|||
let search_res: Vec<DbArticle> =
|
||||
get_query(data.hostname_alpha, "search", Some(search_form)).await?;
|
||||
assert_eq!(1, search_res.len());
|
||||
assert_eq!(edit_res, search_res[0]);
|
||||
assert_eq!(edit_res.article, search_res[0]);
|
||||
|
||||
data.stop()
|
||||
}
|
||||
|
@ -68,8 +68,8 @@ async fn test_create_duplicate_article() -> MyResult<()> {
|
|||
// create article
|
||||
let title = "Manu_Chao".to_string();
|
||||
let create_res = create_article(data.hostname_alpha, title.clone()).await?;
|
||||
assert_eq!(title, create_res.title);
|
||||
assert!(create_res.local);
|
||||
assert_eq!(title, create_res.article.title);
|
||||
assert!(create_res.article.local);
|
||||
|
||||
let create_res = create_article(data.hostname_alpha, title.clone()).await;
|
||||
assert!(create_res.is_err());
|
||||
|
@ -107,21 +107,21 @@ async fn test_synchronize_articles() -> MyResult<()> {
|
|||
// create article on alpha
|
||||
let title = "Manu_Chao".to_string();
|
||||
let create_res = create_article(data.hostname_alpha, title.clone()).await?;
|
||||
assert_eq!(title, create_res.title);
|
||||
assert_eq!(title, create_res.article.title);
|
||||
assert_eq!(1, create_res.edits.len());
|
||||
assert!(create_res.local);
|
||||
assert!(create_res.article.local);
|
||||
|
||||
// edit the article
|
||||
let edit_form = EditArticleData {
|
||||
article_id: create_res.id,
|
||||
article_id: create_res.article.id,
|
||||
new_text: "Lorem Ipsum 2\n".to_string(),
|
||||
previous_version: create_res.latest_version,
|
||||
previous_version: create_res.article.latest_version,
|
||||
resolve_conflict_id: None,
|
||||
};
|
||||
edit_article(data.hostname_alpha, &edit_form).await?;
|
||||
|
||||
// article is not yet on beta
|
||||
let get_res = get_article(data.hostname_beta, create_res.id).await;
|
||||
let get_res = get_article(data.hostname_beta, create_res.article.id).await;
|
||||
assert!(get_res.is_err());
|
||||
|
||||
// fetch alpha instance on beta, articles are also fetched automatically
|
||||
|
@ -132,12 +132,12 @@ async fn test_synchronize_articles() -> MyResult<()> {
|
|||
.await?;
|
||||
|
||||
// get the article and compare
|
||||
let get_res = get_article(data.hostname_beta, create_res.id).await?;
|
||||
assert_eq!(create_res.ap_id, get_res.ap_id);
|
||||
assert_eq!(title, get_res.title);
|
||||
let get_res = get_article(data.hostname_beta, create_res.article.id).await?;
|
||||
assert_eq!(create_res.article.ap_id, get_res.article.ap_id);
|
||||
assert_eq!(title, get_res.article.title);
|
||||
assert_eq!(2, get_res.edits.len());
|
||||
assert_eq!(edit_form.new_text, get_res.text);
|
||||
assert!(!get_res.local);
|
||||
assert_eq!(edit_form.new_text, get_res.article.text);
|
||||
assert!(!get_res.article.local);
|
||||
|
||||
data.stop()
|
||||
}
|
||||
|
@ -152,36 +152,36 @@ async fn test_edit_local_article() -> MyResult<()> {
|
|||
// create new article
|
||||
let title = "Manu_Chao".to_string();
|
||||
let create_res = create_article(data.hostname_beta, title.clone()).await?;
|
||||
assert_eq!(title, create_res.title);
|
||||
assert!(create_res.local);
|
||||
assert_eq!(title, create_res.article.title);
|
||||
assert!(create_res.article.local);
|
||||
|
||||
// article should be federated to alpha
|
||||
let get_res = get_article(data.hostname_alpha, create_res.id).await?;
|
||||
assert_eq!(create_res.title, get_res.title);
|
||||
let get_res = get_article(data.hostname_alpha, create_res.article.id).await?;
|
||||
assert_eq!(create_res.article.title, get_res.article.title);
|
||||
assert_eq!(1, get_res.edits.len());
|
||||
assert!(!get_res.local);
|
||||
assert_eq!(create_res.text, get_res.text);
|
||||
assert!(!get_res.article.local);
|
||||
assert_eq!(create_res.article.text, get_res.article.text);
|
||||
|
||||
// edit the article
|
||||
let edit_form = EditArticleData {
|
||||
article_id: create_res.id,
|
||||
article_id: create_res.article.id,
|
||||
new_text: "Lorem Ipsum 2".to_string(),
|
||||
previous_version: get_res.latest_version,
|
||||
previous_version: get_res.article.latest_version,
|
||||
resolve_conflict_id: None,
|
||||
};
|
||||
let edit_res = edit_article(data.hostname_beta, &edit_form).await?;
|
||||
assert_eq!(edit_res.text, edit_form.new_text);
|
||||
assert_eq!(edit_res.article.text, edit_form.new_text);
|
||||
assert_eq!(edit_res.edits.len(), 2);
|
||||
assert!(edit_res.edits[0]
|
||||
.id
|
||||
.ap_id
|
||||
.to_string()
|
||||
.starts_with(&edit_res.ap_id.to_string()));
|
||||
.starts_with(&edit_res.article.ap_id.to_string()));
|
||||
|
||||
// edit should be federated to alpha
|
||||
let get_res = get_article(data.hostname_alpha, edit_res.id).await?;
|
||||
assert_eq!(edit_res.title, get_res.title);
|
||||
let get_res = get_article(data.hostname_alpha, edit_res.article.id).await?;
|
||||
assert_eq!(edit_res.article.title, get_res.article.title);
|
||||
assert_eq!(edit_res.edits.len(), 2);
|
||||
assert_eq!(edit_res.text, get_res.text);
|
||||
assert_eq!(edit_res.article.text, get_res.article.text);
|
||||
|
||||
data.stop()
|
||||
}
|
||||
|
@ -197,44 +197,44 @@ async fn test_edit_remote_article() -> MyResult<()> {
|
|||
// create new article
|
||||
let title = "Manu_Chao".to_string();
|
||||
let create_res = create_article(data.hostname_beta, title.clone()).await?;
|
||||
assert_eq!(title, create_res.title);
|
||||
assert!(create_res.local);
|
||||
assert_eq!(title, create_res.article.title);
|
||||
assert!(create_res.article.local);
|
||||
|
||||
// article should be federated to alpha and gamma
|
||||
let get_res = get_article(data.hostname_alpha, create_res.id).await?;
|
||||
assert_eq!(create_res.title, get_res.title);
|
||||
let get_res = get_article(data.hostname_alpha, create_res.article.id).await?;
|
||||
assert_eq!(create_res.article.title, get_res.article.title);
|
||||
assert_eq!(1, get_res.edits.len());
|
||||
assert!(!get_res.local);
|
||||
assert!(!get_res.article.local);
|
||||
|
||||
let get_res = get_article(data.hostname_gamma, create_res.id).await?;
|
||||
assert_eq!(create_res.title, get_res.title);
|
||||
assert_eq!(create_res.text, get_res.text);
|
||||
let get_res = get_article(data.hostname_gamma, create_res.article.id).await?;
|
||||
assert_eq!(create_res.article.title, get_res.article.title);
|
||||
assert_eq!(create_res.article.text, get_res.article.text);
|
||||
|
||||
let edit_form = EditArticleData {
|
||||
article_id: create_res.id,
|
||||
article_id: create_res.article.id,
|
||||
new_text: "Lorem Ipsum 2".to_string(),
|
||||
previous_version: get_res.latest_version,
|
||||
previous_version: get_res.article.latest_version,
|
||||
resolve_conflict_id: None,
|
||||
};
|
||||
let edit_res = edit_article(data.hostname_alpha, &edit_form).await?;
|
||||
assert_eq!(edit_form.new_text, edit_res.text);
|
||||
assert_eq!(edit_form.new_text, edit_res.article.text);
|
||||
assert_eq!(2, edit_res.edits.len());
|
||||
assert!(!edit_res.local);
|
||||
assert!(!edit_res.article.local);
|
||||
assert!(edit_res.edits[0]
|
||||
.id
|
||||
.ap_id
|
||||
.to_string()
|
||||
.starts_with(&edit_res.ap_id.to_string()));
|
||||
.starts_with(&edit_res.article.ap_id.to_string()));
|
||||
|
||||
// edit should be federated to beta and gamma
|
||||
let get_res = get_article(data.hostname_alpha, create_res.id).await?;
|
||||
assert_eq!(edit_res.title, get_res.title);
|
||||
let get_res = get_article(data.hostname_alpha, create_res.article.id).await?;
|
||||
assert_eq!(edit_res.article.title, get_res.article.title);
|
||||
assert_eq!(edit_res.edits.len(), 2);
|
||||
assert_eq!(edit_res.text, get_res.text);
|
||||
assert_eq!(edit_res.article.text, get_res.article.text);
|
||||
|
||||
let get_res = get_article(data.hostname_gamma, create_res.id).await?;
|
||||
assert_eq!(edit_res.title, get_res.title);
|
||||
let get_res = get_article(data.hostname_gamma, create_res.article.id).await?;
|
||||
assert_eq!(edit_res.article.title, get_res.article.title);
|
||||
assert_eq!(edit_res.edits.len(), 2);
|
||||
assert_eq!(edit_res.text, get_res.text);
|
||||
assert_eq!(edit_res.article.text, get_res.article.text);
|
||||
|
||||
data.stop()
|
||||
}
|
||||
|
@ -247,25 +247,25 @@ async fn test_local_edit_conflict() -> MyResult<()> {
|
|||
// create new article
|
||||
let title = "Manu_Chao".to_string();
|
||||
let create_res = create_article(data.hostname_alpha, title.clone()).await?;
|
||||
assert_eq!(title, create_res.title);
|
||||
assert!(create_res.local);
|
||||
assert_eq!(title, create_res.article.title);
|
||||
assert!(create_res.article.local);
|
||||
|
||||
// one user edits article
|
||||
let edit_form = EditArticleData {
|
||||
article_id: create_res.id,
|
||||
article_id: create_res.article.id,
|
||||
new_text: "Lorem Ipsum\n".to_string(),
|
||||
previous_version: create_res.latest_version.clone(),
|
||||
previous_version: create_res.article.latest_version.clone(),
|
||||
resolve_conflict_id: None,
|
||||
};
|
||||
let edit_res = edit_article(data.hostname_alpha, &edit_form).await?;
|
||||
assert_eq!(edit_res.text, edit_form.new_text);
|
||||
assert_eq!(edit_res.article.text, edit_form.new_text);
|
||||
assert_eq!(2, edit_res.edits.len());
|
||||
|
||||
// another user edits article, without being aware of previous edit
|
||||
let edit_form = EditArticleData {
|
||||
article_id: create_res.id,
|
||||
article_id: create_res.article.id,
|
||||
new_text: "Ipsum Lorem\n".to_string(),
|
||||
previous_version: create_res.latest_version,
|
||||
previous_version: create_res.article.latest_version,
|
||||
resolve_conflict_id: None,
|
||||
};
|
||||
let edit_res = edit_article_with_conflict(data.hostname_alpha, &edit_form)
|
||||
|
@ -279,13 +279,13 @@ async fn test_local_edit_conflict() -> MyResult<()> {
|
|||
assert_eq!(conflicts[0], edit_res);
|
||||
|
||||
let edit_form = EditArticleData {
|
||||
article_id: create_res.id,
|
||||
article_id: create_res.article.id,
|
||||
new_text: "Lorem Ipsum and Ipsum Lorem\n".to_string(),
|
||||
previous_version: edit_res.previous_version,
|
||||
resolve_conflict_id: Some(edit_res.id),
|
||||
};
|
||||
let edit_res = edit_article(data.hostname_alpha, &edit_form).await?;
|
||||
assert_eq!(edit_form.new_text, edit_res.text);
|
||||
assert_eq!(edit_form.new_text, edit_res.article.text);
|
||||
|
||||
let conflicts: Vec<ApiConflict> =
|
||||
get_query(data.hostname_alpha, "edit_conflicts", None::<()>).await?;
|
||||
|
@ -304,45 +304,45 @@ async fn test_federated_edit_conflict() -> MyResult<()> {
|
|||
// create new article
|
||||
let title = "Manu_Chao".to_string();
|
||||
let create_res = create_article(data.hostname_beta, title.clone()).await?;
|
||||
assert_eq!(title, create_res.title);
|
||||
assert!(create_res.local);
|
||||
assert_eq!(title, create_res.article.title);
|
||||
assert!(create_res.article.local);
|
||||
|
||||
// fetch article to gamma
|
||||
let resolve_object = ResolveObject {
|
||||
id: create_res.ap_id.inner().clone(),
|
||||
id: create_res.article.ap_id.inner().clone(),
|
||||
};
|
||||
let resolve_res: DbArticle =
|
||||
get_query(data.hostname_gamma, "resolve_article", Some(resolve_object)).await?;
|
||||
assert_eq!(create_res.text, resolve_res.text);
|
||||
assert_eq!(create_res.article.text, resolve_res.text);
|
||||
|
||||
// alpha edits article
|
||||
let edit_form = EditArticleData {
|
||||
article_id: create_res.id,
|
||||
article_id: create_res.article.id,
|
||||
new_text: "Lorem Ipsum\n".to_string(),
|
||||
previous_version: create_res.latest_version.clone(),
|
||||
previous_version: create_res.article.latest_version.clone(),
|
||||
resolve_conflict_id: None,
|
||||
};
|
||||
let edit_res = edit_article(data.hostname_alpha, &edit_form).await?;
|
||||
assert_eq!(edit_res.text, edit_form.new_text);
|
||||
assert_eq!(edit_res.article.text, edit_form.new_text);
|
||||
assert_eq!(2, edit_res.edits.len());
|
||||
assert!(!edit_res.local);
|
||||
assert!(!edit_res.article.local);
|
||||
assert!(edit_res.edits[1]
|
||||
.id
|
||||
.ap_id
|
||||
.to_string()
|
||||
.starts_with(&edit_res.ap_id.to_string()));
|
||||
.starts_with(&edit_res.article.ap_id.to_string()));
|
||||
|
||||
// gamma also edits, as its not the latest version there is a conflict. local version should
|
||||
// not be updated with this conflicting version, instead user needs to handle the conflict
|
||||
let edit_form = EditArticleData {
|
||||
article_id: create_res.id,
|
||||
article_id: create_res.article.id,
|
||||
new_text: "aaaa\n".to_string(),
|
||||
previous_version: create_res.latest_version,
|
||||
previous_version: create_res.article.latest_version,
|
||||
resolve_conflict_id: None,
|
||||
};
|
||||
let edit_res = edit_article(data.hostname_gamma, &edit_form).await?;
|
||||
assert_ne!(edit_form.new_text, edit_res.text);
|
||||
assert_ne!(edit_form.new_text, edit_res.article.text);
|
||||
assert_eq!(2, edit_res.edits.len());
|
||||
assert!(!edit_res.local);
|
||||
assert!(!edit_res.article.local);
|
||||
|
||||
let conflicts: Vec<ApiConflict> =
|
||||
get_query(data.hostname_gamma, "edit_conflicts", None::<()>).await?;
|
||||
|
@ -350,13 +350,13 @@ async fn test_federated_edit_conflict() -> MyResult<()> {
|
|||
|
||||
// resolve the conflict
|
||||
let edit_form = EditArticleData {
|
||||
article_id: create_res.id,
|
||||
article_id: create_res.article.id,
|
||||
new_text: "aaaa\n".to_string(),
|
||||
previous_version: conflicts[0].previous_version.clone(),
|
||||
resolve_conflict_id: Some(conflicts[0].id),
|
||||
};
|
||||
let edit_res = edit_article(data.hostname_gamma, &edit_form).await?;
|
||||
assert_eq!(edit_form.new_text, edit_res.text);
|
||||
assert_eq!(edit_form.new_text, edit_res.article.text);
|
||||
assert_eq!(3, edit_res.edits.len());
|
||||
|
||||
let conflicts: Vec<ApubEdit> =
|
||||
|
@ -374,25 +374,25 @@ async fn test_overlapping_edits_no_conflict() -> MyResult<()> {
|
|||
// create new article
|
||||
let title = "Manu_Chao".to_string();
|
||||
let create_res = create_article(data.hostname_alpha, title.clone()).await?;
|
||||
assert_eq!(title, create_res.title);
|
||||
assert!(create_res.local);
|
||||
assert_eq!(title, create_res.article.title);
|
||||
assert!(create_res.article.local);
|
||||
|
||||
// one user edits article
|
||||
let edit_form = EditArticleData {
|
||||
article_id: create_res.id,
|
||||
article_id: create_res.article.id,
|
||||
new_text: "my\nexample\ntext\n".to_string(),
|
||||
previous_version: create_res.latest_version.clone(),
|
||||
previous_version: create_res.article.latest_version.clone(),
|
||||
resolve_conflict_id: None,
|
||||
};
|
||||
let edit_res = edit_article(data.hostname_alpha, &edit_form).await?;
|
||||
assert_eq!(edit_res.text, edit_form.new_text);
|
||||
assert_eq!(edit_res.article.text, edit_form.new_text);
|
||||
assert_eq!(2, edit_res.edits.len());
|
||||
|
||||
// another user edits article, without being aware of previous edit
|
||||
let edit_form = EditArticleData {
|
||||
article_id: create_res.id,
|
||||
article_id: create_res.article.id,
|
||||
new_text: "some\nexample\narticle\n".to_string(),
|
||||
previous_version: create_res.latest_version,
|
||||
previous_version: create_res.article.latest_version,
|
||||
resolve_conflict_id: None,
|
||||
};
|
||||
let edit_res = edit_article(data.hostname_alpha, &edit_form).await?;
|
||||
|
@ -400,7 +400,7 @@ async fn test_overlapping_edits_no_conflict() -> MyResult<()> {
|
|||
get_query(data.hostname_alpha, "edit_conflicts", None::<()>).await?;
|
||||
assert_eq!(0, conflicts.len());
|
||||
assert_eq!(3, edit_res.edits.len());
|
||||
assert_eq!("my\nexample\narticle\n", edit_res.text);
|
||||
assert_eq!("my\nexample\narticle\n", edit_res.article.text);
|
||||
|
||||
data.stop()
|
||||
}
|
||||
|
@ -413,32 +413,36 @@ async fn test_fork_article() -> MyResult<()> {
|
|||
// create article
|
||||
let title = "Manu_Chao".to_string();
|
||||
let create_res = create_article(data.hostname_alpha, title.clone()).await?;
|
||||
assert_eq!(title, create_res.title);
|
||||
assert!(create_res.local);
|
||||
assert_eq!(title, create_res.article.title);
|
||||
assert!(create_res.article.local);
|
||||
|
||||
// fetch on beta
|
||||
let resolve_object = ResolveObject {
|
||||
id: create_res.ap_id.into_inner(),
|
||||
id: create_res.article.ap_id.into_inner(),
|
||||
};
|
||||
let resolved_article =
|
||||
get_query::<DbArticle, _>(data.hostname_beta, "resolve_article", Some(resolve_object))
|
||||
.await?;
|
||||
assert_eq!(create_res.edits.len(), resolved_article.edits.len());
|
||||
let resolve_res: ArticleView =
|
||||
get_query(data.hostname_beta, "resolve_article", Some(resolve_object)).await?;
|
||||
let resolved_article = resolve_res.article;
|
||||
assert_eq!(create_res.edits.len(), resolve_res.edits.len());
|
||||
|
||||
// fork the article to local instance
|
||||
let fork_form = ForkArticleData {
|
||||
article_id: resolved_article.id,
|
||||
};
|
||||
let fork_res: DbArticle = post(data.hostname_beta, "article/fork", &fork_form).await?;
|
||||
assert_eq!(resolved_article.title, fork_res.title);
|
||||
assert_eq!(resolved_article.text, fork_res.text);
|
||||
assert_eq!(resolved_article.edits, fork_res.edits);
|
||||
assert_eq!(resolved_article.latest_version, fork_res.latest_version);
|
||||
assert_ne!(resolved_article.ap_id, fork_res.ap_id);
|
||||
assert!(fork_res.local);
|
||||
let fork_res: ArticleView = post(data.hostname_beta, "article/fork", &fork_form).await?;
|
||||
let forked_article = fork_res.article;
|
||||
assert_eq!(resolved_article.title, forked_article.title);
|
||||
assert_eq!(resolved_article.text, forked_article.text);
|
||||
assert_eq!(resolve_res.edits, fork_res.edits);
|
||||
assert_eq!(
|
||||
resolved_article.latest_version,
|
||||
forked_article.latest_version
|
||||
);
|
||||
assert_ne!(resolved_article.ap_id, forked_article.ap_id);
|
||||
assert!(forked_article.local);
|
||||
|
||||
let beta_instance: DbInstance = get(data.hostname_beta, "instance").await?;
|
||||
assert_eq!(fork_res.instance_id, beta_instance.ap_id);
|
||||
assert_eq!(forked_article.instance_id, beta_instance.ap_id);
|
||||
|
||||
// now search returns two articles for this title (original and forked)
|
||||
let search_form = SearchArticleData {
|
||||
|
|
Loading…
Reference in a new issue