Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ jobs:
run: yarn workspace main build

javascript-tests:
if: false #TODO
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
Expand Down Expand Up @@ -146,6 +145,7 @@ jobs:
run: yarn run lint-check

- name: Typecheck
if: false # To be reinstated. Anything actually used in `main` is typecheck during build
run: yarn run typecheck

- name: Get number of CPU cores
Expand All @@ -164,7 +164,6 @@ jobs:
file: coverage/lcov.info

build-storybook:
if: false #TODO
runs-on: ubuntu-latest
steps:
- name: Checkout
Expand Down
7 changes: 0 additions & 7 deletions frontends/api/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,6 @@ const config: Config.InitialOptions = {
...baseConfig.setupFilesAfterEnv,
"./test-utils/setupJest.ts",
],
globals: {
APP_SETTINGS: {
MITOL_AXIOS_WITH_CREDENTIALS: false,
MITOL_API_BASE_URL: "https://api.test.learn.mit.edu",
CSRF_COOKIE_NAME: "csrftoken-test",
},
},
}

export default config
102 changes: 102 additions & 0 deletions frontends/api/src/test-utils/mock-requests-example.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import axiosBase from "axios"
import { setMockResponse } from "./mockAxios"
import { ControlledPromise, allowConsoleErrors } from "ol-test-utilities"

const axios = axiosBase.create()

