### Application Layer Structure (Next.js) Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/architecture/overview.md Example structure for the Application layer in a Next.js project, where the 'pages' directory serves as the application layer. This layer manages routing and application setup, dependent on Next.js specifics. ```Next.js ├── pages/ | ├── index.tsx | ├── _app.tsx ``` -------------------------------- ### Project Structure Example Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/architecture/overview.md Illustrates a typical project directory structure for the r3d-stack, showing the main application folders. ```bash ├── app/ ├── screens/ ├── modules/ ├── data/ └── shared/ ``` -------------------------------- ### Incorrect unit-test for GoodsListStore.getList (testing-library mock) Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/unit-testing/mock-and-stub.md This incorrect unit test example for `GoodsListStore.getList` uses `setupServer` from a testing library to mock server responses. Similar to the `axios` mocking example, it suffers from low refactoring resistance due to direct coupling with network endpoints and response structures. ```typescript it('Book list is formatted for display', async () => { const fakeBookList = bookRepositoryFaker.makeBookList(2, { price: 1000 }); const fakeBookListItem = fakeBookList.data[0]; const mockServer = setupServer([ http.get('https://rest-endpoint.example/path/to/books', () => { return HttpResponse.json(fakeBookList); }), ]); mockServer.listen({ onUnhandledRequest: 'error' }); const bookRepository = new BookRepository(bookNetworkSources); const sut = new GoodsListStore(bookRepository); const resultList = await sut.getList(); expect(resultList[0]).toMatchObject({ id: fakeBookListItem.id, name: fakeBookListItem.name, price: '1 000 руб.', }); }); ``` -------------------------------- ### Initialize ProductCartManagerStore with CartStore (TypeScript) Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/unit-testing/mock-and-stub.md Demonstrates the initialization of ProductCartManagerStore, which depends on CartStore. The example shows a brittle test setup that directly initializes CartStore and its dependencies, making it susceptible to refactoring. ```TypeScript class ProductCartManagerStore { constructor(private readonly cartStore: CartStore) {} } ``` ```TypeScript class CartStore { constructor( private readonly cartRepository: CartRepository, private readonly notifyService: typeof notify, ) {} } ``` ```TypeScript const fakeGoods = cartRepositoryFaker.makeGoodsList(); const currentProduct = fakeGoods[0]; const cache = createCacheService(); const cartNetworkSourcesMock = mock({ getGoods: async () => fakeGoods, }); const cartRepository = new CartRepository(cartNetworkSourcesMock, cache); const notifyMock = mock(); const cartStore = new CartStore(cartRepository, notifyMock); const sut = new ProductCartManagerStore(cartStore); ``` -------------------------------- ### Shared Layer Structure Example (React) Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/architecture/overview.md Provides an example of the directory structure within the 'shared' layer, tailored for a React stack. It highlights common subdirectories like constants, types, utils, services, stores, and UI components. ```bash ├── app/ ├── screens/ ├── modules/ ├── data/ └── shared/ | ├── constants/ | ├── types/ | ├── utils/ | ├── services/ | ├── stores/ | ├── ui/ | | ├── components/ | | ├── hooks/ | | ├── external.ts | | └── index.ts | └── index.ts ``` -------------------------------- ### Business Logic Test Case Requirements Example Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/unit-testing/test-case-formatting.md Presents an example of task requirements for testing business logic, specifically for a shopping cart payment scenario. It outlines the steps and conditions for payment processing. ```tsx # Shopping Cart Payment ## Main Scenario 1. User added goods to cart 2. User went to cart 3. System displays list of goods added to cart 4. If user has saved card, then clicking "Pay" button: 1. Payment of goods through saved card starts in background 2. System displays modal window to show payment status 5. System redirects user to popular goods page ``` -------------------------------- ### Project Structure Example (File Paths) Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/unit-testing/mock-and-stub.md Illustrates a project directory structure, highlighting the location of CartStore, its tests, and utility/service modules like format-item-to-view and cart-manager. ```plaintext ├── cart-store/ | ├── cart-store.ts | ├── cart-store.test.ts | ├── utils | | ├── format-item-to-view | | | ├── format-item-to-view.ts | | | └── index.ts | | └── index.ts | ├── services | | ├── cart-manager | | | ├── cart-manager.ts | | | └── index.ts | | └── index.ts | └── index.ts ``` -------------------------------- ### Data Layer Structure Example Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/architecture/overview.md Shows the directory layout for the 'data' layer, including 'repositories' and 'sources' segments, which are responsible for data management and retrieval. ```bash ├── app/ ├── screens/ ├── modules/ ├── data/ | ├── repositories/ | ├── sources/ | └── index.ts └── shared/ ``` -------------------------------- ### Modules Layer Structure Example Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/architecture/overview.md Demonstrates the structure of a module within the 'modules' layer, typically containing 'features' and 'domain' segments for business logic implementation. ```bash ├── app/ ├── screens/ ├── modules/ | └── payment/ | | ├── features/ | | ├── domain/ | | └── index.ts ├── data/ └── shared/ ``` -------------------------------- ### Example Project Structure Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/architecture/intro.md Demonstrates a typical directory structure for a project utilizing the R3D Stack architecture. This structure helps organize code by feature and responsibility, promoting maintainability and scalability. ```tree ├── app/ ├── screens/ ├── modules/ ├── data/ └── shared/ ``` -------------------------------- ### Example Module Structure Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/architecture/modules/overview.md Illustrates a typical directory structure for a module within the r3d-stack, showing the 'features' and 'domain' subdirectories, along with an 'index.ts' file for the public API. ```tree ├── app/ ├── screens/ ├── modules/ | └── payment/ | | ├── features/ | | ├── domain/ | | └── index.ts ├── data/ └── shared/ ``` -------------------------------- ### DI for Class: CartScreenStore Mocking Example Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/unit-testing/mock-and-stub.md Demonstrates Dependency Injection (DI) for a class named CartScreenStore. It shows how to create a mock for a dependency (CardPaymentStore) and inject it into the System Under Test (SUT) for testing purposes. This example highlights the benefit of DI in isolating components and reducing test brittleness. ```tsx export class CartScreenStore { private readonly modalStore = createFlagStore(); constructor( private readonly cardPaymentStore: CardPaymentStore, private readonly routerService: Router, ) {} ... } ...describe('CartScreenStore', () => { it('Payment process starts in background when modal is opened', () => { const cartPaymentStoreMock = mock(); const sut = new CartScreenStore(cartPaymentStoreMock, createRouterMock()); sut.openModal(); expect(cartPaymentStoreMock.pay).toBeCalled(); }); }; ``` -------------------------------- ### Domain Stores: Cart Store Example Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/architecture/modules/domain.md Illustrates a store in the Domain layer managing cart state and operations. Stores can leverage services for business logic and interact with repositories for data persistence. This example uses MobX for state management. ```typescript // domain/stores/cart-store/cart-store.ts import { makeAutoObservable } from 'mobx'; import { CartCalculator } from '../services/cart-calculator'; import { CartRepository } from '@data/repositories/cart-repository'; export class CartStore { private items: CartItem[] = []; private calculator: CartCalculator; constructor( private readonly cartRepository: CartRepository ) { this.calculator = new CartCalculator(); makeAutoObservable(this); } public get total(): number { return this.calculator.calculateTotal(this.items); } public addItem(item: CartItem) { this.items.push(item); } public removeItem(itemId: string) { this.items = this.items.filter(item => item.id !== itemId); } } ``` -------------------------------- ### Directory Structure for Test Location Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/unit-testing/overview.md This example illustrates the recommended directory structure for locating test files alongside their corresponding source files. This practice enhances the visual connection between the System Under Test (SUT) and its tests. ```bash ├── data/ | └── repositories/ | | └── user-repository/ | | | ├── user-repository.ts | | | ├── user-repository.test.ts | | | └── index.ts ``` -------------------------------- ### Example Module Feature Structure Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/architecture/modules/features/overview.md Illustrates the general structure of features within a module in the R3D Stack, showing how specific functionalities like payment processing are organized. ```tree ├── app/ ├── screens/ ├── modules/ | └── payment/ | | ├── features/ | | | ├── payment-switch/ | | | ├── card-payment/ | | | ├── cash-payment/ | | | └── index.ts | | ├── domain/ | | └── index.ts ├── data/ └── shared/ ``` -------------------------------- ### Kebab-Case Naming Convention Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/style-guides/react/created.md Illustrates the required kebab-case naming convention for component directories and files. This ensures standardization across the project. Invalid examples show camelCase, which should be avoided. ```bash ├── user-info/ | ├── user-info.tsx | └── index.ts ├── button-group/ | ├── button-group.tsx | └── index.ts ``` ```bash ❌ Invalid ├── userInfo/ | ├── userInfo.tsx | └── index.ts ├── buttonGroup/ | ├── buttonGroup.tsx | └── index.ts ``` -------------------------------- ### Valid Arrange Stage Usage in Tests (TSX) Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/unit-testing/antipatterns.md Demonstrates the correct way to use arrange stages in tests by calling a setup function for each 'it' block. This ensures test isolation and prevents mock reuse issues. The setup function `setupSuccessCreation` is called independently for each test. ```tsx describe('CreateBookScreenStore', () => { const setupSuccessCreation = () => { const routerMock = createRouterMock(); const notifyMock = mock(); const sut = new CreateBookScreenStore(routerMock, notifyMock); return { sut, notifyMock, routerMock }; }; describe('Successful book creation', () => { it('Shows success notification', async () => { const fakeBookFormValues = makeFakeBookFormValues({ name: 'Clean Code' }); const { sut, notifyMock } = setupSuccessCreation(); await sut.createBook(fakeBookFormValues); expect(notifyMock.success).toBeCalledWith('Clean Code successfully created'); }); it('Redirects to books list page', async () => { const fakeBookFormValues = makeFakeBookFormValues(); const { sut, routerMock } = setupSuccessCreation(); await sut.createBook(fakeBookFormValues); expect(routerMock).toMatchObject({ pathname: APP_ROUTES.books.getRedirectPath(), }); }); }); }); ``` -------------------------------- ### Application Layer Structure (React) Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/architecture/overview.md Example structure for the Application layer in a React project. This layer is the sole dependency on the environment and framework specifics, handling application routing and service initialization. ```React ├── app/ | ├── routing/ | └── app.tsx ``` -------------------------------- ### Format Price to View - Zero Handling (TypeScript) Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/unit-testing/antipatterns.md Demonstrates how to correctly name a test case for the `formatPriceToView` function when handling zero input. The valid example clearly states that for zero, a default text is returned. ```tsx describe('formatPriceToView', () => { it('Works correctly with zero', () => { expect(formatPriceToView(0)).toBe('Free'); }); }); ``` ```tsx describe('formatPriceToView', () => { it('For zero returns default text', () => { expect(formatPriceToView(0)).toBe('Free'); }); }); ``` -------------------------------- ### Repository Faker Implementation Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/architecture/data.md Provides an example of a faker for a BookRepository, demonstrating how it can leverage fakes from network sources to generate data. This promotes code reuse and consistency in test data generation. ```TypeScript export const bookRepositoryFaker = { makeBookList( length?: number, item?: Partial, ): BookRepositoryDTO.BookListDTO { return bookNetworkSourcesFaker.makeBookList(length, item); }, makeBookByName(): BookRepositoryDTO.BookByName { return { ...bookNetworkSourcesFaker.makeBookByName(), genre: bookNetworkSourcesFaker.makeGenre(), }; }, }; ``` -------------------------------- ### Bind Component Mount/Unmount with UIStore Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/architecture/modules/features/ui-store.md Illustrates how to bind component mount and unmount events to UIStore methods. This ensures proper setup and cleanup of subscriptions or resources tied to the component's lifecycle. ```ts import { autorun, makeAutoObservable } from 'mobx'; import type { Ref } from 'react'; export class UIStore { private unobserveSearch: () => void = () => {}; public search: string = ''; constructor( private readonly listStore: ListStore, private readonly scroller: Scroller, ) { makeAutoObservable(this); } private observeSearch = () => autorun(() => { this.listStore.changeParams({ search: this.search }); }); public setSearch = (search: string) => { this.search = search; }; public get list() { return this.listStore.data; } public mount = (containerRef: Ref) => { this.scroller.setScrollContainer(containerRef); this.unobserveSearch = this.observeSearch(); }; public unmount = () => { this.unobserveSearch(); }; } ``` ```tsx import { useLocalObservable } from 'mobx-react-lite'; import { createUIStore } from './ui-store'; const List = () => { const containerRef = useRef(); const { mount, unmount } = useLocalObservable(createUIStore); useEffect(() => { mount(containerRef); return unmount; }, []); ... }; ``` -------------------------------- ### Invalid Module Naming (With 'Module' Postfix) Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/style-guides/architecture/modules/creation.md Provides examples of invalid module directory names that incorrectly include the 'Module' postfix. This practice is discouraged as it is redundant given the 'modules' parent directory. ```bash ├── modules/ | ├── cartModule/ | ├── pymentModule/ | ├── requestModule/ | └── layoutModule/ ``` -------------------------------- ### Valid Function Declarations (TypeScript) Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/style-guides/naming/functions.md Examples of valid function declarations in TypeScript, starting with verbs to clearly indicate their action. ```TypeScript const calcSum = () => {}; const getUserData = () => {}; const removeID = () => {}; const refreshData = () => {}; const formatToView = () => {}; const createRequest = () => {}; ``` -------------------------------- ### DI for Class: CreateBookScreenStore Substitution Example Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/unit-testing/mock-and-stub.md Demonstrates substituting dependencies for a class named CreateBookScreenStore, specifically those interacting with the environment like Router and notifyService. It shows how to create mock instances of these dependencies and inject them into the SUT for a test case verifying successful book creation and redirection. ```tsx export class CreateBookScreenStore { constructor( private readonly administrationRepository: AdministrationRepository, private readonly routerService: Router, private readonly notifyService: typeof notify, ) {} } it('Successful book creation redirects to books list page', async () => { const fakeBookFormValues = makeFakeBookFormValues(); const adminRepositoryMock = mock(); const routerMock = createRouterMock(); const notifyMock = mock(); const sut = new CreateBookScreenStore( adminRepositoryMock, routerMock, notifyMock, ); await sut.createBook(fakeBookFormValues); expect(routerMock).toMatchObject({ pathname: APP_ROUTES.books.getRedirectPath(), }); }); ``` -------------------------------- ### Pass HTMLElement to Logic with useRef and useEffect Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/architecture/modules/features/ui-logic.md This example shows how to get a reference to an HTMLElement using `useRef` and pass it to your UI store logic using `useEffect`. This is useful for direct DOM manipulation or measurements. ```tsx import { useLocalObservable } from 'mobx-react-lite'; import { createUIStore } from './ui-store'; export const Card = () => { const { setContainer } = useLocalObservable(createUIStore); const containerRef = useRef(); useEffect(() => { setContainer(containerRef.current); }, []); return ( ... ); }; ``` -------------------------------- ### Circular Dependency Example (Invalid TS) Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/style-guides/react/props.md This example demonstrates how defining prop types in separate files can lead to circular dependencies. The 'HeaderProps' type in 'header/types.ts' depends on 'UserCardProps' from the parent 'types.ts', creating a problematic unidirectional relationship. ```ts export type UserCardProps = { headerTitle: ReactNode; }; ``` ```ts import { type UserCardProps } from '../types'; export type HeaderProps = { title: UserCardProps['headerTitle']; }; ``` -------------------------------- ### Directly Pass Handlers to Components Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/style-guides/react/logic.md This snippet clarifies when it's acceptable to pass handlers directly to child components. It shows a valid example where a prop `onPay` is directly passed, and an invalid example that includes unnecessary intermediate handler code. ```tsx const Cart = ({ onPay }: Props) => { return (
); }; ``` ```tsx const Cart = ({ onPay }: Props) => { // Extra code that does nothing: const handlePay = () => { onPay(); }; return (
); }; ``` -------------------------------- ### Simplify JSX with Extracted Conditions Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/style-guides/react/logic.md This snippet illustrates how to simplify complex conditional logic within JSX by extracting it into separate variables. It shows an invalid example with a long, nested condition and a valid example where the condition is pre-calculated for better readability. ```tsx const Cart = ({ list, isSuccess, userName, onPay }: Props) => { return (
{(Boolean(list.length) && isSuccess) || (userName.startsWith('Vasya') && ( ))}
); }; ``` ```tsx const Cart = ({ list, isSuccess, userName, onPay }: Props) => { const isVasya = userName.startsWith('Vasya'); const isShowPayButton = (Boolean(list.length) && isSuccess) || isVasya; return (
{isShowPayButton && }
); }; ``` -------------------------------- ### Identify React Handlers with 'handle' Prefix Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/style-guides/react/logic.md This snippet demonstrates the correct way to identify React handlers by prefixing them with 'handle'. It shows a valid example where a handler function is correctly named and an invalid example where a non-handler function is incorrectly prefixed. ```tsx const Cart = ({ list, onSetSum }: Props) => { // calcSum - not a handler, so no prefix is needed const { calcSum } = useLogic(); const handleClickPay = () => { onSetSum(calcSum(list)); }; return (
); }; ``` ```tsx const Cart = ({ list, onSetSum }: Props) => { // handleCalcSum is not a handler, so no prefix should be used const { handleCalcSum } = useLogic(); // Handler not in the correct format const clickPayHandler = () => { onSetSum(handleCalcSum(list)); }; return (
); }; ``` -------------------------------- ### Work with Browser API via Abstraction Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/architecture/modules/features/ui-store.md Explains the practice of interacting with Browser APIs through abstractions in UIStore. This facilitates easier testing by allowing the substitution of real dependencies with mock or test versions. ```ts export class UIStore { constructor( private readonly storage: LocalStorageService, ) { makeAutoObservable(this); } public setSearch = (search: string) => { this.storage.setItem('search', search) } } ``` ```ts export class UIStore { constructor( private readonly intersectionObserver: IntersectionObserver, ) { makeAutoObservable(this); } ... public mount = (itemRef: Ref) => { this.intersectionObserver(this.showAction, { root: itemRef.current }) } } ``` -------------------------------- ### Correct unit-test for GoodsListStore.getList (dependency injection mock) Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/unit-testing/mock-and-stub.md This is a correct unit test example for the `getList` method of `GoodsListStore`. It demonstrates improved refactoring resistance by substituting the `BookRepository` dependency with a mock object using a mocking library. This approach isolates the test to the `GoodsListStore` logic. ```typescript describe('GoodsListStore', () => { it('Book list is formatted for display', async () => { const fakeBookList = bookRepositoryFaker.makeBookList(2, { price: 1000 }); const fakeBookListItem = fakeBookList.data[0]; const bookRepositoryMock = mock({ getBookList: async () => fakeBookList, }); const sut = new GoodsListStore(bookRepositoryMock); const resultList = await sut.getList(); expect(resultList[0]).toMatchObject({ id: fakeBookListItem.id, name: fakeBookListItem.name, price: '1 000 руб.', }); }); }); ``` -------------------------------- ### Implement Handlers Outside JSX Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/style-guides/react/logic.md This snippet shows the correct way to implement event handlers outside of the JSX markup. It contrasts an invalid example where the handler logic is directly within the `onClick` prop with a valid example where the handler is defined within the component function. ```tsx const Cart = ({ list, onRemoveProduct }: Props) => { const handleRemoveProduct = (id: string) => () => { onRemoveProduct(id); }; return (
    {list.map(({ id }) => (
  • ))}
); }; ``` ```tsx const Cart = ({ list, onRemoveProduct }: Props) => { return (
    {list.map(({ id }) => (
  • ))}
); }; ``` -------------------------------- ### GoodsListStore with BookRepository dependency Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/unit-testing/mock-and-stub.md This TypeScript code defines a `GoodsListStore` class that depends on a `BookRepository`. The `getList` method fetches a list of books and formats them for display, including price formatting and creating a `ProductCartManagerStore` for each item. ```tsx class GoodsListStore { constructor(private readonly bookRepository: BookRepository) { makeAutoObservable(this); } public async getList(): Promise { const data = await this.bookRepository.getBookList(); return data.map(({ id, name, price }) => ({ id, name, price: formatPriceToView(price), store: createProductCartManagerStore(id), })); } } ``` -------------------------------- ### Shared Layer Structure Example (React) - Independence Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/architecture/shared.md This example reiterates the Shared layer's directory structure, emphasizing the 'external.ts' file within the 'utils' directory. This file is crucial for managing and re-exporting external dependencies, facilitating dependency inversion. ```tree ├── app/ ├── screens/ ├── modules/ ├── data/ └── shared/ ├── constants/ ├── types/ ├── utils/ | ├── format-date/ | ├── external.ts | └── index.ts ├── services/ ├── stores/ ├── ui/ └── index.ts ``` -------------------------------- ### Switch to Real Sources with Cart Repository Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/architecture/contract-first.md This snippet shows the transition from using fake data sources to real ones. It demonstrates how to re-instantiate the `CartRepository` with the actual `cartNetworkSources` and `cacheService` after the API implementation is complete. ```typescript export const cartRepository = new CartRepository( cartNetworkSources, cacheService, ); ``` -------------------------------- ### Move Loop Logic Out of JSX Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/style-guides/react/logic.md This snippet demonstrates the best practice of moving logic within loops in JSX to a separate component or the component's body. It presents an invalid example with inline logic inside a map function and a valid example where the logic is encapsulated in a dedicated `ListItem` component. ```tsx const MainPage = ({ list }: Props) => { return (
    {list.map((item) => { // Perception and maintenance complexity will increase as component logic grows const price = formatPriceToView(item.price); const nickName = [item.name, item.surname].join(' '); return (
  • {price} {nickName}
  • ); })}
); }; ``` ```tsx const ListItem = ({ itemInfo }: ListItemProps) => { const price = formatPriceToView(item.price); const nickName = [item.name, item.surname].join(' '); return (
  • {price} {nickName}
  • ); }; const MainPage = ({ list }: MainPageProps) => { return (
      {list.map((item) => ( ))}
    ); }; ``` -------------------------------- ### GoodsListStore Initialization Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/architecture/data.md Initializes the GoodsListStore with a BookRepository dependency. This class is designed to work with data through repositories, abstracting away data sources. ```TypeScript class GoodsListStore { constructor(private readonly bookRepository: BookRepository) { makeAutoObservable(this); } private get listQuery() { return this.bookRepository.getBookListQuery(); } public get list(): ListItem[] { const data = this.listQuery.data?.data || []; return data.map(({ id, name, price }) => ({ id, name, price: formatPriceToView(price), store: createProductCartManagerStore(id), })); } } ``` -------------------------------- ### Domain Layer Dependency Injection Example Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/architecture/modules/domain.md Demonstrates the use of Dependency Injection (DI) within the Domain layer for managing dependencies like repositories and services. DI promotes loose coupling and simplifies testing. ```typescript // domain/stores/cart-store/cart-store.ts export class CartStore { constructor( private readonly cartRepository: CartRepository, private readonly cartCalculator: CartCalculator ) {} // ... implementation } ``` -------------------------------- ### Avoid SUT Implementation Details in Tests: Format Book Item Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/unit-testing/antipatterns.md This snippet addresses the antipattern of using SUT implementation details, like object spreading, when testing. The invalid example uses `toEqual` with a spread operator, which relies on the internal structure of the SUT. The valid example explicitly lists and checks each expected property of the output object, ensuring the test is robust against internal refactoring of the `formatBookItemToView` function. ```tsx const formatBookItemToView = (book: BookRepositoryDTO.BookListItemDTO) => ({ ...book, price: formatPriceToView(book.price), }); ``` ```tsx describe('formatBookItem', () => { it('Book data is returned in display format', () => { const fakeBookItem = bookRepositoryFaker.makeBookItem({ price: 1000 }); const result = formatBookItemToView(fakeBookItem); expect(result).toEqual({ ...fakeBookItem, price: '1 000 руб.', }); }); }); ``` ```tsx describe('formatBookItem', () => { it('Book data is returned in display format', () => { const fakeBookItem = bookRepositoryFaker.makeBookItem({ price: 1000 }); const result = formatBookItemToView(fakeBookItem); expect(result).toEqual({ id: fakeBookItem.id, name: fakeBookItem.name, price: '1 000 руб.', }); }); }); ``` -------------------------------- ### Avoid SUT Implementation Details in Tests: Format Price Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/unit-testing/antipatterns.md This snippet illustrates how to avoid leaking System Under Test (SUT) implementation details into tests, specifically for a price formatting function. The invalid example duplicates the SUT's formatting logic within the test, making it brittle. The valid example directly asserts the expected output string, ensuring the test focuses on the function's behavior rather than its internal implementation. ```tsx export const formatPriceToView = (price: number): string => price ? `${price.toLocaleString('ru')} руб.` : 'Free'; ``` ```tsx describe('formatPriceToView', () => { it.each([[1000], [10000], [100000], [1000000]])( 'For "%s" non-breaking space is added in numbers', (input) => { const result = formatPriceToView(input); expect(result).toBe(`${input.toLocaleString('ru')} руб.`); }, ); }; ``` ```tsx describe('formatPriceToView', () => { it.each([ [1000, '1 000 руб.'], [10000, '10 000 руб.'], [100000, '100 000 руб.'], [1000000, '1 000 000 руб.'], ])('For "%s" non-breaking space is added in numbers', (input, output) => { const result = formatPriceToView(input); expect(result).toBe(output); }); }; ``` -------------------------------- ### Format Best Product Name with CartStore and CartRepository (TypeScript) Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/unit-testing/mock-and-stub.md Illustrates how CartStore accesses the best product via CartRepository. The example includes a test with low refactoring resistance that requires multiple steps to set up the CartRepository's state. ```TypeScript class CartStore { constructor(private readonly cartRepository: CartRepository) { makeAutoObservable(this); } public get bestProduct() { return `Best product: ${this.cartRepository.bestProduct.name}`; } } ``` ```TypeScript it('Best product name is formatted for display', async () => { const fakeBookList = cartRepositoryFaker.makeBookList(); const cartRepository = new CartRepository(cartNetworkSourcesMock); const sut = new CartStore(cartRepository); cartRepository.addGoods(fakeBookList); cartRepository.setBestProduct(fakeBookList[0].id); expect(sut.bestProduct).toBe('Best product: Crime and Punishment'); }); ``` -------------------------------- ### Catalog Module Features Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/architecture/modules/overview.md Illustrates the internal structure of the Catalog module, highlighting its features such as product list, product photo display, product cards, filtering, and search functionality. It also shows the domain and index files. ```bash ├── app/ ├── screens/ ├── modules/ | ├── catalog/ | | ├── features/ | | | ├── catalog-list/ # Product list | | | ├── product-photo/ # Product photo. Is a private feature. | | | ├── catalog-card/ # Product card | | | ├── filters/ # Product filtering | | | ├── search-bar/ # Product search | | | └── index.ts | | ├── domain/ | | └── index.ts | ├── cart/ | ├── payment/ | ├── auth/ | ├── layout/ ├── data/ └── shared/ ``` -------------------------------- ### Invalid Function Declarations (TypeScript) Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/style-guides/naming/functions.md Examples of invalid function declarations in TypeScript where the naming convention is not followed, making the intent unclear. ```TypeScript // Verb at the end const sumCalc = () => {}; // Judging by the name, this is not a function but an object const userDataGetter = () => {}; // Judging by the name, this is not a function but an object const toViewFormatter = () => {}; // The name indicates that this is a process, not a function const refreshingData = () => {}; ``` -------------------------------- ### Valid Method Declarations (TypeScript Class) Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/style-guides/naming/functions.md Examples of valid method declarations within a TypeScript class, adhering to the verb-first naming convention. ```TypeScript class Example { public calcSum = () => {}; public getUserData = () => {}; public removeID = () => {}; public refresh = () => {}; public formatToView = () => {}; } ``` -------------------------------- ### Example Feature Structure (React) Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/architecture/modules/features/overview.md Demonstrates a typical directory structure for a feature within a React-based R3D Stack project, highlighting the separation of concerns like UI components, logic, styles, and utilities. ```tree ├── app/ ├── screens/ ├── modules/ | └── payment/ | | ├── payment-switch/ | | | ├── payment-switch.tsx | | | ├── payment-switch.test.tsx | | | ├── switch-btn/ | | | ├── styles.ts | | | ├── utils/ | | | ├── ui-store/ | | | ├── constants.ts | | | ├── types.ts | | | └── index.ts | | ├── card-payment/ | | ├── cash-payment/ | | └── index.ts | ├── domain/ | └── index.ts ├── data/ └── shared/ ``` -------------------------------- ### React Component with Boolean Check (tsx) Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/style-guides/naming/functions.md A React component example demonstrating the use of a renamed boolean check function to avoid conflicts with props. ```tsx // Have to rename the function due to conflicts with parameters and variables import { isEmpty as checkIsEmpty } from 'utils'; export const UserInfo = ({ data, isEmpty }: Props) => { const isEmptyData = isEmpty && checkIsEmpty(data); return ( {isEmpty && } ); }; ``` -------------------------------- ### Invalid Boolean-Returning Functions (TypeScript) Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/style-guides/naming/functions.md Examples of invalid TypeScript functions returning booleans, where naming conflicts or lack of a verb prefix hinder clarity. ```TypeScript // Name is identical to variable const isEmpty = (value: unknown) => remeda.isEmpty(value); // Name is identical to variable const hasRemoved = (obj?: Record): obj is undefined => obj === undefined; // No verb const removed = (obj?: Record): obj is undefined => obj === undefined; ``` -------------------------------- ### Create Basic Mock with Spy Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/unit-testing/mock-and-stub.md Demonstrates creating a mock object for a CartStore interface. It replaces all methods and properties except 'goods' with a spy, allowing focused testing. Dependencies like cartRepositoryFaker are assumed to be available. ```tsx const fakeGoodsList = cartRepositoryFaker.makeGoodsList(2); const cartStoreMock = mock({ goods: fakeGoodsList, }); const sut = new CardPaymentStore(cartStoreMock); ``` -------------------------------- ### Valid Boolean-Returning Methods (TypeScript Class) Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/style-guides/naming/functions.md Examples of valid methods within a TypeScript class that return a boolean, using a verb prefix for clarity. ```TypeScript class Example { public checkIsEmpty = (value: unknown) => remeda.isEmpty(value); public checkWasRemoved = (obj?: Record): obj is undefined => obj === undefined; public validateID = (obj: { id?: string }) => Boolean(obj.id); } ``` -------------------------------- ### Short Notation for React.Fragment Source: https://github.com/r3d-stack/r3d-stack-docs/blob/main/docs/en/style-guides/react/created.md Shows the preferred short notation (`<>...`) for React.Fragment to reduce code verbosity. The extended notation (`...`) is only recommended when a `key` prop is necessary, as demonstrated in the second valid example. ```tsx const Info = () => { return ( <> Name Surname ); }; ``` ```tsx export const List = ({ list }: Props) => { return list.map(({ name, surname }) => { Name Surname ; }); }; ``` ```tsx ❌ Invalid export const Info = () => { return ( Name Surname ); }; ```