Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve login error handling #794

Merged
merged 1 commit into from
Apr 20, 2022
Merged

Improve login error handling #794

merged 1 commit into from
Apr 20, 2022

Conversation

JacobMGEvans
Copy link
Contributor

@JacobMGEvans JacobMGEvans commented Apr 13, 2022

Error messaging from failed login would dump a JSON.parse error in some situations. Added a fallback if .json fails to parse it will attempt .text() then throw result. If both attempts to parse fail it will throw an UnknownError with a message showing where it originated.
resolves #539

@changeset-bot
Copy link

changeset-bot bot commented Apr 13, 2022

🦋 Changeset detected

Latest commit: 0dd05c9

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
wrangler Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Contributor

github-actions bot commented Apr 13, 2022

A wrangler prerelease is available for testing. You can install this latest build in your project with:

npm install --save-dev https://prerelease-registry.developers.workers.dev/runs/2196591553/npm-package-wrangler-794

You can reference the automatically updated head of this PR with:

npm install --save-dev https://prerelease-registry.developers.workers.dev/prs/794/npm-package-wrangler-794

Or you can use npx with this latest build directly:

npx https://prerelease-registry.developers.workers.dev/runs/2196591553/npm-package-wrangler-794 dev path/to/script.js

@JacobMGEvans JacobMGEvans changed the title Improve Login Error Handling Improve login error handling Apr 13, 2022
@threepointone
Copy link
Contributor

This probably deserves a test.

@JacobMGEvans
Copy link
Contributor Author

This probably deserves a test.

That's fair 😅

@JacobMGEvans
Copy link
Contributor Author

At a lost on how to test this particular function. Will come back to it.

@@ -48,6 +51,25 @@ describe("wrangler", () => {
expiration_time: expect.any(String),
});
});

it.only("should confirm error message and output for failed login", async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

forgot to remove the .only here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch


if (tokenExhangeResErr !== undefined) {
// We will throw the parsed error if it parsed correctly, otherwise we throw an unknown error.
throw tokenExhangeResErr;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
throw tokenExhangeResErr;
throw typeof tokenExhangeResErr === 'string' ? new Error(tokenExhangeResErr): tokenExhangeResErr;

@petebacondarwin
Copy link
Contributor

I think you need to make this change to get the test not to hang (and to pass):

diff --git a/packages/wrangler/src/__tests__/user.test.ts b/packages/wrangler/src/__tests__/user.test.ts
index b043048..3d8edb7 100644
--- a/packages/wrangler/src/__tests__/user.test.ts
+++ b/packages/wrangler/src/__tests__/user.test.ts
@@ -54,23 +54,19 @@ describe("wrangler", () => {
       });
     });
 
-    it.only("should confirm error message and output for failed login", async () => {
-      const accessTokenRequest = mockGrantAccessToken({ respondWith: "ok" });
+    it("should confirm error message and output for failed login", async () => {
+      mockOAuthServerCallback();
+      mockGrantAccessToken({ respondWith: "ok" });
       mockGrantAuthorization({ respondWith: "failure" });
 
       await runWrangler("login");
 
-      expect(accessTokenRequest.actual.url).toEqual("");
-      expect(accessTokenRequest.actual.method).toEqual("");
-
-      expect(std.out).toMatchInlineSnapshot(``);
-
-      expect(readAuthConfigFile()).toEqual<UserAuthConfig>({
-        api_token: undefined,
-        oauth_token: "test-access-token",
-        refresh_token: "test-refresh-token",
-        expiration_time: expect.any(String),
-      });
+      expect(std.out).toMatchInlineSnapshot(`
+        "Attempting to login via OAuth...
+        Error: Consent denied. You must grant consent to Wrangler in order to login.
+        If you don't want to do this consider passing an API token via the \`CLOUDFLARE_API_TOKEN\` environment variable"
+      `);
+      expect(std.warn).toMatchInlineSnapshot(`""`);
     });
   });

@JacobMGEvans
Copy link
Contributor Author

I think you need to make this change to get the test not to hang (and to pass):

