Skip to content

Conversation

@kdmccormick
Copy link
Member

@kdmccormick kdmccormick commented Oct 21, 2025

Background / Supporting Info

As part of our effort to remove legacy studio pages and get rid of studio-frontend, we removed the legacy course & library listing in openedx/openedx-platform#37454. This removed the ability to create legacy libraries. At the time of review we deemed this to be OK, but upon further reflection, we were mistaken, for at least two different reasons:

  1. We did not formally deprecate any features of legacy libraries yet.
  2. Legacy libraries still have one feature not supported in Libraries V2: support for python_lib.zip.

So, we need to reinstate the ability to create legacy libraries for Ulmo. Rather than reintroduce all the legacy studio frontend code, we're opting to just reinstate the ability to create legacy libraries using frontend-app-authoring.

We will be able to remove the ability to create legacy libraries before Verawood. So, rather than factoring out common logic between CreateLibrary and CreateLegacyLibrary, this PR aims to just duplicate and modify CreateLibrary logic, such that it will be very easy to delete CreateLegacyLibrary.

Description

This adds a CreateLegacyLibrary component. It functions the same as CreateLibrary, but it calls the V1 (legacy) creation REST API rather the V2 (new/beta) REST API.

Screenshot 2025-10-22 at 5 26 59 PM

Testing instructions

Getting there:

  • Open Studio, log in as staff / course creator
  • Go to the "Legacy Libraries" tab
  • Hit "+ New Library"
  • You should brought to the new CreateLegacyLibraries page.

Test happy path:

  • Enter a valid title, org, and library ID.
  • Hit "Create legacy library"
  • You should be navigated to the new legacy library's editor in Legacy Studio

Test ID conflict:

  • Enter a valid title, org
  • Enter the ID of a library which already exists in your chosen org
  • Hit "Create legacy library"
  • You should see an "Axios Error (Response)" message. Not an ideal UX, but it's what the other libraries page does

Test v2 CreateLibrary unchanged:

  • In Studio, go to the "Libraries (Beta)" tab
  • Hit "+ New Library"
  • You should be brought to the regular v2 "Create Library" page.

Other information

Needs to merge ASAP, definitely before Ulmo cutoff

Best Practices Checklist

We're trying to move away from some deprecated patterns in this codebase. Please
check if your PR meets these recommendations before asking for a review:

  • Any new files are using TypeScript (.ts, .tsx).
  • Deprecated propTypes, defaultProps, and injectIntl patterns are not used in any new or modified code.
  • Tests should use the helpers in src/testUtils.tsx (specifically initializeMocks)
  • Do not add new fields to the Redux state/store. Use React Context to share state among multiple components.
  • Use React Query to load data from REST APIs. See any apiHooks.ts in this repo for examples.
  • All new i18n messages in messages.ts files have a description for translators to use.
  • Imports avoid using ../. To import from parent folders, use @src, e.g. import { initializeMocks } from '@src/testUtils'; instead of from '../../../../testUtils'

@bradenmacdonald
Copy link
Contributor

What's the rationale for implementing this in the MFE when you can't view legacy libraries in the MFE?

@kdmccormick
Copy link
Member Author

kdmccormick commented Oct 21, 2025

@bradenmacdonald As part of our effort to remove legacy studio pages and get rid of studio-frontend, we removed the legacy course & library listing in openedx/openedx-platform#37454, which also removed the ability to create legacy libraries. When we merged that, I made the judgement call that it was OK to remove the ability to create new legacy libraries, because:

  1. libraries v2 now replicate all the features of v1.
  2. we had announced the deprecation of legacy libraries a while ago.

But, I was wrong--

  1. libraries v2 do not support python_lib.zip.
  2. I never got the legacy libraries deprecation formally approved, so some operators are likely to still expect to able to make new ones in Ulmo .

So, our options are (a) reinstate all of those legacy studio pages and re-install studio-frontend, or (b) just reinstate the ability to create legacy libs in the MFE, and remove it shortly after the Ulmo cutoff.

@kdmccormick kdmccormick force-pushed the kdmccormick/create-legacy branch from 0688d52 to c362bc2 Compare October 21, 2025 18:09
@bradenmacdonald
Copy link
Contributor

@kdmccormick Ah, that makes sense.

libraries v2 do not support python_lib.zip.

