diff --git a/.woodpecker.yml b/.woodpecker.yml index f8f4eb5f3..46eb4c5d5 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -236,6 +236,7 @@ steps: - cd api_tests/ - pnpm i - pnpm api-test + - pnpm api-test # run twice to ensure they don't create state when: *slow_check_paths federation_tests_server_output: diff --git a/api_tests/src/follow.spec.ts b/api_tests/src/follow.spec.ts index 161c7f045..5e7f70e70 100644 --- a/api_tests/src/follow.spec.ts +++ b/api_tests/src/follow.spec.ts @@ -21,39 +21,36 @@ test("Follow local community", async () => { let user = await registerUser(beta, betaUrl); let community = (await resolveBetaCommunity(user)).community!; - expect(community.counts.subscribers).toBe(1); - expect(community.counts.subscribers_local).toBe(1); let follow = await followCommunity(user, true, community.community.id); // Make sure the follow response went through expect(follow.community_view.community.local).toBe(true); expect(follow.community_view.subscribed).toBe("Subscribed"); - expect(follow.community_view.counts.subscribers).toBe(2); - expect(follow.community_view.counts.subscribers_local).toBe(2); + expect(follow.community_view.counts.subscribers).toBe(community.counts.subscribers + 1); + expect(follow.community_view.counts.subscribers_local).toBe(community.counts.subscribers_local + 1); // Test an unfollow let unfollow = await followCommunity(user, false, community.community.id); expect(unfollow.community_view.subscribed).toBe("NotSubscribed"); - expect(unfollow.community_view.counts.subscribers).toBe(1); - expect(unfollow.community_view.counts.subscribers_local).toBe(1); + expect(unfollow.community_view.counts.subscribers).toBe(community.counts.subscribers); + expect(unfollow.community_view.counts.subscribers_local).toBe(community.counts.subscribers_local); }); test("Follow federated community", async () => { // It takes about 1 second for the community aggregates to federate - let betaCommunity = ( + const betaCommunityInitial = ( await waitUntil( () => resolveBetaCommunity(alpha), c => - c.community?.counts.subscribers === 1 && - c.community.counts.subscribers_local === 0, + !!c.community && (c.community?.counts.subscribers >= 1) ) ).community; - if (!betaCommunity) { + if (!betaCommunityInitial) { throw "Missing beta community"; } - let follow = await followCommunity(alpha, true, betaCommunity.community.id); + let follow = await followCommunity(alpha, true, betaCommunityInitial.community.id); expect(follow.community_view.subscribed).toBe("Pending"); - betaCommunity = ( + const betaCommunity = ( await waitUntil( () => resolveBetaCommunity(alpha), c => c.community?.subscribed === "Subscribed", @@ -64,20 +61,19 @@ test("Follow federated community", async () => { expect(betaCommunity?.community.local).toBe(false); expect(betaCommunity?.community.name).toBe("main"); expect(betaCommunity?.subscribed).toBe("Subscribed"); - expect(betaCommunity?.counts.subscribers_local).toBe(1); + expect(betaCommunity?.counts.subscribers_local).toBe(betaCommunityInitial.counts.subscribers_local + 1); // check that unfollow was federated let communityOnBeta1 = await resolveBetaCommunity(beta); - expect(communityOnBeta1.community?.counts.subscribers).toBe(2); - expect(communityOnBeta1.community?.counts.subscribers_local).toBe(1); + expect(communityOnBeta1.community?.counts.subscribers).toBe(betaCommunityInitial.counts.subscribers + 1); + expect(communityOnBeta1.community?.counts.subscribers_local).toBe(betaCommunityInitial.counts.subscribers_local); // Check it from local let site = await getSite(alpha); let remoteCommunityId = site.my_user?.follows.find( - c => c.community.local == false, + c => c.community.local == false && c.community.id === betaCommunityInitial.community.id, )?.community.id; expect(remoteCommunityId).toBeDefined(); - expect(site.my_user?.follows.length).toBe(2); if (!remoteCommunityId) { throw "Missing remote community id"; @@ -89,10 +85,10 @@ test("Follow federated community", async () => { // Make sure you are unsubbed locally let siteUnfollowCheck = await getSite(alpha); - expect(siteUnfollowCheck.my_user?.follows.length).toBe(1); + expect(siteUnfollowCheck.my_user?.follows.find(c => c.community.id === betaCommunityInitial.community.id)).toBe(undefined); // check that unfollow was federated - let communityOnBeta2 = await resolveBetaCommunity(beta); - expect(communityOnBeta2.community?.counts.subscribers).toBe(1); + let communityOnBeta2 = await waitUntil(() => resolveBetaCommunity(beta), c => c.community?.counts.subscribers === betaCommunityInitial.counts.subscribers); + expect(communityOnBeta2.community?.counts.subscribers).toBe(betaCommunityInitial.counts.subscribers); expect(communityOnBeta2.community?.counts.subscribers_local).toBe(1); }); diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index cb45274c6..f77dbb2ae 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -52,17 +52,19 @@ beforeAll(async () => { afterAll(unfollows); -async function assertPostFederation(postOne: PostView, postTwo: PostView) { +async function assertPostFederation(postOne: PostView, postTwo: PostView, waitForMeta = true) { // Link metadata is generated in background task and may not be ready yet at this time, // so wait for it explicitly. For removed posts we cant refetch anything. - postOne = await waitForPost(beta, postOne.post, res => { - return res === null || res?.post.embed_title !== null; - }); - postTwo = await waitForPost( - beta, - postTwo.post, - res => res === null || res?.post.embed_title !== null, - ); +if(waitForMeta) { + postOne = await waitForPost(beta, postOne.post, res => { + return res === null || !!res?.post.embed_title; + }); + postTwo = await waitForPost( + beta, + postTwo.post, + res => res === null || !!res?.post.embed_title, + ); + } expect(postOne?.post.ap_id).toBe(postTwo?.post.ap_id); expect(postOne?.post.name).toBe(postTwo?.post.name); @@ -408,7 +410,7 @@ test("Remove a post from admin and community on same instance", async () => { p => p?.post_view.post.removed ?? false, ); expect(alphaPost?.post_view.post.removed).toBe(true); - await assertPostFederation(alphaPost.post_view, removePostRes.post_view); + await assertPostFederation(alphaPost.post_view, removePostRes.post_view, false); // Undelete let undeletedPost = await removePost(beta, false, betaPost.post); diff --git a/api_tests/src/user.spec.ts b/api_tests/src/user.spec.ts index f44f3cc0a..302e0c0b0 100644 --- a/api_tests/src/user.spec.ts +++ b/api_tests/src/user.spec.ts @@ -130,7 +130,7 @@ test("Requests with invalid auth should be treated as unauthenticated", async () }); test("Create user with Arabic name", async () => { - let user = await registerUser(alpha, alphaUrl, "تجريب"); + let user = await registerUser(alpha, alphaUrl, "تجريب" + Math.random().toString().slice(2, 5)); let site = await getSite(user); expect(site.my_user).toBeDefined(); diff --git a/crates/federate/src/send.rs b/crates/federate/src/send.rs index 9658acf66..09fac10cc 100644 --- a/crates/federate/src/send.rs +++ b/crates/federate/src/send.rs @@ -26,7 +26,8 @@ impl PartialEq for SendSuccessInfo { self.activity_id == other.activity_id } } -/// order backwards because the binary heap is a max heap, and we need the smallest element to be on top +/// order backwards because the binary heap is a max heap, and we need the smallest element to be on +/// top impl PartialOrd for SendSuccessInfo { fn partial_cmp(&self, other: &Self) -> Option { other.activity_id.partial_cmp(&self.activity_id)