Migrate to Vite 7, improve UI (Copy/Download), and enhance API security

This commit is contained in:
2026-01-31 10:16:49 +01:00
parent 452e6e74cb
commit d398c34aa5
14 changed files with 2012 additions and 14637 deletions

View File

@@ -83,22 +83,10 @@ function App() {
// Get headers for API requests
const getApiHeaders = () => {
const headers = {
return {
Accept: "application/json",
"X-API-Key": apiKey,
};
// Only send API key for non-localhost requests
// For localhost, let server use its default LOCALHOST_API_KEY
if (
window.location.hostname !== "localhost" &&
window.location.hostname !== "127.0.0.1" &&
!window.location.hostname.startsWith("127.") &&
window.location.hostname !== "::1"
) {
headers["X-API-Key"] = apiKey;
}
return headers;
};
// Load sample data from API on startup and setup periodic state checking

View File

@@ -1,13 +1,27 @@
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import App from './App';
import { vi } from 'vitest';
import '@testing-library/jest-dom';
// Mock localStorage
const localStorageMock = (function() {
let store = {};
return {
getItem: vi.fn((key) => store[key] || null),
setItem: vi.fn((key, value) => { store[key] = value.toString(); }),
clear: vi.fn(() => { store = {}; }),
removeItem: vi.fn((key) => { delete store[key]; })
};
})();
Object.defineProperty(window, 'localStorage', { value: localStorageMock });
// Mock fetch for API calls
global.fetch = jest.fn();
global.fetch = vi.fn();
describe('App Component', () => {
beforeEach(() => {
fetch.mockClear();
vi.clearAllMocks();
// Mock successful API responses
fetch.mockImplementation((url) => {
if (url.includes('/api/v1/sample')) {

View File

@@ -55,8 +55,7 @@ function ApiKeyPage({ apiKey, onRegenerateApiKey }) {
</button>
</div>
<div className="form-text">
This API key is used to encrypt and authenticate data uploads from remote clients.
<strong>Note:</strong> Requests from localhost (127.0.0.1) do not require an API key.
This API key is used to encrypt and authenticate data uploads.
</div>
</div>
@@ -64,7 +63,7 @@ function ApiKeyPage({ apiKey, onRegenerateApiKey }) {
<h6>📡 Remote Data Upload API</h6>
<p className="text-muted">
External tools can upload sample data remotely using the REST API.
For remote clients, the API key is required for authentication. Define two
The API key is required for authentication. Define two
environment variables in your <code>.bashrc</code>.
</p>
<pre className="bg-light p-3 rounded border">
@@ -80,10 +79,9 @@ function ApiKeyPage({ apiKey, onRegenerateApiKey }) {
"$\{JMESPATH_PLAYGROUND_API_URL}/api/v1/upload"`}</code>
</pre>
<div className="form-text">
Replace <code>{'__JSON_FILE_NAME__'}</code> with the path to your JSON file containing the sample data.
or use <code>-</code> to read from standard input.
<br />
<strong>For localhost clients:</strong> The X-API-Key should be omitted.
Replace <code>{"__JSON_FILE_NAME__"}</code> with the path to your
JSON file containing the sample data. or use <code>-</code> to
read from standard input.
</div>
</div>
</div>

View File

@@ -1,46 +0,0 @@
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';
// Add TextEncoder/TextDecoder for Node.js compatibility
if (typeof TextEncoder === 'undefined') {
global.TextEncoder = require('util').TextEncoder;
}
if (typeof TextDecoder === 'undefined') {
global.TextDecoder = require('util').TextDecoder;
}
// Mock crypto.getRandomValues for test environment
if (typeof global.crypto === 'undefined') {
global.crypto = {
getRandomValues: (array) => {
// Simple predictable mock for testing
for (let i = 0; i < array.length; i++) {
array[i] = Math.floor(Math.random() * 256);
}
return array;
}
};
}
// Suppress console errors during tests
const originalError = console.error;
beforeAll(() => {
console.error = (...args) => {
if (
typeof args[0] === 'string' &&
(args[0].includes('Warning: ReactDOMTestUtils.act is deprecated') ||
args[0].includes('Warning: An update to App inside a test was not wrapped in act'))
) {
return;
}
originalError.call(console, ...args);
};
});
afterAll(() => {
console.error = originalError;
});