|
| 1 | +import { test } from 'node:test'; |
| 2 | +import assert from 'node:assert/strict'; |
| 3 | +import * as React from 'react'; |
| 4 | +import { renderToStaticMarkup } from 'react-dom/server'; |
| 5 | +import { I18nextProvider } from 'react-i18next'; |
| 6 | +import i18next from 'i18next'; |
| 7 | + |
| 8 | +import { EnvPill } from '../EnvPill.tsx'; |
| 9 | + |
| 10 | +i18next.init({ |
| 11 | + lng: 'en', |
| 12 | + resources: { |
| 13 | + en: { |
| 14 | + translation: { |
| 15 | + 'admin_settings.env_pill.tooltip': 'env {{variable}}', |
| 16 | + 'admin_settings.env_pill.default_label': 'default', |
| 17 | + 'admin_settings.env_pill.input_aria': 'aria {{variable}}', |
| 18 | + 'admin_settings.env_pill.runtime_label': 'active value', |
| 19 | + 'admin_settings.env_pill.runtime_tooltip': 'using {{variable}}', |
| 20 | + 'admin_settings.env_pill.redacted_tooltip': 'hidden {{variable}}', |
| 21 | + }, |
| 22 | + }, |
| 23 | + }, |
| 24 | + interpolation: { escapeValue: false }, |
| 25 | +}); |
| 26 | + |
| 27 | +const wrap = (el: React.ReactElement) => |
| 28 | + renderToStaticMarkup( |
| 29 | + React.createElement(I18nextProvider, { i18n: i18next }, el), |
| 30 | + ); |
| 31 | + |
| 32 | +test('omits runtime chip when resolvedValue is undefined', () => { |
| 33 | + const html = wrap(React.createElement(EnvPill, { |
| 34 | + placeholder: { variable: 'DB_TYPE', defaultValue: 'dirty' }, |
| 35 | + path: ['dbType'], |
| 36 | + onChange: () => {}, |
| 37 | + })); |
| 38 | + assert.ok(!html.includes('settings-widget-env-runtime'), |
| 39 | + `runtime chip should be absent, got: ${html}`); |
| 40 | +}); |
| 41 | + |
| 42 | +test('renders runtime chip with resolved value', () => { |
| 43 | + const html = wrap(React.createElement(EnvPill, { |
| 44 | + placeholder: { variable: 'DB_TYPE', defaultValue: 'dirty' }, |
| 45 | + path: ['dbType'], |
| 46 | + onChange: () => {}, |
| 47 | + resolvedValue: 'sqlite', |
| 48 | + } as any)); |
| 49 | + assert.ok(html.includes('settings-widget-env-runtime'), |
| 50 | + `runtime chip class should appear, got: ${html}`); |
| 51 | + assert.ok(html.includes('sqlite'), |
| 52 | + `resolved value text should appear, got: ${html}`); |
| 53 | +}); |
| 54 | + |
| 55 | +test('renders redacted chip when resolvedValue is [REDACTED]', () => { |
| 56 | + const html = wrap(React.createElement(EnvPill, { |
| 57 | + placeholder: { variable: 'DB_PASS', defaultValue: '' }, |
| 58 | + path: ['dbSettings', 'password'], |
| 59 | + onChange: () => {}, |
| 60 | + resolvedValue: '[REDACTED]', |
| 61 | + } as any)); |
| 62 | + assert.ok(html.includes('settings-widget-env-runtime-redacted'), |
| 63 | + `redacted chip class should appear, got: ${html}`); |
| 64 | + assert.ok(!html.includes('[REDACTED]'), |
| 65 | + `literal sentinel must not be displayed to the user, got: ${html}`); |
| 66 | +}); |
| 67 | + |
| 68 | +test('coerces non-string resolved values to display strings', () => { |
| 69 | + const html = wrap(React.createElement(EnvPill, { |
| 70 | + placeholder: { variable: 'TRUST_PROXY', defaultValue: 'false' }, |
| 71 | + path: ['trustProxy'], |
| 72 | + onChange: () => {}, |
| 73 | + resolvedValue: true, |
| 74 | + } as any)); |
| 75 | + assert.ok(html.includes('true'), `expected "true" in ${html}`); |
| 76 | +}); |
| 77 | + |
| 78 | +test('renders null resolved value as the string null', () => { |
| 79 | + const html = wrap(React.createElement(EnvPill, { |
| 80 | + placeholder: { variable: 'IP', defaultValue: '' }, |
| 81 | + path: ['ip'], |
| 82 | + onChange: () => {}, |
| 83 | + resolvedValue: null, |
| 84 | + } as any)); |
| 85 | + assert.ok(html.includes('null'), `expected "null" in ${html}`); |
| 86 | +}); |
0 commit comments