diff --git a/og.module b/og.module
index c8ba0e0..acd8e9f 100644
--- a/og.module
+++ b/og.module
@@ -372,6 +372,39 @@ function og_is_group_member($gid, $include_admins = TRUE, $uid = NULL) {
 }
 
 /**
+ * Determine the moderated groups a user has petitioned to join.
+ *
+ * @param gid
+ *  An integer or a node object representing the group node.
+ * @param $uid
+ *   Pass a user id, or pass NULL in order to check current user.
+ * @param $reset
+ *   If TRUE, the cached user object (if any) will be reset for the given $uid
+ *   (or the current $user if $uid is NULL).
+ *
+ * @return
+ *  Whether the user is a pending member of the specified group. If no $gid is specified,
+ *  will return an array of all pending groups.
+ */
+function og_is_pending_member($gid = NULL, $uid = NULL, $reset = FALSE) {
+  static $pending;
+
+  if (!isset($uid)) {
+    $uid = $GLOBALS['user']->uid;
+  }
+
+  if (empty($pending[$uid]) || $reset) {
+    $pending[$uid] = array();
+    $groups = array_diff_assoc(og_get_subscriptions($nid, 0, $reset), og_get_subscriptions($nid, 1));
+    foreach ($groups as $group_nid => $group) {
+      $pending[$uid][$group_nid] = $group_nid;
+    }
+  }
+  return isset($gid) ? in_array($gid, $pending[$uid]) : $pending[$uid];
+}
+
+
+/**
   * Determine whether user can act as a group administrator for a given group.
   *
   * @param string $node
@@ -2398,9 +2431,18 @@ function og_block_details() {
   return array($txt, $subscription);
 }
 
+/**
+ * Create a link for user to subscribe to a group.
+ *
+ * @param $node
+ *  Pass the group node object.
+ */
 function og_subscribe_link($node) {
   if ($node->og_selective == OG_MODERATED) {
     $txt = t('Request membership');
+    if (og_is_pending_member($node->nid)) {
+      return t('Awaiting approval');
+    }
   }
   elseif ($node->og_selective == OG_OPEN) {
     $txt = t('Join');
diff --git a/og.pages.inc b/og.pages.inc
index 1dad843..de0da5d 100644
--- a/og.pages.inc
+++ b/og.pages.inc
@@ -317,17 +317,20 @@ function og_confirm_subscribe($form_state, $gid, $node, $account) {
       '#title' => t('Additional details'),
       '#description' => t('Add any detail which will help an administrator decide whether to approve or deny your membership request.')
     );
+    $submit_label = t('Request membership');
   }
   else {
     $form['request'] = array(
       '#type' => 'value',
       '#value' => '',
    );
+   $submit_label = t('Join');
  }
+
  return confirm_form($form,
                 t('Are you sure you want to join the group %title?', array('%title' => $node->title)),
                 'node/'. $node->nid, ' ',
-                t('Join'), t('Cancel'));
+                $submit_label, t('Cancel'));
 }
 
 /**
diff --git a/tests/og.subscribe.test b/tests/og.subscribe.test
index b3c2a66..1e5c25d 100644
--- a/tests/og.subscribe.test
+++ b/tests/og.subscribe.test
@@ -49,40 +49,128 @@ class OgSubscribe extends OgTestCase {
    */
   function testWebUserSubscribeOg() {
     $this->drupalLogin($this->web_user);
-    foreach ($this->selective as $key => $selective) {
-      // Get the join page.
-      $this->drupalGet('og/subscribe/'. $this->nodes[$key]->nid);
-      if ($key == 'open' || $key == 'moderated') {
-        $this->assertRaw(t('Are you sure you want to join the group %title?', array('%title' => $this->nodes[$key]->title)), t('Subscribe to @selective group text found.', array('@selective' => $key)));
-        // Click the join button.
-        $this->drupalPost(NULL, array(), t('Join'));
-        // Assert membership approval, waiting for approval text.
-        $this->assertRaw(t($key == 'open' ? 'You are now a member of %title.' : 'Membership request to the %title group awaits approval by an administrator.', array('%title' => $this->nodes[$key]->title)), t('Subscribed @selective group text found.', array('@selective' => $key)));
-        // Assert user is properly subscribed to open group.
-        if ($key == 'open') {
-          // Only in the 'open' group the web user is considered subscribed.
-          $this->assertTrue(array_key_exists($this->nodes[$key]->nid, og_get_subscriptions($this->web_user->uid, 1, TRUE)), t('Subscribed open group is loaded into user object.'));
-        }
 
-        // Unsubscribe a group.
-        $this->drupalGet('og/unsubscribe/'. $this->nodes[$key]->nid .'/'. $this->web_user->uid);
-        $this->assertRaw(t('Are you sure you want to leave the group %title?', array('%title' => $this->nodes[$key]->title)), t('Unsubscribe @selective group text found.', array('@selective' => $key)));
-
-        // Click the join button.
-        $this->drupalPost(NULL, array(), t('Leave'));
-        // Assert membership removal.
-        $this->assertRaw(t('You left the group %group.', array('%group' => $this->nodes[$key]->title)), t('Confirmation of unsubscribing @selective group text found.', array('@selective' => $key)));
-        // Assert user is properly removed to group.
-        if ($key == 'open') {
-          // Assert the group was removed from web user.
-          $this->assertFalse(array_key_exists($this->nodes[$key]->nid, og_get_subscriptions($this->web_user->uid, 1, TRUE)), t('Open group was removed from the og_uid table.'));
-        }
+    $cases = array();
+    $cases['open'] = array(
+      'join_button' => t('Join'),
+      'request_response' => t('You are now a member of %title.', array('%title' => $this->nodes['open']->title)),
+    );
+    $cases['moderated'] = array(
+      'join_button' => t('Request membership'),
+      'request_response' => t('Membership request to the %title group awaits approval by an administrator.', array('%title' => $this->nodes['moderated']->title)),
+    );
+    
+    foreach ($this->selective as $selective_id => $value) {
+      if (array_key_exists($selective_id, $cases)) {
+        $this->_testWebUserSubscribe($selective_id, $cases[$selective_id]);
+        $this->_testWebUserUnsubscribeOg($selective_id);
       }
       else {
         // Assert a 403 page is given.
-        $this->assertResponse(403, t('User got a 403 page while trying to access @selective group subscription.', array('@selective' => $key)));
+        $this->assertResponse(403, t('User got a 403 page while trying to access @selective group subscription.', array('@selective' => $selective_id)));
       }
     }
   }
 
+  /**
+   * Test current user subscription to a group.
+   */
+  protected function _testWebUserSubscribe($selective, $text) {
+    $node = $this->nodes[$selective];
+    // Get the subscription page.
+    $this->drupalGet('og/subscribe/' . $node->nid);
+
+    $this->assertRaw('Are you sure you want to join the group %title?',
+      array('%title' => $node->title),
+      t('Confirmation of subscribe to @selective group text found.',
+        array('@selective' => $selective))
+    );
+    // Click the join button.
+    $this->drupalPost(NULL, array(), $text['join_button']);
+    // Assert membership request response text.
+    $this->assertRaw($text['request_response'], t('Subscribed to @selective group text found.',
+      array('@selective' => $selective))
+    );
+    if ($selective == 'open') {
+      $this->assertOgMember($this->web_user, $node);
+    }
+    else {
+      $this->assertNotOgMember($this->web_user, $node);
+    }
+  }
+
+  /**
+   * Test user unsubscribed from a group.
+   */
+  protected function _testWebUserUnsubscribeOg($selective) {
+    $this->drupalGet('og/unsubscribe/'. $this->nodes[$selective]->nid .'/'. $this->web_user->uid);
+    $this->assertRaw(t('Are you sure you want to leave the group %title?', array('%title' => $this->nodes[$selective]->title)), t('Unsubscribe @selective group text found.', array('@selective' => $selective)));
+    // Click the join button.
+    $this->drupalPost(NULL, array(), t('Leave'));
+    // Assert membership removal.
+    $this->assertRaw(t('You left the group %group.', array('%group' => $this->nodes[$selective]->title)), t('Confirmation of unsubscribing @selective group text found.', array('@selective' => $selective)));
+    // Assert user is properly removed to group.
+    $this->assertNotOgMember($this->web_user, $this->nodes[$selective]);
+  }
+  
+  /**
+   * Assert the specified user is a member of the specified group.
+   *
+   * @param $account
+   *   User object.
+   * @param $group
+   *   Group node object.
+   *
+   * @return
+   *   TRUE if user is a group member.
+   */
+  protected function assertOgMember($account, $group) {
+    $vars = array(
+      '%user' => theme('username', $account),
+      '%group' => $group->title,
+      '@selective' => $group->og_selective,
+    );
+    $message = t('%user is a member of @selective group %group', $vars);
+    return $this->assertTrue(_checkOgMembershipStatus($account, $group), $message);
+  }
+
+  /**
+   * Assert the specified user is not a member of the specified group.
+   *
+   * @param $account
+   *   User object.
+   * @param $group
+   *   Group node object.
+   *
+   * @return
+   *   TRUE if user is not a group member.
+   */
+  protected function assertNotOgMember($account, $group) {
+    $vars = array(
+      '%user' => theme('username', $account),
+      '%group' => $group->title,
+      '@selective' => $group->og_selective,
+    );
+    $message = t('%user is not a member of @selective group %group', $vars);
+    return $this->assertFalse(_checkOgMembershipStatus($account, $group), $message);
+  }
+
+  /**
+   * Check the group membership status of the specified user.
+   *
+   * @param $account
+   *   User object.
+   * @param $group
+   *   Group node object.
+   *
+   * @return
+   *   TRUE if user is a group member.
+   *
+   * @todo
+   *   Find a smarter way to test for group membership. Perhaps dependent on
+   *   OG Views.
+   */
+  protected function _checkOgMembershipStatus($account, $group) {
+    return array_key_exists($group->nid, og_get_subscriptions($account->uid, 1, TRUE));
+  }
 }
