Skip to content

Commit

Permalink
Merge pull request #45 from BrightspaceUILabs/jorge-ramirez-arredondo…
Browse files Browse the repository at this point in the history
…/NavigateAndRedirectFns

feat: Export separate navigate and redirect functions
  • Loading branch information
jorge-ramirez-arredondo authored Oct 17, 2024
2 parents d38d0a2 + 8acdd8c commit 86be5b2
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 30 deletions.
40 changes: 24 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The aim of this library is to provide an easy way to define routes, lazy load th
> - [ ] [Visual diff tests](https://daylight.d2l.dev/developing/testing/visual-difference/)
> - [ ] Localization with Serge (if applicable)
> - [x] Demo page
> - [ ] README documentation
> - [ ] README documentation
## Route Loading and Registration
```js
Expand Down Expand Up @@ -65,14 +65,14 @@ The view is given a context object that contains:
- route: The route pattern given to the view in the router.
- title: The title in the push state.
```js
```js
pattern: '/user/:id/:page' // search: ?semester=1
view: ctx => html`
<user-view
<user-view
id=${ctx.options.id}
page=${ctx.params.page}
semester=${ctx.search.semester}>
</user-view>`
page=${ctx.params.page}
semester=${ctx.search.semester}>
</user-view>`
```
### Multiple Route Loaders
Expand Down Expand Up @@ -122,10 +122,10 @@ export const loader () => [
]
```
Route-loaders can be nested as far as you would like. You could have a folder path `/src/user/settings/profile/password` and have route-loaders at each point that import the next route-loader one level above. Therefore,
Route-loaders can be nested as far as you would like. You could have a folder path `/src/user/settings/profile/password` and have route-loaders at each point that import the next route-loader one level above. Therefore,
`/user/route-loader.js` could import and register
`/user/settings/route-loader.js` which in turn imports and registers
`/user/route-loader.js` could import and register
`/user/settings/route-loader.js` which in turn imports and registers
`/user/settings/profile/route-loaders.js`.
and on and on...
Expand Down Expand Up @@ -172,7 +172,7 @@ class FooBar extends LitElement {
```bash
npm i
npm run start
npm run start
```
### Testing
Expand All @@ -181,13 +181,13 @@ npm run start
npm test
```
The repo is based on the @open-wc template and comes with husky. Testing will run each time you commit. Failed tests may keep you from pushing. Prettier is also used to format the code. You may need to run
The repo is based on the @open-wc template and comes with husky. Testing will run each time you commit. Failed tests may keep you from pushing. Prettier is also used to format the code. You may need to run
```
npx run prettier:write
```
to silence any Prettier related errors. Husky runs the above command on commit so it is probably unnecessary.
to silence any Prettier related errors. Husky runs the above command on commit so it is probably unnecessary.
For testing page routing in your application we recommend using this template.
Expand All @@ -196,7 +196,7 @@ describe('Page Routing', () => {
beforeEach(async () => {
initRouter(); // Either initialize your routes here or import a file that calls routeRegister and make a way to recall it.
entryPoint = await fixture(html`<!-- Your ViewReactor component here -->`);
redirect('/'); // Reset tests back to the index, clears the url
navigate('/'); // Reset tests back to the index, clears the url
});

afterEach(() => {
Expand All @@ -215,9 +215,17 @@ To learn how to create major releases and release from maintenance branches, ref
## Helpers
### Redirecting
### Navigating and Redirecting
Page.js will hook into any `<a>` tags and handle the navigation but if you want to navigate in javascript you can use `navigate(path)`:
```js
import { navigate } from '@brightspace-ui-labs/router';

navigate('/');
```
Page.js will hook into any `<a>` tags and run the redirect but if you want to redirect in javascript you can use.
If you wish to programmatically redirect to a page and have the previous history item be replaced with the new one, you can use `redirect(path)`:
```js
import { redirect } from '@brightspace-ui-labs/router';
Expand All @@ -229,7 +237,7 @@ redirect('/');
Options are the second parameter in the registerRoutes functions. The two tables below encompasses all of the attributes that the options object can use.
The configurable page.js options are
The configurable page.js options are
| Name | Description | Default |
| :------------------ | :---------------------------------------------------------------------: | ------: |
Expand Down
10 changes: 9 additions & 1 deletion router.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,16 @@ const addMiddleware = callback => {
});
};

