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:
@ -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'));
|
||||
});
|
||||
});
|
61
client/src/pages/challenges.test.tsx
Normal file
61
client/src/pages/challenges.test.tsx
Normal 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`
|
||||
);
|
||||
});
|
||||
});
|
@ -1,32 +1,25 @@
|
||||
// this exists purely to redirect legacy challenge paths to /learn
|
||||
import { Router } from '@reach/router';
|
||||
// This exists purely to redirect legacy challenge paths to /learn that could
|
||||
// exist in the web (posts, url shares, etc).
|
||||
|
||||
import { Router, RouteComponentProps } from '@reach/router';
|
||||
import { navigate, withPrefix } from 'gatsby';
|
||||
import React from 'react';
|
||||
|
||||
import toLearnPath from '../utils/to-learn-path';
|
||||
|
||||
// interface RedirectProps1 {
|
||||
// superBlock: string;
|
||||
// block: string;
|
||||
// challenge: string;
|
||||
// }
|
||||
type RouteComponentPropsExtended = RouteComponentProps & {
|
||||
block?: string;
|
||||
challenge?: string;
|
||||
superBlock?: string;
|
||||
};
|
||||
|
||||
// interface RedirectProps2 {
|
||||
// path?: string;
|
||||
// default?: boolean;
|
||||
// }
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
function Redirect(props) {
|
||||
function Redirect(props: RouteComponentPropsExtended): null {
|
||||
if (typeof window !== 'undefined') {
|
||||
void navigate(toLearnPath(props));
|
||||
}
|
||||
|
||||
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 {
|
||||
return (
|
||||
|
31
client/src/utils/to-learn-path.test.ts
Normal file
31
client/src/utils/to-learn-path.test.ts
Normal 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`);
|
||||
});
|
||||
});
|
@ -1,18 +1,30 @@
|
||||
import { withPrefix } from 'gatsby';
|
||||
|
||||
interface ToLearnPathKwargs {
|
||||
superBlock: string;
|
||||
block: string;
|
||||
challenge: string;
|
||||
block?: 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({
|
||||
superBlock,
|
||||
block,
|
||||
challenge
|
||||
challenge,
|
||||
superBlock
|
||||
}: ToLearnPathKwargs): string {
|
||||
let path = withPrefix('/learn');
|
||||
if (superBlock) path += `/${superBlock}`;
|
||||
if (block) path += `/${block}`;
|
||||
if (challenge) path += `/${challenge}`;
|
||||
return path;
|
||||
// Match path order /:super-block/:block/:challenge
|
||||
const folders = [superBlock, block, challenge];
|
||||
|
||||
return folders.reduce((path: string, folder) => {
|
||||
if (folder) {
|
||||
return `${path}/${folder}`;
|
||||
}
|
||||
|
||||
return path;
|
||||
}, withPrefix('/learn'));
|
||||
}
|
||||
|
Reference in New Issue
Block a user