Skip to content

Commit 11548fe

Browse files
committed
updated to make it work with tests
1 parent 35a172d commit 11548fe

File tree

8 files changed

+162
-45
lines changed

8 files changed

+162
-45
lines changed

src/Sentry.Unity/ScreenshotEventProcessor.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,23 @@
11
using Sentry.Extensibility;
2-
using Sentry.Unity.Integrations;
3-
using UnityEngine;
42

53
namespace Sentry.Unity;
64

75
public class ScreenshotEventProcessor : ISentryEventProcessor
86
{
97
private readonly SentryUnityOptions _options;
10-
private readonly SentryMonoBehaviour _sentryMonoBehaviour;
8+
private readonly ISentryMonoBehaviour _sentryMonoBehaviour;
119

1210
public ScreenshotEventProcessor(SentryUnityOptions sentryOptions) : this(sentryOptions, SentryMonoBehaviour.Instance) { }
1311

14-
internal ScreenshotEventProcessor(SentryUnityOptions sentryOptions, SentryMonoBehaviour? sentryMonoBehaviour)
12+
internal ScreenshotEventProcessor(SentryUnityOptions sentryOptions, ISentryMonoBehaviour sentryMonoBehaviour)
1513
{
1614
_options = sentryOptions;
17-
_sentryMonoBehaviour = sentryMonoBehaviour ?? SentryMonoBehaviour.Instance;
15+
_sentryMonoBehaviour = sentryMonoBehaviour;
1816
}
1917

2018
public SentryEvent Process(SentryEvent @event)
2119
{
20+
// Screenshot capture is happening within the MonoBehaviour as it has to happen at the "EndOfFrame"
2221
_sentryMonoBehaviour.CaptureScreenshotForEvent(_options, @event.EventId);
2322
return @event;
2423
}

src/Sentry.Unity/SentryMonoBehaviour.cs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.Collections;
33
using Sentry.Extensibility;
44
using Sentry.Internal;
5-
using Sentry.Protocol.Envelopes;
65
using Sentry.Unity.Integrations;
76
using UnityEngine;
87

@@ -11,6 +10,7 @@ namespace Sentry.Unity;
1110
internal interface ISentryMonoBehaviour
1211
{
1312
event Action? ApplicationResuming;
13+
public void CaptureScreenshotForEvent(SentryUnityOptions options, SentryId eventId);
1414
}
1515

1616
/// <summary>
@@ -120,43 +120,45 @@ private void Awake()
120120
/// <summary>
121121
/// A MonoBehaviour that captures screenshots
122122
/// </summary>
123-
public partial class SentryMonoBehaviour
123+
public partial class SentryMonoBehaviour : ISentryMonoBehaviour
124124
{
125-
private bool _isCapturingScreenshot = false;
125+
private bool _isCapturingScreenshot;
126+
internal Func<SentryUnityOptions, byte[]> ScreenshotCaptureFunction = SentryScreenshot.Capture;
127+
internal Action<SentryId, SentryAttachment> AttachmentCaptureFunction = (eventId, attachment) =>
128+
((Hub)Sentry.SentrySdk.CurrentHub).CaptureAttachment(eventId, attachment);
126129

127130
public void CaptureScreenshotForEvent(SentryUnityOptions options, SentryId eventId)
128131
{
129132
// Only ever capture one screenshot per frame
130133
if (!_isCapturingScreenshot)
131134
{
132135
_isCapturingScreenshot = true;
133-
StartCoroutine(CaptureScreenshotCoroutine(options, eventId));
136+
StartCoroutine(CaptureScreenshot(options, eventId));
134137
}
135138
}
136139

137-
private IEnumerator CaptureScreenshotCoroutine(SentryUnityOptions options, SentryId eventId)
140+
private IEnumerator CaptureScreenshot(SentryUnityOptions options, SentryId eventId)
138141
{
139-
options.LogDebug("Screenshot capturing triggered. Waiting for End of Frame.");
142+
options.LogDebug("Screenshot capture triggered. Waiting for End of Frame.");
140143

141144
yield return new WaitForEndOfFrame();
142145

143146
try
144147
{
145-
options.LogDebug("Capturing screenshot.");
146-
var screenshotBytes = SentryScreenshot.Capture(options);
148+
var screenshotBytes = ScreenshotCaptureFunction(options);
147149
var attachment = new SentryAttachment(
148150
AttachmentType.Default,
149151
new ByteAttachmentContent(screenshotBytes),
150152
"screenshot.jpg",
151153
"image/jpeg");
152154

153-
Sentry.SentrySdk.CaptureAttachment(eventId, attachment);
155+
options.LogDebug("Screenshot captured for event {0}", eventId);
154156

155-
options.LogDebug("Screenshot captured and sent for event {0}", eventId);
157+
AttachmentCaptureFunction(eventId, attachment);
156158
}
157159
catch (Exception e)
158160
{
159-
options.LogError(e, "Failed to capture screenshot: {0}");
161+
options.LogError(e, "Failed to capture screenshot.");
160162
}
161163
finally
162164
{

src/Sentry.Unity/SentrySdk.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ public static void Init(Action<SentryUnityOptions> sentryUnityOptionsConfigure)
2020
var options = new SentryUnityOptions();
2121
sentryUnityOptionsConfigure.Invoke(options);
2222

23-
2423
Init(options);
2524
}
2625

src/Sentry.Unity/SentryUnitySdk.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,11 @@ internal void CaptureAttachment(SentryId eventId, SentryAttachment attachment)
134134
if (Sentry.SentrySdk.CurrentHub is Hub hub)
135135
{
136136
hub.CaptureAttachment(eventId, attachment);
137-
_options.DiagnosticLogger?.LogDebug("Attachment captured for event {0}", eventId);
137+
_options.LogDebug("Attachment captured for event {0}", eventId);
138+
}
139+
else
140+
{
141+
_options.LogError("Capturing the attachment failed due to the current hub.");
138142
}
139143
}
140144
catch (Exception ex)
Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,18 @@
1-
using System.Threading;
21
using NUnit.Framework;
32
using Sentry.Unity.Tests.Stubs;
43

54
namespace Sentry.Unity.Tests;
65

76
public class ScreenshotEventProcessorTests
87
{
9-
private class Fixture
8+
[Test]
9+
public void SentryEventProcessor_Process_CallsCaptureScreenshotForEvent()
1010
{
11-
public SentryUnityOptions Options = new() { AttachScreenshot = true };
12-
public TestApplication TestApplication = new();
11+
var sentryMonoBehaviour = new TestSentryMonoBehaviour();
1312

14-
public ScreenshotEventProcessor GetSut() => new(Options);
15-
}
16-
17-
private Fixture _fixture = null!;
18-
19-
[SetUp]
20-
public void SetUp() => _fixture = new Fixture();
13+
var screenshotProcessor = new ScreenshotEventProcessor(new SentryUnityOptions(), sentryMonoBehaviour);
14+
screenshotProcessor.Process(new SentryEvent());
2115

22-
[TearDown]
23-
public void TearDown()
24-
{
25-
if (SentrySdk.IsEnabled)
26-
{
27-
SentrySdk.Close();
28-
}
16+
Assert.IsTrue(sentryMonoBehaviour.CaptureScreenshotForEventCalled);
2917
}
30-
31-
// Todo: Add tests that verify passing the capture on to the MonoBehaviour
3218
}

test/Sentry.Unity.Tests/SentryMonoBehaviourTests.cs

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
using System.Collections;
2+
using System.Collections.Generic;
13
using NUnit.Framework;
24
using Sentry.Unity.Tests.Stubs;
35
using UnityEngine;
6+
using UnityEngine.TestTools;
47

58
namespace Sentry.Unity.Tests;
69

@@ -78,4 +81,122 @@ public void UpdatePauseStatus_ResumedTwice_ApplicationResumingInvokedOnlyOnce()
7881

7982
Assert.AreEqual(1, counter);
8083
}
84+
85+
[UnityTest]
86+
public IEnumerator CaptureScreenshotForEvent_Called_CapturesScreenshotAttachmentForEventId()
87+
{
88+
// Arrange
89+
var options = new SentryUnityOptions();
90+
var sut = _fixture.GetSut();
91+
92+
var capturedId = SentryId.Empty;
93+
SentryAttachment? capturedAttachment = null;
94+
sut.AttachmentCaptureFunction = (eventId, attachment) =>
95+
{
96+
capturedId = eventId;
97+
capturedAttachment = attachment;
98+
};
99+
100+
var eventId = SentryId.Create();
101+
102+
// Act
103+
sut.CaptureScreenshotForEvent(options, eventId);
104+
105+
// Wait for the coroutine to complete
106+
yield return 0;
107+
108+
// Assert
109+
Assert.AreEqual(eventId, capturedId);
110+
Assert.IsNotNull(capturedAttachment); // Sanity check
111+
Assert.AreEqual("screenshot.jpg", capturedAttachment!.FileName);
112+
Assert.AreEqual("image/jpeg", capturedAttachment.ContentType);
113+
Assert.AreEqual(AttachmentType.Default, capturedAttachment.Type);
114+
}
115+
116+
[UnityTest]
117+
public IEnumerator CaptureScreenshotForEvent_CalledMultipleTimesInOneFrame_OnlyExecutesOnce()
118+
{
119+
// Arrange
120+
var options = new SentryUnityOptions();
121+
var sut = _fixture.GetSut();
122+
123+
var didScreenshotCaptureGetCalled = false;
124+
sut.ScreenshotCaptureFunction = _ =>
125+
{
126+
didScreenshotCaptureGetCalled = true;
127+
return [0];
128+
};
129+
130+
var didCaptureMethodGetCalled = false;
131+
var captureMethodCallCount = 0;
132+
sut.AttachmentCaptureFunction = (_, _) =>
133+
{
134+
didCaptureMethodGetCalled = true;
135+
captureMethodCallCount++;
136+
};
137+
138+
var eventId = SentryId.Create();
139+
140+
// Act
141+
sut.CaptureScreenshotForEvent(options, eventId);
142+
sut.CaptureScreenshotForEvent(options, eventId);
143+
sut.CaptureScreenshotForEvent(options, eventId);
144+
145+
// Wait for the coroutine to complete
146+
yield return 0;
147+
148+
// Assert
149+
Assert.IsTrue(didScreenshotCaptureGetCalled);
150+
Assert.IsTrue(didCaptureMethodGetCalled);
151+
Assert.AreEqual(1, captureMethodCallCount);
152+
}
153+
154+
[UnityTest]
155+
public IEnumerator CaptureScreenshotForEvent_CalledTwoFramesApart_CapturesBothScreenshots()
156+
{
157+
// Arrange
158+
var options = new SentryUnityOptions();
159+
var sut = _fixture.GetSut();
160+
161+
var capturedEventIds = new List<SentryId>();
162+
var capturedAttachments = new List<SentryAttachment>();
163+
sut.AttachmentCaptureFunction = (eventId, attachment) =>
164+
{
165+
capturedEventIds.Add(eventId);
166+
capturedAttachments.Add(attachment);
167+
};
168+
169+
var eventId1 = SentryId.Create();
170+
var eventId2 = SentryId.Create();
171+
172+
// Act
173+
sut.CaptureScreenshotForEvent(options, eventId1);
174+
175+
// Wait for the first coroutine to complete
176+
yield return 0;
177+
178+
// Capture second screenshot in next frame
179+
sut.CaptureScreenshotForEvent(options, eventId2);
180+
181+
// Wait for the second coroutine to complete
182+
yield return 0;
183+
184+
// Assert
185+
Assert.AreEqual(2, capturedEventIds.Count);
186+
Assert.AreEqual(2, capturedAttachments.Count);
187+
188+
// First screenshot
189+
Assert.AreEqual(eventId1, capturedEventIds[0]);
190+
Assert.IsNotNull(capturedAttachments[0]);
191+
Assert.AreEqual("screenshot.jpg", capturedAttachments[0].FileName);
192+
Assert.AreEqual("image/jpeg", capturedAttachments[0].ContentType);
193+
Assert.AreEqual(AttachmentType.Default, capturedAttachments[0].Type);
194+
195+
// Second screenshot
196+
Assert.AreEqual(eventId2, capturedEventIds[1]);
197+
Assert.IsNotNull(capturedAttachments[1]);
198+
Assert.AreEqual("screenshot.jpg", capturedAttachments[1].FileName);
199+
Assert.AreEqual("image/jpeg", capturedAttachments[1].ContentType);
200+
Assert.AreEqual(AttachmentType.Default, capturedAttachments[1].Type);
201+
}
81202
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
3+
namespace Sentry.Unity.Tests.Stubs;
4+
5+
internal class TestSentryMonoBehaviour : ISentryMonoBehaviour
6+
{
7+
public event Action? ApplicationResuming;
8+
public bool CaptureScreenshotForEventCalled {get; private set;}
9+
10+
public void ResumeApplication() => ApplicationResuming?.Invoke();
11+
public void CaptureScreenshotForEvent(SentryUnityOptions options, SentryId eventId)
12+
=> CaptureScreenshotForEventCalled = true;
13+
}

test/Sentry.Unity.Tests/TraceGenerationIntegrationTests.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,4 @@ public void TraceGeneration_OnActiveSceneChange_GeneratesNewTrace()
9393

9494
Assert.AreNotEqual(initialPropagationContext, scope.PropagationContext);
9595
}
96-
97-
internal class TestSentryMonoBehaviour : ISentryMonoBehaviour
98-
{
99-
public event Action? ApplicationResuming;
100-
101-
public void ResumeApplication() => ApplicationResuming?.Invoke();
102-
}
10396
}

0 commit comments

Comments
 (0)