Skip to content

Commit

Permalink
feat: add WIP RouterHistoryStore#nextUrl$ property
Browse files Browse the repository at this point in the history
  • Loading branch information
LayZeeDK committed May 22, 2023
1 parent 412324c commit 6120835
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ function createTestComponent(name: string, selector: string) {
>&lt; Back</a
>
<a
id="forward-link"
*ngIf="routerHistory.nextUrl$ | async as nextUrl"
[href]="nextUrl"
(click)="onNext($event)"
>&gt; Next</a
>
<a id="home-link" routerLink="/">Home</a>
<a id="about-link" routerLink="about">About</a>
<a id="company-link" routerLink="company">Company</a>
Expand All @@ -45,6 +53,11 @@ class TestAppComponent {
event.preventDefault();
this.routerHistory.onNavigateBack();
}

onNext(event: MouseEvent) {
event.preventDefault();
this.routerHistory.onNavigateForward();
}
}

describe(RouterHistoryStore.name, () => {
Expand Down Expand Up @@ -98,7 +111,7 @@ describe(RouterHistoryStore.name, () => {
}

it('the URLs behave like the History API when navigating using links', async () => {
expect.assertions(2);
expect.assertions(3);

const { click, routerHistory } = await setup();

Expand All @@ -112,10 +125,11 @@ describe(RouterHistoryStore.name, () => {

expect(await firstValueFrom(routerHistory.currentUrl$)).toBe('/products');
expect(await firstValueFrom(routerHistory.previousUrl$)).toBe('/company');
expect(await firstValueFrom(routerHistory.nextUrl$)).toBe(undefined);
});

it('the URLs behave like the History API when navigating back', async () => {
expect.assertions(2);
expect.assertions(3);

const { click, routerHistory } = await setup();

Expand All @@ -129,10 +143,31 @@ describe(RouterHistoryStore.name, () => {

expect(await firstValueFrom(routerHistory.currentUrl$)).toBe('/about');
expect(await firstValueFrom(routerHistory.previousUrl$)).toBe('/home');
expect(await firstValueFrom(routerHistory.nextUrl$)).toBe('/company');
});

it('the URLs behave like the History API when navigating back twice', async () => {
expect.assertions(3);

const { click, routerHistory } = await setup();

// At Home
await click('#about-link');
// At About
await click('#company-link');
// At Company
await click('#back-link');
// At About
await click('#back-link');
// At Home

expect(await firstValueFrom(routerHistory.currentUrl$)).toBe('/home');
expect(await firstValueFrom(routerHistory.previousUrl$)).toBe(undefined);
expect(await firstValueFrom(routerHistory.nextUrl$)).toBe('/about');
});

it('the URLs behave like the History API when navigating back then using links', async () => {
expect.assertions(2);
expect.assertions(3);

const { click, routerHistory } = await setup();

Expand All @@ -148,5 +183,34 @@ describe(RouterHistoryStore.name, () => {

expect(await firstValueFrom(routerHistory.currentUrl$)).toBe('/products');
expect(await firstValueFrom(routerHistory.previousUrl$)).toBe('/about');
expect(await firstValueFrom(routerHistory.nextUrl$)).toBe(undefined);
});

it('the URLs behave like the History API when navigating back then forward', async () => {
expect.assertions(3);

const { click, routerHistory } = await setup();

// At Home
await click('#about-link');
// At About
// Previous: Home
// Next: None
await click('#company-link');
// At Company
// Previous: About
// Next: None
await click('#back-link');
// At About
// Previous: Home
// Next: Company
await click('#forward-link');
// At Company
// Previous: About
// Next: None

expect(await firstValueFrom(routerHistory.currentUrl$)).toBe('/company');
expect(await firstValueFrom(routerHistory.previousUrl$)).toBe('/about');
expect(await firstValueFrom(routerHistory.nextUrl$)).toBe(undefined);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,38 @@ export class RouterHistoryStore extends ComponentStore<RouterHistoryState> {
this.#latestRouterNavigatedSequence$,
([, navigationEnd]) => navigationEnd.urlAfterRedirects
);
/**
* The next URL when taking `popstate` events into account.
*
* `undefined` is emitted when the current navigation is the last in the
* navigation history.
*/
nextUrl$: Observable<string | undefined> = this.select(
this.#history$,
this.#maxNavigatedId$,
(history, maxNavigatedId) => {
if (maxNavigatedId === 1) {
return undefined;
}

const [sourceNavigationStart] = this.#findSourceNavigatedSequence(
maxNavigatedId,
history
);

if (sourceNavigationStart.id === maxNavigatedId) {
return undefined;
}

const nextNavigationId = sourceNavigationStart.id + 1;
const [, nextNavigationEnd] = this.#findSourceNavigatedSequence(
nextNavigationId,
history
);

return nextNavigationEnd.urlAfterRedirects;
}
);
/**
* The previous URL when taking `popstate` events into account.
*
Expand Down

0 comments on commit 6120835

Please sign in to comment.