Skip to content

Commit

Permalink
Merge branch 'main' into DDFBRA-97-frontend-hent-konfig-objekt-fra-ba…
Browse files Browse the repository at this point in the history
…ckend-og-persister-i-applikationen
  • Loading branch information
spaceo committed Nov 23, 2024
2 parents 040681e + a067660 commit 362d10c
Show file tree
Hide file tree
Showing 38 changed files with 3,213 additions and 362 deletions.
5 changes: 2 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ NEXT_PUBLIC_LIBRARY_TOKEN=XXX

UNILOGIN_API_URL=https://et-broker.unilogin.dk
UNILOGIN_WELKNOWN_URL=https://et-broker.unilogin.dk/auth/realms/broker/.well-known/openid-configuration
UNILOGIN_REFRESH_TOKEN_URL=https://et-broker.unilogin.dk/auth/realms/broker/protocol/openid-connect/token
UNILOGIN_CLIENT_ID=https://stg.ereolengo.itkdev.dk/
UNILOGIN_CLIENT_SECRET=XXX
UNILOGIN_SESSION_SECRET=ZIKj+BiUbpitnDO8TeptXnQKsZmh2uGHMR1Wd4GplhE=
UNILOGIN_CLIENT_ID=https://stg.ereolengo.itkdev.dk/
UNILOGIN_CLIENT_SECRET=XXXX

NEXT_PUBLIC_APP_URL=https://localhost:3000
42 changes: 42 additions & 0 deletions .github/workflows/accessibility-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Workflow name
name: "Accessibility Test"

# Event for the workflow
on: push

# List of jobs
jobs:
# Run interaction and accessibility tests
accessibility:
name: Accessibility tests

runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4
# Make sure the actual branch is checked out when running on pull requests.
with:
ref: ${{ github.head_ref }}
fetch-depth: 0 # 👈 Required to retrieve git history

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc"

- name: Install dependencies
run: yarn

- name: Install Playwright
run: npx playwright install --with-deps

- name: Build Storybook
run: yarn build-storybook --quiet

- name: Serve Storybook and run tests
run: |
export FORCE_COLOR=1
npx concurrently -k -s first -n "SB,TEST" -c "magenta,blue" \
"npx http-server storybook-static --port 6006 --silent" \
"npx wait-on tcp:6006 && yarn test-storybook"
2 changes: 1 addition & 1 deletion .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ jobs:
run: yarn install --frozen-lockfile

