diff --git src/bp-groups/bp-groups-functions.php src/bp-groups/bp-groups-functions.php
index 8b19738..283392b 100644
--- src/bp-groups/bp-groups-functions.php
+++ src/bp-groups/bp-groups-functions.php
@@ -431,8 +431,7 @@ function groups_leave_group( $group_id, $user_id = 0 ) {
 		}
 	}
 
-	// This is exactly the same as deleting an invite, just is_confirmed = 1 NOT 0.
-	if ( !groups_uninvite_user( $user_id, $group_id ) ) {
+	if ( ! groups_remove_member( $user_id, $group_id ) ) {
 		return false;
 	}
 
@@ -1401,8 +1400,16 @@ function groups_unban_member( $user_id, $group_id ) {
  */
 function groups_remove_member( $user_id, $group_id ) {
 
-	if ( ! bp_is_item_admin() )
-		return false;
+	if ( ! bp_is_item_admin() ) {
+ 		// bp_is_item_admin may not be set if this function is called outside of group context.
+ 		// Site admins and group admins can remove a member from a group.
+ 		// A member may also request to remove herself from a group.
+ 		if ( ! current_user_can( 'bp_moderate' )
+ 			&& ! groups_is_user_admin( bp_loggedin_user_id(), $group_id )
+ 			&& $user_id != bp_loggedin_user_id() ) {
+ 				return false;
+ 			}
+ 	}
 
 	$member = new BP_Groups_Member( $user_id, $group_id );
 
diff --git tests/phpunit/testcases/groups/class-bp-groups-member.php tests/phpunit/testcases/groups/class-bp-groups-member.php
index 135303f..0855b83 100644
--- tests/phpunit/testcases/groups/class-bp-groups-member.php
+++ tests/phpunit/testcases/groups/class-bp-groups-member.php
@@ -513,4 +513,193 @@ class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase {
 		$u1_has_request = groups_check_for_membership_request( $u1, $g );
 		$this->assertTrue( is_numeric( $u1_has_request ) && $u1_has_request > 0 );
 	}
+
+	/**
+	 * @group groups_join_group
+	 */
+	public function test_groups_join_group_basic_join() {
+		$u1 = $this->factory->user->create();
+		$g = $this->factory->group->create();
+
+		groups_join_group( $g, $u1 );
+		$membership_id = groups_is_user_member( $u1, $g );
+		$this->assertTrue( is_numeric( $membership_id ) && $membership_id > 0 );
+	}
+
+	/**
+	 * @group groups_join_group
+	 */
+	public function test_groups_join_group_basic_join_use_current_user() {
+		$u1 = $this->factory->user->create();
+		$g = $this->factory->group->create();
+		$old_current_user = get_current_user_id();
+		$this->set_current_user( $u1 );
+
+		groups_join_group( $g );
+		$membership_id = groups_is_user_member( $u1, $g );
+		$this->assertTrue( is_numeric( $membership_id ) && $membership_id > 0 );
+		$this->set_current_user( $old_current_user );
+	}
+
+	/**
+	 * @group groups_join_group
+	 */
+	public function test_groups_join_group_already_member() {
+		$u1 = $this->factory->user->create();
+		$g = $this->factory->group->create();
+		$this->add_user_to_group( $u1, $g );
+
+		$this->assertTrue( groups_join_group( $g, $u1 ) );
+	}
+
+	/**
+	 * @group groups_join_group
+	 */
+	public function test_groups_join_group_cleanup_invites() {
+		$u1 = $this->factory->user->create();
+		$u2 = $this->factory->user->create();
+		$g = $this->factory->group->create();
+		$this->add_user_to_group( $u1, $g );
+
+		$m1 = new BP_Groups_Member( $u1, $g );
+		$m1->promote( 'admin' );
+
+		self::invite_user_to_group( $u2, $g, $u1 );
+
+		groups_join_group( $g, $u2 );
+		// Upon joining the group, outstanding invitations should be cleaned up.
+		$this->assertEquals( null, groups_check_user_has_invite( $u2, $g, 'any' ) );
+	}
+
+	/**
+	 * @group groups_join_group
+	 */
+	public function test_groups_join_group_cleanup_requests() {
+		$u1 = $this->factory->user->create();
+		$g = $this->factory->group->create();
+		self::create_group_membership_request( $u1, $g );
+
+		groups_join_group( $g, $u1 );
+		// Upon joining the group, outstanding requests should be cleaned up.
+		$this->assertEquals( null, groups_check_for_membership_request( $u1, $g ) );
+	}
+
+	/**
+	 * @group groups_leave_group
+	 */
+	public function test_groups_leave_group_basic_leave_self_initiated() {
+		$old_current_user = get_current_user_id();
+		$u1 = $this->factory->user->create();
+		$g = $this->factory->group->create( array( 'creator_id' => $u1 ) );
+		$u2 = $this->factory->user->create();
+		$this->add_user_to_group( $u2, $g );
+
+		$before = groups_get_total_member_count( $g );
+		$this->set_current_user( $u2 );
+		groups_leave_group( $g, $u2 );
+		$after = groups_get_total_member_count( $g );
+
+		$this->assertEquals( $before - 1, $after );
+		$this->set_current_user( $old_current_user );
+	}
+
+	/**
+	 * @group groups_leave_group
+	 */
+	public function test_groups_leave_group_basic_leave_use_current_user() {
+		$old_current_user = get_current_user_id();
+		$u1 = $this->factory->user->create();
+		$g = $this->factory->group->create( array( 'creator_id' => $u1 ) );
+		$u2 = $this->factory->user->create();
+		$this->add_user_to_group( $u2, $g );
+
+		$before = groups_get_total_member_count( $g );
+		$this->set_current_user( $u2 );
+		groups_leave_group( $g );
+		$after = groups_get_total_member_count( $g );
+
+		$this->assertEquals( $before - 1, $after );
+		$this->set_current_user( $old_current_user );
+	}
+
+	/**
+	 * @group groups_leave_group
+	 */
+	public function test_groups_leave_group_basic_leave_group_admin_initiated() {
+		$old_current_user = get_current_user_id();
+		$u1 = $this->factory->user->create();
+		$g = $this->factory->group->create( array( 'creator_id' => $u1 ) );
+		$u2 = $this->factory->user->create();
+		$this->add_user_to_group( $u2, $g );
+
+		$before = groups_get_total_member_count( $g );
+		$this->set_current_user( $u1 );
+		groups_leave_group( $g, $u2 );
+		$after = groups_get_total_member_count( $g );
+
+		$this->assertEquals( $before - 1, $after );
+		$this->set_current_user( $old_current_user );
+	}
+
+	/**
+	 * @group groups_leave_group
+	 */
+	public function test_groups_leave_group_basic_leave_site_admin_initiated() {
+		$old_current_user = get_current_user_id();
+		$u1 = $this->factory->user->create();
+		$u1_siteadmin = new WP_User( $u1 );
+		$u1_siteadmin->add_role( 'administrator' );
+		$g = $this->factory->group->create( array( 'creator_id' => $u1 ) );
+		$u2 = $this->factory->user->create();
+		$this->add_user_to_group( $u2, $g );
+
+		$before = groups_get_total_member_count( $g );
+		$this->set_current_user( $u1 );
+		groups_leave_group( $g, $u2 );
+		$after = groups_get_total_member_count( $g );
+
+		$this->assertEquals( $before - 1, $after );
+		$this->set_current_user( $old_current_user );
+	}
+
+
+	/**
+	 * @group groups_leave_group
+	 */
+	public function test_groups_leave_group_single_admin_prevent_leave() {
+		$old_current_user = get_current_user_id();
+		$u1 = $this->factory->user->create();
+		$g = $this->factory->group->create( array( 'creator_id' => $u1 ) );
+		$u2 = $this->factory->user->create();
+		$this->add_user_to_group( $u2, $g );
+
+		$before = groups_get_total_member_count( $g );
+		$this->set_current_user( $u1 );
+		groups_leave_group( $g, $u1 );
+		$after = groups_get_total_member_count( $g );
+
+		$this->assertEquals( $before, $after );
+		$this->set_current_user( $old_current_user );
+	}
+
+	/**
+	 * @group groups_leave_group
+	 */
+	public function test_groups_leave_group_multiple_admins_allow_leave() {
+		$old_current_user = get_current_user_id();
+		$u1 = $this->factory->user->create();
+		$g = $this->factory->group->create( array( 'creator_id' => $u1 ) );
+		$u2 = $this->factory->user->create();
+		$this->add_user_to_group( $u2, $g );
+		$m2 = new BP_Groups_Member( $u2, $g );
+		$m2->promote( 'admin' );
+
+		$before = groups_get_total_member_count( $g );
+		$this->set_current_user( $u1 );
+		groups_leave_group( $g, $u1 );
+		$after = groups_get_total_member_count( $g );
+
+		$this->assertEquals( $before - 1, $after );
+		$this->set_current_user( $old_current_user );
+	}
 }
\ No newline at end of file
diff --git tests/phpunit/testcases/groups/functions.php tests/phpunit/testcases/groups/functions.php
index 04953c5..f73766b 100644
--- tests/phpunit/testcases/groups/functions.php
+++ tests/phpunit/testcases/groups/functions.php
@@ -37,10 +37,10 @@ class BP_Tests_Groups_Functions extends BP_UnitTestCase {
 		groups_join_group( $g1, $u2 );
 		groups_join_group( $g2, $u2 );
 
-		// Test fails because of the change in groups_uninvite_user.
-		// @TODO: restore once groups_leave_group is fixed.
+		// Set the current user so the leave group request goes through.
+		$this->set_current_user( $u2 );
 		groups_leave_group( $g1, $u2 );
-		// $this->assertEquals( 1, bp_get_user_meta( $u2, 'total_group_count', true ) );
+		$this->assertEquals( 1, bp_get_user_meta( $u2, 'total_group_count', true ) );
 	}
 
 	/**
