Skip to content

Commit

Permalink
[Issue #1868] Enforce absolute imports outside of the same directory (#…
Browse files Browse the repository at this point in the history
…2192)

## Summary
Fixes #1868

### Time to review: __5 mins__

## Changes proposed
Enforces absolute imports outside of the same directory.
  • Loading branch information
acouch authored Sep 23, 2024
1 parent 811c2e9 commit c3590d8
Show file tree
Hide file tree
Showing 26 changed files with 62 additions and 53 deletions.
11 changes: 11 additions & 0 deletions frontend/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ module.exports = {
// dependencies to work in standalone mode. It may be overkill for most projects at
// Nava which aren't image heavy.
"@next/next/no-img-element": "off",
"no-restricted-imports": [
"error",
{
patterns: [
{
group: ["../"],
message: "Relative imports are not allowed.",
},
],
},
],
},
// Additional lint rules. These get layered onto the top-level rules.
overrides: [
Expand Down
3 changes: 1 addition & 2 deletions frontend/.storybook/I18nStoryWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
* @see https://storybook.js.org/docs/writing-stories/decorators
*/
import { StoryContext } from "@storybook/react";
import { defaultLocale, formats, timeZone } from "src/i18n/config";

import { NextIntlClientProvider } from "next-intl";
import React from "react";

import { defaultLocale, formats, timeZone } from "../src/i18n/config";

const I18nStoryWrapper = (
Story: React.ComponentType,
context: StoryContext,
Expand Down
7 changes: 4 additions & 3 deletions frontend/.storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
*/
import { Loader, Preview } from "@storybook/react";

import "../src/styles/styles.scss";
import "src/styles/styles.scss";

import { defaultLocale, locales } from "src/i18n/config";
import { getMessagesWithFallbacks } from "src/i18n/getMessagesWithFallbacks";

import { defaultLocale, locales } from "../src/i18n/config";
import { getMessagesWithFallbacks } from "../src/i18n/getMessagesWithFallbacks";
import I18nStoryWrapper from "./I18nStoryWrapper";

const parameters = {
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/app/[locale]/opportunity/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Metadata } from "next";
import OpportunityListingAPI from "src/app/api/OpportunityListingAPI";
import NotFound from "src/app/not-found";
import { OPPORTUNITY_CRUMBS } from "src/constants/breadcrumbs";
import withFeatureFlag from "src/hoc/search/withFeatureFlag";
import {
Expand All @@ -17,8 +19,6 @@ import OpportunityHistory from "src/components/opportunity/OpportunityHistory";
import OpportunityIntro from "src/components/opportunity/OpportunityIntro";
import OpportunityLink from "src/components/opportunity/OpportunityLink";
import OpportunityStatusWidget from "src/components/opportunity/OpportunityStatusWidget";
import OpportunityListingAPI from "../../../api/OpportunityListingAPI";
import NotFound from "../../../not-found";

export async function generateMetadata() {
const t = await getTranslations({ locale: "en" });
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/app/api/SearchOpportunityAPI.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import "server-only";

import { QueryParamData } from "../../services/search/searchfetcher/SearchFetcher";
import { QueryParamData } from "src/services/search/searchfetcher/SearchFetcher";
import {
PaginationOrderBy,
PaginationRequestBody,
PaginationSortDirection,
SearchFetcherActionType,
SearchFilterRequestBody,
SearchRequestBody,
} from "../../types/search/searchRequestTypes";
} from "src/types/search/searchRequestTypes";

import BaseApi from "./BaseApi";

export default class SearchOpportunityAPI extends BaseApi {
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/app/sitemap.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { MetadataRoute } from "next";

import { getNextRoutes } from "../utils/getRoutes";
import { getNextRoutes } from "src/utils/getRoutes";

export default function sitemap(): MetadataRoute.Sitemap {
const routes = getNextRoutes("./src/app");
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/content/FundingContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { nofoPdfs } from "src/constants/nofoPdfs";
import { useTranslations } from "next-intl";
import { Grid, GridContainer } from "@trussworks/react-uswds";

import NofoImageLink from "../../components/NofoImageLink";
import NofoImageLink from "src/components/NofoImageLink";

const FundingContent = () => {
const t = useTranslations("Index");
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/content/IndexGoalContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Link from "next/link";
import { Button, Grid } from "@trussworks/react-uswds";

import ContentLayout from "src/components/ContentLayout";
import { USWDSIcon } from "../USWDSIcon";
import { USWDSIcon } from "src/components/USWDSIcon";

const IndexGoalContent = () => {
const t = useTranslations("Index");
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/hoc/search/withFeatureFlag.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { FeatureFlagsManager } from "src/services/FeatureFlagManager";
import { ServerSideSearchParams } from "src/types/searchRequestURLTypes";

import { cookies } from "next/headers";
import { notFound } from "next/navigation";
import React, { ComponentType } from "react";

import { FeatureFlagsManager } from "../../services/FeatureFlagManager";
import { ServerSideSearchParams } from "../../types/searchRequestURLTypes";

type WithFeatureFlagProps = {
searchParams: ServerSideSearchParams;
};
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/hooks/useFeatureFlags.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import Cookies from "js-cookie";
import { FeatureFlagsManager } from "src/services/FeatureFlagManager";

import { useEffect, useState } from "react";

import { FeatureFlagsManager } from "../services/FeatureFlagManager";

/**
* React hook for reading and managing feature flags in client-side code.
*
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/services/FeatureFlagManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@

import { CookiesStatic } from "js-cookie";
import { featureFlags } from "src/constants/featureFlags";
import { ServerSideSearchParams } from "src/types/searchRequestURLTypes";

import { ReadonlyRequestCookies } from "next/dist/server/web/spec-extension/adapters/request-cookies";
import { NextRequest, NextResponse } from "next/server";

import { ServerSideSearchParams } from "../types/searchRequestURLTypes";

export type FeatureFlags = { [name: string]: boolean };
// Parity with unexported getServerSideProps context cookie type
export type NextServerSideCookies = Partial<{
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/services/search/SearchFilterManager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { FilterOption } from "../../components/search/SearchFilterAccordion/SearchFilterAccordion";
import { QueryParamKey } from "../../types/search/searchResponseTypes";
import { QueryParamKey } from "src/types/search/searchResponseTypes";

import { FilterOption } from "src/components/search/SearchFilterAccordion/SearchFilterAccordion";

type UpdateQueryParamsFunction = (
checkedSet: Set<string>,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import "server-only";

import SearchOpportunityAPI from "../../../app/api/SearchOpportunityAPI";
import { SearchAPIResponse } from "../../../types/search/searchResponseTypes";
import SearchOpportunityAPI from "src/app/api/SearchOpportunityAPI";
import { SearchAPIResponse } from "src/types/search/searchResponseTypes";

import { QueryParamData, SearchFetcher } from "./SearchFetcher";

export class APISearchFetcher extends SearchFetcher {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import "server-only";

import mockData from "../../../app/api/mock/APIMockResponse.json";
import { SearchAPIResponse } from "../../../types/search/searchResponseTypes";
import mockData from "src/app/api/mock/APIMockResponse.json";
import { SearchAPIResponse } from "src/types/search/searchResponseTypes";

import { SearchFetcher } from "./SearchFetcher";

export class MockSearchFetcher extends SearchFetcher {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/utils/opportunity/isSummary.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Summary } from "../../types/opportunity/opportunityResponseTypes";
import { Summary } from "src/types/opportunity/opportunityResponseTypes";

export function isSummary(value: unknown): value is Summary {
if (typeof value === "object" && value !== null) {
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/utils/search/convertSearchParamsToProperTypes.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { QueryParamData } from "../../services/search/searchfetcher/SearchFetcher";
import { SearchFetcherActionType } from "../../types/search/searchRequestTypes";
import { ServerSideSearchParams } from "../../types/searchRequestURLTypes";
import { QueryParamData } from "src/services/search/searchfetcher/SearchFetcher";
import { SearchFetcherActionType } from "src/types/search/searchRequestTypes";
import { ServerSideSearchParams } from "src/types/searchRequestURLTypes";

// Search params (query string) coming from the request URL into the server
// can be a string, string[], or undefined.
Expand Down
3 changes: 1 addition & 2 deletions frontend/stories/pages/search.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Meta } from "@storybook/react";

import Search from "../../src/app/[locale]/search/page";
import Search from "src/app/[locale]/search/page";

const meta: Meta<typeof Search> = {
title: "Pages/Search",
Expand Down
3 changes: 1 addition & 2 deletions frontend/tests/api/BaseApi.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import "server-only";

import BaseApi, { ApiMethod, JSONRequestBody } from "src/app/api/BaseApi";
import { NetworkError, UnauthorizedError } from "src/errors";

import BaseApi, { ApiMethod, JSONRequestBody } from "../../src/app/api/BaseApi";

// Define a concrete implementation of BaseApi for testing
class TestApi extends BaseApi {
get basePath(): string {
Expand Down
6 changes: 3 additions & 3 deletions frontend/tests/api/SearchOpportunityApi.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import SearchOpportunityAPI from "../../src/app/api/SearchOpportunityAPI";
import { QueryParamData } from "../../src/services/search/searchfetcher/SearchFetcher";
import { SearchRequestBody } from "../../src/types/search/searchRequestTypes";
import SearchOpportunityAPI from "src/app/api/SearchOpportunityAPI";
import { QueryParamData } from "src/services/search/searchfetcher/SearchFetcher";
import { SearchRequestBody } from "src/types/search/searchRequestTypes";

// mockFetch should match the SearchAPIResponse type structure
const mockFetch = ({
Expand Down
2 changes: 1 addition & 1 deletion frontend/tests/components/Spinner.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { render, screen } from "@testing-library/react";

import React from "react";

import Spinner from "../../src/components/Spinner";
import Spinner from "src/components/Spinner";

describe("Spinner Component", () => {
test("renders with correct attributes", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { render, screen } from "tests/react-utils";

import React from "react";

import SectionLinkCount from "../../../../../src/components/search/SearchFilterAccordion/SearchFilterSection/SectionLinkCount";
import SectionLinkCount from "src/components/search/SearchFilterAccordion/SearchFilterSection/SectionLinkCount";

describe("SectionLinkCount", () => {
it("should not have basic accessibility issues", async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { render, screen } from "tests/react-utils";

import React from "react";

import { FilterOption } from "../../../../../src/components/search/SearchFilterAccordion/SearchFilterAccordion";
import SectionLinkLabel from "../../../../../src/components/search/SearchFilterAccordion/SearchFilterSection/SectionLinkLabel";
import { FilterOption } from "src/components/search/SearchFilterAccordion/SearchFilterAccordion";
import SectionLinkLabel from "src/components/search/SearchFilterAccordion/SearchFilterSection/SectionLinkLabel";

// Mock the Icon component from "@trussworks/react-uswds"
jest.mock("@trussworks/react-uswds", () => ({
Expand Down
11 changes: 5 additions & 6 deletions frontend/tests/services/FeatureFlagManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
*/

import Cookies from "js-cookie";

import { NextRequest, NextResponse } from "next/server";

import { FeatureFlagsManager } from "../../src/services/FeatureFlagManager";
import { mockProcessEnv } from "../utils/commonTestUtils";
import { FeatureFlagsManager } from "src/services/FeatureFlagManager";
import { mockProcessEnv } from "tests/utils/commonTestUtils";
import {
mockDefaultFeatureFlags,
mockFeatureFlagsCookie,
} from "../utils/FeatureFlagTestUtils";
} from "tests/utils/FeatureFlagTestUtils";

import { NextRequest, NextResponse } from "next/server";

describe("FeatureFlagsManager", () => {
const COOKIE_VALUE = { feature1: true };
Expand Down
2 changes: 1 addition & 1 deletion frontend/tests/utils/FeatureFlagTestUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import {
FeatureFlags,
FeatureFlagsManager,
} from "../../src/services/FeatureFlagManager";
} from "src/services/FeatureFlagManager";

/**
* Mock feature flags cookie in `window.document` so that we don't need to mock
Expand Down
6 changes: 3 additions & 3 deletions frontend/tests/utils/getRoutes.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { getNextRoutes, listPaths } from "../../src/utils/getRoutes";
import { getNextRoutes, listPaths } from "src/utils/getRoutes";

/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-return */
jest.mock("../../src/utils/getRoutes", () => {
const originalModule = jest.requireActual("../../src/utils/getRoutes");
jest.mock("src/utils/getRoutes", () => {
const originalModule = jest.requireActual("src/utils/getRoutes");
return {
...originalModule,
listPaths: jest.fn(),
Expand Down
4 changes: 2 additions & 2 deletions frontend/tests/utils/isSummary.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Summary } from "../../src/types/opportunity/opportunityResponseTypes";
import { isSummary } from "../../src/utils/opportunity/isSummary";
import { Summary } from "src/types/opportunity/opportunityResponseTypes";
import { isSummary } from "src/utils/opportunity/isSummary";

describe("isSummary", () => {
it("should return true for a valid Summary object", () => {
Expand Down

1 comment on commit c3590d8

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage report for ./frontend

St.
Category Percentage Covered / Total
🟢 Statements 90.6% 790/872
🟡 Branches 71.79% 224/312
🟢 Functions 87.89% 167/190
🟢 Lines 91.27% 742/813

Test suite run success

178 tests passing in 54 suites.

Report generated by 🧪jest coverage report action from c3590d8

Please sign in to comment.