Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Code review modifications.
  • Loading branch information
slightfoot committed Jul 21, 2018
commit 11c14e23cb07c8391eb9ce8c11692558b4eb9a36
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
# Name/Organization <email address>

Google Inc.
Simon Lightfoot <[email protected]>
14 changes: 10 additions & 4 deletions lib/sentry.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import 'src/version.dart';

export 'src/version.dart';

/// Used to provide time-stamp for logging.
/// Used to provide timestamp for logging.
typedef ClockProvider = DateTime Function();

/// Logs crash reports and events to the Sentry.io service.
Expand Down Expand Up @@ -48,7 +48,9 @@ class SentryClient {
/// make HTTP calls to Sentry.io. This is useful in tests.
///
/// If [clock] is provided, it is used to get time instead of the system
/// clock. This is useful in tests.
/// clock. This is useful in tests. Should be an implementation of ClockProvider.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

References to in-scope identifiers should be wrapped in square brackets so that dartdoc can create links to them, in this case [ClockProvider].

/// This parameter is dynamic to maintain backwards compatibility with
/// previous use of Clock from the Quiver library.
///
/// If [uuidGenerator] is provided, it is used to generate the "event_id"
/// field instead of the built-in random UUID v4 generator. This is useful in
Expand All @@ -58,14 +60,18 @@ class SentryClient {
Event environmentAttributes,
bool compressPayload,
Client httpClient,
ClockProvider clock,
dynamic clock,
UuidGenerator uuidGenerator,
}) {
httpClient ??= new Client();
clock ??= _getUtcDateTime;
uuidGenerator ??= _generateUuidV4WithoutDashes;
compressPayload ??= true;

final ClockProvider clockProvider = clock is ClockProvider
? clock
: clock.get;

final Uri uri = Uri.parse(dsn);
final List<String> userInfo = uri.userInfo.split(':');

Expand All @@ -83,7 +89,7 @@ class SentryClient {

return new SentryClient._(
httpClient: httpClient,
clock: clock,
clock: clockProvider,
uuidGenerator: uuidGenerator,
environmentAttributes: environmentAttributes,
dsnUri: uri,
Expand Down
69 changes: 67 additions & 2 deletions test/sentry_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:sentry/sentry.dart';
import 'package:test/test.dart';

const String _testDsn = 'https://public:[email protected]/1';
const String _testDsnWithoutSecret = 'https://[email protected]/1';

void main() {
group('$SentryClient', () {
Expand All @@ -23,6 +24,70 @@ void main() {
await client.close();
});

test('can parse DSN without secret', () async {
final SentryClient client = new SentryClient(dsn: _testDsnWithoutSecret);
expect(client.dsnUri, Uri.parse(_testDsnWithoutSecret));
expect(client.postUri, 'https://sentry.example.com/api/1/store/');
expect(client.publicKey, 'public');
expect(client.secretKey, null);
expect(client.projectId, '1');
await client.close();
});

test('sends client auth header without secret', () async {
final MockClient httpMock = new MockClient();
final ClockProvider fakeClockProvider = () => new DateTime.utc(2017, 1, 2);

Map<String, String> headers;

httpMock.answerWith((Invocation invocation) async {
if (invocation.memberName == #close) {
return null;
}
if (invocation.memberName == #post) {
headers = invocation.namedArguments[#headers];
return new Response('{"id": "test-event-id"}', 200);
}
fail('Unexpected invocation of ${invocation.memberName} in HttpMock');
});

final SentryClient client = new SentryClient(
dsn: _testDsnWithoutSecret,
httpClient: httpMock,
clock: fakeClockProvider,
compressPayload: false,
uuidGenerator: () => 'X' * 32,
environmentAttributes: const Event(
serverName: 'test.server.com',
release: '1.2.3',
environment: 'staging',
),
);

try {
throw new ArgumentError('Test error');
} catch (error, stackTrace) {
final SentryResponse response = await client.captureException(
exception: error, stackTrace: stackTrace);
expect(response.isSuccessful, true);
expect(response.eventId, 'test-event-id');
expect(response.error, null);
}

final Map<String, String> expectedHeaders = <String, String>{
'User-Agent': '$sdkName/$sdkVersion',
'Content-Type': 'application/json',
'X-Sentry-Auth': 'Sentry sentry_version=6, '
'sentry_client=${SentryClient.sentryClient}, '
'sentry_timestamp=${fakeClockProvider().millisecondsSinceEpoch}, '
'sentry_key=public',
};

expect(headers, expectedHeaders);

await client.close();
});

testCaptureException(bool compressPayload) async {
final MockClient httpMock = new MockClient();
final ClockProvider fakeClockProvider =
Expand Down Expand Up @@ -131,7 +196,7 @@ void main() {

test('reads error message from the x-sentry-error header', () async {
final MockClient httpMock = new MockClient();
final ClockProvider fakeClockProvider = () => DateTime(2017, 1, 2);
final ClockProvider fakeClockProvider = () => new DateTime.utc(2017, 1, 2);

httpMock.answerWith((Invocation invocation) async {
if (invocation.memberName == #close) {
Expand Down Expand Up @@ -174,7 +239,7 @@ void main() {

test('$Event userContext overrides client', () async {
final MockClient httpMock = new MockClient();
final ClockProvider fakeClockProvider = () => DateTime(2017, 1, 2);
final ClockProvider fakeClockProvider = () => new DateTime.utc(2017, 1, 2);

String loggedUserId; // used to find out what user context was sent
httpMock.answerWith((Invocation invocation) async {
Expand Down