From 9033584205bf1b5d2073d18fe921d72a0b6d5ce2 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Fri, 11 Sep 2020 16:05:30 -0700 Subject: [PATCH 1/2] Move many package and library tests from end2end to unit tests --- lib/src/package_config_provider.dart | 2 + lib/src/package_meta.dart | 6 + test/end2end/html_generator_test.dart | 1 - test/end2end/model_special_cases_test.dart | 136 +++------ test/end2end/model_test.dart | 74 +---- test/library_test.dart | 67 ++++ test/package_test.dart | 336 ++++++++++++++------- test/src/utils.dart | 79 ++++- 8 files changed, 430 insertions(+), 271 deletions(-) create mode 100644 test/library_test.dart diff --git a/lib/src/package_config_provider.dart b/lib/src/package_config_provider.dart index 259ed379cf..3221aa4ea8 100644 --- a/lib/src/package_config_provider.dart +++ b/lib/src/package_config_provider.dart @@ -33,6 +33,8 @@ class FakePackageConfigProvider implements PackageConfigProvider { @override Future findPackageConfig(Folder dir) async { + assert(_packageConfigData[dir.path] != null, + 'Package config data at ${dir.path} should not be null'); return package_config.PackageConfig(_packageConfigData[dir.path]); } } diff --git a/lib/src/package_meta.dart b/lib/src/package_meta.dart index 369782f61b..53029f8c34 100644 --- a/lib/src/package_meta.dart +++ b/lib/src/package_meta.dart @@ -12,6 +12,7 @@ import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/file_system/physical_file_system.dart'; import 'package:analyzer/src/generated/sdk.dart'; import 'package:dartdoc/dartdoc.dart'; +import 'package:meta/meta.dart'; import 'package:path/path.dart' as p; import 'package:yaml/yaml.dart'; @@ -487,3 +488,8 @@ class _SdkMeta extends PubPackageMeta { @override File getChangelogContents() => null; } + +@visibleForTesting +clearPackageMetaCache() { + _packageMetaCache.clear(); +} diff --git a/test/end2end/html_generator_test.dart b/test/end2end/html_generator_test.dart index bd8bf71897..d2b2bd1b8e 100644 --- a/test/end2end/html_generator_test.dart +++ b/test/end2end/html_generator_test.dart @@ -121,7 +121,6 @@ void main() { generator = await _initGeneratorForTest(); packageGraph = await utils.bootBasicPackage( testPackageDuplicateDir.path, - [], pubPackageMetaProvider, PhysicalPackageConfigProvider()); tempOutput = await resourceProvider.createSystemTemp('doc_test_temp'); diff --git a/test/end2end/model_special_cases_test.dart b/test/end2end/model_special_cases_test.dart index ee3d731b7a..4d63a6a884 100644 --- a/test/end2end/model_special_cases_test.dart +++ b/test/end2end/model_special_cases_test.dart @@ -27,27 +27,30 @@ final Version _platformVersion = Version.parse(_platformVersionString); final _testPackageGraphExperimentsMemo = AsyncMemoizer(); Future get _testPackageGraphExperiments => _testPackageGraphExperimentsMemo.runOnce(() => utils.bootBasicPackage( - 'testing/test_package_experiments', - [], - pubPackageMetaProvider, - PhysicalPackageConfigProvider(), - additionalArguments: [ - '--enable-experiment', - 'non-nullable', - '--no-link-to-remote' - ])); + 'testing/test_package_experiments', + pubPackageMetaProvider, + PhysicalPackageConfigProvider(), + additionalArguments: [ + '--enable-experiment', + 'non-nullable', + '--no-link-to-remote' + ])); final _testPackageGraphGinormousMemo = AsyncMemoizer(); Future get _testPackageGraphGinormous => _testPackageGraphGinormousMemo.runOnce(() => utils.bootBasicPackage( - 'testing/test_package', - ['css', 'code_in_commnets', 'excluded'], - pubPackageMetaProvider, - PhysicalPackageConfigProvider(), - additionalArguments: [ - '--auto-include-dependencies', - '--no-link-to-remote' - ])); + 'testing/test_package', + pubPackageMetaProvider, + PhysicalPackageConfigProvider(), + excludeLibraries: [ + 'css', + 'code_in_commnets', + 'excluded' + ], + additionalArguments: [ + '--auto-include-dependencies', + '--no-link-to-remote' + ])); final _testPackageGraphSdkMemo = AsyncMemoizer(); Future get _testPackageGraphSdk => @@ -261,9 +264,9 @@ void main() { setUpAll(() async { injectionPackageGraph = await utils.bootBasicPackage( 'testing/test_package', - ['css', 'code_in_comments', 'excluded'], pubPackageMetaProvider, PhysicalPackageConfigProvider(), + excludeLibraries: ['css', 'code_in_comments', 'excluded'], additionalArguments: ['--inject-html']); injectionExLibrary = @@ -429,79 +432,30 @@ void main() { sdkAsPackageGraph = await _testPackageGraphSdk; }); - group('test package', () { - test('sdk name', () { - expect(sdkAsPackageGraph.defaultPackage.name, equals('Dart')); - expect(sdkAsPackageGraph.defaultPackage.kind, equals('SDK')); - }); - - test('sdk homepage', () { - expect(sdkAsPackageGraph.defaultPackage.hasHomepage, isTrue); - expect(sdkAsPackageGraph.defaultPackage.homepage, - equals('https://github.com/dart-lang/sdk')); - }); - - test('sdk version', () { - expect(sdkAsPackageGraph.defaultPackage.version, isNotNull); - }); - - test('sdk description', () { - expect(sdkAsPackageGraph.defaultPackage.documentation, - startsWith('Welcome')); - }); - }); - - group('SDK-specific cases', () { - test('Verify Interceptor is hidden from inheritance in docs', () { - var htmlLibrary = sdkAsPackageGraph.libraries - .singleWhere((l) => l.name == 'dart:html'); - var EventTarget = - htmlLibrary.allClasses.singleWhere((c) => c.name == 'EventTarget'); - var hashCode = EventTarget.publicInstanceFields - .singleWhere((f) => f.name == 'hashCode'); - var objectModelElement = - sdkAsPackageGraph.specialClasses[SpecialClass.object]; - // If this fails, EventTarget might have been changed to no longer - // inherit from Interceptor. If that's true, adjust test case to - // another class that does. - expect( - hashCode.inheritance.any((c) => c.name == 'Interceptor'), isTrue); - // If EventTarget really does start implementing hashCode, this will - // fail. - expect(hashCode.href, - equals('${HTMLBASE_PLACEHOLDER}dart-core/Object/hashCode.html')); - expect( - hashCode.canonicalEnclosingContainer, equals(objectModelElement)); - expect( - EventTarget.publicSuperChainReversed - .any((et) => et.name == 'Interceptor'), - isFalse); - }); - - test('Verify pragma is hidden in SDK docs', () { - var pragmaModelElement = - sdkAsPackageGraph.specialClasses[SpecialClass.pragma]; - expect(pragmaModelElement.name, equals('pragma')); - }); - }); - }); - - group('Library', () { - Library dartAsyncLib; - - setUpAll(() async { - dartAsyncLib = (await _testPackageGraphSdk) - .libraries - .firstWhere((l) => l.name == 'dart:async'); - // Make sure the first library is dart:async - expect(dartAsyncLib.name, 'dart:async'); - }); - - test('sdk library have formatted names', () { - expect(dartAsyncLib.name, 'dart:async'); - expect(dartAsyncLib.dirName, 'dart-async'); - expect(dartAsyncLib.href, - '${HTMLBASE_PLACEHOLDER}dart-async/dart-async-library.html'); + // Analyzer's MockSdk's html library doesn't conform to the expectations + // of this test. + test('Verify Interceptor is hidden from inheritance in docs', () { + var htmlLibrary = + sdkAsPackageGraph.libraries.singleWhere((l) => l.name == 'dart:html'); + var EventTarget = + htmlLibrary.allClasses.singleWhere((c) => c.name == 'EventTarget'); + var hashCode = EventTarget.publicInstanceFields + .singleWhere((f) => f.name == 'hashCode'); + var objectModelElement = + sdkAsPackageGraph.specialClasses[SpecialClass.object]; + // If this fails, EventTarget might have been changed to no longer + // inherit from Interceptor. If that's true, adjust test case to + // another class that does. + expect(hashCode.inheritance.any((c) => c.name == 'Interceptor'), isTrue); + // If EventTarget really does start implementing hashCode, this will + // fail. + expect(hashCode.href, + equals('${HTMLBASE_PLACEHOLDER}dart-core/Object/hashCode.html')); + expect(hashCode.canonicalEnclosingContainer, equals(objectModelElement)); + expect( + EventTarget.publicSuperChainReversed + .any((et) => et.name == 'Interceptor'), + isFalse); }); }); } diff --git a/test/end2end/model_test.dart b/test/end2end/model_test.dart index b589aeed4d..038347d7d4 100644 --- a/test/end2end/model_test.dart +++ b/test/end2end/model_test.dart @@ -24,9 +24,9 @@ final _testPackageGraphMemo = AsyncMemoizer(); Future get _testPackageGraph => _testPackageGraphMemo.runOnce(() => utils.bootBasicPackage( 'testing/test_package', - ['css', 'code_in_comments'], pubPackageMetaProvider, PhysicalPackageConfigProvider(), + excludeLibraries: ['css', 'code_in_comments'], additionalArguments: ['--no-link-to-remote'])); /// For testing sort behavior. @@ -70,7 +70,6 @@ void main() { Library exLibrary; Library fakeLibrary; Library twoExportsLib; - Library interceptorsLib; Library baseClassLib; Library dartAsync; @@ -85,8 +84,6 @@ void main() { packageGraph.libraries.firstWhere((lib) => lib.name == 'dart:async'); twoExportsLib = packageGraph.libraries.firstWhere((lib) => lib.name == 'two_exports'); - interceptorsLib = packageGraph.libraries - .firstWhere((lib) => lib.name == 'dart:_interceptors'); baseClassLib = packageGraph.libraries.firstWhere((lib) => lib.name == 'base_class'); }); @@ -474,75 +471,6 @@ void main() { }); }); - group('Package', () { - group('test package', () { - test('name', () { - expect(packageGraph.defaultPackage.name, 'test_package'); - }); - - test('libraries', () { - expect(packageGraph.localPublicLibraries, - hasLength(utils.kTestPackagePublicLibraries)); - expect(interceptorsLib.isPublic, isFalse); - }); - - test('homepage', () { - expect(packageGraph.defaultPackage.hasHomepage, true); - expect(packageGraph.defaultPackage.homepage, - equals('http://github.com/dart-lang')); - }); - - test('packages', () { - expect(packageGraph.localPackages, hasLength(1)); - - var package = packageGraph.localPackages.first; - expect(package.name, 'test_package'); - expect(package.publicLibraries, - hasLength(utils.kTestPackagePublicLibraries)); - }); - - test('is documented in library', () { - expect(exLibrary.isDocumented, isTrue); - }); - - test('has documentation', () { - expect(packageGraph.defaultPackage.hasDocumentationFile, isTrue); - expect(packageGraph.defaultPackage.hasDocumentation, isTrue); - }); - - test('documentation exists', () { - expect( - packageGraph.defaultPackage.documentation - .startsWith('# Best Package'), - isTrue); - }); - - test('documentation can be rendered as HTML', () { - expect(packageGraph.defaultPackage.documentationAsHtml, - contains('

