Skip to content

Latest commit

 

History

History
142 lines (113 loc) · 3.93 KB

File metadata and controls

142 lines (113 loc) · 3.93 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with this repository.

Pull Requests

Always create PRs targeting the develop branch by default.

Commit Messages

Every commit message must be prefixed with an issue number following this pattern:

GO-{issueNumber} Short description

Optional longer description.

Example:

GO-6443 Add chat name to push notifications

Include chatName field in push notification payload so users can see
which chat a message was sent from.

Testing Guidelines

Test Structure

  1. Use fixture pattern for consistent test setup:

    type fixture struct {
        *service
        objectStore          *objectstore.StoreFixture
        // other dependencies
    }
    
    func newFixture(t *testing.T) *fixture {
        objectStore := objectstore.NewStoreFixture(t)
        // setup mocks and dependencies
        return &fixture{
            service:     New().(*service),
            objectStore: objectStore,
        }
    }
  2. Use want structure in tests for clarity - it makes expected values explicit:

    t.Run("test case name", func(t *testing.T) {
        // given
        fx := newFixture(t)
        req := SomeRequest{...}
        want := &ExpectedType{
            Field1: "expected value",
            Field2: 123,
        }
    
        // when
        got, err := fx.methodUnderTest(req)
    
        // then
        require.NoError(t, err)
        assert.Equal(t, want, got)
    })
  3. Use AddObjects method of StoreFixture for setting up test data:

    fx.objectStore.AddObjects(t, spaceId, []objectstore.TestObject{
        {
            bundle.RelationKeyId:             domain.String("objectId"),
            bundle.RelationKeyName:           domain.String("Object Name"),
            bundle.RelationKeyResolvedLayout: domain.Int64(int64(model.ObjectType_basic)),
        },
    })
  4. Tech space ID - use objectstore.TestTechSpaceId constant for space view setup:

    fx.objectStore.AddObjects(t, objectstore.TestTechSpaceId, []objectstore.TestObject{
        {
            bundle.RelationKeyId:             domain.String("spaceView1"),
            bundle.RelationKeyResolvedLayout: domain.Int64(int64(model.ObjectType_spaceView)),
            bundle.RelationKeyTargetSpaceId:  domain.String(spaceId),
            bundle.RelationKeyName:           domain.String(spaceName),
        },
    })
  5. Test naming: Use descriptive names that explain what's being tested:

    • "basic message with space and sender names"
    • "message with attachments"
    • "message with emoji marks"
    • "empty chat name"

Assertion Style

Use testify assertions:

assert.Equal(t, expected, actual)
require.NoError(t, err)
require.Len(t, slice, expectedLen)

Mock Usage

  1. Mock generation: Use mockery with .mockery.yaml configuration

    # Regenerate mocks
    make test-deps
  2. Mock expectations: Use EXPECT() pattern with testify/mock:

    fx.crossSpaceSubService.EXPECT().Subscribe(mock.Anything, mock.Anything).Return(&subscription.SubscribeResponse{
        Records: []*domain.Details{},
    }, nil).Maybe()
  3. Flexible matching: Use mock.Anything for parameters you don't need to match exactly

Error Handling

Always wrap errors with context using fmt.Errorf("operation description: %w", err). Never return bare err from functions — every error should carry information about which operation failed.

// Bad
if err != nil {
    return err
}

// Good
if err != nil {
    return fmt.Errorf("query objects by relation: %w", err)
}
  • Use short, lowercase descriptions that identify the failed operation
  • Avoid redundant prefixes like "failed to" or "error in" — just name the operation
  • Use %w verb to preserve the error chain for errors.Is / errors.As
  • Do not change bare return to return err without wrapping — change it to return fmt.Errorf("context: %w", err)