diff --git a/.github/workflows/mason.yaml b/.github/workflows/mason.yaml index d8594a9d4..2d76c8a75 100644 --- a/.github/workflows/mason.yaml +++ b/.github/workflows/mason.yaml @@ -90,4 +90,4 @@ jobs: dart pub global activate pana - name: Verify Pub Score - run: ../../tool/verify_pub_score.sh + run: ../../tool/verify_pub_score.sh 150 diff --git a/packages/mason/lib/src/brick_yaml.dart b/packages/mason/lib/src/brick_yaml.dart index 2d505b774..9833e7740 100644 --- a/packages/mason/lib/src/brick_yaml.dart +++ b/packages/mason/lib/src/brick_yaml.dart @@ -100,21 +100,21 @@ class BrickYaml { /// The type of brick variable. enum BrickVariableType { - /// An array (e.g. ["one", "two", "three"]). + /// An array (e.g. `["one", "two", "three"]`). /// Values must be present in the list of /// available options. array, - /// A number (e.g. 42) + /// A number (e.g. `42`) number, - /// A string (e.g. "Dash") + /// A string (e.g. `"Dash"`) string, - /// A boolean (e.g. true/false) + /// A boolean (e.g. `true`/`false`) boolean, - /// An enumeration (e.g. ["red", "green", "blue"]) + /// An enumeration (e.g. `["red", "green", "blue"]`) @JsonValue('enum') enumeration, diff --git a/packages/mason/lib/src/mason_lock_json.dart b/packages/mason/lib/src/mason_lock_json.dart index 9e1629e0c..ac2e683b9 100644 --- a/packages/mason/lib/src/mason_lock_json.dart +++ b/packages/mason/lib/src/mason_lock_json.dart @@ -8,7 +8,7 @@ part 'mason_lock_json.g.dart'; /// {@endtemplate} @JsonSerializable() class MasonLockJson { - /// {@macro mason_lock} + /// {@macro mason_lock_json} const MasonLockJson({Map? bricks}) : bricks = bricks ?? const {}; diff --git a/packages/mason/test/src/bundler_test.dart b/packages/mason/test/src/bundler_test.dart index 8cec8ccc2..2ccae718f 100644 --- a/packages/mason/test/src/bundler_test.dart +++ b/packages/mason/test/src/bundler_test.dart @@ -67,7 +67,7 @@ void main() { expect(bundle.name, equals('hello')); expect(bundle.description, equals('An example brick.')); - expect(bundle.version, equals('0.1.0+1')); + expect(bundle.version, equals('0.1.0+2')); expect( bundle.repository, equals('https://github.com/felangel/mason/tree/master/bricks/hello'), @@ -238,7 +238,7 @@ void main() { equals( 'name: hello\n' 'description: An example brick.\n' - 'version: 0.1.0+1\n' + 'version: 0.1.0+2\n' 'environment:\n' ' mason: ^$packageVersion\n' 'repository: "https://github.com/felangel/mason/tree/master/bricks/hello"\n' @@ -259,27 +259,13 @@ void main() { expect(readme.existsSync(), isTrue); expect( readme.readAsNormalizedStringSync(), - equals( - '# hello\n' - '\n' - 'A new brick created with the Mason CLI.\n' - '\n' - '_Generated by [mason][1] 🧱_\n' - '\n' - '## Getting Started 🚀\n' - '\n' - 'This is a starting point for a new brick.\n' - '''A few resources to get you started if this is your first brick template:\n''' - '\n' - '- [Official Mason Documentation][2]\n' - '- [Code generation with Mason Blog][3]\n' - '- [Very Good Livestream: Felix Angelov Demos Mason][4]\n' - '\n' - '[1]: https://github.com/felangel/mason\n' - '[2]: https://github.com/felangel/mason/tree/master/packages/mason_cli#readme\n' - '[3]: https://verygood.ventures/blog/code-generation-with-mason\n' - '[4]: https://youtu.be/G4PTjA6tpTU\n', - ), + equals('# hello\n' + '\n' + 'A hello world brick created with the Mason CLI.\n' + '\n' + '_Generated by [mason][1] 🧱_\n' + '\n' + '[1]: https://github.com/felangel/mason\n'), ); final changelog = File(path.join(tempDir.path, 'CHANGELOG.md')); @@ -287,9 +273,13 @@ void main() { expect( changelog.readAsNormalizedStringSync(), equals( + '# 0.1.0+2\n' + '\n' + '- chore: upgrade to `mason ^0.1.0`\n' + '\n' '# 0.1.0+1\n' '\n' - '- TODO: Describe initial release.\n', + '- chore: initial release\n', ), ); @@ -297,7 +287,29 @@ void main() { expect(license.existsSync(), isTrue); expect( license.readAsNormalizedStringSync(), - equals('TODO: Add your license here.\n'), + equals( + 'The MIT License (MIT)\n' + 'Copyright (c) 2024 Felix Angelov\n' + '\n' + 'Permission is hereby granted, free of charge, to any person\n' + 'obtaining a copy of this software and associated documentation\n' + '''files (the "Software"), to deal in the Software without restriction,\n''' + '''including without limitation the rights to use, copy, modify, merge,\n''' + '''publish, distribute, sublicense, and/or sell copies of the Software,\n''' + '''and to permit persons to whom the Software is furnished to do so,\n''' + 'subject to the following conditions:\n' + '\n' + '''The above copyright notice and this permission notice shall be included\n''' + 'in all copies or substantial portions of the Software.\n' + '\n' + 'THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\n' + '''EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n''' + '''MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n''' + '''IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n''' + '''DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n''' + '''OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n''' + 'USE OR OTHER DEALINGS IN THE SOFTWARE.', + ), ); }); diff --git a/packages/mason_cli/test/commands/make_test.dart b/packages/mason_cli/test/commands/make_test.dart index cd8e5dacb..612998c1c 100644 --- a/packages/mason_cli/test/commands/make_test.dart +++ b/packages/mason_cli/test/commands/make_test.dart @@ -452,7 +452,7 @@ bricks: test('exits with code 70 when exception occurs while generating', () async { const url = - 'https://cdn.dribbble.com/users/163325/screenshots/6214023/app_icon.jpg'; + 'https://storage.googleapis.com/cms-storage-bucket/c823e53b3a1a7b0d36a9.png'; when( () => logger.prompt(any(), defaultValue: any(named: 'defaultValue')), ).thenReturn(url); @@ -485,7 +485,7 @@ bricks: 'make', 'app_icon', '--url', - 'https://cdn.dribbble.com/users/163325/screenshots/6214023/app_icon.jpg', + 'https://storage.googleapis.com/cms-storage-bucket/c823e53b3a1a7b0d36a9.png', ]); expect(result, equals(ExitCode.success.code)); @@ -500,7 +500,7 @@ bricks: test('generates app_icon (from prompt)', () async { const url = - 'https://cdn.dribbble.com/users/163325/screenshots/6214023/app_icon.jpg'; + 'https://storage.googleapis.com/cms-storage-bucket/c823e53b3a1a7b0d36a9.png'; when(() => logger.prompt(any())).thenReturn(url); final testDir = Directory( path.join(Directory.current.path, 'app_icon'), diff --git a/packages/mason_cli/test/fixtures/make/app_icon/app_icon.jpg b/packages/mason_cli/test/fixtures/make/app_icon/app_icon.jpg deleted file mode 100644 index 4bcae1652..000000000 Binary files a/packages/mason_cli/test/fixtures/make/app_icon/app_icon.jpg and /dev/null differ diff --git a/packages/mason_cli/test/fixtures/make/app_icon/c823e53b3a1a7b0d36a9.png b/packages/mason_cli/test/fixtures/make/app_icon/c823e53b3a1a7b0d36a9.png new file mode 100644 index 000000000..cfc0ee42f Binary files /dev/null and b/packages/mason_cli/test/fixtures/make/app_icon/c823e53b3a1a7b0d36a9.png differ diff --git a/packages/mason_logger/lib/src/link.dart b/packages/mason_logger/lib/src/link.dart index 47bdb64fb..31328a7e3 100644 --- a/packages/mason_logger/lib/src/link.dart +++ b/packages/mason_logger/lib/src/link.dart @@ -1,3 +1,5 @@ +import 'package:io/ansi.dart'; + /// Wraps [uri] with an escape sequence so it's recognized as a hyperlink. /// An optional message can be used in place of the [uri]. /// If no [message] is provided, the text content will be the full [uri]. @@ -10,6 +12,10 @@ /// print(richLink); // Equivalent to `[The Dart Website](https://dart.dev)` in markdown /// ``` String link({required Uri uri, String? message}) { + if (!ansiOutputEnabled) { + return message != null ? '[$message]($uri)' : uri.toString(); + } + const leading = '\x1B]8;;'; const trailing = '\x1B\\'; diff --git a/packages/mason_logger/test/src/link_test.dart b/packages/mason_logger/test/src/link_test.dart index 38a11adaf..a8fb0ae28 100644 --- a/packages/mason_logger/test/src/link_test.dart +++ b/packages/mason_logger/test/src/link_test.dart @@ -1,8 +1,31 @@ +import 'dart:io'; + import 'package:mason_logger/mason_logger.dart'; +import 'package:mocktail/mocktail.dart'; import 'package:test/test.dart'; +class _MockStdout extends Mock implements Stdout {} + void main() { group('link', () { + late Stdout stdout; + late Stdout stderr; + + setUp(() { + stdout = _MockStdout(); + stderr = _MockStdout(); + when(() => stdout.supportsAnsiEscapes).thenReturn(true); + when(() => stderr.supportsAnsiEscapes).thenReturn(true); + }); + + R runWithOverrides(R Function() body) { + return IOOverrides.runZoned( + body, + stdout: () => stdout, + stderr: () => stderr, + ); + } + final uri = Uri.parse('https://github.com/felangel/mason/issues/'); const lead = '\x1B]8;;'; const trail = '\x1B\\'; @@ -11,7 +34,7 @@ void main() { 'builds output with correct encodings: ' r'\x1B]8;;' ' and ' r'\x1B\\', () { const message = 'message'; - final output = link(message: message, uri: uri); + final output = runWithOverrides(() => link(message: message, uri: uri)); final matcher = stringContainsInOrder( [lead, '$uri', trail, message, lead, trail], ); @@ -21,12 +44,28 @@ void main() { ); test('builds String with Uri when message is null: ', () { - final output = link(uri: uri); + final output = runWithOverrides(() => link(uri: uri)); final matcher = stringContainsInOrder( [lead, '$uri', trail, '$uri', lead, trail], ); expect(output, matcher); }); + + test('builds output when ansi escapes are not supported', () { + when(() => stdout.supportsAnsiEscapes).thenReturn(false); + when(() => stderr.supportsAnsiEscapes).thenReturn(false); + final output = runWithOverrides(() => link(uri: uri)); + final matcher = stringContainsInOrder(['$uri']); + expect(output, matcher); + }); + + test('builds output with message when ansi escapes are not supported', () { + when(() => stdout.supportsAnsiEscapes).thenReturn(false); + when(() => stderr.supportsAnsiEscapes).thenReturn(false); + const message = 'message'; + final output = runWithOverrides(() => link(uri: uri, message: message)); + expect(output, equals('[$message]($uri)')); + }); }); }