diff --git a/coderd/notifications/fetcher.go b/coderd/notifications/fetcher.go index a579275d127bf..0688b88907981 100644 --- a/coderd/notifications/fetcher.go +++ b/coderd/notifications/fetcher.go @@ -38,6 +38,10 @@ func (n *notifier) fetchAppName(ctx context.Context) (string, error) { } return "", xerrors.Errorf("get application name: %w", err) } + + if appName == "" { + appName = notificationsDefaultAppName + } return appName, nil } @@ -49,5 +53,9 @@ func (n *notifier) fetchLogoURL(ctx context.Context) (string, error) { } return "", xerrors.Errorf("get logo URL: %w", err) } + + if logoURL == "" { + logoURL = notificationsDefaultLogoURL + } return logoURL, nil } diff --git a/coderd/notifications/fetcher_internal_test.go b/coderd/notifications/fetcher_internal_test.go new file mode 100644 index 0000000000000..a8d0149c883b8 --- /dev/null +++ b/coderd/notifications/fetcher_internal_test.go @@ -0,0 +1,231 @@ +package notifications + +import ( + "context" + "database/sql" + "testing" + "text/template" + + "github.com/stretchr/testify/require" + "go.uber.org/mock/gomock" + "golang.org/x/xerrors" + + "github.com/coder/coder/v2/coderd/database/dbmock" +) + +func TestNotifier_FetchHelpers(t *testing.T) { + t.Parallel() + + t.Run("ok", func(t *testing.T) { + t.Parallel() + + ctrl := gomock.NewController(t) + dbmock := dbmock.NewMockStore(ctrl) + + n := ¬ifier{ + store: dbmock, + helpers: template.FuncMap{}, + } + + dbmock.EXPECT().GetApplicationName(gomock.Any()).Return("ACME Inc.", nil) + dbmock.EXPECT().GetLogoURL(gomock.Any()).Return("https://example.com/logo.png", nil) + + ctx := context.Background() + helpers, err := n.fetchHelpers(ctx) + require.NoError(t, err) + + appName, ok := helpers["app_name"].(func() string) + require.True(t, ok) + require.Equal(t, "ACME Inc.", appName()) + + logoURL, ok := helpers["logo_url"].(func() string) + require.True(t, ok) + require.Equal(t, "https://example.com/logo.png", logoURL()) + }) + + t.Run("failed to fetch app name", func(t *testing.T) { + t.Parallel() + + ctrl := gomock.NewController(t) + dbmock := dbmock.NewMockStore(ctrl) + + n := ¬ifier{ + store: dbmock, + helpers: template.FuncMap{}, + } + + dbmock.EXPECT().GetApplicationName(gomock.Any()).Return("", xerrors.New("internal error")) + + ctx := context.Background() + _, err := n.fetchHelpers(ctx) + require.Error(t, err) + require.ErrorContains(t, err, "get application name") + }) + + t.Run("failed to fetch logo URL", func(t *testing.T) { + t.Parallel() + + ctrl := gomock.NewController(t) + dbmock := dbmock.NewMockStore(ctrl) + + n := ¬ifier{ + store: dbmock, + helpers: template.FuncMap{}, + } + + dbmock.EXPECT().GetApplicationName(gomock.Any()).Return("ACME Inc.", nil) + dbmock.EXPECT().GetLogoURL(gomock.Any()).Return("", xerrors.New("internal error")) + + ctx := context.Background() + _, err := n.fetchHelpers(ctx) + require.ErrorContains(t, err, "get logo URL") + }) +} + +func TestNotifier_FetchAppName(t *testing.T) { + t.Parallel() + + t.Run("ok", func(t *testing.T) { + t.Parallel() + + ctrl := gomock.NewController(t) + dbmock := dbmock.NewMockStore(ctrl) + + n := ¬ifier{ + store: dbmock, + } + + dbmock.EXPECT().GetApplicationName(gomock.Any()).Return("ACME Inc.", nil) + + ctx := context.Background() + appName, err := n.fetchAppName(ctx) + require.NoError(t, err) + require.Equal(t, "ACME Inc.", appName) + }) + + t.Run("No rows", func(t *testing.T) { + t.Parallel() + ctrl := gomock.NewController(t) + dbmock := dbmock.NewMockStore(ctrl) + + n := ¬ifier{ + store: dbmock, + } + + dbmock.EXPECT().GetApplicationName(gomock.Any()).Return("", sql.ErrNoRows) + + ctx := context.Background() + appName, err := n.fetchAppName(ctx) + require.NoError(t, err) + require.Equal(t, notificationsDefaultAppName, appName) + }) + + t.Run("Empty string", func(t *testing.T) { + t.Parallel() + + ctrl := gomock.NewController(t) + dbmock := dbmock.NewMockStore(ctrl) + + n := ¬ifier{ + store: dbmock, + } + + dbmock.EXPECT().GetApplicationName(gomock.Any()).Return("", nil) + + ctx := context.Background() + appName, err := n.fetchAppName(ctx) + require.NoError(t, err) + require.Equal(t, notificationsDefaultAppName, appName) + }) + + t.Run("internal error", func(t *testing.T) { + t.Parallel() + + ctrl := gomock.NewController(t) + dbmock := dbmock.NewMockStore(ctrl) + + n := ¬ifier{ + store: dbmock, + } + + dbmock.EXPECT().GetApplicationName(gomock.Any()).Return("", xerrors.New("internal error")) + + ctx := context.Background() + _, err := n.fetchAppName(ctx) + require.Error(t, err) + }) +} + +func TestNotifier_FetchLogoURL(t *testing.T) { + t.Parallel() + + t.Run("ok", func(t *testing.T) { + t.Parallel() + + ctrl := gomock.NewController(t) + dbmock := dbmock.NewMockStore(ctrl) + + n := ¬ifier{ + store: dbmock, + } + + dbmock.EXPECT().GetLogoURL(gomock.Any()).Return("https://example.com/logo.png", nil) + + ctx := context.Background() + logoURL, err := n.fetchLogoURL(ctx) + require.NoError(t, err) + require.Equal(t, "https://example.com/logo.png", logoURL) + }) + + t.Run("No rows", func(t *testing.T) { + t.Parallel() + ctrl := gomock.NewController(t) + dbmock := dbmock.NewMockStore(ctrl) + + n := ¬ifier{ + store: dbmock, + } + + dbmock.EXPECT().GetLogoURL(gomock.Any()).Return("", sql.ErrNoRows) + + ctx := context.Background() + logoURL, err := n.fetchLogoURL(ctx) + require.NoError(t, err) + require.Equal(t, notificationsDefaultLogoURL, logoURL) + }) + + t.Run("Empty string", func(t *testing.T) { + t.Parallel() + + ctrl := gomock.NewController(t) + dbmock := dbmock.NewMockStore(ctrl) + + n := ¬ifier{ + store: dbmock, + } + + dbmock.EXPECT().GetLogoURL(gomock.Any()).Return("", nil) + + ctx := context.Background() + logoURL, err := n.fetchLogoURL(ctx) + require.NoError(t, err) + require.Equal(t, notificationsDefaultLogoURL, logoURL) + }) + + t.Run("internal error", func(t *testing.T) { + t.Parallel() + + ctrl := gomock.NewController(t) + dbmock := dbmock.NewMockStore(ctrl) + + n := ¬ifier{ + store: dbmock, + } + + dbmock.EXPECT().GetLogoURL(gomock.Any()).Return("", xerrors.New("internal error")) + + ctx := context.Background() + _, err := n.fetchLogoURL(ctx) + require.Error(t, err) + }) +}
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: