Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Determine encoding of source files used for coverage #1691

Merged
merged 4 commits into from Apr 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions pkgs/test/CHANGELOG.md
@@ -1,3 +1,8 @@
## 1.21.1

* Fix a bug loading JS sources with non-utf8 content while parsing coverage
information from chrome.

## 1.21.0

* Allow analyzer version `4.x`.
Expand Down
14 changes: 13 additions & 1 deletion pkgs/test/lib/src/runner/browser/chrome.dart
Expand Up @@ -194,11 +194,23 @@ Future<WipConnection> _connect(
}

extension on HttpClient {
Encoding determineEncoding(HttpHeaders headers) {
final contentType = headers.contentType?.charset;

/// Using the `charset` property of the `contentType` if available.
/// If it's unavailable or if the encoding name is unknown, [latin1] is used by default,
/// as per [RFC 2616][].
///
/// [RFC 2616]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html
return Encoding.getByName(contentType) ?? latin1;
}

Future<String?> getString(String url) async {
final request = await getUrl(Uri.parse(url));
final response = await request.close();
if (response.statusCode != HttpStatus.ok) return null;
var bytes = [await for (var chunk in response) ...chunk];
return utf8.decode(bytes);
final encoding = determineEncoding(response.headers);
return encoding.decode(bytes);
}
}
2 changes: 1 addition & 1 deletion pkgs/test/pubspec.yaml
@@ -1,5 +1,5 @@
name: test
version: 1.21.0
version: 1.21.1
description: >-
A full featured library for writing and running Dart tests across platforms.
repository: https://github.com/dart-lang/test/blob/master/pkgs/test
Expand Down
65 changes: 65 additions & 0 deletions pkgs/test/test/runner/coverage_test.dart
Expand Up @@ -62,5 +62,70 @@ void main() {
['--coverage', coverageDirectory.path, 'test.dart', '-p', 'chrome']);
await _validateCoverage(test, 'test.dart.chrome.json');
});

test(
'gathers coverage for Chrome tests when JS files contain unicode characters',
() async {
final sourceMapFileContent =
'{"version":3,"file":"","sources":[],"names":[],"mappings":""}';
final jsContent = '''
(function() {
'© '
window.foo = function foo() {
return 'foo';
};
})({

'© ': ''
});
''';
await d.file('file_with_unicode.js', jsContent).create();
await d.file('file_with_unicode.js.map', sourceMapFileContent).create();

await d.file('js_with_unicode_test.dart', '''
import 'dart:html';
import 'dart:js';

import 'package:test/test.dart';

Future<void> loadScript(String src) async {
final script = ScriptElement()..src = src;
final scriptLoaded = script.onLoad.first;
document.body!.append(script);
await scriptLoaded.timeout(Duration(seconds: 1));
}

void main() {
test("test 1", () async {
await loadScript('file_with_unicode.js');
expect(context['foo'], isNotNull);
context.callMethod('foo', []);
expect(true, isTrue);
});
}
''').create();

final jsBytes = utf8.encode(jsContent);
final jsLatin1 = latin1.decode(jsBytes);
final jsUtf8 = utf8.decode(jsBytes);
expect(jsLatin1, isNot(jsUtf8),
reason: 'test setup: should have decoded differently');

const functionPattern = 'function foo';
expect([jsLatin1, jsUtf8], everyElement(contains(functionPattern)));
expect(jsLatin1.indexOf(functionPattern),
isNot(jsUtf8.indexOf(functionPattern)),
reason:
'test setup: decoding should have shifted the position of the function');

var test = await runTest([
'--coverage',
coverageDirectory.path,
'js_with_unicode_test.dart',
'-p',
'chrome'
]);
await _validateCoverage(test, 'js_with_unicode_test.dart.chrome.json');
});
});
}