chore: fix urls

Co-authored-by: Nathan Sprenkle <nsprenkle@users.noreply.github.com>

chore: marketing and upgrade url are full urls
This commit is contained in:
Leangseu Kim
2022-09-28 11:35:56 -04:00
committed by leangseu-edx
parent 00e978dca3
commit 7f210e7483
14 changed files with 116 additions and 53 deletions

1
.env
View File

@@ -30,3 +30,4 @@ ENTERPRISE_MARKETING_URL=''
ENTERPRISE_MARKETING_UTM_SOURCE=''
ENTERPRISE_MARKETING_UTM_CAMPAIGN=''
ENTERPRISE_MARKETING_FOOTER_UTM_MEDIUM=''
LEARNING_MICROFRONTEND_URL=''

View File

@@ -36,3 +36,4 @@ ENTERPRISE_MARKETING_URL='http://example.com'
ENTERPRISE_MARKETING_UTM_SOURCE='example.com'
ENTERPRISE_MARKETING_UTM_CAMPAIGN='example.com Referral'
ENTERPRISE_MARKETING_FOOTER_UTM_MEDIUM='Footer'
LEARNING_MICROFRONTEND_URL='http://localhost:2000'

View File

@@ -36,3 +36,4 @@ ENTERPRISE_MARKETING_URL='http://example.com'
ENTERPRISE_MARKETING_UTM_SOURCE='example.com'
ENTERPRISE_MARKETING_UTM_CAMPAIGN='example.com Referral'
ENTERPRISE_MARKETING_FOOTER_UTM_MEDIUM='Footer'
LEARNING_MICROFRONTEND_URL='http://localhost:2000'

View File

@@ -9,6 +9,7 @@ const configuration = {
// SECURE_COOKIES: process.env.NODE_ENV !== 'development',
// SEGMENT_KEY: process.env.SEGMENT_KEY,
// ACCESS_TOKEN_COOKIE_NAME: process.env.ACCESS_TOKEN_COOKIE_NAME,
LEARNING_MICROFRONTEND_URL: process.env.LEARNING_MICROFRONTEND_URL,
};
const features = {};

View File

@@ -8,9 +8,6 @@
.pgn__card-header-content {
margin-top: 1.5rem;
}
.course-card-content-vertical {
}
}
.course-card-banners {

View File

@@ -8,7 +8,7 @@ import { hooks } from 'data/redux';
import messages from './messages';
export const ViewCourseButton = ({ cardId }) => {
const { marketingUrl } = hooks.useCardCourseRunData(cardId);
const { homeUrl } = hooks.useCardCourseRunData(cardId);
const { hasAccess } = hooks.useCardEnrollmentData(cardId);
const { isEntitlement, isExpired } = hooks.useCardEntitlementData(cardId);
const { isMasquerading } = hooks.useMasqueradeData();
@@ -17,7 +17,7 @@ export const ViewCourseButton = ({ cardId }) => {
<Button
disabled={isMasquerading || !hasAccess || (isEntitlement && isExpired)}
as="a"
href={marketingUrl}
href={homeUrl}
>
{formatMessage(messages.viewCourse)}
</Button>

View File

@@ -6,48 +6,60 @@ import ViewCourseButton from './ViewCourseButton';
jest.mock('data/redux', () => ({
hooks: {
useCardCourseRunData: jest.fn(() => ({ marketingUrl: 'marketing-url' })),
useCardEnrollmentData: jest.fn(() => ({ hasAccess: true })),
useCardEntitlementData: jest.fn(() => ({ isEntitlement: false, isExpired: false })),
useMasqueradeData: jest.fn(() => ({ isMasquerading: false })),
useCardCourseRunData: jest.fn(),
useCardEnrollmentData: jest.fn(),
useCardEntitlementData: jest.fn(),
useMasqueradeData: jest.fn(),
},
}));
let wrapper;
describe('ViewCourseButton', () => {
const props = {
cardId: 'cardId',
};
const { marketingUrl } = hooks.useCardCourseRunData();
const homeUrl = 'homeUrl';
hooks.useCardCourseRunData.mockReturnValue({ homeUrl });
const createWrapper = ({
hasAccess = false,
isEntitlement = false,
isExpired = false,
isMasquerading = false,
}) => {
hooks.useCardEnrollmentData.mockReturnValueOnce({ hasAccess });
hooks.useCardEntitlementData.mockReturnValueOnce({ isEntitlement, isExpired });
hooks.useMasqueradeData.mockReturnValueOnce({ isMasquerading });
return shallow(<ViewCourseButton {...props} />);
};
describe('snapshot', () => {
test('default button', () => {
wrapper = shallow(<ViewCourseButton {...props} />);
const wrapper = createWrapper({ hasAccess: true });
expect(wrapper).toMatchSnapshot();
expect(wrapper.prop(htmlProps.disabled)).toEqual(false);
expect(wrapper.prop(htmlProps.href)).toEqual(marketingUrl);
expect(wrapper.prop(htmlProps.href)).toEqual(homeUrl);
});
test('disabled button', () => {
const wrapper = createWrapper({});
expect(wrapper).toMatchSnapshot();
expect(wrapper.prop(htmlProps.disabled)).toEqual(true);
expect(wrapper.prop(htmlProps.href)).toEqual(homeUrl);
});
});
describe('behavior', () => {
describe('disabled states', () => {
test('learner does not have access', () => {
hooks.useCardEnrollmentData.mockReturnValueOnce({ hasAccess: false });
wrapper = shallow(<ViewCourseButton {...props} />);
expect(wrapper.prop(htmlProps.disabled)).toEqual(true);
});
test('expired entitlement', () => {
hooks.useCardEntitlementData.mockReturnValueOnce({
isEntitlement: true,
isExpired: true,
});
wrapper = shallow(<ViewCourseButton {...props} />);
expect(wrapper.prop(htmlProps.disabled)).toEqual(true);
});
test('masquerading', () => {
hooks.useMasqueradeData.mockReturnValueOnce({ isMasquerading: true });
wrapper = shallow(<ViewCourseButton {...props} />);
expect(wrapper.prop(htmlProps.disabled)).toEqual(true);
});
it('disabled button when masquerading', () => {
const wrapper = createWrapper({ isMasquerading: true });
expect(wrapper.prop('disabled')).toEqual(true);
});
it('disabled button without access', () => {
const wrapper = createWrapper({ hasAccess: false, isEntitlement: false, isExpired: false });
expect(wrapper.prop('disabled')).toEqual(true);
});
it('disabled button with access', () => {
const wrapper = createWrapper({ hasAccess: true, isEntitlement: true, isExpired: true });
expect(wrapper.prop('disabled')).toEqual(true);
});
it('enabled button', () => {
const wrapper = createWrapper({ hasAccess: true, isEntitlement: false, isExpired: false });
expect(wrapper.prop('disabled')).toEqual(false);
});
});
});

View File

@@ -4,7 +4,17 @@ exports[`ViewCourseButton snapshot default button 1`] = `
<Button
as="a"
disabled={false}
href="marketing-url"
href="homeUrl"
>
View Course
</Button>
`;
exports[`ViewCourseButton snapshot disabled button 1`] = `
<Button
as="a"
disabled={true}
href="homeUrl"
>
View Course
</Button>

View File

@@ -17,15 +17,23 @@ import messages from '../messages';
export const CourseCardContent = ({ cardId, orientation }) => {
const { formatMessage } = useIntl();
const { courseName, bannerImgSrc } = appHooks.useCardCourseData(cardId);
const { homeUrl } = appHooks.useCardCourseRunData(cardId);
return (
<>
<Card.ImageCap
src={bannerImgSrc}
srcAlt={formatMessage(messages.bannerAlt)}
/>
<a className="pgn__card-wrapper-image-cap horizontal" href={homeUrl}>
<img
className="pgn__card-image-cap"
src={bannerImgSrc}
alt={formatMessage(messages.bannerAlt)}
/>
</a>
<Card.Body>
<Card.Header
title={<span data-testid="CourseCardTitle">{courseName}</span>}
title={(
<a href={homeUrl} data-testid="CourseCardTitle">
{courseName}
</a>
)}
actions={<CourseCardMenu cardId={cardId} />}
/>
<Card.Section className="pt-0">

View File

@@ -6,6 +6,7 @@ import CourseCardContent from './CourseCardContent';
jest.mock('data/redux', () => ({
hooks: {
useCardCourseData: jest.fn(),
useCardCourseRunData: jest.fn(),
},
}));
@@ -23,6 +24,9 @@ describe('CourseCardContent', () => {
courseName: 'test-course-name',
bannerImgSrc: 'test-banner-img-src',
});
hooks.useCardCourseRunData.mockReturnValue({
homeUrl: 'test-home-url',
});
describe('snapshot', () => {
test('orientation vertical', () => {
const wrapper = shallow(<CourseCardContent {...props} />);

View File

@@ -2,10 +2,16 @@
exports[`CourseCardContent snapshot orientation horizontal 1`] = `
<Fragment>
<Card.ImageCap
src="test-banner-img-src"
srcAlt="Course thumbnail"
/>
<a
className="pgn__card-wrapper-image-cap horizontal"
href="test-home-url"
>
<img
alt="Course thumbnail"
className="pgn__card-image-cap"
src="test-banner-img-src"
/>
</a>
<Card.Body>
<Card.Header
actions={
@@ -14,11 +20,12 @@ exports[`CourseCardContent snapshot orientation horizontal 1`] = `
/>
}
title={
<span
<a
data-testid="CourseCardTitle"
href="test-home-url"
>
test-course-name
</span>
</a>
}
/>
<Card.Section
@@ -46,10 +53,16 @@ exports[`CourseCardContent snapshot orientation horizontal 1`] = `
exports[`CourseCardContent snapshot orientation vertical 1`] = `
<Fragment>
<Card.ImageCap
src="test-banner-img-src"
srcAlt="Course thumbnail"
/>
<a
className="pgn__card-wrapper-image-cap horizontal"
href="test-home-url"
>
<img
alt="Course thumbnail"
className="pgn__card-image-cap"
src="test-banner-img-src"
/>
</a>
<Card.Body>
<Card.Header
actions={
@@ -58,11 +71,12 @@ exports[`CourseCardContent snapshot orientation vertical 1`] = `
/>
}
title={
<span
<a
data-testid="CourseCardTitle"
href="test-home-url"
>
test-course-name
</span>
</a>
}
/>
<Card.Section

View File

@@ -2,9 +2,12 @@ import { createSelector } from 'reselect';
import { StrictDict } from 'utils';
import { FilterKeys } from 'data/constants/app';
import urls from 'data/services/lms/urls';
import * as module from './selectors';
const { baseAppUrl, learningMfeUrl } = urls;
export const appSelector = (state) => state.app;
const mkSimpleSelector = (cb) => createSelector([module.appSelector], cb);
@@ -56,7 +59,7 @@ export const courseCard = StrictDict({
isRestricted: certificate.isRestricted,
})),
course: mkCardSelector(({ course }) => ({
bannerImgSrc: process.env.LMS_BASE_URL + course.bannerImgSrc,
bannerImgSrc: baseAppUrl(course.bannerImgSrc),
courseNumber: course.courseNumber,
courseName: course.courseName,
website: course.website,
@@ -69,6 +72,12 @@ export const courseCard = StrictDict({
isFinished: courseRun.isFinished,
minPassingGrade: Math.floor(courseRun.minPassingGrade * 100),
startDate: new Date(courseRun.startDate),
homeUrl: courseRun.homeUrl,
marketingUrl: courseRun.marketingUrl,
progressUrl: learningMfeUrl(courseRun.progressUrl),
unenrollUrl: learningMfeUrl(courseRun.unenrollUrl),
upgradeUrl: courseRun.upgradeUrl,
resumeUrl: learningMfeUrl(courseRun.resumeUrl),
})),
enrollment: mkCardSelector(({ enrollment }) => {
if (enrollment == null) {

View File

@@ -12,10 +12,15 @@ const courseUnenroll = `${baseUrl}/change_enrollment`;
const updateEmailSettings = `${api}/change_email_settings`;
const entitlementEnrollment = (uuid) => `${api}/entitlements/v1/entitlements/${uuid}/enrollments`;
const baseAppUrl = (url) => baseUrl + url;
const learningMfeUrl = (url) => configuration.LEARNING_MICROFRONTEND_URL + url;
export default StrictDict({
api,
init,
courseUnenroll,
updateEmailSettings,
entitlementEnrollment,
baseAppUrl,
learningMfeUrl,
});

View File

@@ -41,7 +41,7 @@ subscribe(APP_INIT_ERROR, (error) => {
);
});
export const appName = 'OraGradingAppConfig';
export const appName = 'LearnerHomeAppConfig';
initialize({
handlers: {