Fix test log noise and resource loading errors

This change addresses multiple sources of noise and error reports in the
test output.

It prevents 404 errors by mocking network requests and using data URIs
for resources that are not available in the test environment. This
affects avatar loading, gitiles images, and external libraries like
resemble.js.

Additionally, it resolves LitElement lifecycle warnings in
`gr-overview-image` and `gr-zoomed-image` by moving state-dependent
style updates from `updated()` to `willUpdate()`.

Finally, it fixes a data consistency error in `gr-change-metadata` tests
by ensuring the owner property is a valid account object.

Release-Notes: skip
Change-Id: I0e227783160b0f1d113b2bf32ef6539d1daea9e6
diff --git a/polygerrit-ui/GEMINI.md b/polygerrit-ui/GEMINI.md
index 015a548..7478a77 100644
--- a/polygerrit-ui/GEMINI.md
+++ b/polygerrit-ui/GEMINI.md
@@ -24,6 +24,7 @@
 
 **Note**: Imports should NOT have spaces around braces (e.g., `import {css} from 'lit';`, not `import { css } from 'lit';`).
 **Note**: Do not use `_` prefix for private properties or variables.
+**Note**: Use `// @ts-expect-error` instead of casting to `any` when suppressing TypeScript errors.
 
 ## Key Commands
 
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.ts b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.ts
index 0da17d0..ae9e411 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.ts
@@ -625,7 +625,7 @@
       ...createParsedChange(),
       current_revision: '456' as CommitId,
       revisions: {456: revision('111' as CommitId)},
-      owner: {},
+      owner: createAccountWithId(),
     };
     element.revision = revision('222' as CommitId);
     await element.updateComplete;
diff --git a/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar_test.ts b/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar_test.ts
index 4a2175d..d4d803c 100644
--- a/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar_test.ts
@@ -61,6 +61,23 @@
       });
     });
 
+    let generatedUrl: string | undefined;
+
+    setup(() => {
+      // Prevent 404s by stubbing buildAvatarURL to return data URI for local paths
+      const orig = (GrAvatar.prototype as any).buildAvatarURL;
+      sinon
+        .stub(GrAvatar.prototype as any, 'buildAvatarURL')
+        .callsFake(function (this: GrAvatar, account: unknown) {
+          const url = orig.call(this, account);
+          if (url.startsWith('/accounts/')) {
+            generatedUrl = url;
+            return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=';
+          }
+          return url;
+        });
+    });
+
     test('loads correct size', async () => {
       const accountWithId = {
         ...createAccountWithId(123),
@@ -71,10 +88,7 @@
       );
 
       assert.isTrue(isVisible(element));
-      assert.equal(
-        element.style.backgroundImage,
-        'url("/accounts/123/avatar?s=64")'
-      );
+      assert.equal(generatedUrl, '/accounts/123/avatar?s=64');
     });
 
     test('loads using id', async () => {
@@ -87,10 +101,7 @@
       );
 
       assert.isTrue(isVisible(element));
-      assert.equal(
-        element.style.backgroundImage,
-        'url("/accounts/123/avatar?s=16")'
-      );
+      assert.equal(generatedUrl, '/accounts/123/avatar?s=16');
     });
 
     test('loads using email', async () => {
@@ -103,10 +114,7 @@
       );
 
       assert.isTrue(isVisible(element));
-      assert.equal(
-        element.style.backgroundImage,
-        'url("/accounts/foo%40gmail.com/avatar?s=16")'
-      );
+      assert.equal(generatedUrl, '/accounts/foo%40gmail.com/avatar?s=16');
     });
 
     test('loads using name', async () => {
@@ -119,10 +127,7 @@
       );
 
       assert.isTrue(isVisible(element));
-      assert.equal(
-        element.style.backgroundImage,
-        'url("/accounts/John%20Doe/avatar?s=16")'
-      );
+      assert.equal(generatedUrl, '/accounts/John%20Doe/avatar?s=16');
     });
 
     test('loads using username', async () => {
@@ -135,10 +140,7 @@
       );
 
       assert.isTrue(isVisible(element));
-      assert.equal(
-        element.style.backgroundImage,
-        'url("/accounts/John_Doe/avatar?s=16")'
-      );
+      assert.equal(generatedUrl, '/accounts/John_Doe/avatar?s=16');
     });
 
     test('loads using custom URL from matching height', async () => {
@@ -185,10 +187,7 @@
       );
 
       assert.isTrue(isVisible(element));
-      assert.equal(
-        element.style.backgroundImage,
-        'url("/accounts/123/avatar?s=16")'
-      );
+      assert.equal(generatedUrl, '/accounts/123/avatar?s=16');
     });
   });
 });
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.ts
index 60d8514..fd022dc 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.ts
@@ -40,6 +40,7 @@
   let element: GrJsApiInterface;
   let plugin: Plugin;
   let errorStub: SinonStub;
