Browse Source

fix(member invite): update error message to be more helpful (#80924)

https://github.com/user-attachments/assets/c721b94e-d2e1-4604-a3d9-9c2dabf65422

Previously, the error message said "This organization invite link is no
longer valid," regardless of the error that triggered it. However, this
could be confusing if the error was NOT caused by an expired invitation
(for example, if the user is signed into an account that is already a
member of the inviting org). Update the error message to be more
helpful; see screen recording.
Michelle Fu 3 months ago
parent
commit
ad4ef9eaed

+ 21 - 0
static/app/views/acceptOrganizationInvite/index.spec.tsx

@@ -100,6 +100,27 @@ describe('AcceptOrganizationInvite', function () {
     expect(browserHistory.replace).toHaveBeenCalledWith('/org-slug/');
   });
 
+  it('renders error message', function () {
+    MockApiClient.addMockResponse({
+      url: '/accept-invite/1/abc/',
+      method: 'GET',
+      statusCode: 400,
+      body: {detail: 'uh oh'},
+    });
+
+    render(
+      <AcceptOrganizationInvite
+        {...RouteComponentPropsFixture()}
+        params={{memberId: '1', token: 'abc'}}
+      />
+    );
+    expect(getJoinButton()).not.toBeInTheDocument();
+
+    expect(
+      screen.getByRole('link', {name: 'sign in with a different account'})
+    ).toBeInTheDocument();
+  });
+
   it('requires authentication to join', function () {
     addMock({
       orgSlug: organization.slug,

+ 25 - 1
static/app/views/acceptOrganizationInvite/index.tsx

@@ -65,6 +65,12 @@ class AcceptOrganizationInvite extends DeprecatedAsyncView<Props, State> {
     logout(this.api);
   };
 
+  handleLogoutAndRetry = (e: React.MouseEvent) => {
+    const {memberId, token} = this.props.params;
+    e.preventDefault();
+    logout(this.api, `/accept/${memberId}/${token}/`);
+  };
+
   handleAcceptInvite = async () => {
     const {memberId, token} = this.props.params;
 
@@ -249,10 +255,28 @@ class AcceptOrganizationInvite extends DeprecatedAsyncView<Props, State> {
   }
 
   renderError() {
+    /**
+     * NOTE (mifu67): this error view could show up for multiple reasons, including:
+     * invite link expired, signed into account that is already in the inviting
+     * org, and invite not approved. Previously, the message seemed to indivate that
+     * the link had expired, regardless of which error prompted it, so update the
+     * error message to be a little more helpful.
+     */
     return (
       <NarrowLayout>
         <Alert type="warning">
-          {t('This organization invite link is no longer valid.')}
+          {tct(
+            'This organization invite link is invalid. It may be expired, or you may need to [switchLink:sign in with a different account].',
+            {
+              switchLink: (
+                <Link
+                  to=""
+                  data-test-id="existing-member-link"
+                  onClick={this.handleLogoutAndRetry}
+                />
+              ),
+            }
+          )}
         </Alert>
       </NarrowLayout>
     );