mirror of
https://github.com/Nutomic/ibis.git
synced 2024-11-22 18:21:08 +00:00
some cleanup
This commit is contained in:
parent
132d9c8389
commit
5c969078a8
9 changed files with 145 additions and 83 deletions
|
@ -273,11 +273,10 @@ async fn fork_article(
|
||||||
let article = DbArticle::create(&form, &data.db_connection)?;
|
let article = DbArticle::create(&form, &data.db_connection)?;
|
||||||
|
|
||||||
// copy edits to new article
|
// copy edits to new article
|
||||||
// TODO: convert to sql
|
// this could also be done in sql
|
||||||
let edits = DbEdit::read_for_article(&original_article, &data.db_connection)?;
|
let edits = DbEdit::read_for_article(&original_article, &data.db_connection)?;
|
||||||
for e in edits {
|
for e in edits {
|
||||||
let ap_id = DbEditForm::generate_ap_id(&article, &e.hash)?;
|
let ap_id = DbEditForm::generate_ap_id(&article, &e.hash)?;
|
||||||
// TODO: id gives db unique violation
|
|
||||||
let form = DbEditForm {
|
let form = DbEditForm {
|
||||||
ap_id,
|
ap_id,
|
||||||
diff: e.diff,
|
diff: e.diff,
|
||||||
|
@ -285,7 +284,7 @@ async fn fork_article(
|
||||||
hash: e.hash,
|
hash: e.hash,
|
||||||
previous_version_id: e.previous_version_id,
|
previous_version_id: e.previous_version_id,
|
||||||
};
|
};
|
||||||
dbg!(DbEdit::create(&form, &data.db_connection))?;
|
DbEdit::create(&form, &data.db_connection)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateArticle::send_to_followers(article.clone(), &data).await?;
|
CreateArticle::send_to_followers(article.clone(), &data).await?;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::database::edit::DbEdit;
|
use crate::database::edit::DbEdit;
|
||||||
|
|
||||||
use crate::database::schema::article;
|
use crate::database::schema::{article, edit};
|
||||||
use crate::error::MyResult;
|
use crate::error::MyResult;
|
||||||
use crate::federation::objects::edits_collection::DbEditCollection;
|
use crate::federation::objects::edits_collection::DbEditCollection;
|
||||||
use activitypub_federation::fetch::collection_id::CollectionId;
|
use activitypub_federation::fetch::collection_id::CollectionId;
|
||||||
|
@ -76,7 +76,7 @@ impl DbArticle {
|
||||||
.get_result::<Self>(conn.deref_mut())?)
|
.get_result::<Self>(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(id: i32, conn: &Mutex<PgConnection>) -> MyResult<DbArticle> {
|
pub fn read(id: i32, conn: &Mutex<PgConnection>) -> MyResult<Self> {
|
||||||
let mut conn = conn.lock().unwrap();
|
let mut conn = conn.lock().unwrap();
|
||||||
Ok(article::table.find(id).get_result(conn.deref_mut())?)
|
Ok(article::table.find(id).get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
@ -98,14 +98,14 @@ impl DbArticle {
|
||||||
pub fn read_from_ap_id(
|
pub fn read_from_ap_id(
|
||||||
ap_id: &ObjectId<DbArticle>,
|
ap_id: &ObjectId<DbArticle>,
|
||||||
conn: &Mutex<PgConnection>,
|
conn: &Mutex<PgConnection>,
|
||||||
) -> MyResult<DbArticle> {
|
) -> MyResult<Self> {
|
||||||
let mut conn = conn.lock().unwrap();
|
let mut conn = conn.lock().unwrap();
|
||||||
Ok(article::table
|
Ok(article::table
|
||||||
.filter(article::dsl::ap_id.eq(ap_id))
|
.filter(article::dsl::ap_id.eq(ap_id))
|
||||||
.get_result(conn.deref_mut())?)
|
.get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_local_title(title: &str, conn: &Mutex<PgConnection>) -> MyResult<DbArticle> {
|
pub fn read_local_title(title: &str, conn: &Mutex<PgConnection>) -> MyResult<Self> {
|
||||||
let mut conn = conn.lock().unwrap();
|
let mut conn = conn.lock().unwrap();
|
||||||
Ok(article::table
|
Ok(article::table
|
||||||
.filter(article::dsl::title.eq(title))
|
.filter(article::dsl::title.eq(title))
|
||||||
|
@ -113,14 +113,14 @@ impl DbArticle {
|
||||||
.get_result(conn.deref_mut())?)
|
.get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_all_local(conn: &Mutex<PgConnection>) -> MyResult<Vec<DbArticle>> {
|
pub fn read_all_local(conn: &Mutex<PgConnection>) -> MyResult<Vec<Self>> {
|
||||||
let mut conn = conn.lock().unwrap();
|
let mut conn = conn.lock().unwrap();
|
||||||
Ok(article::table
|
Ok(article::table
|
||||||
.filter(article::dsl::local.eq(true))
|
.filter(article::dsl::local.eq(true))
|
||||||
.get_results(conn.deref_mut())?)
|
.get_results(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn search(query: &str, conn: &Mutex<PgConnection>) -> MyResult<Vec<DbArticle>> {
|
pub fn search(query: &str, conn: &Mutex<PgConnection>) -> MyResult<Vec<Self>> {
|
||||||
let mut conn = conn.lock().unwrap();
|
let mut conn = conn.lock().unwrap();
|
||||||
let replaced = query
|
let replaced = query
|
||||||
.replace('%', "\\%")
|
.replace('%', "\\%")
|
||||||
|
@ -135,10 +135,16 @@ impl DbArticle {
|
||||||
.get_results(conn.deref_mut())?)
|
.get_results(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: shouldnt have to read all edits from db
|
|
||||||
pub fn latest_edit_version(&self, conn: &Mutex<PgConnection>) -> MyResult<EditVersion> {
|
pub fn latest_edit_version(&self, conn: &Mutex<PgConnection>) -> MyResult<EditVersion> {
|
||||||
let edits: Vec<DbEdit> = DbEdit::read_for_article(self, conn)?;
|
let mut conn = conn.lock().unwrap();
|
||||||
match edits.last().map(|e| e.hash.clone()) {
|
let latest_version: Option<EditVersion> = edit::table
|
||||||
|
.filter(edit::dsl::article_id.eq(self.id))
|
||||||
|
.order_by(edit::dsl::id.desc())
|
||||||
|
.limit(1)
|
||||||
|
.select(edit::dsl::hash)
|
||||||
|
.get_result(conn.deref_mut())
|
||||||
|
.ok();
|
||||||
|
match latest_version {
|
||||||
Some(latest_version) => Ok(latest_version),
|
Some(latest_version) => Ok(latest_version),
|
||||||
None => Ok(EditVersion::default()),
|
None => Ok(EditVersion::default()),
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ impl DbConflict {
|
||||||
.values(form)
|
.values(form)
|
||||||
.get_result(conn.deref_mut())?)
|
.get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list(conn: &Mutex<PgConnection>) -> MyResult<Vec<Self>> {
|
pub fn list(conn: &Mutex<PgConnection>) -> MyResult<Vec<Self>> {
|
||||||
let mut conn = conn.lock().unwrap();
|
let mut conn = conn.lock().unwrap();
|
||||||
Ok(conflict::table.get_results(conn.deref_mut())?)
|
Ok(conflict::table.get_results(conn.deref_mut())?)
|
||||||
|
@ -60,7 +61,6 @@ impl DbConflict {
|
||||||
/// Delete a merge conflict after it is resolved.
|
/// Delete a merge conflict after it is resolved.
|
||||||
pub fn delete(id: EditVersion, conn: &Mutex<PgConnection>) -> MyResult<Self> {
|
pub fn delete(id: EditVersion, conn: &Mutex<PgConnection>) -> MyResult<Self> {
|
||||||
let mut conn = conn.lock().unwrap();
|
let mut conn = conn.lock().unwrap();
|
||||||
// TODO: should throw error on invalid id param
|
|
||||||
Ok(delete(conflict::table.find(id)).get_result(conn.deref_mut())?)
|
Ok(delete(conflict::table.find(id)).get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,7 @@ impl DbEdit {
|
||||||
.set(form)
|
.set(form)
|
||||||
.get_result(conn.deref_mut())?)
|
.get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(version: &EditVersion, conn: &Mutex<PgConnection>) -> MyResult<Self> {
|
pub fn read(version: &EditVersion, conn: &Mutex<PgConnection>) -> MyResult<Self> {
|
||||||
let mut conn = conn.lock().unwrap();
|
let mut conn = conn.lock().unwrap();
|
||||||
Ok(edit::table
|
Ok(edit::table
|
||||||
|
@ -86,6 +87,13 @@ impl DbEdit {
|
||||||
.get_result(conn.deref_mut())?)
|
.get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn read_from_ap_id(ap_id: &ObjectId<DbEdit>, conn: &Mutex<PgConnection>) -> MyResult<Self> {
|
||||||
|
let mut conn = conn.lock().unwrap();
|
||||||
|
Ok(edit::table
|
||||||
|
.filter(edit::dsl::ap_id.eq(ap_id))
|
||||||
|
.get_result(conn.deref_mut())?)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn read_for_article(
|
pub fn read_for_article(
|
||||||
article: &DbArticle,
|
article: &DbArticle,
|
||||||
conn: &Mutex<PgConnection>,
|
conn: &Mutex<PgConnection>,
|
||||||
|
|
|
@ -1,14 +1,10 @@
|
||||||
use crate::database::schema::{instance, instance_follow};
|
use crate::database::schema::{instance, instance_follow};
|
||||||
use crate::database::MyDataHandle;
|
use crate::database::MyDataHandle;
|
||||||
use crate::error::{Error, MyResult};
|
use crate::error::MyResult;
|
||||||
|
|
||||||
use crate::federation::objects::articles_collection::DbArticleCollection;
|
use crate::federation::objects::articles_collection::DbArticleCollection;
|
||||||
use activitypub_federation::activity_sending::SendActivityTask;
|
|
||||||
use activitypub_federation::config::Data;
|
use activitypub_federation::config::Data;
|
||||||
use activitypub_federation::fetch::collection_id::CollectionId;
|
use activitypub_federation::fetch::collection_id::CollectionId;
|
||||||
use activitypub_federation::fetch::object_id::ObjectId;
|
use activitypub_federation::fetch::object_id::ObjectId;
|
||||||
use activitypub_federation::protocol::context::WithContext;
|
|
||||||
use activitypub_federation::traits::ActivityHandler;
|
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use diesel::ExpressionMethods;
|
use diesel::ExpressionMethods;
|
||||||
use diesel::{
|
use diesel::{
|
||||||
|
@ -19,8 +15,6 @@ use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use tracing::warn;
|
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Queryable, Selectable, Identifiable)]
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Queryable, Selectable, Identifiable)]
|
||||||
#[diesel(table_name = instance, check_for_backend(diesel::pg::Pg))]
|
#[diesel(table_name = instance, check_for_backend(diesel::pg::Pg))]
|
||||||
|
@ -59,62 +53,6 @@ pub struct InstanceView {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DbInstance {
|
impl DbInstance {
|
||||||
pub fn followers_url(&self) -> MyResult<Url> {
|
|
||||||
Ok(Url::parse(&format!("{}/followers", self.ap_id.inner()))?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn follower_ids(&self, data: &Data<MyDataHandle>) -> MyResult<Vec<Url>> {
|
|
||||||
Ok(DbInstance::read_followers(self.id, &data.db_connection)?
|
|
||||||
.into_iter()
|
|
||||||
.map(|f| f.ap_id.into())
|
|
||||||
.collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn send_to_followers<Activity>(
|
|
||||||
&self,
|
|
||||||
activity: Activity,
|
|
||||||
extra_recipients: Vec<DbInstance>,
|
|
||||||
data: &Data<MyDataHandle>,
|
|
||||||
) -> Result<(), <Activity as ActivityHandler>::Error>
|
|
||||||
where
|
|
||||||
Activity: ActivityHandler + Serialize + Debug + Send + Sync,
|
|
||||||
<Activity as ActivityHandler>::Error: From<activitypub_federation::error::Error>,
|
|
||||||
<Activity as ActivityHandler>::Error: From<Error>,
|
|
||||||
{
|
|
||||||
let mut inboxes: Vec<_> = DbInstance::read_followers(self.id, &data.db_connection)?
|
|
||||||
.iter()
|
|
||||||
.map(|f| Url::parse(&f.inbox_url).unwrap())
|
|
||||||
.collect();
|
|
||||||
inboxes.extend(
|
|
||||||
extra_recipients
|
|
||||||
.into_iter()
|
|
||||||
.map(|i| Url::parse(&i.inbox_url).unwrap()),
|
|
||||||
);
|
|
||||||
self.send(activity, inboxes, data).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn send<Activity>(
|
|
||||||
&self,
|
|
||||||
activity: Activity,
|
|
||||||
recipients: Vec<Url>,
|
|
||||||
data: &Data<MyDataHandle>,
|
|
||||||
) -> Result<(), <Activity as ActivityHandler>::Error>
|
|
||||||
where
|
|
||||||
Activity: ActivityHandler + Serialize + Debug + Send + Sync,
|
|
||||||
<Activity as ActivityHandler>::Error: From<activitypub_federation::error::Error>,
|
|
||||||
{
|
|
||||||
let activity = WithContext::new_default(activity);
|
|
||||||
let sends = SendActivityTask::prepare(&activity, self, recipients, data).await?;
|
|
||||||
for send in sends {
|
|
||||||
let send = send.sign_and_send(data).await;
|
|
||||||
if let Err(e) = send {
|
|
||||||
warn!("Failed to send activity {:?}: {e}", activity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create(form: &DbInstanceForm, conn: &Mutex<PgConnection>) -> MyResult<Self> {
|
pub fn create(form: &DbInstanceForm, conn: &Mutex<PgConnection>) -> MyResult<Self> {
|
||||||
let mut conn = conn.lock().unwrap();
|
let mut conn = conn.lock().unwrap();
|
||||||
Ok(insert_into(instance::table)
|
Ok(insert_into(instance::table)
|
||||||
|
|
|
@ -33,10 +33,10 @@ impl Object for DbEdit {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
async fn read_from_id(
|
async fn read_from_id(
|
||||||
_object_id: Url,
|
object_id: Url,
|
||||||
_data: &Data<Self::DataType>,
|
data: &Data<Self::DataType>,
|
||||||
) -> Result<Option<Self>, Self::Error> {
|
) -> Result<Option<Self>, Self::Error> {
|
||||||
todo!()
|
Ok(DbEdit::read_from_ap_id(&object_id.into(), data).ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn into_json(self, data: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
|
async fn into_json(self, data: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
use crate::database::instance::{DbInstance, DbInstanceForm};
|
use crate::database::instance::{DbInstance, DbInstanceForm};
|
||||||
use crate::database::MyDataHandle;
|
use crate::database::MyDataHandle;
|
||||||
use crate::error::Error;
|
use crate::error::{Error, MyResult};
|
||||||
use crate::federation::objects::articles_collection::DbArticleCollection;
|
use crate::federation::objects::articles_collection::DbArticleCollection;
|
||||||
|
use activitypub_federation::activity_sending::SendActivityTask;
|
||||||
use activitypub_federation::fetch::collection_id::CollectionId;
|
use activitypub_federation::fetch::collection_id::CollectionId;
|
||||||
use activitypub_federation::kinds::actor::ServiceType;
|
use activitypub_federation::kinds::actor::ServiceType;
|
||||||
|
use activitypub_federation::protocol::context::WithContext;
|
||||||
|
use activitypub_federation::traits::ActivityHandler;
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
config::Data,
|
config::Data,
|
||||||
fetch::object_id::ObjectId,
|
fetch::object_id::ObjectId,
|
||||||
|
@ -13,6 +16,7 @@ use activitypub_federation::{
|
||||||
use chrono::{DateTime, Local, Utc};
|
use chrono::{DateTime, Local, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use tracing::log::warn;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
@ -26,6 +30,64 @@ pub struct ApubInstance {
|
||||||
public_key: PublicKey,
|
public_key: PublicKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DbInstance {
|
||||||
|
pub fn followers_url(&self) -> MyResult<Url> {
|
||||||
|
Ok(Url::parse(&format!("{}/followers", self.ap_id.inner()))?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn follower_ids(&self, data: &Data<MyDataHandle>) -> MyResult<Vec<Url>> {
|
||||||
|
Ok(DbInstance::read_followers(self.id, &data.db_connection)?
|
||||||
|
.into_iter()
|
||||||
|
.map(|f| f.ap_id.into())
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send_to_followers<Activity>(
|
||||||
|
&self,
|
||||||
|
activity: Activity,
|
||||||
|
extra_recipients: Vec<DbInstance>,
|
||||||
|
data: &Data<MyDataHandle>,
|
||||||
|
) -> Result<(), <Activity as ActivityHandler>::Error>
|
||||||
|
where
|
||||||
|
Activity: ActivityHandler + Serialize + Debug + Send + Sync,
|
||||||
|
<Activity as ActivityHandler>::Error: From<activitypub_federation::error::Error>,
|
||||||
|
<Activity as ActivityHandler>::Error: From<Error>,
|
||||||
|
{
|
||||||
|
let mut inboxes: Vec<_> = DbInstance::read_followers(self.id, &data.db_connection)?
|
||||||
|
.iter()
|
||||||
|
.map(|f| Url::parse(&f.inbox_url).unwrap())
|
||||||
|
.collect();
|
||||||
|
inboxes.extend(
|
||||||
|
extra_recipients
|
||||||
|
.into_iter()
|
||||||
|
.map(|i| Url::parse(&i.inbox_url).unwrap()),
|
||||||
|
);
|
||||||
|
self.send(activity, inboxes, data).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send<Activity>(
|
||||||
|
&self,
|
||||||
|
activity: Activity,
|
||||||
|
recipients: Vec<Url>,
|
||||||
|
data: &Data<MyDataHandle>,
|
||||||
|
) -> Result<(), <Activity as ActivityHandler>::Error>
|
||||||
|
where
|
||||||
|
Activity: ActivityHandler + Serialize + Debug + Send + Sync,
|
||||||
|
<Activity as ActivityHandler>::Error: From<activitypub_federation::error::Error>,
|
||||||
|
{
|
||||||
|
let activity = WithContext::new_default(activity);
|
||||||
|
let sends = SendActivityTask::prepare(&activity, self, recipients, data).await?;
|
||||||
|
for send in sends {
|
||||||
|
let send = send.sign_and_send(data).await;
|
||||||
|
if let Err(e) = send {
|
||||||
|
warn!("Failed to send activity {:?}: {e}", activity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl Object for DbInstance {
|
impl Object for DbInstance {
|
||||||
type DataType = MyDataHandle;
|
type DataType = MyDataHandle;
|
||||||
|
|
51
src/utils.rs
51
src/utils.rs
|
@ -37,3 +37,54 @@ pub fn generate_article_version(edits: &Vec<DbEdit>, version: &EditVersion) -> M
|
||||||
}
|
}
|
||||||
Err(anyhow!("failed to generate article version").into())
|
Err(anyhow!("failed to generate article version").into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use activitypub_federation::fetch::object_id::ObjectId;
|
||||||
|
use diffy::create_patch;
|
||||||
|
|
||||||
|
fn create_edits() -> MyResult<Vec<DbEdit>> {
|
||||||
|
let generate_edit = |a, b| -> MyResult<DbEdit> {
|
||||||
|
let diff = create_patch(a, b).to_string();
|
||||||
|
Ok(DbEdit {
|
||||||
|
id: 0,
|
||||||
|
hash: EditVersion::new(&diff)?,
|
||||||
|
ap_id: ObjectId::parse("http://example.com")?,
|
||||||
|
diff,
|
||||||
|
article_id: 0,
|
||||||
|
previous_version_id: Default::default(),
|
||||||
|
})
|
||||||
|
};
|
||||||
|
Ok([
|
||||||
|
generate_edit("", "test\n")?,
|
||||||
|
generate_edit("test\n", "sda\n")?,
|
||||||
|
generate_edit("sda\n", "123\n")?,
|
||||||
|
]
|
||||||
|
.to_vec())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_generate_article_version() -> MyResult<()> {
|
||||||
|
let edits = create_edits()?;
|
||||||
|
let generated = generate_article_version(&edits, &edits[1].hash)?;
|
||||||
|
assert_eq!("sda\n", generated);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_generate_invalid_version() -> MyResult<()> {
|
||||||
|
let edits = create_edits()?;
|
||||||
|
let generated = generate_article_version(&edits, &EditVersion::new("invalid")?);
|
||||||
|
assert!(generated.is_err());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_generate_first_version() -> MyResult<()> {
|
||||||
|
let edits = create_edits()?;
|
||||||
|
let generated = generate_article_version(&edits, &EditVersion::default())?;
|
||||||
|
assert_eq!("", generated);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ use fediwiki::database::instance::{DbInstance, InstanceView};
|
||||||
use pretty_assertions::{assert_eq, assert_ne};
|
use pretty_assertions::{assert_eq, assert_ne};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
// TODO: can run tests in parallel if we use different ports
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_create_read_and_edit_article() -> MyResult<()> {
|
async fn test_create_read_and_edit_article() -> MyResult<()> {
|
||||||
let data = TestData::start();
|
let data = TestData::start();
|
||||||
|
@ -354,8 +353,7 @@ async fn test_federated_edit_conflict() -> MyResult<()> {
|
||||||
};
|
};
|
||||||
let edit_res = edit_article(&data.gamma.hostname, &edit_form).await?;
|
let edit_res = edit_article(&data.gamma.hostname, &edit_form).await?;
|
||||||
assert_ne!(edit_form.new_text, edit_res.article.text);
|
assert_ne!(edit_form.new_text, edit_res.article.text);
|
||||||
// TODO
|
assert_eq!(1, edit_res.edits.len());
|
||||||
//assert_eq!(2, edit_res.edits.len());
|
|
||||||
assert!(!edit_res.article.local);
|
assert!(!edit_res.article.local);
|
||||||
|
|
||||||
let conflicts: Vec<ApiConflict> =
|
let conflicts: Vec<ApiConflict> =
|
||||||
|
|
Loading…
Reference in a new issue