-
Notifications
You must be signed in to change notification settings - Fork 1
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
Feature/tas 8 helper methods for authentication #20
Changes from all commits
1e0644f
f89c9ca
653e62f
da9a6ce
9a2fd53
c389197
818124b
2f0d86b
0ad0c79
0925c37
a5f6fc1
839a882
d10f696
18427d3
f149598
08547f5
1033599
310c656
22a5305
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
name: Atlas 3.0 CI | ||
|
||
on: | ||
pull_request: | ||
branches: | ||
- main | ||
- epic/* | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
if: github.event.pull_request.draft == false | ||
|
||
env: | ||
VITE_IGNORE_MSW: false | ||
|
||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v4 | ||
|
||
- name: Setup NodeJS | ||
uses: actions/setup-node@v4 | ||
with: | ||
node-version: 20 | ||
cache: 'yarn' | ||
|
||
- name: Install dependencies | ||
run: yarn | ||
|
||
- name: Run Vitest | ||
run: yarn vitest |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
const BASE_URL = 'https://example.com/auth'; | ||
const LOGIN_URL = `${BASE_URL}/login`; | ||
const LOGOUT_URL = `${BASE_URL}/logout`; | ||
|
||
export const signIn = async (username: string, password: string): Promise<any> => { | ||
const response = await fetch(LOGIN_URL, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. need to set |
||
body: JSON.stringify({ username, password }), | ||
}); | ||
|
||
if (!response.ok) { | ||
throw new Error('Failed to sign in'); | ||
} | ||
|
||
return response.json(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should return response object and not json |
||
}; | ||
|
||
export const signOut = async (): Promise<void> => { | ||
const response = await fetch(LOGOUT_URL, { | ||
method: 'POST', | ||
}); | ||
|
||
if (!response.ok) { | ||
throw new Error('Failed to sign out'); | ||
} | ||
|
||
// Clear cookies on the client side | ||
document.cookie.split(';').forEach(cookie => { | ||
document.cookie = cookie.replace(/^ +/, '').replace(/=.*/, '=;expires=' + new Date().toUTCString() + ';path=/'); | ||
}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should return response too, in case sign out failed and errors can be handled |
||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
//src/mocks/authentication/auth_handlers.ts | ||
|
||
import { http, HttpResponse } from "msw" | ||
import resolveURL from "../../api/fetch"; | ||
|
||
|
||
export const mockCSRFToken: string = "SUPERSECRETCSRFTOKEN" | ||
export const mockUsername: string = "testuser" | ||
export const mockPassword: string = "mockpassword" | ||
|
||
export const auth_handlers = [ | ||
http.post(resolveURL("/auth/csrf"), () => { | ||
return new HttpResponse(null, { | ||
headers: { | ||
'Set-Cookie': mockCSRFToken | ||
} | ||
}) | ||
}), | ||
|
||
http.post(resolveURL("/auth/login"), async ({ cookies, request }) => { | ||
if (!cookies.csrfmiddlewaretoken) return new HttpResponse(null, {status: 403}) | ||
if (cookies.csrfmiddlewaretoken !== mockCSRFToken) return new HttpResponse(null, {status: 403}) | ||
|
||
const data = await request.formData() | ||
if (data.get("username") !== mockUsername || data.get("password") !== mockPassword) return new HttpResponse(null, {status: 403}) | ||
|
||
return new HttpResponse(null, { | ||
headers: { | ||
'Set-Cookie': mockCSRFToken | ||
} | ||
}) | ||
}) | ||
] |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
//src/mocks/handlers.ts | ||
|
||
import { http, HttpResponse } from "msw" | ||
import resolveURL from "../api/fetch.ts"; | ||
|
||
import { auth_handlers } from "./authentication/auth_handlers.ts"; | ||
|
||
|
||
const default_handlers = [ | ||
http.get(resolveURL('/resource'), () => { | ||
return HttpResponse.json({ | ||
result: "Hello World!" | ||
}) | ||
}) | ||
] | ||
|
||
|
||
export const handlers = [ | ||
...default_handlers, | ||
...auth_handlers | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { setupServer } from 'msw/node' | ||
import { handlers } from "./handlers"; | ||
|
||
|
||
export const server = setupServer(...handlers) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { setupWorker, SetupWorker } from "msw/browser" | ||
import { handlers } from "./handlers.ts" | ||
|
||
export const worker: SetupWorker = setupWorker(...handlers) | ||
|
||
worker.events.on("request:start", ({ request }) => { | ||
console.log('MSW intercepted: ', request.method, request.url) | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { describe, expect, test } from "vitest" | ||
import { getCSRF, signIn, signOut } from "../../src/api/authentication"; | ||
import { mockCSRFToken, mockUsername, mockPassword } from "../../src/mocks/authentication/auth_handlers"; | ||
|
||
describe("authentication helper functions", () => { | ||
|
||
test("should get csrf token", async () => { | ||
const response: Response = await getCSRF() | ||
expect(response.headers).toBe({ | ||
'Set-Cookie': mockCSRFToken | ||
}) | ||
}) | ||
|
||
test("should be able to sign in", async () => { | ||
const response = await signIn(mockUsername, mockPassword) | ||
expect(response.status).toBe(200) | ||
}) | ||
|
||
test("should be able to sign out", async () => { | ||
const response = await signOut() | ||
expect(response.status).toBe(200) | ||
}) | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import {beforeEach, describe, expect, test } from "vitest" | ||
import {render, screen} from "@testing-library/react" | ||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query" | ||
import App from "../src/App" | ||
|
||
const queryClient = new QueryClient() | ||
|
||
describe("Vitest Test", () => { | ||
|
||
beforeEach(() => { | ||
render(<QueryClientProvider client={queryClient}><App></App></QueryClientProvider>) | ||
}) | ||
|
||
test("Should show Hello World!", async () => { | ||
expect(await screen.findByText(/Hello World!/)).toBeDefined() | ||
}) | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,15 @@ | ||
/// <reference types="vitest" /> | ||
/// <reference types="vite/client" /> | ||
|
||
import { defineConfig } from 'vite' | ||
import react from '@vitejs/plugin-react' | ||
|
||
// https://vitejs.dev/config/ | ||
export default defineConfig({ | ||
plugins: [react()], | ||
test: { | ||
globals: true, | ||
environment: "jsdom", | ||
setupFiles: ["./vitest.setup.ts"] | ||
} | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { afterAll, afterEach, beforeAll } from 'vitest' | ||
import { server } from "./src/mocks/server" | ||
|
||
beforeAll(() => server.listen({ onUnhandledRequest: 'error' })) | ||
afterAll(() => server.close()) | ||
afterEach(() => server.resetHandlers()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use resolveURL function from
@/src/api/fetch