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
|
// 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 (
|
||||||
|
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';
|
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'));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user