react-router#useOutlet TypeScript Examples

The following examples show how to use react-router#useOutlet. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: SettingsPage.tsx    From backstage with Apache License 2.0 6 votes vote down vote up
SettingsPage = ({ providerSettings }: Props) => {
  const { isMobile } = useSidebarPinState();
  const outlet = useOutlet();

  const tabs = useElementFilter(outlet, elements =>
    elements
      .selectByComponentData({
        key: USER_SETTINGS_TAB_KEY,
      })
      .getElements<UserSettingsTabProps>(),
  );

  return (
    <Page themeId="home">
      {!isMobile && <Header title="Settings" />}
      <TabbedLayout>
        <TabbedLayout.Route path="general" title="General">
          <UserSettingsGeneral />
        </TabbedLayout.Route>
        <TabbedLayout.Route
          path="auth-providers"
          title="Authentication Providers"
        >
          <UserSettingsAuthProviders providerSettings={providerSettings} />
        </TabbedLayout.Route>
        <TabbedLayout.Route path="feature-flags" title="Feature Flags">
          <UserSettingsFeatureFlags />
        </TabbedLayout.Route>

        {tabs.map((child, i) => (
          <TabbedLayout.Route key={i} {...child.props}>
            {child}
          </TabbedLayout.Route>
        ))}
      </TabbedLayout>
    </Page>
  );
}
Example #2
Source File: ApiExplorerPage.test.tsx    From backstage with Apache License 2.0 6 votes vote down vote up
describe('ApiExplorerPage', () => {
  it('renders provided router element', async () => {
    const { getByText } = await renderInTestApp(<ApiExplorerPage />);

    expect(getByText('Route Children')).toBeInTheDocument();
  });

  it('renders DefaultApiExplorerPage home when no router children are provided', async () => {
    (useOutlet as jest.Mock).mockReturnValueOnce(null);
    const { getByText } = await renderInTestApp(<ApiExplorerPage />);

    expect(getByText('DefaultApiExplorerPage')).toBeInTheDocument();
  });
});
Example #3
Source File: SettingsPage.test.tsx    From backstage with Apache License 2.0 6 votes vote down vote up
describe('<SettingsPage />', () => {
  beforeEach(() => {
    (useOutlet as jest.Mock).mockReset();
  });

  it('should render the settings page with 3 tabs', async () => {
    const { container } = await renderWithEffects(
      wrapInTestApp(<SettingsPage />),
    );

    const tabs = container.querySelectorAll('[class*=MuiTabs-root] button');
    expect(tabs).toHaveLength(3);
  });

  it('should render the settings page with 4 tabs when extra tabs are provided', async () => {
    const advancedTabRoute = (
      <UserSettingsTab path="/advanced" title="Advanced">
        <div>Advanced settings</div>
      </UserSettingsTab>
    );
    (useOutlet as jest.Mock).mockReturnValue(advancedTabRoute);
    const { container } = await renderWithEffects(
      wrapInTestApp(<SettingsPage />),
    );

    const tabs = container.querySelectorAll('[class*=MuiTabs-root] button');
    expect(tabs).toHaveLength(4);
    expect(tabs[3].textContent).toEqual('Advanced');
  });
});
Example #4
Source File: CatalogPage.test.tsx    From backstage with Apache License 2.0 6 votes vote down vote up
describe('CatalogPage', () => {
  it('renders provided router element', async () => {
    const { getByText } = await renderInTestApp(<CatalogPage />);

    expect(getByText('Route Children')).toBeInTheDocument();
  });

  it('renders DefaultCatalogPage home when no router children are provided', async () => {
    (useOutlet as jest.Mock).mockReturnValueOnce(null);
    const { getByText } = await renderInTestApp(<CatalogPage />);

    expect(getByText('DefaultCatalogPage')).toBeInTheDocument();
  });
});
Example #5
Source File: TechDocsIndexPage.test.tsx    From backstage with Apache License 2.0 6 votes vote down vote up
describe('TechDocsIndexPage', () => {
  it('renders provided router element', async () => {
    const { getByText } = await renderInTestApp(<TechDocsIndexPage />);

    expect(getByText('Route Children')).toBeInTheDocument();
  });

  it('renders DefaultTechDocsHome when no router children are provided', async () => {
    (useOutlet as jest.Mock).mockReturnValueOnce(null);
    const { getByText } = await renderInTestApp(<TechDocsIndexPage />);

    expect(getByText('DefaultTechDocsHomeMock')).toBeInTheDocument();
  });
});
Example #6
Source File: SearchPage.tsx    From backstage with Apache License 2.0 6 votes vote down vote up
SearchPage = () => {
  const outlet = useOutlet();

  return (
    <SearchContextProvider>
      <UrlUpdater />
      {outlet || <LegacySearchPage />}
    </SearchContextProvider>
  );
}
Example #7
Source File: ExplorePage.test.tsx    From backstage with Apache License 2.0 6 votes vote down vote up
describe('ExplorePage', () => {
  it('renders provided router element', async () => {
    const { getByText } = await renderInTestApp(<ExplorePage />);

    expect(getByText('Route Children')).toBeInTheDocument();
  });

  it('renders default explorer page when no router children are provided', async () => {
    (useOutlet as jest.Mock).mockReturnValueOnce(null);
    const { getByText } = await renderInTestApp(<ExplorePage />);

    expect(getByText('DefaultExplorePageMock')).toBeInTheDocument();
  });
});
Example #8
Source File: Router.tsx    From backstage with Apache License 2.0 6 votes vote down vote up
Router = (props: RouterProps) => {
  const { groups, components = {}, defaultPreviewTemplate } = props;

  const { TemplateCardComponent, TaskPageComponent } = components;

  const outlet = useOutlet();
  const TaskPageElement = TaskPageComponent ?? TaskPage;

  const customFieldExtensions = useElementFilter(outlet, elements =>
    elements
      .selectByComponentData({
        key: FIELD_EXTENSION_WRAPPER_KEY,
      })
      .findComponentData<FieldExtensionOptions>({
        key: FIELD_EXTENSION_KEY,
      }),
  );

  const fieldExtensions = [
    ...customFieldExtensions,
    ...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter(
      ({ name }) =>
        !customFieldExtensions.some(
          customFieldExtension => customFieldExtension.name === name,
        ),
    ),
  ];

  return (
    <Routes>
      <Route
        element={
          <ScaffolderPage
            groups={groups}
            TemplateCardComponent={TemplateCardComponent}
            contextMenu={props.contextMenu}
          />
        }
      />
      <Route
        path={selectedTemplateRouteRef.path}
        element={
          <SecretsContextProvider>
            <TemplatePage customFieldExtensions={fieldExtensions} />
          </SecretsContextProvider>
        }
      />
      <Route
        path={scaffolderListTaskRouteRef.path}
        element={<ListTasksPage />}
      />
      <Route path={scaffolderTaskRouteRef.path} element={<TaskPageElement />} />
      <Route path={actionsRouteRef.path} element={<ActionsPage />} />
      <Route
        path={editRouteRef.path}
        element={
          <SecretsContextProvider>
            <TemplateEditorPage
              defaultPreviewTemplate={defaultPreviewTemplate}
              customFieldExtensions={fieldExtensions}
            />
          </SecretsContextProvider>
        }
      />

      <Route path="preview" element={<Navigate to="../edit" />} />
    </Routes>
  );
}
Example #9
Source File: ExplorePage.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
ExplorePage = () => {
  const outlet = useOutlet();

  return <>{outlet || <DefaultExplorePage />}</>;
}
Example #10
Source File: SettingsPage.test.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
jest.mock('react-router', () => ({
  ...jest.requireActual('react-router'),
  useOutlet: jest.fn().mockReturnValue(undefined),
}));
Example #11
Source File: TechDocsIndexPage.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
TechDocsIndexPage = () => {
  const outlet = useOutlet();

  return outlet || <DefaultTechDocsHome />;
}
Example #12
Source File: TechDocsIndexPage.test.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
jest.mock('react-router', () => ({
  ...jest.requireActual('react-router'),
  useOutlet: jest.fn().mockReturnValue('Route Children'),
}));
Example #13
Source File: SearchPage.test.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
describe('SearchPage', () => {
  const origReplaceState = window.history.replaceState;

  beforeEach(() => {
    window.history.replaceState = jest.fn();
  });

  afterEach(() => {
    window.history.replaceState = origReplaceState;
  });

  it('sets term state from location', async () => {
    // Given this initial location.search value...
    const expectedFilterField = 'anyKey';
    const expectedFilterValue = 'anyValue';
    const expectedTerm = 'justin bieber';
    const expectedTypes = ['software-catalog'];
    const expectedFilters = { [expectedFilterField]: expectedFilterValue };
    const expectedPageCursor = 'SOMEPAGE';

    // e.g. ?query=petstore&pageCursor=SOMEPAGE&filters[lifecycle][]=experimental&filters[kind]=Component
    (useLocation as jest.Mock).mockReturnValue({
      search: `?query=${expectedTerm}&types[]=${expectedTypes[0]}&filters[${expectedFilterField}]=${expectedFilterValue}&pageCursor=${expectedPageCursor}`,
    });

    // When we render the page...
    await renderInTestApp(<SearchPage />);

    // Then search context should be set with these values...
    expect(setTermMock).toHaveBeenCalledWith(expectedTerm);
    expect(setTypesMock).toHaveBeenCalledWith(expectedTypes);
    expect(setPageCursorMock).toHaveBeenCalledWith(expectedPageCursor);
    expect(setFiltersMock).toHaveBeenCalledWith(expectedFilters);
  });

  it('renders provided router element', async () => {
    const { getByText } = await renderInTestApp(<SearchPage />);

    expect(getByText('Route Children')).toBeInTheDocument();
  });

  it('renders legacy search when no router children are provided', async () => {
    (useOutlet as jest.Mock).mockReturnValueOnce(null);
    const { getByText } = await renderInTestApp(<SearchPage />);

    expect(getByText('LegacySearchPageMock')).toBeInTheDocument();
  });

  it('replaces window history with expected query parameters', async () => {
    (useSearch as jest.Mock).mockReturnValueOnce({
      term: 'bieber',
      types: ['software-catalog'],
      pageCursor: 'SOMEPAGE',
      filters: { anyKey: 'anyValue' },
      setTerm: setTermMock,
      setTypes: setTypesMock,
      setFilters: setFiltersMock,
      setPageCursor: setPageCursorMock,
    });
    const expectedLocation = encodeURI(
      '?query=bieber&types[]=software-catalog&pageCursor=SOMEPAGE&filters[anyKey]=anyValue',
    );

    await renderInTestApp(<SearchPage />);

    const calls = (window.history.replaceState as jest.Mock).mock.calls[0];
    expect(calls[2]).toContain(expectedLocation);
  });
});
Example #14
Source File: SearchPage.test.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
jest.mock('react-router', () => ({
  ...jest.requireActual('react-router'),
  useLocation: jest.fn().mockReturnValue({
    search: '',
  }),
  useOutlet: jest.fn().mockReturnValue('Route Children'),
}));
Example #15
Source File: Router.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
Router = (props: PropsWithChildren<NextRouterProps>) => {
  const { components: { TemplateCardComponent } = {} } = props;

  const outlet = useOutlet() || props.children;

  const customFieldExtensions = useElementFilter(outlet, elements =>
    elements
      .selectByComponentData({
        key: FIELD_EXTENSION_WRAPPER_KEY,
      })
      .findComponentData<FieldExtensionOptions>({
        key: FIELD_EXTENSION_KEY,
      }),
  );

  const fieldExtensions = [
    ...customFieldExtensions,
    ...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter(
      ({ name }) =>
        !customFieldExtensions.some(
          customFieldExtension => customFieldExtension.name === name,
        ),
    ),
  ];

  return (
    <Routes>
      <Route
        element={
          <TemplateListPage
            TemplateCardComponent={TemplateCardComponent}
            groups={props.groups}
          />
        }
      />

      <Route
        path={selectedTemplateRouteRef.path}
        element={
          <SecretsContextProvider>
            <TemplateWizardPage customFieldExtensions={fieldExtensions} />
          </SecretsContextProvider>
        }
      />
    </Routes>
  );
}
Example #16
Source File: HomepageCompositionRoot.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
HomepageCompositionRoot = (props: {
  title?: string;
  children?: ReactNode;
}) => {
  const outlet = useOutlet();
  const children = props.children ?? outlet;
  return <>{children}</>;
}
Example #17
Source File: OpsgeniePage.tsx    From backstage-plugin-opsgenie with MIT License 5 votes vote down vote up
OpsgeniePage = () => {
  const outlet = useOutlet();

  return outlet || <DefaultOpsgeniePage />;
}
Example #18
Source File: ExplorePage.test.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
jest.mock('react-router', () => ({
  ...jest.requireActual('react-router'),
  useLocation: jest.fn().mockReturnValue({
    search: '',
  }),
  useOutlet: jest.fn().mockReturnValue('Route Children'),
}));
Example #19
Source File: ImportPage.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
ImportPage = () => {
  const outlet = useOutlet();

  return outlet || <DefaultImportPage />;
}
Example #20
Source File: ImportPage.test.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
describe('<ImportPage />', () => {
  const identityApi = {
    getUserId: () => {
      return 'user';
    },
    getProfile: () => {
      return {};
    },
    getIdToken: () => {
      return Promise.resolve('token');
    },
    signOut: () => {
      return Promise.resolve();
    },
    getProfileInfo: jest.fn(),
    getBackstageIdentity: jest.fn(),
    getCredentials: jest.fn(),
  };

  let apis: TestApiRegistry;

  beforeEach(() => {
    apis = TestApiRegistry.from(
      [configApiRef, new ConfigReader({ integrations: {} })],
      [catalogApiRef, new CatalogClient({ discoveryApi: {} as any })],
      [
        catalogImportApiRef,
        new CatalogImportClient({
          discoveryApi: {} as any,
          identityApi,
          scmAuthApi: {} as any,
          scmIntegrationsApi: {} as any,
          catalogApi: {} as any,
          configApi: new ConfigReader({}),
        }),
      ],
    );
  });

  afterEach(() => jest.resetAllMocks());

  it('renders without exploding', async () => {
    const { getByText } = await renderInTestApp(
      <ApiProvider apis={apis}>
        <ImportPage />
      </ApiProvider>,
    );

    expect(
      getByText('Start tracking your component in Backstage'),
    ).toBeInTheDocument();
  });

  it('renders with custom children', async () => {
    (useOutlet as jest.Mock).mockReturnValue(<div>Hello World</div>);

    const { getByText } = await renderInTestApp(
      <ApiProvider apis={apis}>
        <ImportPage />
      </ApiProvider>,
    );

    expect(getByText('Hello World')).toBeInTheDocument();
  });
});
Example #21
Source File: ImportPage.test.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
jest.mock('react-router', () => ({
  ...jest.requireActual('react-router'),
  useOutlet: jest.fn(),
}));
Example #22
Source File: CatalogPage.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
export function CatalogPage(props: DefaultCatalogPageProps) {
  const outlet = useOutlet();

  return outlet || <DefaultCatalogPage {...props} />;
}
Example #23
Source File: CatalogPage.test.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
jest.mock('react-router', () => ({
  ...jest.requireActual('react-router'),
  useOutlet: jest.fn().mockReturnValue('Route Children'),
}));
Example #24
Source File: ApiExplorerPage.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
ApiExplorerPage = (props: DefaultApiExplorerPageProps) => {
  const outlet = useOutlet();

  return outlet || <DefaultApiExplorerPage {...props} />;
}
Example #25
Source File: ApiExplorerPage.test.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
jest.mock('react-router', () => ({
  ...jest.requireActual('react-router'),
  useOutlet: jest.fn().mockReturnValue('Route Children'),
}));