Best Package

')); - }); - - test('has anonymous libraries', () { - expect( - packageGraph.libraries - .where((lib) => lib.name == 'anonymous_library'), - hasLength(1)); - expect( - packageGraph.libraries - .where((lib) => lib.name == 'another_anonymous_lib'), - hasLength(1)); - }); - }); - - group('SDK-specific cases', () { - test('Verify pragma is hidden in docs', () { - var HasPragma = fakeLibrary.allClasses - .firstWhere((Class c) => c.name == 'HasPragma'); - expect(HasPragma.annotations, isEmpty); - }); - }); - }); - group('Library', () { Library anonLib, isDeprecated, diff --git a/test/library_test.dart b/test/library_test.dart new file mode 100644 index 0000000000..4ecd63d2ed --- /dev/null +++ b/test/library_test.dart @@ -0,0 +1,67 @@ +// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analyzer/file_system/file_system.dart'; +import 'package:analyzer/file_system/memory_file_system.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; +import 'package:dartdoc/src/dartdoc_options.dart'; +import 'package:dartdoc/src/model/model.dart'; +import 'package:dartdoc/src/package_config_provider.dart'; +import 'package:dartdoc/src/package_meta.dart'; +import 'package:test/test.dart'; + +import 'src/utils.dart' as utils; + +void main() { + MemoryResourceProvider resourceProvider; + MockSdk mockSdk; + Folder sdkFolder; + + PackageMetaProvider packageMetaProvider; + FakePackageConfigProvider packageConfigProvider; + + setUp(() async { + resourceProvider = MemoryResourceProvider(); + mockSdk = MockSdk(resourceProvider: resourceProvider); + sdkFolder = utils.writeMockSdkFiles(mockSdk); + + packageMetaProvider = PackageMetaProvider( + PubPackageMeta.fromElement, + PubPackageMeta.fromFilename, + PubPackageMeta.fromDir, + resourceProvider, + sdkFolder, + defaultSdk: mockSdk, + ); + var optionSet = await DartdocOptionSet.fromOptionGenerators( + 'dartdoc', [createDartdocOptions], packageMetaProvider); + optionSet.parseArguments([]); + packageConfigProvider = FakePackageConfigProvider(); + // To build the package graph, we always ask package_config for a + // [PackageConfig] for the SDK directory. Put a dummy entry in. + packageConfigProvider.addPackageToConfigFor( + sdkFolder.path, 'analyzer', Uri.file('/sdk/pkg/analyzer/')); + }); + + test('libraries in SDK package have appropriate data', () async { + var packageGraph = await utils.bootBasicPackage( + sdkFolder.path, packageMetaProvider, packageConfigProvider, + additionalArguments: [ + '--input', + packageMetaProvider.defaultSdkDir.path, + ]); + + var localPackages = packageGraph.localPackages; + expect(localPackages, hasLength(1)); + var sdkPackage = localPackages.single; + expect(sdkPackage.name, equals('Dart')); + + var dartAsyncLib = + sdkPackage.libraries.firstWhere((l) => l.name == 'dart:async'); + expect(dartAsyncLib.name, 'dart:async'); + expect(dartAsyncLib.dirName, 'dart-async'); + expect(dartAsyncLib.href, + '${HTMLBASE_PLACEHOLDER}dart-async/dart-async-library.html'); + }); +} diff --git a/test/package_test.dart b/test/package_test.dart index a11671ef7b..728e2c13ca 100644 --- a/test/package_test.dart +++ b/test/package_test.dart @@ -6,9 +6,9 @@ import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:dartdoc/src/dartdoc_options.dart'; -import 'package:dartdoc/src/model/model.dart'; import 'package:dartdoc/src/package_config_provider.dart'; import 'package:dartdoc/src/package_meta.dart'; +import 'package:dartdoc/src/special_elements.dart'; import 'package:test/test.dart'; import 'src/utils.dart' as utils; @@ -17,65 +17,17 @@ void main() { MemoryResourceProvider resourceProvider; MockSdk mockSdk; Folder sdkFolder; - String projectRoot; + + Folder projectRoot; + String projectPath; var packageName = 'my_package'; PackageMetaProvider packageMetaProvider; FakePackageConfigProvider packageConfigProvider; - PackageGraph packageGraph; - - /// Dartdoc has a few indicator files it uses to verify that a directory - /// represents a Dart SDK. These include "bin/dart" and "bin/pub". - void writeSdkBinFiles(Folder root) { - var sdkBinFolder = root.getChildAssumingFolder('bin'); - sdkBinFolder.getChildAssumingFile('dart').writeAsStringSync(''); - sdkBinFolder.getChildAssumingFile('pub').writeAsStringSync(''); - } - - void writeSdk() { - mockSdk = MockSdk(resourceProvider: resourceProvider); - // The [MockSdk] only works in non-canonicalized paths, which include - // "C:\sdk", on Windows. Howerver, dartdoc works almost exclusively with - // canonical paths ("c:\sdk"). Copy all MockSdk files to the canonicalized - // path. - for (var l in mockSdk.sdkLibraries) { - var p = l.path; - resourceProvider - .getFile(resourceProvider.pathContext.canonicalize(p)) - .writeAsStringSync(resourceProvider.getFile(p).readAsStringSync()); - } - sdkFolder = resourceProvider.getFolder(resourceProvider.pathContext - .canonicalize(resourceProvider.convertPath(sdkRoot))) - ..create(); - sdkFolder.getChildAssumingFile('version').writeAsStringSync('2.9.0'); - - writeSdkBinFiles(sdkFolder); - writeSdkBinFiles( - resourceProvider.getFolder(resourceProvider.convertPath(sdkRoot))); - } - - void writePackage() { - var pathContext = resourceProvider.pathContext; - var projectsFolder = resourceProvider.getFolder( - pathContext.canonicalize(resourceProvider.convertPath('/projects'))); - var projectFolder = projectsFolder.getChildAssumingFolder(packageName) - ..create; - projectRoot = projectFolder.path; - projectFolder.getChildAssumingFile('pubspec.yaml').writeAsStringSync(''' -name: $packageName -version: 0.0.1 -'''); - projectFolder - .getChildAssumingFolder('.dart_tool') - .getChildAssumingFile('package_config.json') - .writeAsStringSync(''); - projectFolder.getChildAssumingFolder('lib').create(); - packageConfigProvider.addPackageToConfigFor( - projectRoot, packageName, Uri.file('$projectRoot/')); - } setUp(() async { resourceProvider = MemoryResourceProvider(); - writeSdk(); + mockSdk = MockSdk(resourceProvider: resourceProvider); + sdkFolder = utils.writeMockSdkFiles(mockSdk); packageMetaProvider = PackageMetaProvider( PubPackageMeta.fromElement, @@ -89,59 +41,228 @@ version: 0.0.1 'dartdoc', [createDartdocOptions], packageMetaProvider); optionSet.parseArguments([]); packageConfigProvider = FakePackageConfigProvider(); + // To build the package graph, we always ask package_config for a + // [PackageConfig] for the SDK directory. Put a dummy entry in. + packageConfigProvider.addPackageToConfigFor( + sdkFolder.path, 'analyzer', Uri.file('/sdk/pkg/analyzer/')); }); - test('package with no deps has 2 local packages, including SDK', () async { - writePackage(); - resourceProvider - .getFile( - resourceProvider.pathContext.join(projectRoot, 'lib', 'a.dart')) - .writeAsStringSync(''' + tearDown(() { + projectRoot = null; + projectPath = null; + clearPackageMetaCache(); + }); + + group('typical package', () { + setUp(() { + projectRoot = utils.writePackage( + packageName, resourceProvider, packageConfigProvider); + projectPath = projectRoot.path; + projectRoot + .getChildAssumingFolder('lib') + .getChildAssumingFile('a.dart') + .writeAsStringSync(''' /// Documentation comment. int x; '''); - packageGraph = await utils.bootBasicPackage( - projectRoot, [], packageMetaProvider, packageConfigProvider, - additionalArguments: [ - '--auto-include-dependencies', - '--no-link-to-remote' - ]); - - var localPackages = packageGraph.localPackages; - expect(localPackages, hasLength(2)); - expect(localPackages[0].name, equals(packageName)); - expect(localPackages[1].name, equals('Dart')); - }); + }); - test('package with no deps has 1 local package, excluding SDK', () async { - writePackage(); - resourceProvider - .getFile( - resourceProvider.pathContext.join(projectRoot, 'lib', 'a.dart')) - .writeAsStringSync(''' + test('with no deps has 2 local packages, including SDK', () async { + var packageGraph = await utils.bootBasicPackage( + projectPath, packageMetaProvider, packageConfigProvider, + additionalArguments: [ + '--auto-include-dependencies', + '--no-link-to-remote' + ]); + + var localPackages = packageGraph.localPackages; + expect(localPackages, hasLength(2)); + expect(localPackages[0].name, equals(packageName)); + expect(localPackages[1].name, equals('Dart')); + }); + + test('with no deps has 1 local package, excluding SDK', () async { + var packageGraph = await utils.bootBasicPackage( + projectPath, packageMetaProvider, packageConfigProvider, + additionalArguments: ['--no-link-to-remote']); + + var localPackages = packageGraph.localPackages; + expect(localPackages, hasLength(1)); + expect(localPackages[0].name, equals(packageName)); + }); + + test('has proper name and kind', () async { + var packageGraph = await utils.bootBasicPackage( + projectPath, packageMetaProvider, packageConfigProvider); + + var package = packageGraph.defaultPackage; + expect(package.name, equals('my_package')); + expect(package.kind, equals('package')); + }); + + test('has public libraries', () async { + var packageGraph = await utils.bootBasicPackage( + projectPath, packageMetaProvider, packageConfigProvider); + + expect(packageGraph.localPublicLibraries, hasLength(1)); + }); + + test('has private libraries', () async { + var packageGraph = await utils.bootBasicPackage( + projectPath, packageMetaProvider, packageConfigProvider); + var interceptorsLib = packageGraph.libraries + .firstWhere((lib) => lib.name == 'dart:_interceptors'); + + expect(interceptorsLib.isPublic, isFalse); + }); + + test('has a homepage', () async { + var packageGraph = await utils.bootBasicPackage( + projectPath, packageMetaProvider, packageConfigProvider); + + expect(packageGraph.defaultPackage.hasHomepage, isTrue); + expect(packageGraph.defaultPackage.homepage, + equals('https://github.com/dart-lang')); + }); + + test('has a public library', () async { + var packageGraph = await utils.bootBasicPackage( + projectPath, packageMetaProvider, packageConfigProvider); + var library = packageGraph.libraries.firstWhere((lib) => lib.name == 'a'); + expect(library.isDocumented, true); + }); + + test('has anonymous libraries', () async { + projectRoot + .getChildAssumingFolder('lib') + .getChildAssumingFile('b.dart') + .writeAsStringSync(''' /// Documentation comment. int x; '''); - packageGraph = await utils.bootBasicPackage( - projectRoot, [], packageMetaProvider, packageConfigProvider, - additionalArguments: ['--no-link-to-remote']); + var packageGraph = await utils.bootBasicPackage( + projectPath, packageMetaProvider, packageConfigProvider); + expect( + packageGraph.libraries.where((lib) => lib.name == 'b'), hasLength(1)); + }); + + test('has documentation via Markdown README', () async { + projectRoot + .getChildAssumingFile('README.md') + .writeAsStringSync('Readme text.'); + var packageGraph = await utils.bootBasicPackage( + projectPath, packageMetaProvider, packageConfigProvider); + expect(packageGraph.defaultPackage.hasDocumentationFile, true); + expect(packageGraph.defaultPackage.hasDocumentation, true); + }); + + test('has documentation via text README', () async { + projectRoot + .getChildAssumingFile('README') + .writeAsStringSync('Readme text.'); + var packageGraph = await utils.bootBasicPackage( + projectPath, packageMetaProvider, packageConfigProvider); + expect(packageGraph.defaultPackage.hasDocumentationFile, true); + expect(packageGraph.defaultPackage.hasDocumentation, true); + }); + + test('has documentation content', () async { + projectRoot + .getChildAssumingFile('README.md') + .writeAsStringSync('Readme text.'); + var packageGraph = await utils.bootBasicPackage( + projectPath, packageMetaProvider, packageConfigProvider); + expect(packageGraph.defaultPackage.documentation, equals('Readme text.')); + }); + + test('has documentation content rendered as HTML', () async { + projectRoot + .getChildAssumingFile('README.md') + .writeAsStringSync('Readme text.'); + var packageGraph = await utils.bootBasicPackage( + projectPath, packageMetaProvider, packageConfigProvider); + expect(packageGraph.defaultPackage.documentationAsHtml, + equals('

Readme text.

')); + }); + }); + + group('SDK package', () { + test('has proper name and kind', () async { + var packageGraph = await utils.bootBasicPackage( + sdkFolder.path, packageMetaProvider, packageConfigProvider, + additionalArguments: [ + '--input', + packageMetaProvider.defaultSdkDir.path, + ]); - var localPackages = packageGraph.localPackages; - expect(localPackages, hasLength(1)); - expect(localPackages[0].name, equals(packageName)); + var sdkPackage = packageGraph.defaultPackage; + expect(sdkPackage.name, equals('Dart')); + expect(sdkPackage.kind, equals('SDK')); + }); + + test('has a homepage', () async { + var packageGraph = await utils.bootBasicPackage( + sdkFolder.path, packageMetaProvider, packageConfigProvider, + additionalArguments: [ + '--input', + packageMetaProvider.defaultSdkDir.path, + ]); + + var sdkPackage = packageGraph.defaultPackage; + expect(sdkPackage.hasHomepage, isTrue); + expect(sdkPackage.homepage, equals('https://github.com/dart-lang/sdk')); + }); + + test('has a version', () async { + var packageGraph = await utils.bootBasicPackage( + sdkFolder.path, packageMetaProvider, packageConfigProvider, + additionalArguments: [ + '--input', + packageMetaProvider.defaultSdkDir.path, + ]); + + var sdkPackage = packageGraph.defaultPackage; + expect(sdkPackage.version, isNotNull); + }); + + test('has a description', () async { + var packageGraph = await utils.bootBasicPackage( + sdkFolder.path, packageMetaProvider, packageConfigProvider, + additionalArguments: [ + '--input', + packageMetaProvider.defaultSdkDir.path, + ]); + + var sdkPackage = packageGraph.defaultPackage; + expect(sdkPackage.documentation, startsWith('Welcome')); + }); + + test('Pragma is hidden in docs', () async { + var packageGraph = await utils.bootBasicPackage( + sdkFolder.path, packageMetaProvider, packageConfigProvider, + additionalArguments: [ + '--input', + packageMetaProvider.defaultSdkDir.path, + ]); + + var pragmaModelElement = packageGraph.specialClasses[SpecialClass.pragma]; + expect(pragmaModelElement.name, equals('pragma')); + }); }); test('package with no doc comments has no docs', () async { - writePackage(); - resourceProvider - .getFile( - resourceProvider.pathContext.join(projectRoot, 'lib', 'a.dart')) + projectRoot = utils.writePackage( + packageName, resourceProvider, packageConfigProvider); + projectPath = projectRoot.path; + projectRoot + .getChildAssumingFolder('lib') + .getChildAssumingFile('a.dart') .writeAsStringSync(''' // No documentation comment. int x; '''); - packageGraph = await utils.bootBasicPackage( - projectRoot, [], packageMetaProvider, packageConfigProvider); + var packageGraph = await utils.bootBasicPackage( + projectPath, packageMetaProvider, packageConfigProvider); expect(packageGraph.defaultPackage.hasDocumentation, isFalse); expect(packageGraph.defaultPackage.hasDocumentationFile, isFalse); @@ -149,33 +270,40 @@ int x; expect(packageGraph.defaultPackage.documentation, isNull); }); - test('package with no README has no homepage', () async { - writePackage(); - resourceProvider - .getFile( - resourceProvider.pathContext.join(projectRoot, 'lib', 'a.dart')) + test('package with no homepage in the pubspec has no homepage', () async { + projectRoot = utils.writePackage( + packageName, resourceProvider, packageConfigProvider, + pubspecContent: ''' +name: $packageName +version: 0.0.1 +'''); + projectPath = projectRoot.path; + projectRoot + .getChildAssumingFolder('lib') + .getChildAssumingFile('a.dart') .writeAsStringSync(''' /// Documentation comment. int x; '''); - packageGraph = await utils.bootBasicPackage( - projectRoot, [], packageMetaProvider, packageConfigProvider); + var packageGraph = await utils.bootBasicPackage( + projectPath, packageMetaProvider, packageConfigProvider); expect(packageGraph.defaultPackage.hasHomepage, isFalse); - expect(packageGraph.localPublicLibraries, hasLength(1)); }); test('package with no doc comments has no categories', () async { - writePackage(); - resourceProvider - .getFile( - resourceProvider.pathContext.join(projectRoot, 'lib', 'a.dart')) + projectRoot = utils.writePackage( + packageName, resourceProvider, packageConfigProvider); + projectPath = projectRoot.path; + projectRoot + .getChildAssumingFolder('lib') + .getChildAssumingFile('a.dart') .writeAsStringSync(''' // No documentation comment. int x; '''); - packageGraph = await utils.bootBasicPackage( - projectRoot, [], packageMetaProvider, packageConfigProvider); + var packageGraph = await utils.bootBasicPackage( + projectPath, packageMetaProvider, packageConfigProvider); expect(packageGraph.localPackages.first.hasCategories, isFalse); expect(packageGraph.localPackages.first.categories, isEmpty); diff --git a/test/src/utils.dart b/test/src/utils.dart index 6cc3109fa1..f09319d2e2 100644 --- a/test/src/utils.dart +++ b/test/src/utils.dart @@ -7,6 +7,8 @@ library test_utils; import 'dart:async'; import 'package:analyzer/file_system/file_system.dart'; +import 'package:analyzer/file_system/memory_file_system.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:dartdoc/dartdoc.dart'; import 'package:dartdoc/src/package_config_provider.dart'; import 'package:dartdoc/src/package_meta.dart'; @@ -38,10 +40,10 @@ Future contextFromArgv( Future bootBasicPackage( String dirPath, - List excludeLibraries, PackageMetaProvider packageMetaProvider, PackageConfigProvider packageConfigProvider, - {List additionalArguments = const []}) async { + {List excludeLibraries = const [], + List additionalArguments = const []}) async { var resourceProvider = packageMetaProvider.resourceProvider; var dir = resourceProvider.getFolder(resourceProvider.pathContext .absolute(resourceProvider.pathContext.normalize(dirPath))); @@ -60,3 +62,76 @@ Future bootBasicPackage( packageConfigProvider) .buildPackageGraph(); } + +/// Writes [mockSdk] to disk at both its original path, and its canonicalized +/// path (they may be different on Windows). +/// +/// Included is a "version" file and an "api_readme.md" file. +Folder writeMockSdkFiles(MockSdk mockSdk) { + var resourceProvider = mockSdk.resourceProvider; + var pathContext = resourceProvider.pathContext; + + // The [MockSdk] only works in non-canonicalized paths, which include + // "C:\sdk", on Windows. However, dartdoc works almost exclusively with + // canonical paths ("c:\sdk"). Copy all MockSdk files to the canonicalized + // path. + for (var l in mockSdk.sdkLibraries) { + var p = l.path; + resourceProvider + .getFile(pathContext.canonicalize(p)) + .writeAsStringSync(resourceProvider.getFile(p).readAsStringSync()); + } + var sdkFolder = resourceProvider.getFolder( + pathContext.canonicalize(resourceProvider.convertPath(sdkRoot))) + ..create(); + sdkFolder.getChildAssumingFile('version').writeAsStringSync('2.9.0'); + sdkFolder.getChildAssumingFile('api_readme.md').writeAsStringSync( + 'Welcome to the [Dart](https://dart.dev/) API reference documentation'); + + _writeMockSdkBinFiles(sdkFolder); + _writeMockSdkBinFiles( + resourceProvider.getFolder(resourceProvider.convertPath(sdkRoot))); + + return sdkFolder; +} + +/// Dartdoc has a few indicator files it uses to verify that a directory +/// represents a Dart SDK. These include "bin/dart" and "bin/pub". +void _writeMockSdkBinFiles(Folder root) { + var sdkBinFolder = root.getChildAssumingFolder('bin'); + sdkBinFolder.getChildAssumingFile('dart').writeAsStringSync(''); + sdkBinFolder.getChildAssumingFile('pub').writeAsStringSync(''); +} + +/// Writes a package named [packageName], with [resourceProvider], to the +/// "/projects" directory. +/// +/// The package is added to [packageConfigProvider]. A standard pubspec is +/// written if one is not provided via [pubspecContent]. +Folder writePackage(String packageName, MemoryResourceProvider resourceProvider, + FakePackageConfigProvider packageConfigProvider, + {String pubspecContent}) { + pubspecContent ??= ''' +name: $packageName +version: 0.0.1 +homepage: https://github.com/dart-lang +'''; + var pathContext = resourceProvider.pathContext; + var projectsFolder = resourceProvider.getFolder( + pathContext.canonicalize(resourceProvider.convertPath('/projects'))); + var projectFolder = projectsFolder.getChildAssumingFolder(packageName) + ..create; + var projectRoot = projectFolder.path; + projectFolder + .getChildAssumingFile('pubspec.yaml') + .writeAsStringSync(pubspecContent); + projectFolder + .getChildAssumingFolder('.dart_tool') + .getChildAssumingFile('package_config.json') + .writeAsStringSync(''); + projectFolder.getChildAssumingFolder('lib').create(); + packageConfigProvider.addPackageToConfigFor( + projectRoot, packageName, Uri.file('$projectRoot/')); + + return projectFolder; +} From e11eb83be22cd175b0c9f86eb9d34daed7c226d4 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Fri, 11 Sep 2020 16:21:33 -0700 Subject: [PATCH 2/2] void; --- lib/src/package_meta.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/package_meta.dart b/lib/src/package_meta.dart index 53029f8c34..406555c89a 100644 --- a/lib/src/package_meta.dart +++ b/lib/src/package_meta.dart @@ -490,6 +490,6 @@ class _SdkMeta extends PubPackageMeta { } @visibleForTesting -clearPackageMetaCache() { +void clearPackageMetaCache() { _packageMetaCache.clear(); }