Skip to content

Commit

Permalink
refactor: Refactor authentication test suite for clarity
Browse files Browse the repository at this point in the history
- Refactor auth.test.ts for improved code quality and readability
- Update setupServer scope in describe block
- Streamline test process and assertions in auth test file
  • Loading branch information
johnnyhuy committed Jul 28, 2024
1 parent 651acf7 commit 3ef56a5
Showing 1 changed file with 42 additions and 108 deletions.
150 changes: 42 additions & 108 deletions packages/backend/src/auth.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
/* eslint-disable @typescript-eslint/no-shadow */
import request from 'supertest';
import { decodeOAuthState } from '@backstage/plugin-auth-node';
import { setupServer } from 'msw/node';
import { http, HttpResponse } from 'msw';
import {
Expand All @@ -11,61 +9,48 @@ import {
import { Server } from 'http';
import { githubAuth } from './auth';

let accessToken: string;

const githubApiUrl = 'https://api.github.com';
const githubAuthUrl = 'https://github.com/login/oauth';
describe('githubAuth', () => {
let server: Server;
let baseUrl: string;

const mockGithubAuth = setupServer(
// Mock GitHub's OAuth endpoints
http.get('https://github.com/login/oauth/authorize', params => {
const url = new URL(params.request.url);
const callbackUrl = new URL(url.searchParams.get('redirect_uri')!);
callbackUrl.searchParams.set('code', 'github_auth_code');
callbackUrl.searchParams.set('state', url.searchParams.get('state')!);
return HttpResponse.redirect(callbackUrl.toString());
}),

http.post('https://github.com/login/oauth/access_token', () => {
return HttpResponse.json({
access_token: 'github_access_token',
token_type: 'bearer',
scope: 'read:user',
});
}),

const handlers = [
http.get(`${githubAuthUrl}/authorize`, ({ request }) => {
const url = new URL(request.url);
const callbackUrl = new URL(url.searchParams.get('redirect_uri')!);
callbackUrl.searchParams.set('code', 'github_auth_code');
callbackUrl.searchParams.set('state', url.searchParams.get('state')!);
return HttpResponse.json(null, {
status: 302,
headers: {
location: callbackUrl.toString(),
},
});
}),
http.post(`${githubAuthUrl}/access_token`, () => {
accessToken = 'github_access_token';
return HttpResponse.json({
access_token: accessToken,
token_type: 'bearer',
scope: 'read:user',
});
}),
http.get(`${githubApiUrl}/user`, ({ request }) => {
if (request.headers.get('Authorization') === `token ${accessToken}`) {
http.get('https://api.github.com/user', () => {
return HttpResponse.json({
login: 'octocat',
name: 'Octocat',
email: 'octocat@github.com',
avatar_url: 'https://github.com/images/error/octocat_happy.gif',
});
}
return new HttpResponse(null, { status: 401 });
}),
];
}),
);

const mswServer = setupServer(...handlers);
registerMswTestHooks(mswServer);

describe('githubAuth', () => {
let backstageServer: Server;
let appUrl: string;
registerMswTestHooks(mockGithubAuth);

beforeAll(async () => {
mswServer.listen();
const backend = await startTestBackend({
features: [
githubAuth,
import('@backstage/plugin-auth-backend'),
mockServices.rootConfig.factory({
data: {
app: { baseUrl: 'http://localhost' },
app: { baseUrl: 'http://localhost:3000' },
auth: {
providers: {
github: {
Expand All @@ -81,86 +66,35 @@ describe('githubAuth', () => {
],
});

backstageServer = backend.server;
const port = backend.server.port();
appUrl = `http://localhost:${port}`;
});

beforeEach(async () => {
jest.clearAllMocks();
});

afterEach(() => {
mswServer.resetHandlers();
server = backend.server;
baseUrl = `http://localhost:${backend.server.port()}`;
mockGithubAuth.listen();
});

afterAll(() => {
backstageServer.close();
mswServer.close();
});

it('should start the GitHub auth flow', async () => {
// Arrange
const agent = request.agent(backstageServer);

// Act
const startResponse = await agent.get(
'/api/auth/github/start?env=development',
);
const startUrl = new URL(startResponse.get('location')!);
const expected = Object.fromEntries(startUrl.searchParams);
const state = decodeOAuthState(startUrl.searchParams.get('state')!);

// Assert
expect(startResponse.status).toEqual(302);
expect(startUrl.origin).toBe('https://github.com');
expect(startUrl.pathname).toBe('/login/oauth/authorize');
expect(expected).toEqual({
client_id: 'github-client-id',
redirect_uri: `${appUrl}/api/auth/github/handler/frame`,
response_type: 'code',
scope: 'read:user',
state: expect.any(String),
});
expect(state.env).toEqual('development');
expect(state.nonce).toBeDefined();
expect(state.scope).toEqual('read:user');
server.close();
});

it('should complete the GitHub auth flow', async () => {
const agent = request.agent(backstageServer);

// Start the auth flow
const startResponse = await agent.get(
'/api/auth/github/start?env=development',
);
expect(startResponse.status).toBe(302);
const test = await agent.get(
'/api/auth/github/handler/frame?code=github_auth_code&state=6e6f6e63653d70595572584f37374363597a786f57414c2532465042325125334425334426656e763d646576656c6f706d656e742673636f70653d7265616425334175736572',
);
expect(test.text).toContain('test');
expect(startResponse.status).toBe(302);

const startUrl = new URL(startResponse.get('location')!);
const state = startUrl.searchParams.get('state')!;
const decodedState = decodeOAuthState(state);
const nonce = decodedState.nonce;
const startResponse = await request(server)
.get('/api/auth/github/start?env=development')
.expect(302);

// Set the nonce cookie
agent.jar.setCookie(`github-nonce=${nonce}; Path=/; HttpOnly`);
const startUrl = new URL(startResponse.header.location);
expect(startUrl.searchParams.get('response_type')).not.toBeNull();
expect(startUrl.searchParams.get('redirect_uri')).not.toBeNull();

// Simulate the OAuth callback
const callbackUrl = new URL(`${appUrl}/api/auth/github/handler/frame`);
const callbackUrl = new URL('/api/auth/github/handler/frame', baseUrl);
callbackUrl.searchParams.set('env', 'development');
callbackUrl.searchParams.set('code', 'github_auth_code');
callbackUrl.searchParams.set('state', state);
callbackUrl.searchParams.set('state', 'mock_state');

const handlerResponse = await agent.get(
callbackUrl.href.replace(callbackUrl.origin, ''),
const handlerResponse = await request(server).get(
callbackUrl.pathname + callbackUrl.search,
);
expect(handlerResponse.status).toBe(200);

expect(handlerResponse.text).toContain(
encodeURIComponent(`"accessToken":"${accessToken}"`),
);
expect(handlerResponse.status).toBe(200);
});
});

0 comments on commit 3ef56a5

Please sign in to comment.