feat: 初始化项目并完成基础功能开发

- 完成项目初始化
- 实现用户注册、登录功能
- 完成用户管理与权限管理模块
- 开发后端 Tracker 服务器项目管理接口
- 实现日志管理接口
Change-Id: Ia4bde1c9ff600352a7ff0caca0cc50b02cad1af7
diff --git a/react-ui/tests/setupTests.jsx b/react-ui/tests/setupTests.jsx
new file mode 100644
index 0000000..952561d
--- /dev/null
+++ b/react-ui/tests/setupTests.jsx
@@ -0,0 +1,64 @@
+const localStorageMock = {
+  getItem: jest.fn(),
+  setItem: jest.fn(),
+  removeItem: jest.fn(),
+  clear: jest.fn(),
+};
+
+global.localStorage = localStorageMock;
+
+Object.defineProperty(URL, 'createObjectURL', {
+  writable: true,
+  value: jest.fn(),
+});
+
+class Worker {
+  constructor(stringUrl) {
+    this.url = stringUrl;
+    this.onmessage = () => {};
+  }
+
+  postMessage(msg) {
+    this.onmessage(msg);
+  }
+}
+window.Worker = Worker;
+
+/* eslint-disable global-require */
+if (typeof window !== 'undefined') {
+  // ref: https://github.com/ant-design/ant-design/issues/18774
+  if (!window.matchMedia) {
+    Object.defineProperty(global.window, 'matchMedia', {
+      writable: true,
+      configurable: true,
+      value: jest.fn(() => ({
+        matches: false,
+        addListener: jest.fn(),
+        removeListener: jest.fn(),
+      })),
+    });
+  }
+  if (!window.matchMedia) {
+    Object.defineProperty(global.window, 'matchMedia', {
+      writable: true,
+      configurable: true,
+      value: jest.fn((query) => ({
+        matches: query.includes('max-width'),
+        addListener: jest.fn(),
+        removeListener: jest.fn(),
+      })),
+    });
+  }
+}
+const errorLog = console.error;
+Object.defineProperty(global.window.console, 'error', {
+  writable: true,
+  configurable: true,
+  value: (...rest) => {
+    const logStr = rest.join('');
+    if (logStr.includes('Warning: An update to %s inside a test was not wrapped in act(...)')) {
+      return;
+    }
+    errorLog(...rest);
+  },
+});