describe("request mocking", () => {
test("mocking specific responses and spying", async () => {
setMockResponse.post(
"/some-example",
{ someResponseKey: "response for request with {a:5}" },
{ requestBody: expect.objectContaining({ a: 5 }) },
)
setMockResponse.post(
"/some-example",
{ someResponseKey: "response for request with {b:10}" },
{ requestBody: expect.objectContaining({ b: 10 }) },
)
setMockResponse.post(
"/some-example",
{ someResponseKey: "fallback post response" },
// if 3rd arg is undefined, the response (2nd arg) will be used for all unmatched request bodies
)

setMockResponse.patch("/another-example", { someResponseKey: "patched!" })

const r0 = await axios.post("/some-example", { dog: "woof" })
const r1 = await axios.patch("/another-example", { dog: "bark bark" })
const r2 = await axios.post("/some-example", { baby: "sleep", b: 10 })
const r3 = await axios.post("/some-example", { cat: "meow", a: 5 })

// toHaveBeenNthCalledWith is 1-indexed
expect(axios.post).toHaveBeenNthCalledWith(1, "/some-example", {
dog: "woof",
})
expect(axios.patch).toHaveBeenNthCalledWith(1, "/another-example", {
dog: "bark bark",
})
expect(axios.post).toHaveBeenNthCalledWith(2, "/some-example", {
baby: "sleep",
b: 10,
})
expect(axios.post).toHaveBeenNthCalledWith(3, "/some-example", {
cat: "meow",
a: 5,
})

expect(r0.data).toEqual({ someResponseKey: "fallback post response" })
expect(r1.data).toEqual({ someResponseKey: "patched!" })
expect(r2.data).toEqual({
someResponseKey: "response for request with {b:10}",
})
expect(r3.data).toEqual({
someResponseKey: "response for request with {a:5}",
})
})

test("Error codes reject", async () => {
setMockResponse.post("/some-example", "Bad request", { code: 400 })
await expect(axios.post("/some-example", { a: 5 })).rejects.toEqual(
expect.objectContaining({
response: { data: "Bad request", status: 400 },
}),
)
})

test("Errors if mock value is not set.", async () => {
const { consoleError } = allowConsoleErrors()
expect(consoleError).not.toHaveBeenCalled()
let error: Error | null = null
try {
await axios.post("/some-example", { dog: "woof" })
} catch (err) {
error = err as Error
}
expect(error?.message).toBe("No response specified for post /some-example")
expect(consoleError).toHaveBeenCalledWith(
"No response specified for post /some-example",
)
})

test("Manually resolving a response", async () => {
const responseBody = new ControlledPromise<number>()
setMockResponse.get("/respond-when-i-say", responseBody)
const response = axios.get("/respond-when-i-say")
let responseStatus = "pending"
response.then(() => {
responseStatus = "resolved"
})

await Promise.resolve() // flush the event queue
expect(responseStatus).toBe("pending") // response is still pending
responseBody.resolve(37)
expect(await response).toEqual(
expect.objectContaining({
data: 37,
status: 200,
}),
)
expect(responseStatus).toBe("resolved")
})
})
2 changes: 1 addition & 1 deletion frontends/api/src/test-utils/urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import type {
import type { BaseAPI } from "../generated/v1/base"
import type { BaseAPI as BaseAPIv0 } from "../generated/v0/base"

const { MITOL_API_BASE_URL: API_BASE_URL } = APP_SETTINGS
const API_BASE_URL = process.env.NEXT_PUBLIC_MITOL_API_BASE_URL

// OpenAPI Generator declares parameters using interfaces, which makes passing
// them to functions a little annoying.
Expand Down
11 changes: 11 additions & 0 deletions frontends/jest-shared-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import * as matchers from "jest-extended"

expect.extend(matchers)

// env vars
process.env.NEXT_PUBLIC_MITOL_API_BASE_URL =
"http://api.test.learn.odl.local:8063"

// Pulled from the docs - see https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom

Object.defineProperty(window, "matchMedia", {
Expand Down Expand Up @@ -71,6 +75,13 @@ configure({
},
})

jest.mock("next/navigation", () => {
return {
...jest.requireActual("ol-test-utilities/mocks/nextNavigation")
.nextNavigationMocks,
}
})

afterEach(() => {
/**
* Clear all mock call counts between tests.
Expand Down
27 changes: 0 additions & 27 deletions frontends/main/jest.config.ts

This file was deleted.

5 changes: 2 additions & 3 deletions frontends/main/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
"react": "^18",
"react-dom": "^18",
"react-slick": "^0.30.2",
"sharp": "^0.33.4",
"slick-carousel": "^1.8.1",
"tiny-invariant": "^1.3.3",
"yup": "^1.4.0"
Expand All @@ -39,8 +38,8 @@
"@types/jest": "^29.5.12",
"@types/lodash": "^4.17.7",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"@types/react": "^18.3.5",
"@types/react-dom": "^18.3.0",
"@types/react-slick": "^0.23.13",
"@types/slick-carousel": "^1",
"eslint": "8.57.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ const AUTH_TEXT_DATA = {
text: "As a member, get personalized recommendations, curate learning lists, and follow your areas of interest.",
linkProps: {
children: "Sign Up for Free",
reloadDocument: true,
rawAnchor: true,
href: urls.login({
pathname: urls.DASHBOARD_HOME,
}),
Expand Down
2 changes: 1 addition & 1 deletion frontends/main/src/page-components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ const SearchButton: FunctionComponent = () => {
<ActionButtonLink
edge="circular"
variant="text"
reloadDocument={true}
rawAnchor={true}
href={SEARCH}
aria-label="Search"
>
Expand Down
4 changes: 2 additions & 2 deletions frontends/main/src/page-components/Header/UserMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ const UserMenu: React.FC<UserMenuProps> = ({ variant }) => {
<ButtonLink
data-testid="login-button-desktop"
size="small"
reloadDocument={true}
rawAnchor={true}
href={loginUrl}
>
Log In
Expand All @@ -177,7 +177,7 @@ const UserMenu: React.FC<UserMenuProps> = ({ variant }) => {
data-testid="login-button-mobile"
edge="circular"
variant="text"
reloadDocument={true}
rawAnchor={true}
href={loginUrl}
aria-label="Log in"
>
Expand Down
26 changes: 0 additions & 26 deletions frontends/mit-learn/jest.config.ts

This file was deleted.

1 change: 1 addition & 0 deletions frontends/ol-ckeditor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"ol-utilities": "0.0.0"
},
"devDependencies": {
"@faker-js/faker": "^8.0.0",
"@testing-library/react": "16.0.1"
}
}
11 changes: 8 additions & 3 deletions frontends/ol-ckeditor/src/components/cloudServices.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import getCloudServicesConfig from "./cloudServices"
import axios from "axios"
import { faker } from "@faker-js/faker/locale/en"

jest.mock("axios")

describe("cloudServicesConfig", () => {
const uploadUrl = faker.internet.url()
beforeAll(() => {
process.env.NEXT_PUBLIC_CKEDITOR_UPLOAD_URL = uploadUrl
})

test("tokenUrl queries correct API", async () => {
const cloud = getCloudServicesConfig()
const mockGet = axios.get as jest.Mock
Expand All @@ -12,9 +18,8 @@ describe("cloudServicesConfig", () => {
expect(token).toBe("the-cool-token")
})

test("CKEDITOR_UPLOAD_URL is set from global APP_SETTINGS", () => {
APP_SETTINGS.CKEDITOR_UPLOAD_URL = "https://meowmeow.com"
test("CKEDITOR_UPLOAD_URL is set from env", () => {
const cloud = getCloudServicesConfig()
expect(cloud.uploadUrl).toBe("https://meowmeow.com")
expect(cloud.uploadUrl).toBe(uploadUrl)
})
})
2 changes: 1 addition & 1 deletion frontends/ol-ckeditor/src/components/cloudServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import axios from "axios"

const cloudServicesConfig = () =>
({
uploadUrl: APP_SETTINGS.CKEDITOR_UPLOAD_URL,
uploadUrl: process.env.NEXT_PUBLIC_CKEDITOR_UPLOAD_URL,
tokenUrl: async () => {
const { data } = await axios.get("/api/v0/ckeditor/")
return data.token as string
Expand Down
27 changes: 13 additions & 14 deletions frontends/ol-components/.storybook/main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { resolve, join, dirname } from "path"
import * as dotenv from "dotenv"
import * as webpack from "webpack"
import { StorybookConfig } from '@storybook/nextjs';
import { StorybookConfig } from "@storybook/nextjs"

dotenv.config({ path: resolve(__dirname, "../../../.env") })

Expand All @@ -28,12 +28,12 @@ const config: StorybookConfig = {
getAbsolutePath("@storybook/addon-essentials"),
getAbsolutePath("@storybook/addon-interactions"),
getAbsolutePath("@storybook/addon-webpack5-compiler-swc"),
getAbsolutePath("@storybook/addon-mdx-gfm")
getAbsolutePath("@storybook/addon-mdx-gfm"),
],

framework: {
framework: {
name: getAbsolutePath("@storybook/nextjs"),
options: {}
options: {},
},

docs: {},
Expand All @@ -48,7 +48,6 @@ const config: StorybookConfig = {
}),
)


/* Fix for this error:
Module not found: Error: Can't resolve 'react-dom/test-utils' in './node_modules/@testing-library/react/dist/@testing-library'

Expand All @@ -60,20 +59,20 @@ const config: StorybookConfig = {
We should not use @storybook packages in ol-test-utilities or anywhere outside of ol-components as they are not related
so below we are aliasing @testing-library/react.
*/
config.resolve = {
...config.resolve,
alias: {
...config.resolve?.alias,
"@testing-library/react": "@storybook/test"
}
}
config.resolve = {
...config.resolve,
alias: {
...config.resolve?.alias,
"@testing-library/react": "@storybook/test",
},
}

return config
},

typescript: {
reactDocgen: "react-docgen-typescript"
}
reactDocgen: "react-docgen-typescript",
},
}

export default config
Loading