{"id":69,"date":"2024-12-20T22:50:11","date_gmt":"2024-12-20T09:50:11","guid":{"rendered":"https:\/\/systemreset.io\/journal\/?p=69"},"modified":"2024-12-21T08:52:28","modified_gmt":"2024-12-20T19:52:28","slug":"custom-asset-bundle-for-flutter-tests","status":"publish","type":"post","link":"https:\/\/systemreset.io\/journal\/custom-asset-bundle-for-flutter-tests\/","title":{"rendered":"Custom asset bundle for flutter golden tests"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Tests in a flutter project or game often require assets that you don&#8217;t want in the root asset bundle (rootBundle) -w specially if you are writing golden tests. Wouldn&#8217;t it be great if you could create a custom asset bundle for your tests?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Today I ran in to this exact problem. I&#8217;ve written an image utility class that resizes images, and supports other transforms at the same time (like scale, rotation and crop). I need some image assets to test this class that I don&#8217;t want as part of the rootBundle. Flutter doesn&#8217;t currently support &#8220;dev&#8221; assets &#8211; <a href=\"https:\/\/github.com\/flutter\/flutter\/issues\/5813\">see open issue #5813<\/a> &#8211; but luckily it is possible to create your own custom asset bundle.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I based my asset bundle class <a href=\"https:\/\/github.com\/flutter\/flutter\/issues\/12999#issuecomment-450677379\" target=\"_blank\" rel=\"noreferrer noopener\">on this one<\/a> that a Google Flutter engineer posted in a thread on another issue. I modified it to work better for my purpose.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Asset bundle class<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This is the code for the custom asset bundle:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" data-code=\"import 'dart:convert';\nimport 'dart:io';\n\nimport 'package:flutter\/services.dart';\nimport 'package:glob\/glob.dart';\nimport 'package:glob\/list_local_fs.dart';\n\n\/\/\/ A custom [AssetBundle] that reads files from a directory.\n\/\/\/\n\/\/\/ This is meant to be used in place of [rootBundle] for testing\nclass DiskAssetBundle extends CachingAssetBundle {\n  static const _assetManifestDotJson = 'AssetManifest.json';\n\n  \/\/\/ Creates a [DiskAssetBundle] by loading files from [path].\n  static Future&lt;AssetBundle&gt; loadFromPath(\n    String path, {\n    String? from,\n  }) async {\n    \/\/ Prepare the file search pattern\n    path = _formatPath(path);\n    String pattern = path;\n    if (!pattern.endsWith('\/')) {\n      pattern += '\/';\n    }\n    pattern += '**';\n\n    \/\/ Load the assets\n    final cache = &lt;String, ByteData&gt;{};\n    await for (final entity in Glob(pattern).list(root: from)) {\n      if (entity is File) {\n        final bytes = await (entity as File).readAsBytes();\n\n        \/\/ Keep only the asset name relative to the folder\n        String name = _formatPath(entity.path);\n        name = name.substring(name.indexOf(path) + path.length);\n        cache[name] = ByteData.view(bytes.buffer);\n      }\n    }\n\n    \/\/ Create the asset manifest\n    final manifest = &lt;String, List&lt;String&gt;&gt;{};\n    cache.forEach((key, _) {\n      manifest[key] = [key];\n    });\n    cache[_assetManifestDotJson] = ByteData.view(\n      Uint8List.fromList(jsonEncode(manifest).codeUnits).buffer,\n    );\n\n    return DiskAssetBundle._(cache);\n  }\n\n  \/\/\/ Format a file path to only forward slashes\n  static String _formatPath(String path) {\n    return path.replaceAll(r'\\', '\/');\n  }\n\n  \/\/\/ The cache of assets\n  final Map&lt;String, ByteData&gt; _cache;\n\n  \/\/\/ Private constructor\n  DiskAssetBundle._(this._cache);\n\n  \/\/\/ Load an asset from the cache\n  @override\n  Future&lt;ByteData&gt; load(String key) async {\n    return _cache[key]!;\n  }\n}\" style=\"color:#575279;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki rose-pine-dawn\" style=\"background-color: #faf4ed\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #286983\">import<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #EA9D34\">&#39;dart:convert&#39;<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #286983\">import<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #EA9D34\">&#39;dart:io&#39;<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #286983\">import<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #EA9D34\">&#39;package:flutter\/services.dart&#39;<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #286983\">import<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #EA9D34\">&#39;package:glob\/glob.dart&#39;<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #286983\">import<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #EA9D34\">&#39;package:glob\/list_local_fs.dart&#39;<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #9893A5; font-style: italic\">\/\/\/ A custom <\/span><span style=\"color: #D7827E; font-style: italic\">[AssetBundle]<\/span><span style=\"color: #9893A5; font-style: italic\"> that reads files from a directory.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9893A5; font-style: italic\">\/\/\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9893A5; font-style: italic\">\/\/\/ This is meant to be used in place of <\/span><span style=\"color: #D7827E; font-style: italic\">[rootBundle]<\/span><span style=\"color: #9893A5; font-style: italic\"> for testing<\/span><\/span>\n<span class=\"line\"><span style=\"color: #286983\">class<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #56949F\">DiskAssetBundle<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #286983\">extends<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #56949F\">CachingAssetBundle<\/span><span style=\"color: #575279\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  <\/span><span style=\"color: #286983\">static<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #286983\">const<\/span><span style=\"color: #575279\"> _assetManifestDotJson <\/span><span style=\"color: #286983\">=<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #EA9D34\">&#39;AssetManifest.json&#39;<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  <\/span><span style=\"color: #9893A5; font-style: italic\">\/\/\/ Creates a <\/span><span style=\"color: #D7827E; font-style: italic\">[DiskAssetBundle]<\/span><span style=\"color: #9893A5; font-style: italic\"> by loading files from <\/span><span style=\"color: #D7827E; font-style: italic\">[path]<\/span><span style=\"color: #9893A5; font-style: italic\">.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  <\/span><span style=\"color: #286983\">static<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #56949F\">Future<\/span><span style=\"color: #575279\">&lt;<\/span><span style=\"color: #56949F\">AssetBundle<\/span><span style=\"color: #575279\">&gt; <\/span><span style=\"color: #D7827E\">loadFromPath<\/span><span style=\"color: #575279\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    <\/span><span style=\"color: #56949F\">String<\/span><span style=\"color: #575279\"> path<\/span><span style=\"color: #797593\">,<\/span><span style=\"color: #575279\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    <\/span><span style=\"color: #56949F\">String<\/span><span style=\"color: #286983\">?<\/span><span style=\"color: #575279\"> from<\/span><span style=\"color: #797593\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  }) <\/span><span style=\"color: #286983\">async<\/span><span style=\"color: #575279\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    <\/span><span style=\"color: #9893A5; font-style: italic\">\/\/ Prepare the file search pattern<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    path <\/span><span style=\"color: #286983\">=<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #D7827E\">_formatPath<\/span><span style=\"color: #575279\">(path)<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    <\/span><span style=\"color: #56949F\">String<\/span><span style=\"color: #575279\"> pattern <\/span><span style=\"color: #286983\">=<\/span><span style=\"color: #575279\"> path<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    <\/span><span style=\"color: #286983\">if<\/span><span style=\"color: #575279\"> (<\/span><span style=\"color: #286983\">!<\/span><span style=\"color: #575279\">pattern<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #D7827E\">endsWith<\/span><span style=\"color: #575279\">(<\/span><span style=\"color: #EA9D34\">&#39;\/&#39;<\/span><span style=\"color: #575279\">)) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">      pattern <\/span><span style=\"color: #286983\">+=<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #EA9D34\">&#39;\/&#39;<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    pattern <\/span><span style=\"color: #286983\">+=<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #EA9D34\">&#39;**&#39;<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    <\/span><span style=\"color: #9893A5; font-style: italic\">\/\/ Load the assets<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    <\/span><span style=\"color: #286983\">final<\/span><span style=\"color: #575279\"> cache <\/span><span style=\"color: #286983\">=<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #286983\">&lt;<\/span><span style=\"color: #56949F\">String<\/span><span style=\"color: #797593\">,<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #56949F\">ByteData<\/span><span style=\"color: #286983\">&gt;<\/span><span style=\"color: #575279\">{}<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    <\/span><span style=\"color: #286983\">await<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #286983\">for<\/span><span style=\"color: #575279\"> (<\/span><span style=\"color: #286983\">final<\/span><span style=\"color: #575279\"> entity <\/span><span style=\"color: #286983\">in<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #56949F\">Glob<\/span><span style=\"color: #575279\">(pattern)<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #D7827E\">list<\/span><span style=\"color: #575279\">(root<\/span><span style=\"color: #286983\">:<\/span><span style=\"color: #575279\"> from)) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">      <\/span><span style=\"color: #286983\">if<\/span><span style=\"color: #575279\"> (entity <\/span><span style=\"color: #286983\">is<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #56949F\">File<\/span><span style=\"color: #575279\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">        <\/span><span style=\"color: #286983\">final<\/span><span style=\"color: #575279\"> bytes <\/span><span style=\"color: #286983\">=<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #286983\">await<\/span><span style=\"color: #575279\"> (entity <\/span><span style=\"color: #286983\">as<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #56949F\">File<\/span><span style=\"color: #575279\">)<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #D7827E\">readAsBytes<\/span><span style=\"color: #575279\">()<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #575279\">        <\/span><span style=\"color: #9893A5; font-style: italic\">\/\/ Keep only the asset name relative to the folder<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">        <\/span><span style=\"color: #56949F\">String<\/span><span style=\"color: #575279\"> name <\/span><span style=\"color: #286983\">=<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #D7827E\">_formatPath<\/span><span style=\"color: #575279\">(entity<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #575279\">path)<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">        name <\/span><span style=\"color: #286983\">=<\/span><span style=\"color: #575279\"> name<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #D7827E\">substring<\/span><span style=\"color: #575279\">(name<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #D7827E\">indexOf<\/span><span style=\"color: #575279\">(path) <\/span><span style=\"color: #286983\">+<\/span><span style=\"color: #575279\"> path<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #575279\">length)<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">        cache[name] <\/span><span style=\"color: #286983\">=<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #56949F\">ByteData<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #D7827E\">view<\/span><span style=\"color: #575279\">(bytes<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #575279\">buffer)<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">      }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    <\/span><span style=\"color: #9893A5; font-style: italic\">\/\/ Create the asset manifest<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    <\/span><span style=\"color: #286983\">final<\/span><span style=\"color: #575279\"> manifest <\/span><span style=\"color: #286983\">=<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #286983\">&lt;<\/span><span style=\"color: #56949F\">String<\/span><span style=\"color: #797593\">,<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #56949F\">List<\/span><span style=\"color: #575279\">&lt;<\/span><span style=\"color: #56949F\">String<\/span><span style=\"color: #575279\">&gt;<\/span><span style=\"color: #286983\">&gt;<\/span><span style=\"color: #575279\">{}<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    cache<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #D7827E\">forEach<\/span><span style=\"color: #575279\">((key<\/span><span style=\"color: #797593\">,<\/span><span style=\"color: #575279\"> _) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">      manifest[key] <\/span><span style=\"color: #286983\">=<\/span><span style=\"color: #575279\"> [key]<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    })<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    cache[_assetManifestDotJson] <\/span><span style=\"color: #286983\">=<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #56949F\">ByteData<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #D7827E\">view<\/span><span style=\"color: #575279\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">      <\/span><span style=\"color: #56949F\">Uint8List<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #D7827E\">fromList<\/span><span style=\"color: #575279\">(<\/span><span style=\"color: #D7827E\">jsonEncode<\/span><span style=\"color: #575279\">(manifest)<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #575279\">codeUnits)<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #575279\">buffer<\/span><span style=\"color: #797593\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    )<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    <\/span><span style=\"color: #286983\">return<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #56949F\">DiskAssetBundle<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #575279\">_(cache)<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  <\/span><span style=\"color: #9893A5; font-style: italic\">\/\/\/ Format a file path to only forward slashes<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  <\/span><span style=\"color: #286983\">static<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #56949F\">String<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #D7827E\">_formatPath<\/span><span style=\"color: #575279\">(<\/span><span style=\"color: #56949F\">String<\/span><span style=\"color: #575279\"> path) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    <\/span><span style=\"color: #286983\">return<\/span><span style=\"color: #575279\"> path<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #D7827E\">replaceAll<\/span><span style=\"color: #575279\">(<\/span><span style=\"color: #EA9D34\">r&#39;\\&#39;<\/span><span style=\"color: #797593\">,<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #EA9D34\">&#39;\/&#39;<\/span><span style=\"color: #575279\">)<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  <\/span><span style=\"color: #9893A5; font-style: italic\">\/\/\/ The cache of assets<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  <\/span><span style=\"color: #286983\">final<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #56949F\">Map<\/span><span style=\"color: #575279\">&lt;<\/span><span style=\"color: #56949F\">String<\/span><span style=\"color: #575279\">, <\/span><span style=\"color: #56949F\">ByteData<\/span><span style=\"color: #575279\">&gt; _cache<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  <\/span><span style=\"color: #9893A5; font-style: italic\">\/\/\/ Private constructor<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  <\/span><span style=\"color: #56949F\">DiskAssetBundle<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #575279\">_(<\/span><span style=\"color: #575279; font-style: italic\">this<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #575279\">_cache)<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  <\/span><span style=\"color: #9893A5; font-style: italic\">\/\/\/ Load an asset from the cache<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  <\/span><span style=\"color: #286983\">@override<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  <\/span><span style=\"color: #56949F\">Future<\/span><span style=\"color: #575279\">&lt;<\/span><span style=\"color: #56949F\">ByteData<\/span><span style=\"color: #575279\">&gt; <\/span><span style=\"color: #D7827E\">load<\/span><span style=\"color: #575279\">(<\/span><span style=\"color: #56949F\">String<\/span><span style=\"color: #575279\"> key) <\/span><span style=\"color: #286983\">async<\/span><span style=\"color: #575279\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    <\/span><span style=\"color: #286983\">return<\/span><span style=\"color: #575279\"> _cache[key]<\/span><span style=\"color: #286983\">!<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#faf4ed;color:#625c88;font-size:12px;line-height:1;position:relative\">Dart<\/span><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Writing a golden test<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This is how you use it for a golden test:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" data-code=\"import 'dart:io';\nimport 'dart:ui';\n\nimport 'package:flutter\/services.dart';\nimport 'package:flutter_test\/flutter_test.dart';\n\nimport 'disk_asset_bundle.dart';\n\nvoid main() async {\n  \/\/ Path to the goldens folder (i.e. project\/test\/_goldens)\n  String goldens =\n    '${Directory.current.path.replaceAll(r'\\', '\/')}\/test\/_goldens';\n\n  \/\/ This is required before an asset bundle is available\n  TestWidgetsFlutterBinding.ensureInitialized();\n\n  \/\/ Create the custom assets bundle from the resources folder\n  \/\/ (i.e. project\/test\/_resources)\n  AssetBundle assets = await DiskAssetBundle.loadFromPath('test\/_resources\/');\n\n  group('Example', () {\n\n    \/\/\/ This test will compare an image to a golden file\n    test('Does match golden', () async {\n      final image = await assets.load('image.png');\n\n      await expectLater(\n        image,\n        matchesGoldenFile('$goldens\/image-no-transform.png'),\n      );\n    });\n  });\n}\" style=\"color:#575279;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki rose-pine-dawn\" style=\"background-color: #faf4ed\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #286983\">import<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #EA9D34\">&#39;dart:io&#39;<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #286983\">import<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #EA9D34\">&#39;dart:ui&#39;<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #286983\">import<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #EA9D34\">&#39;package:flutter\/services.dart&#39;<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #286983\">import<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #EA9D34\">&#39;package:flutter_test\/flutter_test.dart&#39;<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #286983\">import<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #EA9D34\">&#39;disk_asset_bundle.dart&#39;<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #286983\">void<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #D7827E\">main<\/span><span style=\"color: #575279\">() <\/span><span style=\"color: #286983\">async<\/span><span style=\"color: #575279\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  <\/span><span style=\"color: #9893A5; font-style: italic\">\/\/ Path to the goldens folder (i.e. project\/test\/_goldens)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  <\/span><span style=\"color: #56949F\">String<\/span><span style=\"color: #575279\"> goldens <\/span><span style=\"color: #286983\">=<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    <\/span><span style=\"color: #EA9D34\">&#39;${<\/span><span style=\"color: #56949F\">Directory<\/span><span style=\"color: #EA9D34\">.<\/span><span style=\"color: #907AA9; font-style: italic\">current<\/span><span style=\"color: #EA9D34\">.<\/span><span style=\"color: #907AA9; font-style: italic\">path<\/span><span style=\"color: #EA9D34\">.<\/span><span style=\"color: #D7827E\">replaceAll<\/span><span style=\"color: #EA9D34\">(r&#39;\\&#39;, &#39;\/&#39;)}\/test\/_goldens&#39;<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  <\/span><span style=\"color: #9893A5; font-style: italic\">\/\/ This is required before an asset bundle is available<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  <\/span><span style=\"color: #56949F\">TestWidgetsFlutterBinding<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #D7827E\">ensureInitialized<\/span><span style=\"color: #575279\">()<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  <\/span><span style=\"color: #9893A5; font-style: italic\">\/\/ Create the custom assets bundle from the resources folder<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  <\/span><span style=\"color: #9893A5; font-style: italic\">\/\/ (i.e. project\/test\/_resources)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  <\/span><span style=\"color: #56949F\">AssetBundle<\/span><span style=\"color: #575279\"> assets <\/span><span style=\"color: #286983\">=<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #286983\">await<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #56949F\">DiskAssetBundle<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #D7827E\">loadFromPath<\/span><span style=\"color: #575279\">(<\/span><span style=\"color: #EA9D34\">&#39;test\/_resources\/&#39;<\/span><span style=\"color: #575279\">)<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  <\/span><span style=\"color: #D7827E\">group<\/span><span style=\"color: #575279\">(<\/span><span style=\"color: #EA9D34\">&#39;Example&#39;<\/span><span style=\"color: #797593\">,<\/span><span style=\"color: #575279\"> () {<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    <\/span><span style=\"color: #9893A5; font-style: italic\">\/\/\/ This test will compare an image to a golden file<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    <\/span><span style=\"color: #D7827E\">test<\/span><span style=\"color: #575279\">(<\/span><span style=\"color: #EA9D34\">&#39;Does match golden&#39;<\/span><span style=\"color: #797593\">,<\/span><span style=\"color: #575279\"> () <\/span><span style=\"color: #286983\">async<\/span><span style=\"color: #575279\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">      <\/span><span style=\"color: #286983\">final<\/span><span style=\"color: #575279\"> image <\/span><span style=\"color: #286983\">=<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #286983\">await<\/span><span style=\"color: #575279\"> assets<\/span><span style=\"color: #797593\">.<\/span><span style=\"color: #D7827E\">load<\/span><span style=\"color: #575279\">(<\/span><span style=\"color: #EA9D34\">&#39;image.png&#39;<\/span><span style=\"color: #575279\">)<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #575279\">      <\/span><span style=\"color: #286983\">await<\/span><span style=\"color: #575279\"> <\/span><span style=\"color: #D7827E\">expectLater<\/span><span style=\"color: #575279\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">        image<\/span><span style=\"color: #797593\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">        <\/span><span style=\"color: #D7827E\">matchesGoldenFile<\/span><span style=\"color: #575279\">(<\/span><span style=\"color: #EA9D34\">&#39;$<\/span><span style=\"color: #907AA9; font-style: italic\">goldens<\/span><span style=\"color: #EA9D34\">\/image-no-transform.png&#39;<\/span><span style=\"color: #575279\">)<\/span><span style=\"color: #797593\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">      )<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">    })<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">  })<\/span><span style=\"color: #797593\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #575279\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#faf4ed;color:#625c88;font-size:12px;line-height:1;position:relative\">Dart<\/span><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Some tips, especially if you are new to Flutter or dart testing:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A golden test is a comparison of a generated image against a <strong>golden image<\/strong> to ensure that the generated image is correct. Every pixel of the image has to exactly match the same pixel in the golden image.<\/li>\n\n\n\n<li>After you have tested your code yourself and it is working as expected, you generate goldens. These are included in the repo. The golden tests then ensure that future changes do not affect how the images are generated.<\/li>\n\n\n\n<li>To generate the golden images (just once):<br><code>flutter test --update-goldens<\/code><\/li>\n\n\n\n<li>To run the tests once you have generated goldens:<br><code>flutter test<\/code><\/li>\n\n\n\n<li>My file structure is like this:<br><code>project root\/<\/code><br><code>  test\/<\/code><br><code>    _goldens\/<\/code><br><code>    _resources\/<\/code><br><code>      image.png<\/code><br><code>    example_test.dart<\/code><br><code>    disk_asset_bundle.dart<\/code><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Hopefully you can figure it out from here!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Tests in a flutter project or game often require assets that you don&#8217;t want in the root asset bundle (rootBundle) -w specially if you are writing golden tests. Wouldn&#8217;t it be great if you could create a custom asset bundle for your tests? Today I ran in to this exact problem. I&#8217;ve written an image [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":73,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,10,9],"tags":[],"class_list":["post-69","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dart","category-flutter","category-testing"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.9 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Custom asset bundle for flutter golden tests - system reset<\/title>\n<meta name=\"description\" content=\"How to create a custom asset bundle for flutter tests that can be used to load assets from a file to use for goldens.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/systemreset.io\/journal\/custom-asset-bundle-for-flutter-tests\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Custom asset bundle for flutter golden tests - system reset\" \/>\n<meta property=\"og:description\" content=\"How to create a custom asset bundle for flutter tests that can be used to load assets from a file to use for goldens.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/systemreset.io\/journal\/custom-asset-bundle-for-flutter-tests\/\" \/>\n<meta property=\"og:site_name\" content=\"system reset\" \/>\n<meta property=\"article:published_time\" content=\"2024-12-20T09:50:11+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-12-20T19:52:28+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/systemreset.io\/journal\/wp-content\/uploads\/2024\/12\/treasure.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"628\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"System Reset\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"System Reset\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/custom-asset-bundle-for-flutter-tests\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/custom-asset-bundle-for-flutter-tests\\\/\"},\"author\":{\"name\":\"System Reset\",\"@id\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/#\\\/schema\\\/person\\\/06a6e24e1a9461e4155cfc86c122dff5\"},\"headline\":\"Custom asset bundle for flutter golden tests\",\"datePublished\":\"2024-12-20T09:50:11+00:00\",\"dateModified\":\"2024-12-20T19:52:28+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/custom-asset-bundle-for-flutter-tests\\\/\"},\"wordCount\":302,\"publisher\":{\"@id\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/custom-asset-bundle-for-flutter-tests\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/wp-content\\\/uploads\\\/2024\\\/12\\\/treasure.jpg\",\"articleSection\":[\"Dart\",\"Flutter\",\"Testing\"],\"inLanguage\":\"en-NZ\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/custom-asset-bundle-for-flutter-tests\\\/\",\"url\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/custom-asset-bundle-for-flutter-tests\\\/\",\"name\":\"Custom asset bundle for flutter golden tests - system reset\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/custom-asset-bundle-for-flutter-tests\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/custom-asset-bundle-for-flutter-tests\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/wp-content\\\/uploads\\\/2024\\\/12\\\/treasure.jpg\",\"datePublished\":\"2024-12-20T09:50:11+00:00\",\"dateModified\":\"2024-12-20T19:52:28+00:00\",\"description\":\"How to create a custom asset bundle for flutter tests that can be used to load assets from a file to use for goldens.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/custom-asset-bundle-for-flutter-tests\\\/#breadcrumb\"},\"inLanguage\":\"en-NZ\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/systemreset.io\\\/journal\\\/custom-asset-bundle-for-flutter-tests\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-NZ\",\"@id\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/custom-asset-bundle-for-flutter-tests\\\/#primaryimage\",\"url\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/wp-content\\\/uploads\\\/2024\\\/12\\\/treasure.jpg\",\"contentUrl\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/wp-content\\\/uploads\\\/2024\\\/12\\\/treasure.jpg\",\"width\":1200,\"height\":628,\"caption\":\"Gold treasure overflowing a chest\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/custom-asset-bundle-for-flutter-tests\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Custom asset bundle for flutter golden tests\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/#website\",\"url\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/\",\"name\":\"system reset\",\"description\":\"dev journal\",\"publisher\":{\"@id\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-NZ\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/#organization\",\"name\":\"system reset\",\"url\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-NZ\",\"@id\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/wp-content\\\/uploads\\\/2024\\\/11\\\/system-reset-stacked-1024-1.png\",\"contentUrl\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/wp-content\\\/uploads\\\/2024\\\/11\\\/system-reset-stacked-1024-1.png\",\"width\":1024,\"height\":1024,\"caption\":\"system reset\"},\"image\":{\"@id\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/systemreset.io\\\/journal\\\/#\\\/schema\\\/person\\\/06a6e24e1a9461e4155cfc86c122dff5\",\"name\":\"System Reset\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-NZ\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/edbe9aa08d216b02d0781180e15a10381c672def2d9ec0eac19143bb28a9284a?s=96&d=blank&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/edbe9aa08d216b02d0781180e15a10381c672def2d9ec0eac19143bb28a9284a?s=96&d=blank&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/edbe9aa08d216b02d0781180e15a10381c672def2d9ec0eac19143bb28a9284a?s=96&d=blank&r=g\",\"caption\":\"System Reset\"},\"sameAs\":[\"https:\\\/\\\/systemreset.io\\\/journal\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Custom asset bundle for flutter golden tests - system reset","description":"How to create a custom asset bundle for flutter tests that can be used to load assets from a file to use for goldens.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/systemreset.io\/journal\/custom-asset-bundle-for-flutter-tests\/","og_locale":"en_US","og_type":"article","og_title":"Custom asset bundle for flutter golden tests - system reset","og_description":"How to create a custom asset bundle for flutter tests that can be used to load assets from a file to use for goldens.","og_url":"https:\/\/systemreset.io\/journal\/custom-asset-bundle-for-flutter-tests\/","og_site_name":"system reset","article_published_time":"2024-12-20T09:50:11+00:00","article_modified_time":"2024-12-20T19:52:28+00:00","og_image":[{"width":1200,"height":628,"url":"https:\/\/systemreset.io\/journal\/wp-content\/uploads\/2024\/12\/treasure.jpg","type":"image\/jpeg"}],"author":"System Reset","twitter_card":"summary_large_image","twitter_misc":{"Written by":"System Reset","Est. reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/systemreset.io\/journal\/custom-asset-bundle-for-flutter-tests\/#article","isPartOf":{"@id":"https:\/\/systemreset.io\/journal\/custom-asset-bundle-for-flutter-tests\/"},"author":{"name":"System Reset","@id":"https:\/\/systemreset.io\/journal\/#\/schema\/person\/06a6e24e1a9461e4155cfc86c122dff5"},"headline":"Custom asset bundle for flutter golden tests","datePublished":"2024-12-20T09:50:11+00:00","dateModified":"2024-12-20T19:52:28+00:00","mainEntityOfPage":{"@id":"https:\/\/systemreset.io\/journal\/custom-asset-bundle-for-flutter-tests\/"},"wordCount":302,"publisher":{"@id":"https:\/\/systemreset.io\/journal\/#organization"},"image":{"@id":"https:\/\/systemreset.io\/journal\/custom-asset-bundle-for-flutter-tests\/#primaryimage"},"thumbnailUrl":"https:\/\/systemreset.io\/journal\/wp-content\/uploads\/2024\/12\/treasure.jpg","articleSection":["Dart","Flutter","Testing"],"inLanguage":"en-NZ"},{"@type":"WebPage","@id":"https:\/\/systemreset.io\/journal\/custom-asset-bundle-for-flutter-tests\/","url":"https:\/\/systemreset.io\/journal\/custom-asset-bundle-for-flutter-tests\/","name":"Custom asset bundle for flutter golden tests - system reset","isPartOf":{"@id":"https:\/\/systemreset.io\/journal\/#website"},"primaryImageOfPage":{"@id":"https:\/\/systemreset.io\/journal\/custom-asset-bundle-for-flutter-tests\/#primaryimage"},"image":{"@id":"https:\/\/systemreset.io\/journal\/custom-asset-bundle-for-flutter-tests\/#primaryimage"},"thumbnailUrl":"https:\/\/systemreset.io\/journal\/wp-content\/uploads\/2024\/12\/treasure.jpg","datePublished":"2024-12-20T09:50:11+00:00","dateModified":"2024-12-20T19:52:28+00:00","description":"How to create a custom asset bundle for flutter tests that can be used to load assets from a file to use for goldens.","breadcrumb":{"@id":"https:\/\/systemreset.io\/journal\/custom-asset-bundle-for-flutter-tests\/#breadcrumb"},"inLanguage":"en-NZ","potentialAction":[{"@type":"ReadAction","target":["https:\/\/systemreset.io\/journal\/custom-asset-bundle-for-flutter-tests\/"]}]},{"@type":"ImageObject","inLanguage":"en-NZ","@id":"https:\/\/systemreset.io\/journal\/custom-asset-bundle-for-flutter-tests\/#primaryimage","url":"https:\/\/systemreset.io\/journal\/wp-content\/uploads\/2024\/12\/treasure.jpg","contentUrl":"https:\/\/systemreset.io\/journal\/wp-content\/uploads\/2024\/12\/treasure.jpg","width":1200,"height":628,"caption":"Gold treasure overflowing a chest"},{"@type":"BreadcrumbList","@id":"https:\/\/systemreset.io\/journal\/custom-asset-bundle-for-flutter-tests\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/systemreset.io\/journal\/"},{"@type":"ListItem","position":2,"name":"Custom asset bundle for flutter golden tests"}]},{"@type":"WebSite","@id":"https:\/\/systemreset.io\/journal\/#website","url":"https:\/\/systemreset.io\/journal\/","name":"system reset","description":"dev journal","publisher":{"@id":"https:\/\/systemreset.io\/journal\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/systemreset.io\/journal\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-NZ"},{"@type":"Organization","@id":"https:\/\/systemreset.io\/journal\/#organization","name":"system reset","url":"https:\/\/systemreset.io\/journal\/","logo":{"@type":"ImageObject","inLanguage":"en-NZ","@id":"https:\/\/systemreset.io\/journal\/#\/schema\/logo\/image\/","url":"https:\/\/systemreset.io\/journal\/wp-content\/uploads\/2024\/11\/system-reset-stacked-1024-1.png","contentUrl":"https:\/\/systemreset.io\/journal\/wp-content\/uploads\/2024\/11\/system-reset-stacked-1024-1.png","width":1024,"height":1024,"caption":"system reset"},"image":{"@id":"https:\/\/systemreset.io\/journal\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/systemreset.io\/journal\/#\/schema\/person\/06a6e24e1a9461e4155cfc86c122dff5","name":"System Reset","image":{"@type":"ImageObject","inLanguage":"en-NZ","@id":"https:\/\/secure.gravatar.com\/avatar\/edbe9aa08d216b02d0781180e15a10381c672def2d9ec0eac19143bb28a9284a?s=96&d=blank&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/edbe9aa08d216b02d0781180e15a10381c672def2d9ec0eac19143bb28a9284a?s=96&d=blank&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/edbe9aa08d216b02d0781180e15a10381c672def2d9ec0eac19143bb28a9284a?s=96&d=blank&r=g","caption":"System Reset"},"sameAs":["https:\/\/systemreset.io\/journal"]}]}},"_links":{"self":[{"href":"https:\/\/systemreset.io\/journal\/wp-json\/wp\/v2\/posts\/69","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/systemreset.io\/journal\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/systemreset.io\/journal\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/systemreset.io\/journal\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/systemreset.io\/journal\/wp-json\/wp\/v2\/comments?post=69"}],"version-history":[{"count":4,"href":"https:\/\/systemreset.io\/journal\/wp-json\/wp\/v2\/posts\/69\/revisions"}],"predecessor-version":[{"id":75,"href":"https:\/\/systemreset.io\/journal\/wp-json\/wp\/v2\/posts\/69\/revisions\/75"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/systemreset.io\/journal\/wp-json\/wp\/v2\/media\/73"}],"wp:attachment":[{"href":"https:\/\/systemreset.io\/journal\/wp-json\/wp\/v2\/media?parent=69"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/systemreset.io\/journal\/wp-json\/wp\/v2\/categories?post=69"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/systemreset.io\/journal\/wp-json\/wp\/v2\/tags?post=69"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}