But I don't think v1 libraries do either?

@kdmccormick
Copy link
Member Author

I didn't think so, but it turns out they do: openedx/openedx-platform#37500 (comment)

@kdmccormick kdmccormick force-pushed the kdmccormick/create-legacy branch 2 times, most recently from 93e9a8a to a908ef2 Compare October 22, 2025 15:14
Comment on lines 162 to 193
test('show api error', async () => {
const user = userEvent.setup();
axiosMock.onGet(getStudioHomeApiUrl()).reply(200, studioHomeMock);
axiosMock.onPost(getContentLibraryV1CreateApiUrl()).reply(400, {
field: 'Error message',
});
render(<CreateLegacyLibrary />);

const titleInput = await screen.findByRole('textbox', { name: /library name/i });
await user.click(titleInput);
await user.type(titleInput, 'Test Library Name');

const orgInput = await screen.findByRole('combobox', { name: /organization/i });
await user.click(orgInput);
await user.type(orgInput, 'org1');
await user.tab();

const slugInput = await screen.findByRole('textbox', { name: /library id/i });
await user.click(slugInput);
await user.type(slugInput, 'test_library_slug');

fireEvent.click(await screen.findByRole('button', { name: /create/i }));
await waitFor(async () => {
expect(axiosMock.history.post.length).toBe(1);
expect(axiosMock.history.post[0].data).toBe(
'{"display_name":"Test Library Name","org":"org1","number":"test_library_slug"}',
);
expect(mockNavigate).not.toHaveBeenCalled();
const errorMessage = 'Request failed with status code 400{ "field": "Error message" }';
expect(await screen.findByRole('alert')).toHaveTextContent(errorMessage);
});
});
Copy link
Member Author

@kdmccormick kdmccormick Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm struggling to get this test passing, seeking help.