diff --git a/packages/wrangler/src/__tests__/user.test.ts b/packages/wrangler/src/__tests__/user.test.ts
index b043048..3d8edb7 100644
--- a/packages/wrangler/src/__tests__/user.test.ts
+++ b/packages/wrangler/src/__tests__/user.test.ts
@@ -54,23 +54,19 @@ describe("wrangler", () => {
       });
     });
 
-    it.only("should confirm error message and output for failed login", async () => {
-      const accessTokenRequest = mockGrantAccessToken({ respondWith: "ok" });
+    it("should confirm error message and output for failed login", async () => {
+      mockOAuthServerCallback();
+      mockGrantAccessToken({ respondWith: "ok" });
       mockGrantAuthorization({ respondWith: "failure" });
 
       await runWrangler("login");
 
-      expect(accessTokenRequest.actual.url).toEqual("");
-      expect(accessTokenRequest.actual.method).toEqual("");
-
-      expect(std.out).toMatchInlineSnapshot(``);
-
-      expect(readAuthConfigFile()).toEqual<UserAuthConfig>({
-        api_token: undefined,
-        oauth_token: "test-access-token",
-        refresh_token: "test-refresh-token",
-        expiration_time: expect.any(String),
-      });
+      expect(std.out).toMatchInlineSnapshot(`
+        "Attempting to login via OAuth...
+        Error: Consent denied. You must grant consent to Wrangler in order to login.
+        If you don't want to do this consider passing an API token via the \`CLOUDFLARE_API_TOKEN\` environment variable"
+      `);
+      expect(std.warn).toMatchInlineSnapshot(`""`);
     });
   });

@caass graciously helped me figure out how I caused hanging tests. It was silly workaround I was trying to make didn't play nicely with other pieces, now I am trying to mock the response for the token refresh to access function.

@JacobMGEvans JacobMGEvans force-pushed the error-message-login-fail branch 3 times, most recently from c7d3051 to ab4ef3b Compare April 19, 2022 21:30
respondWith: "badResponse",
});

await expect(requireAuth({} as Config, false)).rejects.toThrowError();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the tip on how to get this workaround to work @petebacondarwin

Copy link
Contributor

@petebacondarwin petebacondarwin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for driving this fix through @JacobMGEvans - not a simple part of the code base to test.

packages/wrangler/src/__tests__/helpers/mock-oauth-flow.ts Outdated Show resolved Hide resolved
.changeset/early-ducks-travel.md Outdated Show resolved Hide resolved
packages/wrangler/src/__tests__/user.test.ts Outdated Show resolved Hide resolved
packages/wrangler/src/user.tsx Outdated Show resolved Hide resolved
packages/wrangler/src/__tests__/user.test.ts Outdated Show resolved Hide resolved
});

await expect(requireAuth({} as Config, false)).rejects.toThrowError();
expect(std.err).toContain(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use toMatchInlineSnapshot() here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it breaks in different environments, the callstack is slightly different but the overall Error is the same

@JacobMGEvans JacobMGEvans force-pushed the error-message-login-fail branch 3 times, most recently from 04c5730 to 4af9ee0 Compare April 20, 2022 13:51
import type { UserAuthConfig } from "../user";

describe("wrangler", () => {
describe("User", () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User related tests

Copy link
Contributor

@petebacondarwin petebacondarwin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of NITs left in the tests.

packages/wrangler/src/__tests__/user.test.ts Outdated Show resolved Hide resolved
packages/wrangler/src/__tests__/user.test.ts Show resolved Hide resolved
…r in some situations. Added a fallback if `.json` fails to parse

it will attempt `.text()` then throw result. If both attempts to parse fail it will throw an `UnknownError` with a message showing where
it originated.

should resolve #539
@JacobMGEvans JacobMGEvans merged commit ee3475f into main Apr 20, 2022
@JacobMGEvans JacobMGEvans deleted the error-message-login-fail branch April 20, 2022 15:53
@github-actions github-actions bot mentioned this pull request Apr 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Improve error message when login fails
3 participants