refactor(client): docs, ts and test challenges (#42978)

* refactor(client): relocate to learn path tests file

* refactor(client): add docs for to learn path

Co-authored-by: Huyen Nguyen <25715018+huyenltnguyen@users.noreply.github.com>

* fix: order imports

Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
Victor Duarte
2021-08-10 08:22:39 -05:00
committed by GitHub
parent 0de2cc97db
commit 7c6524186e
5 changed files with 125 additions and 66 deletions

View File

@ -1,38 +0,0 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
/**
* TODO:
* Passing incomplete objects here is causing TS to be angry.
* We should either make the expected properties optional, or reevaluate
* these tests.
*/
import { withPrefix } from 'gatsby';
import toLearnPath from '../utils/to-learn-path';
describe('toLearnPath', () => {
it('should return a string', () => {
expect(typeof toLearnPath({})).toBe('string');
});
it('should include /learn', () => {
expect(toLearnPath({})).toMatch(withPrefix('/learn'));
});
it('should include superBlock after learn', () => {
expect(toLearnPath({ superBlock: 'testSuper' })).toBe(
withPrefix('/learn/testSuper')
);
});
it('should include superBlock, then block after learn', () => {
expect(toLearnPath({ superBlock: 'testSuper', block: 'testBlock' })).toBe(
withPrefix('/learn/testSuper/testBlock')
);
});
it('should include superBlock, block, then challenge after learn', () => {
expect(
toLearnPath({
superBlock: 'testSuper',
block: 'testBlock',
challenge: 'testChallenge'
})
).toBe(withPrefix('/learn/testSuper/testBlock/testChallenge'));
});
});

View File

@ -0,0 +1,61 @@
import {
createHistory,
createMemorySource,
LocationProvider
} from '@reach/router';
import { render } from '@testing-library/react';
import { navigate, withPrefix } from 'gatsby';
import React from 'react';
import Challenges from './challenges';
describe('Challenges', () => {
// Source: https://testing-library.com/docs/example-reach-router/
function renderWithRouterWrapper({
route = '/',
history = createHistory(createMemorySource(route))
} = {}) {
return {
...render(
<LocationProvider history={history}>
<Challenges />
</LocationProvider>
),
// adding `history` to the returned utilities to allow us
// to reference it in our tests (just try to avoid using
// this to test implementation details).
history
};
}
const challenges = withPrefix('/challenges');
const learn = withPrefix('/learn');
it('should handle redirect to /learn', () => {
renderWithRouterWrapper({ route: challenges });
expect(navigate).toHaveBeenLastCalledWith(learn);
});
it('should handle redirect to /learn/:super-block', () => {
renderWithRouterWrapper({ route: `${challenges}/super-block` });
expect(navigate).toHaveBeenLastCalledWith(`${learn}/super-block`);
});
it('should handle redirect to /learn/:super-block/:block', () => {
renderWithRouterWrapper({ route: `${challenges}/super-block/block` });
expect(navigate).toHaveBeenLastCalledWith(`${learn}/super-block/block`);
});
it('should handle redirect to /learn/:super-block/:block/:challenge', () => {
renderWithRouterWrapper({
route: `${challenges}/super-block/block/challenge`
});
expect(navigate).toHaveBeenLastCalledWith(
`${learn}/super-block/block/challenge`
);
});
});

View File

@ -1,32 +1,25 @@
// this exists purely to redirect legacy challenge paths to /learn // This exists purely to redirect legacy challenge paths to /learn that could
import { Router } from '@reach/router'; // exist in the web (posts, url shares, etc).
import { Router, RouteComponentProps } from '@reach/router';
import { navigate, withPrefix } from 'gatsby'; import { navigate, withPrefix } from 'gatsby';
import React from 'react'; import React from 'react';
import toLearnPath from '../utils/to-learn-path'; import toLearnPath from '../utils/to-learn-path';
// interface RedirectProps1 { type RouteComponentPropsExtended = RouteComponentProps & {
// superBlock: string; block?: string;
// block: string; challenge?: string;
// challenge: string; superBlock?: string;
// } };
// interface RedirectProps2 { function Redirect(props: RouteComponentPropsExtended): null {
// path?: string;
// default?: boolean;
// }
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
function Redirect(props) {
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
void navigate(toLearnPath(props)); void navigate(toLearnPath(props));
} }
return null; return null;
} }
// Unsure about Redirect props shape:
// toLearnPath() takes required superBlock, block, and challenge props
// but usage below has optional path and default props
function Challenges(): JSX.Element { function Challenges(): JSX.Element {
return ( return (

View File

@ -0,0 +1,31 @@
import { withPrefix } from 'gatsby';
import toLearnPath from './to-learn-path';
describe('To learn path utility (toLearnPath)', () => {
const learn = withPrefix('/learn');
it('should include /learn', () => {
expect(toLearnPath({})).toMatch(`${learn}`);
});
it('should include superBlock after learn', () => {
expect(toLearnPath({ superBlock: 'testSuper' })).toBe(`${learn}/testSuper`);
});
it('should include superBlock, then block after learn', () => {
expect(toLearnPath({ block: 'testBlock', superBlock: 'testSuper' })).toBe(
`${learn}/testSuper/testBlock`
);
});
it('should include superBlock, block, then challenge after learn', () => {
expect(
toLearnPath({
block: 'testBlock',
challenge: 'testChallenge',
superBlock: 'testSuper'
})
).toBe(`${learn}/testSuper/testBlock/testChallenge`);
});
});

View File

@ -1,18 +1,30 @@
import { withPrefix } from 'gatsby'; import { withPrefix } from 'gatsby';
interface ToLearnPathKwargs { interface ToLearnPathKwargs {
superBlock: string; block?: string;
block: string; challenge?: string;
challenge: string; superBlock?: string;
} }
/**
* Builds a learning url path from folders.
* - /learn/:superBlock/:block/:challenge
* @params {Object} Path kwargs.
* @returns {string} A learning url path.
*/
export default function toLearnPath({ export default function toLearnPath({
superBlock,
block, block,
challenge challenge,
superBlock
}: ToLearnPathKwargs): string { }: ToLearnPathKwargs): string {
let path = withPrefix('/learn'); // Match path order /:super-block/:block/:challenge
if (superBlock) path += `/${superBlock}`; const folders = [superBlock, block, challenge];
if (block) path += `/${block}`;
if (challenge) path += `/${challenge}`; return folders.reduce((path: string, folder) => {
return path; if (folder) {
return `${path}/${folder}`;
}
return path;
}, withPrefix('/learn'));
} }