Compare commits

...

23 Commits

Author SHA1 Message Date
renovate[bot]
813cbb3156 fix(deps): update dependency @fortawesome/react-fontawesome to v0.2.3 (#624)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-28 06:35:01 +00:00
renovate[bot]
20aaa4f2e2 chore(deps): update jest monorepo to v30.0.5 (#623)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-28 06:34:40 +00:00
Braden MacDonald
4dfb1b3053 fix: remove unused jest-chain, babel-polyfill, axios-mock-adapter (#603) 2025-07-21 10:38:01 -07:00
Braden MacDonald
171a770235 feat: enable the use of TypeScript in this repo (#604)
* feat: enable Typescript in this repo

* refactor: rename studio-header files to .ts[x]

* chore: fix minor type warnings

* chore: add types for frontend-platform

* chore: fix type issues

* chore: update name of suppressed lint check
2025-07-21 10:24:52 -07:00
renovate[bot]
f47c1ed1e6 fix(deps): update jest monorepo to v30 (#620)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-14 06:41:21 +00:00
renovate[bot]
c63da3051b chore(deps): update dependency @openedx/paragon to v23.14.0 (#616)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-07 06:16:34 +00:00
renovate[bot]
04b35786d4 fix(deps): update font awesome to v6.7.2 (#610)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-30 12:47:21 +00:00
renovate[bot]
657e9c0190 chore(deps): update dependency @openedx/frontend-build to v14.6.1 (#609)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-30 12:47:03 +00:00
renovate[bot]
2874c9603f chore(deps): update dependency @openedx/paragon to v23.13.0 (#614)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-30 06:47:01 +00:00
renovate[bot]
ec5381ea17 chore(deps): update dependency @openedx/paragon to v23.12.2 (#606)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-16 05:48:54 +00:00
renovate[bot]
d5ac171a5b chore(deps): update dependency @edx/frontend-platform to v8.4.0 (#605)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-16 05:48:36 +00:00
renovate[bot]
3be690b34b chore(deps): update dependency @openedx/paragon to v23.10.1 (#602)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-09 05:36:02 +00:00
renovate[bot]
441e1542ad chore(deps): update dependency @edx/frontend-platform to v8.3.9 (#601)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-09 05:35:41 +00:00
renovate[bot]
c1db3d409e chore(deps): update dependency @openedx/paragon to v23.10.0 (#600)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-02 06:36:18 +00:00
renovate[bot]
0c343cfdf0 chore(deps): update dependency @edx/frontend-platform to v8.3.8 (#599)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-02 06:36:03 +00:00
renovate[bot]
f740d0107e chore(deps): update dependency react-router-dom to v6.30.1 (#597)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-26 06:57:40 +00:00
renovate[bot]
98bc20a282 chore(deps): update dependency @edx/frontend-platform to v8.3.7 (#596)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-26 06:57:30 +00:00
renovate[bot]
ca15863c82 chore(deps): update dependency react-router-dom to v6.30.0 (#595)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 06:08:20 +00:00
renovate[bot]
ff9cb1b238 chore(deps): update dependency @openedx/paragon to v23.6.0 (#594)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 06:08:14 +00:00
renovate[bot]
67967156f4 chore(deps): update dependency @edx/frontend-platform to v8.3.6 (#592)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-12 07:13:35 +00:00
renovate[bot]
e4720ff6b0 chore(deps): update dependency @openedx/paragon to v23.5.1 (#593)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-12 07:12:12 +00:00
renovate[bot]
df704ce6d7 chore(deps): update dependency @openedx/frontend-build to v14.6.0 (#591)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-05 07:44:35 +00:00
renovate[bot]
a2dc80ffb8 chore(deps): update dependency @edx/frontend-platform to v8.3.5 (#590)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-05 07:44:23 +00:00
28 changed files with 4218 additions and 256 deletions

View File

@@ -24,6 +24,8 @@ jobs:
run: make validate-no-uncommitted-package-lock-changes
- name: Lint
run: npm run lint
- name: Type check
run: npm run types
- name: Test
run: npm run test
- name: Build

View File

@@ -25,6 +25,8 @@ jobs:
run: make validate-no-uncommitted-package-lock-changes
- name: Lint
run: npm run lint
- name: Type check
run: npm run types
- name: Test
run: npm run test
- name: i18n_extract

View File

@@ -1,5 +1,3 @@
import 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import { initialize, getConfig, subscribe, APP_READY } from '@edx/frontend-platform';

4366
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,8 @@
"lint:fix": "fedx-scripts eslint --fix --ext .js --ext .jsx .",
"snapshot": "fedx-scripts jest --updateSnapshot",
"start": "fedx-scripts webpack-dev-server --progress",
"test": "fedx-scripts jest --coverage"
"test": "fedx-scripts jest --coverage",
"types": "tsc --noEmit"
},
"files": [
"/dist"
@@ -38,28 +39,25 @@
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "5.17.0",
"@testing-library/react": "^16.2.0",
"jest": "29.7.0",
"jest-chain": "1.1.6",
"jest": "30.0.5",
"jest-environment-jsdom": "^30.0.0",
"prop-types": "15.8.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-redux": "^8.1.1",
"react-router-dom": "6.28.1",
"react-router-dom": "6.30.1",
"react-test-renderer": "^18.3.1",
"redux": "4.2.1",
"redux-saga": "1.3.0"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "6.6.0",
"@fortawesome/free-brands-svg-icons": "6.6.0",
"@fortawesome/free-regular-svg-icons": "6.6.0",
"@fortawesome/free-solid-svg-icons": "6.6.0",
"@fortawesome/fontawesome-svg-core": "6.7.2",
"@fortawesome/free-brands-svg-icons": "6.7.2",
"@fortawesome/free-regular-svg-icons": "6.7.2",
"@fortawesome/free-solid-svg-icons": "6.7.2",
"@fortawesome/react-fontawesome": "^0.2.0",
"@openedx/frontend-plugin-framework": "^1.7.0",
"axios-mock-adapter": "1.22.0",
"babel-polyfill": "6.26.0",
"classnames": "^2.5.1",
"jest-environment-jsdom": "^29.7.0",
"react-responsive": "8.2.0",
"react-transition-group": "4.4.5"
},

View File

@@ -33,6 +33,7 @@ describe('<Header />', () => {
};
const component = <HeaderComponent width={{ width: 1280 }} contextValue={contextValue} />;
// FIXME: react-test-renderer is deprecated. Convert to @testing-library/react.
const wrapper = TestRenderer.create(component);
expect(wrapper.toJSON()).toMatchSnapshot();
@@ -56,6 +57,7 @@ describe('<Header />', () => {
};
const component = <HeaderComponent width={{ width: 1280 }} contextValue={contextValue} />;
// FIXME: react-test-renderer is deprecated. Convert to @testing-library/react.
const wrapper = TestRenderer.create(component);
expect(wrapper.toJSON()).toMatchSnapshot();
@@ -74,6 +76,7 @@ describe('<Header />', () => {
};
const component = <HeaderComponent width={{ width: 500 }} contextValue={contextValue} />;
// FIXME: react-test-renderer is deprecated. Convert to @testing-library/react.
const wrapper = TestRenderer.create(component);
expect(wrapper.toJSON()).toMatchSnapshot();

View File

@@ -22,7 +22,7 @@ import messages from '../Header.messages';
import { CaretIcon } from '../Icons';
class DesktopHeader extends React.Component {
constructor(props) { // eslint-disable-line no-useless-constructor
constructor(props) { // eslint-disable-line @typescript-eslint/no-useless-constructor
super(props);
}

41
src/frontend-platform.d.ts vendored Normal file
View File

@@ -0,0 +1,41 @@
// frontend-platform currently doesn't provide types... do it ourselves for i18n module at least.
// We can remove this in the future when we migrate to frontend-shell, or when frontend-platform gets types
// (whichever comes first).
declare module '@edx/frontend-platform/i18n' {
// eslint-disable-next-line import/no-extraneous-dependencies
import { injectIntl as _injectIntl } from 'react-intl';
/** @deprecated Use useIntl() hook instead. */
export const injectIntl: typeof _injectIntl;
/** @deprecated Use useIntl() hook instead. */
export const intlShape: any;
// eslint-disable-next-line import/no-extraneous-dependencies
export {
createIntl,
FormattedDate,
FormattedTime,
FormattedRelativeTime,
FormattedNumber,
FormattedPlural,
FormattedMessage,
defineMessages,
IntlProvider,
useIntl,
} from 'react-intl';
// Other exports from the i18n module:
export const configure: any;
export const getPrimaryLanguageSubtag: (code: string) => string;
export const getLocale: (locale?: string) => string;
export const getMessages: any;
export const isRtl: (locale?: string) => boolean;
export const handleRtl: any;
export const mergeMessages: any;
export const LOCALE_CHANGED: any;
export const LOCALE_TOPIC: any;
export const getCountryList: any;
export const getCountryMessages: any;
export const getLanguageList: any;
export const getLanguageMessages: any;
}

View File

@@ -21,7 +21,7 @@ import messages from '../Header.messages';
import { MenuIcon } from '../Icons';
class MobileHeader extends React.Component {
constructor(props) { // eslint-disable-line no-useless-constructor
constructor(props) { // eslint-disable-line @typescript-eslint/no-useless-constructor
super(props);
}

View File

@@ -4,8 +4,6 @@ import React from 'react';
import PropTypes from 'prop-types';
import '@testing-library/jest-dom';
import '@testing-library/jest-dom/extend-expect';
import 'babel-polyfill';
import 'jest-chain';
import { getConfig, mergeConfig } from '@edx/frontend-platform';
import { configure as configureLogging } from '@edx/frontend-platform/logging';
import { configure as configureI18n } from '@edx/frontend-platform/i18n';

View File

@@ -34,7 +34,7 @@ describe('BrandNav Component', () => {
it('displays a link that navigates to studioBaseUrl', () => {
render(<RootWrapper />);
const link = screen.getByRole('link');
const link = screen.getByRole('link') as HTMLAnchorElement;
expect(link.href).toBe(studioBaseUrl);
});
});

View File

@@ -16,7 +16,7 @@ const mockProps = {
const RootWrapper = (props) => (
<MemoryRouter>
<IntlProvider locale="en" messages={messages}>
<IntlProvider locale="en" messages={{}}>
<CourseLockUp {...props} />
</IntlProvider>
</MemoryRouter>
@@ -52,7 +52,8 @@ describe('CourseLockUp Component', () => {
it('navigates to an absolute URL when clicked', () => {
render(<RootWrapper {...mockProps} />);
const link = screen.getByTestId('course-lock-up-block');
// FIXME: don't use testId - https://testing-library.com/docs/queries/about#priority
const link = screen.getByTestId('course-lock-up-block') as HTMLAnchorElement;
expect(link.href).toBe(mockProps.outlineLink);
});
});

View File

@@ -35,7 +35,7 @@ const defaultProps = {
const RootWrapper = (props) => (
<MemoryRouter>
<IntlProvider locale="en" messages={messages}>
<IntlProvider locale="en" messages={{}}>
<HeaderBody {...props} />
</IntlProvider>
</MemoryRouter>

View File

@@ -135,6 +135,7 @@ const HeaderBody = ({
logoutUrl,
authenticatedUserAvatar,
isAdmin,
isMobile,
}}
/>
</Nav>

View File

@@ -13,6 +13,7 @@ const MobileHeader = ({
return (
<>
{/* @ts-expect-error The type of 'props' is any until we convert from propTypes to TypeScript interface/types */}
<HeaderBody
{...props}
isMobile

View File

@@ -26,7 +26,7 @@ let screenWidth = 1280;
const RootWrapper = ({
...props
}) => {
}: React.ComponentProps<typeof StudioHeader>) => {
const appContextValue = useMemo(() => ({
authenticatedUser: currentUser,
config: {
@@ -55,7 +55,7 @@ const RootWrapper = ({
);
};
const props = {
const props: React.ComponentProps<typeof StudioHeader> = {
number: '123',
org: 'Ed',
title: 'test',
@@ -74,6 +74,10 @@ const props = {
outlineLink: 'tEsTLInK',
searchButtonAction: null,
isNewHomePage: true,
// These default values shouldn't be needed but typescript is confused by propTypes; can remove after converting
// from propTypes to TypeScript:
containerProps: {},
isHiddenMainMenu: false,
};
describe('Header', () => {

View File

@@ -19,6 +19,7 @@ const StudioHeader = ({
number, org, title, containerProps, isHiddenMainMenu, mainMenuDropdowns,
outlineLink, searchButtonAction, isNewHomePage,
}) => {
// @ts-expect-error - frontend-platform doesn't yet have type information :/
const { authenticatedUser, config } = useContext(AppContext);
const props = {
logo: config.LOGO_URL,

12
tsconfig.json Normal file
View File

@@ -0,0 +1,12 @@
{
"extends": "@edx/typescript-config",
"compilerOptions": {
"noEmit": true,
"baseUrl": "./src",
"paths": {
"*": ["*"]
}
},
"include": ["*.js", ".eslintrc.js", "src/**/*", "plugins/**/*"],
"exclude": ["dist", "node_modules"]
}