// Triggers navigation to the specified route path.
// Creates a new entry in the browser's history stack.
export const navigate = path => {
activePage.show(path);
};

// Triggers navigation to the specified route path.
// Replaces the current entry in the browser's history stack.
export const redirect = path => {
activePage(path);
activePage.redirect(path);
};

export class ContextReactor {
Expand Down
26 changes: 13 additions & 13 deletions test/router.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable no-return-assign */
/* eslint-disable no-new */
import { aTimeout, expect, fixture, html, waitUntil } from '@open-wc/testing';
import { registerRoutes, redirect, RouterTesting } from '../router.js';
import { navigate, registerRoutes, RouterTesting } from '../router.js';
import { loader as load1 } from './helpers/route-loader-1.js';
import { loader as load2 } from './helpers/route-loader-2.js';
import './helpers/main-view.js';
Expand Down Expand Up @@ -67,7 +67,7 @@ describe('Router', () => {
entryPoint = await fixture(
html`<main-view main-prop="Passed"></main-view>`
);
redirect('/');
navigate('/');
});

afterEach(() => {
Expand All @@ -94,7 +94,7 @@ describe('Router', () => {
let p = entryPoint.shadowRoot.querySelector('p').innerText;
expect(p).to.equal('Index');

redirect('/user');
navigate('/user');
await waitUntil(
() => entryPoint.shadowRoot.querySelector('p').innerText === 'User'
);
Expand All @@ -104,15 +104,15 @@ describe('Router', () => {

it('Should load routes from separate files', async () => {
await waitUntil(() => entryPoint.shadowRoot.querySelector('p'));
redirect('/load1');
navigate('/load1');
await waitUntil(
() =>
entryPoint.shadowRoot.querySelector('p').innerText === 'Load 1'
);
let p = entryPoint.shadowRoot.querySelector('p').innerText;
expect(p).to.equal('Load 1');

redirect('/load2');
navigate('/load2');
await waitUntil(
() =>
entryPoint.shadowRoot.querySelector('p').innerText === 'Load 2'
Expand All @@ -122,14 +122,14 @@ describe('Router', () => {
});

it('Should lazy import route dependencies', async () => {
redirect('/lazy');
navigate('/lazy');

await waitUntil(() => customElements.get('lazy-view'));
expect(customElements.get('lazy-view')).to.exist;
});

it('Should pass the context on redirect', async () => {
redirect('/param/hello?test=hello');
navigate('/param/hello?test=hello');
await waitUntil(() =>
entryPoint.shadowRoot.querySelector('route-view')
);
Expand All @@ -144,28 +144,28 @@ describe('Router', () => {
});

it('Should pass parameters', async () => {
redirect('/param/beep/boop');
navigate('/param/beep/boop');
await waitUntil(() => entryPoint.shadowRoot.querySelector('p'));
const p = entryPoint.shadowRoot.querySelector('p').innerText;
expect(p).to.eql('beep, boop,');
});

it('Should pass parameters with search param at the end', async () => {
redirect('/param/zip/zap?test=zop');
navigate('/param/zip/zap?test=zop');
await waitUntil(() => entryPoint.shadowRoot.querySelector('p'));
const p = entryPoint.shadowRoot.querySelector('p').innerText;
expect(p).to.eql('zip, zap, zop');
});

it('Should pass a search parameter without any url params', async () => {
redirect('/search?test=test');
navigate('/search?test=test');
await waitUntil(() => entryPoint.shadowRoot.querySelector('p'));
const p = entryPoint.shadowRoot.querySelector('p').innerText;
expect(p).to.eql('test');
});

it('Should redirect', async () => {
redirect('/redirect');
navigate('/redirect');
await entryPoint.updateComplete;
await aTimeout(50);
await waitUntil(
Expand All @@ -177,7 +177,7 @@ describe('Router', () => {
});

it('Should receive passed values from entry-point', async () => {
redirect('/entry-prop');
navigate('/entry-prop');
await entryPoint.updateComplete;
await waitUntil(
() => entryPoint.shadowRoot.querySelector('p') !== null
Expand All @@ -187,7 +187,7 @@ describe('Router', () => {
});

it('Should receive entry-point as this', async () => {
redirect('/entry-this');
navigate('/entry-this');
await entryPoint.updateComplete;
await waitUntil(
() => entryPoint.shadowRoot.querySelector('p') !== null
Expand Down

0 comments on commit 86be5b2

Please sign in to comment.