- name: Run unit tests
run: yarn test:unit
run: yarn test:unit:once
1 change: 1 addition & 0 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const config: StorybookConfig = {
"@storybook/addon-essentials",
"@chromatic-com/storybook",
"@storybook/addon-interactions",
"@storybook/addon-a11y",
],
framework: {
name: "@storybook/nextjs",
Expand Down
17 changes: 17 additions & 0 deletions .storybook/test-runner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { checkA11y, injectAxe } from "axe-playwright"

module.exports = {
async preVisit(page) {
await injectAxe(page)
},
async postVisit(page) {
await checkA11y(page, "#storybook-root", {
axeOptions: {},
detailedReport: true,
detailedReportOptions: {
html: true,
},
verbose: true,
})
},
}
163 changes: 82 additions & 81 deletions __tests__/refresh-token.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { add } from "date-fns"
import { IronSession, getIronSession } from "iron-session"
import { testApiHandler } from "next-test-api-route-handler"
import { afterAll, beforeAll, beforeEach, expect, test, vi } from "vitest"
import { afterAll, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"

// @ts-ignore
import * as tokenRefreshHandler from "@/app/auth/token/refresh/route"
Expand Down Expand Up @@ -41,93 +41,94 @@ const sessionThatShouldBeRefreshed = () => ({
id_token: "id",
})

// TODO: Enable this when the refresh endpoint is fixed after latest API changes.
test.skip("That the refresh endpoint redirects to the frontpage if there is no active session", async () => {
// Simulate an anonymous session.
// @ts-ignore
getIronSession.mockResolvedValue({
isLoggedIn: false,
})
// TODO: This should be activated when the refresh token logic is fully implemented.
describe.skip("Refresh token test suite", () => {
test("That the refresh endpoint redirects to the frontpage if there is no active session", async () => {
// Simulate an anonymous session.
// @ts-ignore
getIronSession.mockResolvedValue({
isLoggedIn: false,
})

await testApiHandler({
appHandler: tokenRefreshHandler,
url: `/?redirect=http://john.johnson.com/john`,
async test({ fetch }) {
const res = await fetch({ method: "GET" })
expect(res.headers.get("location")).toEqual("https://hellboy.the-movie.com/")
},
await testApiHandler({
appHandler: tokenRefreshHandler,
url: `/?redirect=http://john.johnson.com/john`,
async test({ fetch }) {
const res = await fetch({ method: "GET" })
expect(res.headers.get("location")).toEqual("https://hellboy.the-movie.com/")
},
})
})
})

// TODO: Enable this when the refresh endpoint is fixed after latest API changes.
test.skip("That the refresh endpoint redirects to the given endpoint after refreshing token", async () => {
// This is an authorized session that should be refreshed.
// @ts-ignore
getIronSession.mockResolvedValue(sessionThatShouldBeRefreshed())
test("That the refresh endpoint redirects to the given endpoint after refreshing token", async () => {
// This is an authorized session that should be refreshed.
// @ts-ignore
getIronSession.mockResolvedValue(sessionThatShouldBeRefreshed())

await testApiHandler({
appHandler: tokenRefreshHandler,
url: `/?redirect=http://john.johnson.com/john`,
async test({ fetch }) {
const res = await fetch({ method: "GET" })
expect(res.headers.get("location")).toEqual("http://john.johnson.com/john")
},
})
await testApiHandler({
appHandler: tokenRefreshHandler,
url: `/?redirect=http://john.johnson.com/john`,
async test({ fetch }) {
const res = await fetch({ method: "GET" })
expect(res.headers.get("location")).toEqual("http://john.johnson.com/john")
},
})

// This is an authorized session that should NOT be refreshed.
// @ts-ignore
getIronSession.mockResolvedValue({
isLoggedIn: true,
expires: add(new Date(), { seconds: 300 }),
refresh_expires: add(new Date(), { seconds: 1800 }),
access_token: "access_token",
refresh_token: "refresh",
// This is an authorized session that should NOT be refreshed.
// @ts-ignore
getIronSession.mockResolvedValue({
isLoggedIn: true,
expires: add(new Date(), { seconds: 300 }),
refresh_expires: add(new Date(), { seconds: 1800 }),
access_token: "access_token",
refresh_token: "refresh",
})
})
})

// TODO: Write tests that proves that the session object is updated correctly after a successful refresh.
// TODO: Enable this when the refresh endpoint is fixed after latest API changes.
test.skip("That the refreshValidation validates if the access token should be refreshed correctly", async () => {
// Since there is a buffer of 1 minute added to the refresh time,
// the access token should be refreshed 1 minute before it expires.
expect(
accessTokenShouldBeRefreshed({
type: "unilogin",
expires: add(new Date(), { seconds: 59 }),
refresh_expires: add(new Date(), { seconds: 59 }),
isLoggedIn: true,
} as IronSession<TSessionData>)
).toBe(true)
// TODO: Write tests that proves that the session object is updated correctly after a successful refresh.

// Since there is a buffer of 1 minute added to the refresh time,
// the access token should be refreshed 1 minute before it expires.
// The tipping point in this case is the 60th second.
expect(
accessTokenShouldBeRefreshed({
type: "unilogin",
expires: add(new Date(), { seconds: 60 }),
refresh_expires: add(new Date(), { seconds: 60 }),
isLoggedIn: true,
} as IronSession<TSessionData>)
).toBe(false)
test("That the refreshValidation validates if the access token should be refreshed correctly", async () => {
// Since there is a buffer of 1 minute added to the refresh time,
// the access token should be refreshed 1 minute before it expires.
expect(
accessTokenShouldBeRefreshed({
type: "unilogin",
expires: add(new Date(), { seconds: 59 }),
refresh_expires: add(new Date(), { seconds: 59 }),
isLoggedIn: true,
} as IronSession<TSessionData>)
).toBe(true)

// The refresh logic looks at both expires and refresh_expires.
// Here the expires is the tipping point.
expect(
accessTokenShouldBeRefreshed({
type: "unilogin",
expires: add(new Date(), { seconds: 59 }),
refresh_expires: add(new Date(), { seconds: 1800 }),
isLoggedIn: true,
} as IronSession<TSessionData>)
).toBe(true)
// Here the refresh_expires is the tipping point.
expect(
accessTokenShouldBeRefreshed({
type: "unilogin",
expires: add(new Date(), { seconds: 300 }),
refresh_expires: add(new Date(), { seconds: 59 }),
isLoggedIn: true,
} as IronSession<TSessionData>)
).toBe(true)
// Since there is a buffer of 1 minute added to the refresh time,
// the access token should be refreshed 1 minute before it expires.
// The tipping point in this case is the 60th second.
expect(
accessTokenShouldBeRefreshed({
type: "unilogin",
expires: add(new Date(), { seconds: 60 }),
refresh_expires: add(new Date(), { seconds: 60 }),
isLoggedIn: true,
} as IronSession<TSessionData>)
).toBe(false)

// The refresh logic looks at both expires and refresh_expires.
// Here the expires is the tipping point.
expect(
accessTokenShouldBeRefreshed({
type: "unilogin",
expires: add(new Date(), { seconds: 59 }),
refresh_expires: add(new Date(), { seconds: 1800 }),
isLoggedIn: true,
} as IronSession<TSessionData>)
).toBe(true)
// Here the refresh_expires is the tipping point.
expect(
accessTokenShouldBeRefreshed({
type: "unilogin",
expires: add(new Date(), { seconds: 300 }),
refresh_expires: add(new Date(), { seconds: 59 }),
isLoggedIn: true,
} as IronSession<TSessionData>)
).toBe(true)
})
})
6 changes: 3 additions & 3 deletions __tests__/url.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { expect, test, vi } from "vitest"
import { expect, test } from "vitest"

import { resolveUrl } from "../lib/helpers/helper.routes"

test("That resolveUrl can return a work url", async () => {
const workUrl = resolveUrl({ type: "work", routeParams: { id: 123 } })
const workUrl = resolveUrl({ type: "work", routeParams: { wid: 123 } })
expect(workUrl).toBe("/work/123")
})

test("That resolveUrl can return a work url with a manifestation type", async () => {
const workUrl = resolveUrl({
type: "work",
routeParams: { id: 123 },
routeParams: { wid: 123 },
queryParams: { audio: "true" },
})
expect(workUrl).toBe("/work/123?audio=true")
Expand Down
Loading

0 comments on commit 362d10c

Please sign in to comment.