(For context, this PR is adding a new component--CreateLegacyLibrary-- which is essentially a duplicate of the existing CreateLibrary component, but with some tweaks so that it creates legacy libraries instead of V2 libraries. This is a stop-gap solution just to get us through Ulmo without dropping functionality. The CreateLegacyLibrary component will be deleted between Ulmo and Verawood, so I'm doing a lot of code duplication rather than factoring out common logic between the two components.)

Like the rest of this test file, this test case show api error is copied near-verbatim from CreateLibrary.test.tsx. In particular, it is checking that if the backend returns a 400 when creating a legacy library, we get this a little Axios Error message (I know, not a great UX, but this is what CreateLibrary.tsx does too).

Screenshot 2025-10-22 at 11 16 15 AM

The test is failing with:

  ● <CreateLegacyLibrary /> › show api error

    expect(received).toBe(expected) // Object.is equality

    Expected: 1
    Received: 0

on:

      expect(axiosMock.history.post.length).toBe(1);

The issue seems to be that the test relies on await screen.findByRole('alert') in order to determine whether the error banner has appeared. This works fine in CreateLibrary, but in CreateLegacyLibrary, we have this big omnipresent warning alert which tells users that You are creating content in a deprecated format. Because the alert always exists, findByRole('alert') is returning false-positive immediately rather than blocking until the Axios alert appears.

I've tried updating it to await.screen.findByText(/axios error/i), but that doesn't seem to match the Axios error banner, for some reason.

Copy link
Contributor

@brian-smith-tcril brian-smith-tcril Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test passes if we change it to

    await user.click(await screen.findByRole('button', { name: /create/i }));
    await waitFor(async () => {
      expect(axiosMock.history.post.length).toBe(1);
      expect(axiosMock.history.post[0].data).toBe(
        '{"display_name":"Test Library Name","org":"org1","number":"test_library_slug"}',
      );
      expect(mockNavigate).not.toHaveBeenCalled();
    });
    await screen.findByText('Request failed with status code 400');

the findByText will fail the test if it doesn't find it, verified by seeing the test fail when using

    await screen.findByText('Request failed with status code 9001');

for that line instead

@bradenmacdonald
Copy link
Contributor

bradenmacdonald commented Oct 22, 2025

python_lib.zip does work in v1 libraries if you manually create a library/static/python_lib.zip in an unpacked v1 library tar.gz, pack it, and import it.

Is there any reason to believe that anyone has ever done this, however? I would call that undocumented at best, and perhaps even unsupported.

(Still in favor of this PR, just wanting context for future DEPRs etc.)

@kdmccormick kdmccormick force-pushed the kdmccormick/create-legacy branch from 49db107 to e1d66e2 Compare October 22, 2025 17:35
@feanil feanil self-requested a review October 22, 2025 17:40
@kdmccormick kdmccormick force-pushed the kdmccormick/create-legacy branch from e1d66e2 to cb448e7 Compare October 22, 2025 18:10
@codecov
Copy link

codecov bot commented Oct 22, 2025

Codecov Report

❌ Patch coverage is 97.50000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.74%. Comparing base (9f16041) to head (8ddb6aa).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
...ring/create-legacy-library/CreateLegacyLibrary.tsx 96.55% 2 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##           master    #2551   +/-   ##
=======================================
  Coverage   94.73%   94.74%           
=======================================
  Files        1213     1218    +5     
  Lines       27222    27300   +78     
  Branches     6141     6161   +20     
=======================================
+ Hits        25790    25866   +76     
- Misses       1361     1363    +2     
  Partials       71       71           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@kdmccormick kdmccormick marked this pull request as ready for review October 22, 2025 19:00
@feanil
Copy link
Contributor

feanil commented Oct 22, 2025

I tested this PR and can confirm functionality works as expected. I was able to create a legacy library without any issue. The warning shows up as expected on the legacy library creation form.

@feanil
Copy link
Contributor

feanil commented Oct 22, 2025

@brian-smith-tcril this is all set for a code quality/best practice review.

@kdmccormick kdmccormick force-pushed the kdmccormick/create-legacy branch from 90e03ee to 1ce1dfd Compare October 22, 2025 19:38
Copy link
Contributor

@brian-smith-tcril brian-smith-tcril left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Left some non-blocking suggestions to switch from fireEvent to userEvent in some tests.

@kdmccormick kdmccormick force-pushed the kdmccormick/create-legacy branch from 1ce1dfd to a63321c Compare October 22, 2025 21:06
It has not been cleared yet by UX/Product.
Removing the warning brings us to parity with the old
legacy Create Library page.
We may add this back shortly once UX/Product has reviewed it.
@kdmccormick kdmccormick force-pushed the kdmccormick/create-legacy branch from a63321c to 8ddb6aa Compare October 22, 2025 21:23
@kdmccormick kdmccormick enabled auto-merge (squash) October 22, 2025 21:26
@kdmccormick
Copy link
Member Author

I have temporarily removed the deprecation warning because I didn't have time to get it reviewed by Product/UX today: 8ddb6aa. That warning would have been net-new, so this PR is still valid for parity with the legacy frontend.

I'll open a new PR shortly for the deprecation warning and get Product/UX's eyes on it tomorrow and see if it makes sense to land for Ulmo.

@kdmccormick kdmccormick merged commit 5ce61fa into openedx:master Oct 22, 2025
7 checks passed
@kdmccormick kdmccormick deleted the kdmccormick/create-legacy branch October 23, 2025 02:24
Faraz32123 pushed a commit to edx/frontend-app-authoring that referenced this pull request Oct 24, 2025
This adds a CreateLegacyLibrary component. It functions the same as
CreateLibrary, but it calls the V1 (legacy) creation REST API rather the V2
(new/beta) REST API.

This reinstates, in the MFE, something that was possible using the legacy
frontend until it was prematurely removed by
openedx/openedx-platform#37454. 

We plan to re-remove this ability between Ulmo and Verawood as part of:
openedx/openedx-platform#32457.
So, we have intentionally avoided factoring out common logic between
CreateLibrary and CreateLegacyLibrary, ensuring that the latter
remains easy to remove and clean up.
Faraz32123 pushed a commit to edx/frontend-app-authoring that referenced this pull request Oct 24, 2025
This adds a CreateLegacyLibrary component. It functions the same as
CreateLibrary, but it calls the V1 (legacy) creation REST API rather the V2
(new/beta) REST API.

This reinstates, in the MFE, something that was possible using the legacy
frontend until it was prematurely removed by
openedx/openedx-platform#37454. 

We plan to re-remove this ability between Ulmo and Verawood as part of:
openedx/openedx-platform#32457.
So, we have intentionally avoided factoring out common logic between
CreateLibrary and CreateLegacyLibrary, ensuring that the latter
remains easy to remove and clean up.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants