Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
349a458617 | ||
|
|
abe3d03f58 | ||
|
|
7af4b71faa | ||
|
|
7f2c5b32b1 | ||
|
|
6e0f9cf30a | ||
|
|
3dc70a890f | ||
|
|
a37ef7f701 |
@@ -7,6 +7,9 @@ frontend-component-footer
|
||||
frontend-component-footer is a library containing a site footer
|
||||
component for use when building edX frontend applications.
|
||||
|
||||
At this time, this componenet is hard-coded to match the legacy LMS site footer, including all of its links.
|
||||
Note: As implemented, it should really be called the ``frontend-component-lms-footer``.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
|
||||
16
package-lock.json
generated
16
package-lock.json
generated
@@ -21666,6 +21666,16 @@
|
||||
"snapdragon": "^0.8.1",
|
||||
"to-regex": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"watch": {
|
||||
"version": "0.18.0",
|
||||
"resolved": "https://registry.npmjs.org/watch/-/watch-0.18.0.tgz",
|
||||
"integrity": "sha1-KAlUdsbffJDJYxOJkMClQj60uYY=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"exec-sh": "^0.2.0",
|
||||
"minimist": "^1.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -24627,9 +24637,9 @@
|
||||
}
|
||||
},
|
||||
"watch": {
|
||||
"version": "0.18.0",
|
||||
"resolved": "https://registry.npmjs.org/watch/-/watch-0.18.0.tgz",
|
||||
"integrity": "sha1-KAlUdsbffJDJYxOJkMClQj60uYY=",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/watch/-/watch-1.0.2.tgz",
|
||||
"integrity": "sha1-NApxe952Vyb6CqB9ch4BR6VR3ww=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"exec-sh": "^0.2.0",
|
||||
|
||||
@@ -78,7 +78,6 @@
|
||||
"peerDependencies": {
|
||||
"@edx/paragon": "^3.8.0",
|
||||
"clean-webpack-plugin": "^0.1.19",
|
||||
"copy-webpack-plugin": "^4.6.0",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"prop-types": "^15.5.10",
|
||||
"react": "^16.4.2",
|
||||
|
||||
@@ -1,81 +1,112 @@
|
||||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import { mount } from 'enzyme';
|
||||
|
||||
import FooterLogo from '../../../edx-footer.png';
|
||||
import SiteFooter from '../../index';
|
||||
import SiteFooter, { EVENT_NAMES } from './index';
|
||||
|
||||
const completeSiteFooterComponent = mockHandleAllTrackEvents =>
|
||||
(<SiteFooter
|
||||
siteName="example"
|
||||
siteLogo={FooterLogo}
|
||||
marketingSiteBaseUrl="https://www.example.com"
|
||||
supportUrl="https://www.example.com/support"
|
||||
contactUrl="https://www.example.com/contact"
|
||||
openSourceUrl="https://www.example.com/open"
|
||||
termsOfServiceUrl="https://www.example.com/terms-of-service"
|
||||
privacyPolicyUrl="https://www.example.com/privacy-policy"
|
||||
facebookUrl="https://www.facebook.com"
|
||||
twitterUrl="https://www.twitter.com"
|
||||
youTubeUrl="https://www.youtube.com"
|
||||
linkedInUrl="https://www.linkedin.com"
|
||||
googlePlusUrl="https://plus.google.com"
|
||||
redditUrl="https://reddit.com"
|
||||
appleAppStoreUrl="https://store.apple.com"
|
||||
googlePlayUrl="https://play.google.com"
|
||||
handleAllTrackEvents={mockHandleAllTrackEvents}
|
||||
/>);
|
||||
|
||||
describe('<SiteFooter />', () => {
|
||||
it('renders correctly', () => {
|
||||
const tree = renderer
|
||||
.create(<SiteFooter
|
||||
siteName="example"
|
||||
siteLogo={FooterLogo}
|
||||
marketingSiteBaseUrl="https://www.example.com"
|
||||
supportUrl="https://www.example.com/support"
|
||||
contactUrl="https://www.example.com/contact"
|
||||
openSourceUrl="https://www.example.com/open"
|
||||
termsOfServiceUrl="https://www.example.com/terms-of-service"
|
||||
privacyPolicyUrl="https://www.example.com/privacy-policy"
|
||||
facebookUrl="https://www.facebook.com"
|
||||
twitterUrl="https://www.twitter.com"
|
||||
youTubeUrl="https://www.youtube.com"
|
||||
linkedInUrl="https://www.linkedin.com"
|
||||
googlePlusUrl="https://plus.google.com"
|
||||
redditUrl="https://reddit.com"
|
||||
appleAppStoreUrl="https://store.apple.com"
|
||||
googlePlayUrl="https://play.google.com"
|
||||
/>)
|
||||
.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
describe('renders correctly', () => {
|
||||
it('renders with social and mobile links', () => {
|
||||
const mockHandleAllTrackEvents = jest.fn();
|
||||
const tree = renderer
|
||||
.create(completeSiteFooterComponent(mockHandleAllTrackEvents))
|
||||
.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('does not render social links', () => {
|
||||
const tree = renderer
|
||||
.create(<SiteFooter
|
||||
siteName="example"
|
||||
siteLogo={FooterLogo}
|
||||
marketingSiteBaseUrl="https://www.example.com"
|
||||
supportUrl="https://www.example.com/support"
|
||||
contactUrl="https://www.example.com/contact"
|
||||
openSourceUrl="https://www.example.com/open"
|
||||
termsOfServiceUrl="https://www.example.com/terms-of-service"
|
||||
privacyPolicyUrl="https://www.example.com/privacy-policy"
|
||||
facebookUrl="https://www.facebook.com"
|
||||
twitterUrl="https://www.twitter.com"
|
||||
youTubeUrl="https://www.youtube.com"
|
||||
linkedInUrl="https://www.linkedin.com"
|
||||
googlePlusUrl="https://plus.google.com"
|
||||
redditUrl="https://reddit.com"
|
||||
appleAppStoreUrl="https://store.apple.com"
|
||||
googlePlayUrl="https://play.google.com"
|
||||
handleAllTrackEvents={jest.fn()}
|
||||
showSocialLinks={false}
|
||||
/>)
|
||||
.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('does not render mobile links', () => {
|
||||
const tree = renderer
|
||||
.create(<SiteFooter
|
||||
siteName="example"
|
||||
siteLogo={FooterLogo}
|
||||
marketingSiteBaseUrl="https://www.example.com"
|
||||
supportUrl="https://www.example.com/support"
|
||||
contactUrl="https://www.example.com/contact"
|
||||
openSourceUrl="https://www.example.com/open"
|
||||
termsOfServiceUrl="https://www.example.com/terms-of-service"
|
||||
privacyPolicyUrl="https://www.example.com/privacy-policy"
|
||||
facebookUrl="https://www.facebook.com"
|
||||
twitterUrl="https://www.twitter.com"
|
||||
youTubeUrl="https://www.youtube.com"
|
||||
linkedInUrl="https://www.linkedin.com"
|
||||
googlePlusUrl="https://plus.google.com"
|
||||
redditUrl="https://reddit.com"
|
||||
appleAppStoreUrl="https://store.apple.com"
|
||||
googlePlayUrl="https://play.google.com"
|
||||
handleAllTrackEvents={jest.fn()}
|
||||
showMobileLinks={false}
|
||||
/>)
|
||||
.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
it('does not render social links', () => {
|
||||
const tree = renderer
|
||||
.create(<SiteFooter
|
||||
siteName="example"
|
||||
siteLogo={FooterLogo}
|
||||
marketingSiteBaseUrl="https://www.example.com"
|
||||
supportUrl="https://www.example.com/support"
|
||||
contactUrl="https://www.example.com/contact"
|
||||
openSourceUrl="https://www.example.com/open"
|
||||
termsOfServiceUrl="https://www.example.com/terms-of-service"
|
||||
privacyPolicyUrl="https://www.example.com/privacy-policy"
|
||||
facebookUrl="https://www.facebook.com"
|
||||
twitterUrl="https://www.twitter.com"
|
||||
youTubeUrl="https://www.youtube.com"
|
||||
linkedInUrl="https://www.linkedin.com"
|
||||
googlePlusUrl="https://plus.google.com"
|
||||
redditUrl="https://reddit.com"
|
||||
appleAppStoreUrl="https://store.apple.com"
|
||||
googlePlayUrl="https://play.google.com"
|
||||
showSocialLinks={false}
|
||||
/>)
|
||||
.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
describe('handles analytics', () => {
|
||||
it('calls handleAllTrackEvents prop when external links clicked', () => {
|
||||
const mockHandleAllTrackEvents = jest.fn();
|
||||
const footer = mount((completeSiteFooterComponent(mockHandleAllTrackEvents)));
|
||||
const externalLinks = footer.find("a[target='_blank']");
|
||||
|
||||
it('does not render mobile links', () => {
|
||||
const tree = renderer
|
||||
.create(<SiteFooter
|
||||
siteName="example"
|
||||
siteLogo={FooterLogo}
|
||||
marketingSiteBaseUrl="https://www.example.com"
|
||||
supportUrl="https://www.example.com/support"
|
||||
contactUrl="https://www.example.com/contact"
|
||||
openSourceUrl="https://www.example.com/open"
|
||||
termsOfServiceUrl="https://www.example.com/terms-of-service"
|
||||
privacyPolicyUrl="https://www.example.com/privacy-policy"
|
||||
facebookUrl="https://www.facebook.com"
|
||||
twitterUrl="https://www.twitter.com"
|
||||
youTubeUrl="https://www.youtube.com"
|
||||
linkedInUrl="https://www.linkedin.com"
|
||||
googlePlusUrl="https://plus.google.com"
|
||||
redditUrl="https://reddit.com"
|
||||
appleAppStoreUrl="https://store.apple.com"
|
||||
googlePlayUrl="https://play.google.com"
|
||||
showMobileLinks={false}
|
||||
/>)
|
||||
.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
expect(externalLinks).toHaveLength(8);
|
||||
externalLinks.forEach((externalLink) => {
|
||||
const callIndex = mockHandleAllTrackEvents.mock.calls.length;
|
||||
externalLink.simulate('click');
|
||||
expect(mockHandleAllTrackEvents.mock.calls[callIndex]).toEqual([
|
||||
EVENT_NAMES.FOOTER_LINK,
|
||||
{
|
||||
category: 'outbound_link',
|
||||
label: externalLink.prop('href'),
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<SiteFooter /> does not render mobile links 1`] = `
|
||||
exports[`<SiteFooter /> renders correctly does not render mobile links 1`] = `
|
||||
<footer
|
||||
aria-label="Page Footer"
|
||||
className="footer d-flex justify-content-center border-top py-3 px-4"
|
||||
@@ -188,7 +188,7 @@ exports[`<SiteFooter /> does not render mobile links 1`] = `
|
||||
<span
|
||||
aria-hidden={true}
|
||||
className="fa fa-facebook-square fa-2x"
|
||||
id="Icon1"
|
||||
id="edx-footer-icon-facebook"
|
||||
/>
|
||||
<span
|
||||
className="sr-only"
|
||||
@@ -208,7 +208,7 @@ exports[`<SiteFooter /> does not render mobile links 1`] = `
|
||||
<span
|
||||
aria-hidden={true}
|
||||
className="fa fa-twitter-square fa-2x"
|
||||
id="Icon1"
|
||||
id="edx-footer-icon-twitter"
|
||||
/>
|
||||
<span
|
||||
className="sr-only"
|
||||
@@ -220,6 +220,7 @@ exports[`<SiteFooter /> does not render mobile links 1`] = `
|
||||
<li>
|
||||
<a
|
||||
href="https://www.youtube.com"
|
||||
onClick={[Function]}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
title="Youtube"
|
||||
@@ -227,7 +228,7 @@ exports[`<SiteFooter /> does not render mobile links 1`] = `
|
||||
<span
|
||||
aria-hidden={true}
|
||||
className="fa fa-youtube-square fa-2x"
|
||||
id="Icon1"
|
||||
id="edx-footer-icon-youtube"
|
||||
/>
|
||||
<span
|
||||
className="sr-only"
|
||||
@@ -247,7 +248,7 @@ exports[`<SiteFooter /> does not render mobile links 1`] = `
|
||||
<span
|
||||
aria-hidden={true}
|
||||
className="fa fa-linkedin-square fa-2x"
|
||||
id="Icon1"
|
||||
id="edx-footer-icon-linkedin"
|
||||
/>
|
||||
<span
|
||||
className="sr-only"
|
||||
@@ -267,7 +268,7 @@ exports[`<SiteFooter /> does not render mobile links 1`] = `
|
||||
<span
|
||||
aria-hidden={true}
|
||||
className="fa fa-google-plus-square fa-2x"
|
||||
id="Icon1"
|
||||
id="edx-footer-icon-google"
|
||||
/>
|
||||
<span
|
||||
className="sr-only"
|
||||
@@ -311,7 +312,7 @@ exports[`<SiteFooter /> does not render mobile links 1`] = `
|
||||
</footer>
|
||||
`;
|
||||
|
||||
exports[`<SiteFooter /> does not render social links 1`] = `
|
||||
exports[`<SiteFooter /> renders correctly does not render social links 1`] = `
|
||||
<footer
|
||||
aria-label="Page Footer"
|
||||
className="footer d-flex justify-content-center border-top py-3 px-4"
|
||||
@@ -531,7 +532,7 @@ exports[`<SiteFooter /> does not render social links 1`] = `
|
||||
</footer>
|
||||
`;
|
||||
|
||||
exports[`<SiteFooter /> renders correctly 1`] = `
|
||||
exports[`<SiteFooter /> renders correctly renders with social and mobile links 1`] = `
|
||||
<footer
|
||||
aria-label="Page Footer"
|
||||
className="footer d-flex justify-content-center border-top py-3 px-4"
|
||||
@@ -719,7 +720,7 @@ exports[`<SiteFooter /> renders correctly 1`] = `
|
||||
<span
|
||||
aria-hidden={true}
|
||||
className="fa fa-facebook-square fa-2x"
|
||||
id="Icon1"
|
||||
id="edx-footer-icon-facebook"
|
||||
/>
|
||||
<span
|
||||
className="sr-only"
|
||||
@@ -739,7 +740,7 @@ exports[`<SiteFooter /> renders correctly 1`] = `
|
||||
<span
|
||||
aria-hidden={true}
|
||||
className="fa fa-twitter-square fa-2x"
|
||||
id="Icon1"
|
||||
id="edx-footer-icon-twitter"
|
||||
/>
|
||||
<span
|
||||
className="sr-only"
|
||||
@@ -751,6 +752,7 @@ exports[`<SiteFooter /> renders correctly 1`] = `
|
||||
<li>
|
||||
<a
|
||||
href="https://www.youtube.com"
|
||||
onClick={[Function]}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
title="Youtube"
|
||||
@@ -758,7 +760,7 @@ exports[`<SiteFooter /> renders correctly 1`] = `
|
||||
<span
|
||||
aria-hidden={true}
|
||||
className="fa fa-youtube-square fa-2x"
|
||||
id="Icon1"
|
||||
id="edx-footer-icon-youtube"
|
||||
/>
|
||||
<span
|
||||
className="sr-only"
|
||||
@@ -778,7 +780,7 @@ exports[`<SiteFooter /> renders correctly 1`] = `
|
||||
<span
|
||||
aria-hidden={true}
|
||||
className="fa fa-linkedin-square fa-2x"
|
||||
id="Icon1"
|
||||
id="edx-footer-icon-linkedin"
|
||||
/>
|
||||
<span
|
||||
className="sr-only"
|
||||
@@ -798,7 +800,7 @@ exports[`<SiteFooter /> renders correctly 1`] = `
|
||||
<span
|
||||
aria-hidden={true}
|
||||
className="fa fa-google-plus-square fa-2x"
|
||||
id="Icon1"
|
||||
id="edx-footer-icon-google"
|
||||
/>
|
||||
<span
|
||||
className="sr-only"
|
||||
|
||||
@@ -59,7 +59,7 @@ class SiteFooter extends React.Component {
|
||||
target="_blank"
|
||||
onClick={this.externalLinkClickHandler}
|
||||
>
|
||||
<Icon className={['fa', 'fa-facebook-square', 'fa-2x']} screenReaderText={`Like ${siteName} on Facebook`} />
|
||||
<Icon id="edx-footer-icon-facebook" className={['fa', 'fa-facebook-square', 'fa-2x']} screenReaderText={`Like ${siteName} on Facebook`} />
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -72,7 +72,7 @@ class SiteFooter extends React.Component {
|
||||
target="_blank"
|
||||
onClick={this.externalLinkClickHandler}
|
||||
>
|
||||
<Icon className={['fa', 'fa-twitter-square', 'fa-2x']} screenReaderText={`Follow ${siteName} on Twitter`} />
|
||||
<Icon id="edx-footer-icon-twitter" className={['fa', 'fa-twitter-square', 'fa-2x']} screenReaderText={`Follow ${siteName} on Twitter`} />
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
@@ -81,8 +81,9 @@ class SiteFooter extends React.Component {
|
||||
title="Youtube"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
onClick={this.externalLinkClickHandler}
|
||||
>
|
||||
<Icon className={['fa', 'fa-youtube-square', 'fa-2x']} screenReaderText={`Subscribe to the ${siteName} YouTube channel`} />
|
||||
<Icon id="edx-footer-icon-youtube" className={['fa', 'fa-youtube-square', 'fa-2x']} screenReaderText={`Subscribe to the ${siteName} YouTube channel`} />
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
@@ -93,7 +94,7 @@ class SiteFooter extends React.Component {
|
||||
target="_blank"
|
||||
onClick={this.externalLinkClickHandler}
|
||||
>
|
||||
<Icon className={['fa', 'fa-linkedin-square', 'fa-2x']} screenReaderText={`Follow ${siteName} on LinkedIn`} />
|
||||
<Icon id="edx-footer-icon-linkedin" className={['fa', 'fa-linkedin-square', 'fa-2x']} screenReaderText={`Follow ${siteName} on LinkedIn`} />
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
@@ -104,7 +105,7 @@ class SiteFooter extends React.Component {
|
||||
target="_blank"
|
||||
onClick={this.externalLinkClickHandler}
|
||||
>
|
||||
<Icon className={['fa', 'fa-google-plus-square', 'fa-2x']} screenReaderText={`Follow ${siteName} on Google+`} />
|
||||
<Icon id="edx-footer-icon-google" className={['fa', 'fa-google-plus-square', 'fa-2x']} screenReaderText={`Follow ${siteName} on Google+`} />
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
|
||||
Reference in New Issue
Block a user