Repository: boardgameio/boardgame.io
Pull request #790 (2020-08-31 13:25:15)

fix(debug): Fix runtime error introduced by #781
In #781, I decided we could use `require` to always depend on the compiled JSON Tree component we were adding (rather than the Svelte source files). However, after manual testing I see that this causes runtime errors when the tree component unmounts (for example when toggling to the AI or Info panels). As far as I understand, this is due to the Debug panel and the third-party component depending on different copies of Svelte internals, which causes problems ([this explanation](https://github.com/sveltejs/svelte/issues/3671#issuecomment-544329688) helped me).

So, we need to depend on and compile the Svelte component ourselves to fix this, but that caused test errors (as detailed in #781). To resolve this, I’m now mocking the tree component in tests. I *think* the errors might be because of the tree’s circular dependencies (the error seems to happen the second time we reach `JSONNode`).

To try to catch runtime errors like this in the future, I’ve also added a basic test that makes sure the Debug panel is interactive.


Patch:
diff --git a/package.json b/package.json
index 26d8c6f..40780dc 100644
--- a/package.json
+++ b/package.json
@@ -173,7 +173,8 @@
     "preset": "ts-jest/presets/js-with-babel",
     "moduleNameMapper": {
       "\\.(css)$": "identity-obj-proxy",
-      "\\.(svg)$": "<rootDir>/.empty_module.js"
+      "\\.(svg)$": "<rootDir>/.empty_module.js",
+      "svelte-json-tree-auto": "<rootDir>/src/client/debug/tests/JSONTree.mock.svelte"
     },
     "coveragePathIgnorePatterns": [
       "/node_modules/",
diff --git a/src/client/debug/main/Main.svelte b/src/client/debug/main/Main.svelte
index 129c283..f530cf7 100644
--- a/src/client/debug/main/Main.svelte
+++ b/src/client/debug/main/Main.svelte
@@ -1,7 +1,7 @@
 <script>
   export let client;
 
-  const JSONTree = require('svelte-json-tree-auto');
+  import JSONTree from 'svelte-json-tree-auto/src/Root.svelte';
   import Move from './Move.svelte';
   import Controls from './Controls.svelte';
   import PlayerInfo from './PlayerInfo.svelte';


Test patch:
diff --git a/src/client/debug/tests/JSONTree.mock.svelte b/src/client/debug/tests/JSONTree.mock.svelte
new file mode 100644
index 0000000..7853ff3
--- /dev/null
+++ b/src/client/debug/tests/JSONTree.mock.svelte
@@ -0,0 +1,3 @@
+<script>
+  export let value;
+</script>
diff --git a/src/client/debug/tests/debug.test.js b/src/client/debug/tests/debug.test.js
index ab16dd4..5fa4142 100644
--- a/src/client/debug/tests/debug.test.js
+++ b/src/client/debug/tests/debug.test.js
@@ -7,7 +7,7 @@
  */
 
 import '@testing-library/jest-dom/extend-expect';
-import { render } from '@testing-library/svelte';
+import { render, fireEvent } from '@testing-library/svelte';
 import { Client } from '../../client';
 import Debug from '../Debug.svelte';
 
@@ -20,3 +20,21 @@ test('sanity', () => {
   expect(getByText('G')).toBeInTheDocument();
   expect(getByText('ctx')).toBeInTheDocument();
 });
+
+test('switching panels', async () => {
+  const game = {};
+  const client = Client({ game });
+  const { getByText } = render(Debug, { props: { client } });
+
+  // switch to info tab
+  const InfoTab = getByText('Info');
+  await fireEvent.click(InfoTab);
+  expect(getByText('gameID')).toBeInTheDocument();
+  expect(getByText('playerID')).toBeInTheDocument();
+  expect(getByText('isActive')).toBeInTheDocument();
+
+  // switch to AI tab
+  const AITab = getByText('AI');
+  await fireEvent.click(AITab);
+  expect(getByText('No bots available.')).toBeInTheDocument();
+});