const { test } = require('node:test') const assert = require('node:assert/strict') const fs = require('node:fs') const vm = require('node:vm') const ts = require('typescript') const React = require('react') const { renderToStaticMarkup } = require('react-dom/server') const source = fs.readFileSync(require.resolve('../src/renderer/src/components/AppStatusModals.tsx'), 'utf8') const compiled = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022, jsx: ts.JsxEmit.ReactJSX } }).outputText function loadModals() { const exports = {} vm.runInNewContext(compiled, { exports, require: name => name === '../i18n' ? { t: key => key, useLocaleRender() {} } : require(name) }) return exports } function buttons(element) { if (!React.isValidElement(element)) return [] if (element.type === 'button') return [element] return React.Children.toArray(element.props.children).flatMap(buttons) } for (const dark of [false, true]) { test(`extension action stays on the right in both dialogs (${dark ? 'dark' : 'light'})`, () => { const { StatusNoticeModal, ControlExtensionConfirmModal } = loadModals() let confirmed = 0 let extended = 0 const notice = StatusNoticeModal({ overlayClassName: 'overlay', dark, tone: 'clock', title: '제어 시간 안내', message: '제어 시간이 곧 종료됩니다.', actionLabel: '연장', onAction: () => { extended++ }, onConfirm: () => { confirmed++ } }) const noticeButtons = buttons(notice) assert.deepEqual(noticeButtons.map(button => button.props.children), ['확인', '연장']) assert.match(noticeButtons[1].props.className, /bg-\[#6f4df6\]/) assert.doesNotMatch(noticeButtons[0].props.className, /bg-\[#6f4df6\]/) noticeButtons[0].props.onClick() noticeButtons[1].props.onClick() assert.equal(confirmed, 1) assert.equal(extended, 1) const confirmation = ControlExtensionConfirmModal({ overlayClassName: 'overlay', dark, platformName: 'MK-mini', onCancel() {}, onConfirm() {} }) assert.deepEqual(buttons(confirmation).map(button => button.props.children), ['취소', '연장']) assert.match(buttons(confirmation)[1].props.className, /bg-\[#6f4df6\]/) assert.match(renderToStaticMarkup(confirmation), /취소<\/button>]*>연장<\/button>/) }) } test('notices without an extension action retain their single primary confirmation button', () => { const { StatusNoticeModal } = loadModals() const notice = StatusNoticeModal({ overlayClassName: 'overlay', dark: true, tone: 'warning', title: '안내', message: '메시지', onConfirm() {} }) assert.equal(buttons(notice).length, 1) assert.equal(buttons(notice)[0].props.children, '확인') assert.match(buttons(notice)[0].props.className, /bg-\[#6f4df6\]/) }) test('the extension confirmation keeps the right button disabled while submitting', () => { const { ControlExtensionConfirmModal } = loadModals() const confirmation = ControlExtensionConfirmModal({ overlayClassName: 'overlay', dark: true, platformName: 'MK-mini', submitting: true, onCancel() {}, onConfirm() {} }) assert.deepEqual(buttons(confirmation).map(button => button.props.children), ['취소', '연장 중']) assert.ok(buttons(confirmation).every(button => button.props.disabled)) })