Skip to content

Commit

Permalink
✅ Increase signIn() test coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreMiras committed Dec 4, 2024
1 parent 817afa6 commit 4682a25
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 16 deletions.
60 changes: 59 additions & 1 deletion src/library.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { strict as assert } from "assert";
import axios from "axios";
import sinon from "sinon";

import { configure } from "../src/library";
import { configure, createAuthService } from "../src/library";

describe("library", () => {
let axiosStub: sinon.SinonStub;
Expand All @@ -19,6 +19,64 @@ describe("library", () => {
sinon.restore();
});

describe("signIn", () => {
it("should sign in and return the JWT token", async () => {
const expectedUsername = "testuser";
const expectedPassword = "testpassword";
const expectedToken = "mockJwtToken";
const signIn = sinon.stub().resolves({ isSignedIn: true });
const signOut = sinon.stub();
const fetchAuthSession = sinon.stub().resolves({
tokens: {
accessToken: { toString: () => expectedToken },
},
});
const authStub = {
signIn,
signOut,
fetchAuthSession,
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const authService = createAuthService(authStub as any);
const token = await authService.signIn(
expectedUsername,
expectedPassword
);
assert.deepEqual(authStub.signOut.args, [[]]);
assert.deepEqual(signIn.args, [
[{ username: expectedUsername, password: expectedPassword }],
]);
assert.equal(token, expectedToken);
});

it("should throw an error if sign-in fails", async () => {
const expectedUsername = "testuser";
const expectedPassword = "testpassword";
const expectedToken = "mockJwtToken";
const signIn = sinon.stub().resolves({ isSignedIn: false });
const signOut = sinon.stub();
const fetchAuthSession = sinon.stub().resolves({
tokens: {
accessToken: { toString: () => expectedToken },
},
});
const authStub = {
signIn,
signOut,
fetchAuthSession,
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const authService = createAuthService(authStub as any);
await assert.rejects(
async () => authService.signIn(expectedUsername, expectedPassword),
{
name: "AssertionError",
message: "Sign-in failed",
}
);
});
});

describe("configure", () => {
it("should create API methods with the correct baseURL", () => {
const baseURL = "https://example.com/api";
Expand Down
52 changes: 37 additions & 15 deletions src/library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,54 @@ const amplifyconfiguration = {
aws_user_pools_web_client_id: "7sc1qltkqobo3ddqsk4542dg2h",
};

/**
* Generates headers with a JWT token for authenticated requests.
* @param {string} jwtToken - The JWT token for authorization.
* @returns {object} - The headers object with the Authorization field.
*/
const headers = (jwtToken: string) => ({ Authorization: `Bearer ${jwtToken}` });

/**
* Configures Amplify if not already configured.
* Ensures the configuration is only applied once.
*/
const configureAmplify = () => {
const currentConfig = Amplify.getConfig();
if (Object.keys(currentConfig).length !== 0) return;
Amplify.configure(amplifyconfiguration);
};

/**
* Sign in to return the JWT token.
* Creates an authentication service with sign-in functionality.
* @param {typeof amplifyAuth} auth - The authentication module to use.
* @returns {object} - An object containing authentication-related methods.
*/
const signIn = async (username: string, password: string): Promise<string> => {
configureAmplify();
// in case the user is already signed in, refs:
// https://github.com/aws-amplify/amplify-js/issues/13813
await amplifyAuth.signOut();
const { isSignedIn } = await amplifyAuth.signIn({
username,
password,
});
assert.ok(isSignedIn);
const { tokens } = await amplifyAuth.fetchAuthSession();
assert.ok(tokens);
return tokens.accessToken.toString();
const createAuthService = (auth: typeof amplifyAuth) => {
/**
* Signs in a user with the provided credentials.
* @param {string} username - The username of the user.
* @param {string} password - The password of the user.
* @returns {Promise<string>} - The JWT token of the signed-in user.
* @throws {Error} - If sign-in fails or no tokens are retrieved.
*/
const signIn = async (
username: string,
password: string
): Promise<string> => {
configureAmplify();
await auth.signOut(); // Ensure the user is signed out first
const { isSignedIn } = await auth.signIn({ username, password });
assert.ok(isSignedIn, "Sign-in failed");
const { tokens } = await auth.fetchAuthSession();
assert.ok(tokens, "No tokens found");
return tokens.accessToken.toString();
};
return { signIn };
};

// Create the default auth service using amplifyAuth
const { signIn } = createAuthService(amplifyAuth);

const deviceInfo =
(axiosInstance: AxiosInstance) => (jwtToken: string, macAddress: string) =>
axiosInstance.get<DeviceInfoType>(`device/${macAddress}/info`, {
Expand Down Expand Up @@ -80,4 +102,4 @@ const configure = (baseURL: string = API_URL) => {
};
};

export { configure, signIn };
export { configure, createAuthService, headers, signIn };

0 comments on commit 4682a25

Please sign in to comment.