UrlStore with SignalStore

The store that can save the current route

type UrlState = {
  url: string | null;
};

const initialState: UrlState = {
  url: null,
};

export const UrlStore = signalStore(
  { providedIn: 'root' },
  withState(initialState),
  withMethods((store, router = inject(Router)) => ({
    setCurrentUrl(): void {
      patchState(store, () => ({ url: router.url }));
    },
    clearUrl(): void {
      patchState(store, () => ({ url: null }));
    },
  })),
  withComputed((store) => ({
    hasUrl: computed(() => !!store.url()),
  })),
);

And a small test to go along with it

describe('UrlStore', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
// The DummyComponent can be a shared empty component without any logic and an empty template.
      providers: [UrlStore, provideRouter([{ path: 'detail/:id', component: DummyComponent }])],
    });
  });

  it('should start with a default state', () => {
    const store = TestBed.inject(UrlStore);

    expect(store.url()).toBeNull();
  });

  it('should have the correct URL when set', async () => {
    const store = TestBed.inject(UrlStore);
    await RouterTestingHarness.create('detail/6?foo=bar');

    store.setCurrentUrl();

    expect(store.url()).toEqual('/detail/6?foo=bar');
  });

  it('should return the correct computation for hasUrl when the url is set', async () => {
    const store = TestBed.inject(UrlStore);
    await RouterTestingHarness.create('detail/6?foo=bar');

    store.setCurrentUrl();

    expect(store.hasUrl()).toBe(true);
  });
});