17 | {{if $image}}
18 | {{/* Render screenshot thumbnail with modal functionality */}}
19 |
20 | {{if $caption}}
21 |
{{$caption}}
22 | {{end}}
23 |

35 |
Failed to load screenshot
36 |
37 | {{else}}
38 |
Screenshot (no image data)
39 | {{end}}
40 |
41 | {{- end}}
42 |
43 | {{- define "screenshot-event" -}}
44 | {{template "screenshot-event-details" .}}
45 | {{- end}}
46 |
--------------------------------------------------------------------------------
/services/merrymaker-go/internal/domain/rules/helpers.go:
--------------------------------------------------------------------------------
1 | package rules
2 |
3 | import "strings"
4 |
5 | func appendSample(samples *[]string, domain string) {
6 | if samples == nil {
7 | return
8 | }
9 | domain = strings.TrimSpace(domain)
10 | if domain == "" {
11 | return
12 | }
13 | for _, existing := range *samples {
14 | if strings.EqualFold(existing, domain) {
15 | return
16 | }
17 | }
18 | if len(*samples) < MetricsSampleLimit {
19 | *samples = append(*samples, domain)
20 | }
21 | }
22 |
23 | // MergeUnknownDomainMetrics merges src into dst, preserving sample limits.
24 | func MergeUnknownDomainMetrics(dst *UnknownDomainMetrics, src UnknownDomainMetrics) {
25 | if dst == nil {
26 | return
27 | }
28 | dst.Alerted.Merge(src.Alerted)
29 | dst.AlertedDryRun.Merge(src.AlertedDryRun)
30 | dst.AlertedMuted.Merge(src.AlertedMuted)
31 | dst.SuppressedAllowlist.Merge(src.SuppressedAllowlist)
32 | dst.SuppressedSeen.Merge(src.SuppressedSeen)
33 | dst.SuppressedDedupe.Merge(src.SuppressedDedupe)
34 | dst.NormalizationFailed.Merge(src.NormalizationFailed)
35 | dst.Errors.Merge(src.Errors)
36 | }
37 |
38 | // MergeIOCMetrics merges src into dst, preserving sample limits.
39 | func MergeIOCMetrics(dst *IOCMetrics, src IOCMetrics) {
40 | if dst == nil {
41 | return
42 | }
43 | dst.Matches.Merge(src.Matches)
44 | dst.MatchesDryRun.Merge(src.MatchesDryRun)
45 | dst.Alerts.Merge(src.Alerts)
46 | dst.AlertsMuted.Merge(src.AlertsMuted)
47 | }
48 |
49 | // AppendUniqueLower appends a lower-cased value when not already present.
50 | func AppendUniqueLower(list *[]string, value string) {
51 | if list == nil {
52 | return
53 | }
54 | v := strings.ToLower(strings.TrimSpace(value))
55 | if v == "" {
56 | return
57 | }
58 | for _, existing := range *list {
59 | if existing == v {
60 | return
61 | }
62 | }
63 | *list = append(*list, v)
64 | }
65 |
--------------------------------------------------------------------------------
/services/merrymaker-go/internal/core/secret_repository_stub_test.go:
--------------------------------------------------------------------------------
1 | package core
2 |
3 | import (
4 | "context"
5 | "errors"
6 |
7 | "github.com/target/mmk-ui-api/internal/domain/model"
8 | )
9 |
10 | // stubSecretRepo provides a minimal SecretRepository implementation for tests.
11 | type stubSecretRepo struct {
12 | values map[string]*model.Secret
13 | err error
14 | }
15 |
16 | func newStubSecretRepo(values map[string]*model.Secret, err error) *stubSecretRepo {
17 | return &stubSecretRepo{values: values, err: err}
18 | }
19 |
20 | func (s *stubSecretRepo) Create(context.Context, model.CreateSecretRequest) (*model.Secret, error) {
21 | return nil, errors.New("not implemented")
22 | }
23 |
24 | func (s *stubSecretRepo) GetByID(context.Context, string) (*model.Secret, error) {
25 | return nil, errors.New("not implemented")
26 | }
27 |
28 | func (s *stubSecretRepo) GetByName(_ context.Context, name string) (*model.Secret, error) {
29 | if s.err != nil {
30 | return nil, s.err
31 | }
32 | if secret, ok := s.values[name]; ok {
33 | return secret, nil
34 | }
35 | return nil, errors.New("secret not found")
36 | }
37 |
38 | func (s *stubSecretRepo) List(context.Context, int, int) ([]*model.Secret, error) {
39 | return nil, errors.New("not implemented")
40 | }
41 |
42 | func (s *stubSecretRepo) Update(context.Context, string, model.UpdateSecretRequest) (*model.Secret, error) {
43 | return nil, errors.New("not implemented")
44 | }
45 |
46 | func (s *stubSecretRepo) Delete(context.Context, string) (bool, error) {
47 | return false, errors.New("not implemented")
48 | }
49 |
50 | func (s *stubSecretRepo) FindDueForRefresh(context.Context, int) ([]*model.Secret, error) {
51 | return nil, errors.New("not implemented")
52 | }
53 |
54 | func (s *stubSecretRepo) UpdateRefreshStatus(context.Context, UpdateSecretRefreshStatusParams) error {
55 | return errors.New("not implemented")
56 | }
57 |
--------------------------------------------------------------------------------
/services/merrymaker-go/internal/domain/job/lease_policy_test.go:
--------------------------------------------------------------------------------
1 | package job
2 |
3 | import (
4 | "testing"
5 | "time"
6 |
7 | "github.com/stretchr/testify/assert"
8 | "github.com/stretchr/testify/require"
9 | )
10 |
11 | func TestNewLeasePolicy(t *testing.T) {
12 | t.Run("success", func(t *testing.T) {
13 | policy, err := NewLeasePolicy(30 * time.Second)
14 | require.NoError(t, err)
15 | assert.Equal(t, 30*time.Second, policy.Default())
16 | })
17 |
18 | t.Run("invalid default lease", func(t *testing.T) {
19 | policy, err := NewLeasePolicy(0)
20 | require.ErrorIs(t, err, ErrInvalidDefaultLease)
21 | assert.Nil(t, policy)
22 | })
23 | }
24 |
25 | func TestLeasePolicy_Resolve(t *testing.T) {
26 | policy, err := NewLeasePolicy(30 * time.Second)
27 | require.NoError(t, err)
28 |
29 | t.Run("explicit duration uses whole seconds", func(t *testing.T) {
30 | decision := policy.Resolve(45 * time.Second)
31 | assert.Equal(t, 45, decision.Seconds)
32 | assert.Equal(t, LeaseSourceExplicit, decision.Source)
33 | assert.False(t, decision.Clamped())
34 | })
35 |
36 | t.Run("default duration when request is zero", func(t *testing.T) {
37 | decision := policy.Resolve(0)
38 | assert.Equal(t, 30, decision.Seconds)
39 | assert.Equal(t, LeaseSourceDefault, decision.Source)
40 | assert.True(t, decision.UsedDefault())
41 | })
42 |
43 | t.Run("sub-second duration clamps to minimum", func(t *testing.T) {
44 | decision := policy.Resolve(500 * time.Millisecond)
45 | assert.Equal(t, 1, decision.Seconds)
46 | assert.Equal(t, LeaseSourceClamped, decision.Source)
47 | assert.True(t, decision.Clamped())
48 | })
49 |
50 | t.Run("negative duration clamps to minimum", func(t *testing.T) {
51 | decision := policy.Resolve(-5 * time.Second)
52 | assert.Equal(t, 1, decision.Seconds)
53 | assert.Equal(t, LeaseSourceClamped, decision.Source)
54 | assert.True(t, decision.Clamped())
55 | })
56 | }
57 |
--------------------------------------------------------------------------------
/services/puppeteer-worker/src/file-capture.content-type.test.js:
--------------------------------------------------------------------------------
1 | import assert from "node:assert/strict";
2 | import { describe, test } from "node:test";
3 |
4 | // NOTE: Tests import the built artifact. Run `npm run build` before these tests.
5 | import { FileCapture } from "../dist/file-capture.js";
6 |
7 | function makeMemoryConfig(types = ["document"]) {
8 | return {
9 | enabled: true,
10 | types,
11 | maxFileSize: 1024 * 1024,
12 | storage: "memory",
13 | storageConfig: {},
14 | };
15 | }
16 |
17 | describe("FileCapture content-type coverage", () => {
18 | test("captures JSON as document", async () => {
19 | const sessionId = `sess-json-${Math.random().toString(36).slice(2)}`;
20 | const fc = new FileCapture(makeMemoryConfig(["document"]), sessionId);
21 |
22 | const content = Buffer.from('{"ok":true}');
23 |
24 | const ctx = await fc.captureFile({
25 | url: "https://example.com/data.json",
26 | content,
27 | contentType: "application/json; charset=utf-8",
28 | sessionId,
29 | });
30 |
31 | assert.ok(ctx, "expected JSON to be captured");
32 | assert.equal(ctx.contentType.includes("application/json"), true);
33 |
34 | await fc.cleanup();
35 | });
36 |
37 | test("captures XML (+xml) as document", async () => {
38 | const sessionId = `sess-xml-${Math.random().toString(36).slice(2)}`;
39 | const fc = new FileCapture(makeMemoryConfig(["document"]), sessionId);
40 |
41 | const content = Buffer.from('