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
324 changes: 162 additions & 162 deletions .yarn/releases/yarn-4.4.1.cjs → .yarn/releases/yarn-4.5.0.cjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ enableGlobalCache: false

nodeLinker: node-modules

yarnPath: .yarn/releases/yarn-4.4.1.cjs
yarnPath: .yarn/releases/yarn-4.5.0.cjs

# https://github.com/vitejs/vite-plugin-react-swc/issues/74#issuecomment-1520484130
# https://github.com/swc-project/swc/issues/5616#issuecomment-1265639797
Expand Down
9 changes: 9 additions & 0 deletions RELEASE.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
Release Notes
=============

Version 0.21.3
--------------

- removing invalid flag from clear cache command (#1675)
- Clear Cache on Deploy (#1668)
- Update Yarn to v4.5.0 (#1624)
- topic detail banner / subtopic logic revisions (#1646)
- Restore program letter intercept view (#1643)

Version 0.21.2 (Released October 10, 2024)
--------------

Expand Down
12 changes: 12 additions & 0 deletions frontends/api/src/generated/v0/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2145,6 +2145,18 @@ export interface ProgramCertificate {
* @memberof ProgramCertificate
*/
record_hash: string
/**
*
* @type {string}
* @memberof ProgramCertificate
*/
program_letter_generate_url: string
/**
*
* @type {string}
* @memberof ProgramCertificate
*/
program_letter_share_url: string
/**
*
* @type {string}
Expand Down
12 changes: 12 additions & 0 deletions frontends/api/src/generated/v1/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4930,6 +4930,18 @@ export interface ProgramCertificate {
* @memberof ProgramCertificate
*/
record_hash: string
/**
*
* @type {string}
* @memberof ProgramCertificate
*/
program_letter_generate_url: string
/**
*
* @type {string}
* @memberof ProgramCertificate
*/
program_letter_share_url: string
/**
*
* @type {string}
Expand Down
11 changes: 11 additions & 0 deletions frontends/api/src/hooks/learningResources/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ const useFeaturedLearningResourcesList = (params: FeaturedListParams = {}) => {
return useQuery(learningResources.featured(params))
}

const useLearningResourceTopic = (
id: number,
opts: Pick<UseQueryOptions, "enabled"> = {},
) => {
return useQuery({
...learningResources.topic(id),
...opts,
})
}

const useLearningResourceTopics = (
params: TopicsListRequest = {},
opts: Pick<UseQueryOptions, "enabled"> = {},
Expand Down Expand Up @@ -486,6 +496,7 @@ export {
useLearningResourcesList,
useFeaturedLearningResourcesList,
useLearningResourcesDetail,
useLearningResourceTopic,
useLearningResourceTopics,
useLearningPathsList,
useLearningPathsDetail,
Expand Down
5 changes: 5 additions & 0 deletions frontends/api/src/hooks/learningResources/keyFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ const learningResources = createQueryKeys("learningResources", {
})
},
}),
topic: (id: number | undefined) => ({
queryKey: [id],
queryFn: () =>
id ? topicsApi.topicsRetrieve({ id }).then((res) => res.data) : null,
}),
topics: (params: TopicsListRequest) => ({
queryKey: [params],
queryFn: () => topicsApi.topicsList(params).then((res) => res.data),
Expand Down
7 changes: 6 additions & 1 deletion frontends/api/src/test-utils/urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ const query = (params: any) => {
const queryString = new URLSearchParams()
for (const [key, value] of Object.entries(params)) {
if (Array.isArray(value)) {
value.forEach((v) => queryString.append(key, String(v)))
if (value.length === 0) {
queryString.append(key, "")
} else {
value.forEach((v) => queryString.append(key, String(v)))
}
} else {
queryString.append(key, String(value))
}
Expand Down Expand Up @@ -96,6 +100,7 @@ const platforms = {
}

const topics = {
get: (id: number) => `${API_BASE_URL}/api/v1/topics/${id}/`,
list: (params?: Params<TopicsApi, "topicsList">) =>
`${API_BASE_URL}/api/v1/topics/${query(params)}`,
}
Expand Down
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
136 changes: 109 additions & 27 deletions frontends/mit-learn/src/pages/ChannelPage/ChannelPage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,23 +105,51 @@ const setupApis = (
results: [],
})

if (
channel.channel_type === ChannelTypeEnum.Topic &&
channel.topic_detail.topic
) {
const subTopics = factories.learningResources.topics({ count: 5 })
setMockResponse.get(
urls.topics.list({ parent_topic_id: [channel.topic_detail.topic] }),
subTopics,
)
return {
channel,
subTopics,
}
return {
channel,
}
}

const setupTopicApis = (channel: Channel) => {
invariant(
channel.channel_type === ChannelTypeEnum.Topic,
"Topic channel must have a topic",
)
const topic = factories.learningResources.topic()
channel.channel_url = `/c/${channel.channel_type}/${channel.name.replace(/\s/g, "-")}`
topic.channel_url = channel.channel_url
topic.id = channel.topic_detail.topic ?? 0
const subTopics = factories.learningResources.topics({ count: 5 })
setMockResponse.get(urls.topics.get(topic.id), topic)
setMockResponse.get(
urls.topics.list({ parent_topic_id: [topic.id] }),
subTopics,
)
const subTopicChannels = subTopics.results.map((subTopic) => {
subTopic.parent = topic.id
const subTopicChannel = factories.channels.channel({
channel_type: ChannelTypeEnum.Topic,
name: subTopic.name.replace(/\s/g, "-"),
title: subTopic.name,
topic_detail: { topic: subTopic.id },
})
const channelUrl = `/c/${subTopicChannel.channel_type}/${subTopicChannel.name.replace(/\s/g, "-")}`
subTopic.channel_url = channelUrl
subTopicChannel.channel_url = channelUrl
setMockResponse.get(urls.topics.get(subTopic.id), subTopic)
setMockResponse.get(
urls.channels.details(
subTopicChannel.channel_type,
subTopicChannel.name.replace(/\s/g, "-"),
),
subTopicChannel,
)
return subTopicChannel
})
return {
channel,
topic,
subTopics,
subTopicChannels,
}
}

Expand All @@ -141,6 +169,9 @@ describe.each(ALL_CHANNEL_TYPES)(
"platform=ocw&platform=mitxonline&department=8&department=9",
channel_type: channelType,
})
if (channelType === ChannelTypeEnum.Topic) {
setupTopicApis(channel)
}
renderTestApp({ url: `/c/${channel.channel_type}/${channel.name}` })
await screen.findAllByText(channel.title)
const expectedProps = expect.objectContaining({
Expand All @@ -155,23 +186,29 @@ describe.each(ALL_CHANNEL_TYPES)(
expectedProps,
expectedContext,
)
})
}, 10000)
it("Does not display the channel search if search_filter is undefined", async () => {
const { channel } = setupApis({
channel_type: channelType,
})
channel.search_filter = undefined
if (channelType === ChannelTypeEnum.Topic) {
setupTopicApis(channel)
}
renderTestApp({ url: `/c/${channel.channel_type}/${channel.name}` })
await screen.findAllByText(channel.title)

expect(mockedChannelSearch).toHaveBeenCalledTimes(0)
})
}, 10000)

it("Includes heading and subheading in banner", async () => {
const { channel } = setupApis({
channel_type: channelType,
})
channel.search_filter = undefined
if (channelType === ChannelTypeEnum.Topic) {
setupTopicApis(channel)
}
renderTestApp({ url: `/c/${channel.channel_type}/${channel.name}` })
await screen.findAllByText(channel.title)

Expand All @@ -185,7 +222,7 @@ describe.each(ALL_CHANNEL_TYPES)(
expect(el).toBeInTheDocument()
})
})
})
}, 10000)

it.each([{ isSubscribed: false }, { isSubscribed: true }])(
"Displays the subscribe toggle for authenticated and unauthenticated users",
Expand All @@ -195,10 +232,14 @@ describe.each(ALL_CHANNEL_TYPES)(
{},
{ isSubscribed },
)
if (channelType === ChannelTypeEnum.Topic) {
setupTopicApis(channel)
}
renderTestApp({ url: `/c/${channel.channel_type}/${channel.name}` })
const subscribedButton = await screen.findByText("Follow")
expect(subscribedButton).toBeVisible()
const subscribedButton = await screen.findAllByText("Follow")
expect(subscribedButton[0]).toBeVisible()
},
10000,
)
},
)
Expand All @@ -211,18 +252,24 @@ describe.each(NON_UNIT_CHANNEL_TYPES)(
search_filter: "topic=physics",
channel_type: channelType,
})
if (channelType === ChannelTypeEnum.Topic) {
setupTopicApis(channel)
}

renderTestApp({ url: `/c/${channel.channel_type}/${channel.name}` })
await screen.findAllByText(channel.title)
const carousels = screen.queryByText("Featured Courses")
expect(carousels).toBe(null)
})
}, 10000)

it("Displays the title, background, and avatar (channelType: %s)", async () => {
const { channel } = setupApis({
search_filter: "offered_by=ocw",
channel_type: channelType,
})
if (channelType === ChannelTypeEnum.Topic) {
setupTopicApis(channel)
}

renderTestApp({ url: `/c/${channel.channel_type}/${channel.name}` })
const title = await screen.findByRole("heading", { name: channel.title })
Expand All @@ -245,13 +292,16 @@ describe.each(NON_UNIT_CHANNEL_TYPES)(
img.src.includes(channel.configuration.logo),
)
expect(logos.length).toBe(1)
})
}, 10000)

test("headings", async () => {
const { channel } = setupApis({
search_filter: "topic=Physics",
channel_type: channelType,
})
if (channelType === ChannelTypeEnum.Topic) {
setupTopicApis(channel)
}
renderTestApp({ url: `/c/${channel.channel_type}/${channel.name}` })

await waitFor(() => {
Expand All @@ -262,27 +312,59 @@ describe.each(NON_UNIT_CHANNEL_TYPES)(
{ level: 3, name: "Search Results" },
])
})
})
}, 10000)
},
)

describe("Channel Pages, Topic only", () => {
test("Subtopics display", async () => {
const { channel, subTopics } = setupApis({
const { channel } = setupApis({
search_filter: "topic=Physics",
channel_type: ChannelTypeEnum.Topic,
})
renderTestApp({ url: `/c/${channel.channel_type}/${channel.name}` })
const { topic, subTopics } = setupTopicApis(channel)
invariant(topic)
renderTestApp({
url: `/c/${channel.channel_type}/${channel.name.replace(/\s/g, "-")}`,
})

invariant(subTopics)
const subTopicsTitle = await screen.findByText("Subtopics")
expect(subTopicsTitle).toBeInTheDocument()
const links = await screen.findAllByRole("link", {
// name arg can be string, regex, or function
name: (name) => subTopics?.results.map((t) => t.name).includes(name),
})
links.forEach((link, i) => {
links.forEach(async (link, i) => {
expect(link).toHaveAttribute("href", subTopics.results[i].channel_url)
})
})
}, 10000)

test("Related topics display", async () => {
const { channel } = setupApis({
search_filter: "topic=Physics",
channel_type: ChannelTypeEnum.Topic,
})
const { subTopics, subTopicChannels } = setupTopicApis(channel)
invariant(subTopicChannels)
const subTopicChannel = subTopicChannels[0]
const filteredSubTopics = subTopics?.results.filter(
(t) =>
t.name.replace(/\s/g, "-") !== subTopicChannel.name.replace(/\s/g, "-"),
)
renderTestApp({
url: `/c/${subTopicChannel.channel_type}/${subTopicChannel.name.replace(/\s/g, "-")}`,
})

const relatedTopicsTitle = await screen.findByText("Related Topics")
expect(relatedTopicsTitle).toBeInTheDocument()
const links = await screen.findAllByRole("link", {
// name arg can be string, regex, or function
name: (name) => filteredSubTopics?.map((t) => t.name).includes(name),
})
links.forEach(async (link, i) => {
expect(link).toHaveAttribute("href", filteredSubTopics[i].channel_url)
})
}, 10000)
})

describe("Channel Pages, Unit only", () => {
Expand Down
Loading
Loading