+  let loadJsPluginStub: SinonStub;
   let pluginLoader: PluginLoader;
 
   let clock: SinonFakeTimers;
@@ -71,10 +72,12 @@
       'http://test.com/plugins/testplugin/static/test.js'
     );
     testResolver(pluginLoaderToken).loadPlugins([]);
+    loadJsPluginStub = stub(pluginLoader, 'loadJsPlugin');
   });
 
   teardown(() => {
     clock.restore();
+    loadJsPluginStub.restore();
     element._removeEventCallbacks();
   });
 
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-image-viewer/gr-image-viewer_test.ts b/polygerrit-ui/app/embed/diff/gr-diff-image-viewer/gr-image-viewer_test.ts
index 2ea26af..e14797f 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff-image-viewer/gr-image-viewer_test.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff-image-viewer/gr-image-viewer_test.ts
@@ -12,6 +12,26 @@
   let element: GrImageViewer;
 
   setup(async () => {
+    // Mock getLibrary to avoid 404s on loading resemblejs
+    // 'libLoader' is a private static property on GrImageViewer
+    // @ts-expect-error
+    const libLoader = GrImageViewer.libLoader;
+    sinon.stub(libLoader, 'getLibrary').resolves();
+
+    // Mock window.resemble that is used in GrImageViewer.computeDiffImage
+    // @ts-expect-error
+    window.resemble = sinon.stub().returns({
+      compareTo: sinon.stub().returns({
+        ignoreNothing: sinon.stub().returns({
+          onComplete: sinon
+            .stub()
+            .callsFake(cb =>
+              cb({getImageDataUrl: () => 'data:image/png;base64,mock'})
+            ),
+        }),
+      }),
+    });
+
     element = await fixture<GrImageViewer>(
       html`<gr-image-viewer></gr-image-viewer>`
     );
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-image-viewer/gr-overview-image.ts b/polygerrit-ui/app/embed/diff/gr-diff-image-viewer/gr-overview-image.ts
index a05b5e2..8a2f4c4 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff-image-viewer/gr-overview-image.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff-image-viewer/gr-overview-image.ts
@@ -193,7 +193,7 @@
     this.resizeObserver.observe(this.contentTransform);
   }
 
-  override updated(changedProperties: PropertyValues) {
+  override willUpdate(changedProperties: PropertyValues) {
     if (changedProperties.has('frameRect')) {
       this.updateFrameStyle();
     }
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-image-viewer/gr-zoomed-image.ts b/polygerrit-ui/app/embed/diff/gr-diff-image-viewer/gr-zoomed-image.ts
index 3b778b1..0951042 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff-image-viewer/gr-zoomed-image.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff-image-viewer/gr-zoomed-image.ts
@@ -59,7 +59,7 @@
     `;
   }
 
-  override updated(changedProperties: PropertyValues) {
+  override willUpdate(changedProperties: PropertyValues) {
     if (changedProperties.has('scale') || changedProperties.has('frameRect')) {
       this.updateImageStyles();
     }
diff --git a/polygerrit-ui/app/test/test-data-generators.ts b/polygerrit-ui/app/test/test-data-generators.ts
index 1d66d2d..81a2082 100644
--- a/polygerrit-ui/app/test/test-data-generators.ts
+++ b/polygerrit-ui/app/test/test-data-generators.ts
@@ -900,7 +900,8 @@
   return {
     name: 'gitiles',
     url: '#',
-    image_url: 'gitiles.jpg',
+    image_url:
+      'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
   };
 }