diff --git a/src/components/Output/PrintToZebraDialog.tsx b/src/components/Output/PrintToZebraDialog.tsx index f08489d1..6424e5fa 100644 --- a/src/components/Output/PrintToZebraDialog.tsx +++ b/src/components/Output/PrintToZebraDialog.tsx @@ -4,7 +4,6 @@ import { useT } from "../../lib/useT"; import { DialogShell } from "../ui/DialogShell"; import { discoverBrowserPrintDevices, - isConnectionRefused, sendViaBrowserPrint, sendViaNetwork, type BrowserPrintDevice, @@ -56,14 +55,26 @@ export function PrintToZebraDialog({ zpl, onClose }: Props) { async function handleNetworkSend() { persistNetwork(); setNetStatus({ type: "sending" }); - try { - await sendViaNetwork(ip.trim(), Number(port) || 9100, zpl); - setNetStatus({ type: "success", message: t.zebraPrint.success }); - } catch (e) { - const msg = isConnectionRefused(e) - ? t.zebraPrint.errorRefused - : t.zebraPrint.errorGeneric; - setNetStatus({ type: "error", message: msg }); + const result = await sendViaNetwork(ip.trim(), Number(port) || 9100, zpl); + switch (result.kind) { + case "responded": + // 2xx only counts as success; print servers / proxies that respond + // with 4xx or 5xx must surface as an error rather than green-success. + if (result.status >= 200 && result.status < 300) { + setNetStatus({ type: "success", message: t.zebraPrint.success }); + } else { + setNetStatus({ type: "error", message: t.zebraPrint.errorGeneric }); + } + return; + case "no_response": + // Raw-socket printers (port 9100) never reply with HTTP, so a + // timeout is the typical success case — but it is indistinguishable + // from an unreachable host. Report honestly instead of green-success. + setNetStatus({ type: "success", message: t.zebraPrint.sentNoResponse }); + return; + case "refused": + setNetStatus({ type: "error", message: t.zebraPrint.errorRefused }); + return; } } diff --git a/src/lib/zebraPrint.ts b/src/lib/zebraPrint.ts index d530813c..593a5aaf 100644 --- a/src/lib/zebraPrint.ts +++ b/src/lib/zebraPrint.ts @@ -45,21 +45,47 @@ export function isConnectionRefused(e: unknown): boolean { return e instanceof TypeError && /refused/i.test(e.message); } -// Chrome shows a Private Network Access permission prompt on first use. +/** + * Outcome of a direct network-print attempt. + * + * - `responded`: fetch completed with an HTTP response. Rare for raw-socket + * printers (port 9100), more typical for print servers / web frontends. + * - `no_response`: fetch threw without a connection-refused signal — most + * commonly a timeout. For raw-socket Zebra printers this is the *normal* + * success case (they read the bytes and never reply with HTTP), but the + * same exception is also raised when the host is unreachable. The browser + * cannot tell those apart, so the UI must surface this honestly rather + * than reporting an unverified success. + * - `refused`: TCP RST — host reachable but nothing listening on the port. + */ +export type NetworkPrintResult = + | { kind: "responded"; status: number } + | { kind: "no_response" } + | { kind: "refused" }; + +/** + * Direct raw-socket print attempt. Returns a Result rather than throwing + * because the success and unreachable-host paths raise the same exception + * (the printer never speaks HTTP back). The Browser-Print helpers above + * throw because they speak HTTP end-to-end and have no such ambiguity. + * + * Chrome shows a Private Network Access permission prompt on first use. + */ export async function sendViaNetwork( ip: string, port: number, zpl: string, -): Promise { +): Promise { try { - await fetch(`http://${ip}:${port}`, { + const res = await fetch(`http://${ip}:${port}`, { method: "POST", body: zpl, headers: { "Content-Type": "text/plain" }, signal: AbortSignal.timeout(4000), }); + return { kind: "responded", status: res.status }; } catch (e) { - // Timeout/abort is expected — printer never sends a valid HTTP response. - if (isConnectionRefused(e)) throw e; + if (isConnectionRefused(e)) return { kind: "refused" }; + return { kind: "no_response" }; } } diff --git a/src/locales/ar.ts b/src/locales/ar.ts index 41aca664..37173095 100644 --- a/src/locales/ar.ts +++ b/src/locales/ar.ts @@ -423,6 +423,7 @@ const ar = { noPrinters: 'لم يتم العثور على طابعات', agentNotFound: 'عميل Zebra Browser Print غير نشط. قم بتنزيله من zebra.com.', success: 'تم إرسال ZPL بنجاح', + sentNoResponse: 'تم الإرسال. تحقق من الطابعة.', errorRefused: 'الاتصال مرفوض — تحقق من IP والمنفذ', errorGeneric: 'فشل إرسال ZPL', httpsWarning: 'الصفحة على HTTPS — قد يحظر المتصفح الطباعة المباشرة عبر IP (محتوى مختلط).', diff --git a/src/locales/bg.ts b/src/locales/bg.ts index aa0c5f81..e1ebdf56 100644 --- a/src/locales/bg.ts +++ b/src/locales/bg.ts @@ -423,6 +423,7 @@ const bg = { noPrinters: 'Не са намерени принтери', agentNotFound: 'Агентът Zebra Browser Print не работи. Изтеглете от zebra.com.', success: 'ZPL изпратен успешно', + sentNoResponse: 'Изпратено. Проверете принтера.', errorRefused: 'Връзката е отказана — проверете IP и порт', errorGeneric: 'Неуспешно изпращане на ZPL', httpsWarning: 'Страницата е на HTTPS — директният печат по IP може да бъде блокиран от браузъра (смесено съдържание).', diff --git a/src/locales/cs.ts b/src/locales/cs.ts index 99ada681..d93effe9 100644 --- a/src/locales/cs.ts +++ b/src/locales/cs.ts @@ -423,6 +423,7 @@ const cs = { noPrinters: 'Nenalezeny žádné tiskárny', agentNotFound: 'Agent Zebra Browser Print není spuštěn. Stáhněte z zebra.com.', success: 'ZPL úspěšně odesláno', + sentNoResponse: 'Odesláno. Zkontrolujte tiskárnu.', errorRefused: 'Připojení odmítnuto — zkontrolujte IP a port', errorGeneric: 'Odeslání ZPL selhalo', httpsWarning: 'Stránka používá HTTPS — přímý tisk přes IP může být prohlížečem zablokován (smíšený obsah).', diff --git a/src/locales/da.ts b/src/locales/da.ts index ceba196e..2308af2d 100644 --- a/src/locales/da.ts +++ b/src/locales/da.ts @@ -423,6 +423,7 @@ const da = { noPrinters: 'Ingen printere fundet', agentNotFound: 'Zebra Browser Print-agenten kører ikke. Download fra zebra.com.', success: 'ZPL sendt', + sentNoResponse: 'Sendt. Kontrollér printeren.', errorRefused: 'Forbindelse nægtet — kontroller IP og port', errorGeneric: 'Afsendelse af ZPL mislykkedes', httpsWarning: 'Siden bruger HTTPS — direkte udskrivning via IP kan blive blokeret af browseren (blandet indhold).', diff --git a/src/locales/de.ts b/src/locales/de.ts index b278d645..8a3ddf05 100644 --- a/src/locales/de.ts +++ b/src/locales/de.ts @@ -135,6 +135,7 @@ const de = { noPrinters: 'Keine Drucker gefunden', agentNotFound: 'Zebra Browser Print Agent nicht gefunden. Download auf zebra.com.', success: 'ZPL erfolgreich gesendet', + sentNoResponse: 'Gesendet. Bitte am Drucker prüfen.', errorRefused: 'Verbindung abgelehnt — IP und Port prüfen', errorGeneric: 'Fehler beim Senden', httpsWarning: 'Seite läuft über HTTPS — direktes IP-Drucken kann vom Browser blockiert werden (Mixed Content).', diff --git a/src/locales/el.ts b/src/locales/el.ts index eaf6779c..b030d52c 100644 --- a/src/locales/el.ts +++ b/src/locales/el.ts @@ -423,6 +423,7 @@ const el = { noPrinters: 'Δεν βρέθηκαν εκτυπωτές', agentNotFound: 'Ο πράκτορας Zebra Browser Print δεν εκτελείται. Κατεβάστε από το zebra.com.', success: 'Το ZPL στάλθηκε επιτυχώς', + sentNoResponse: 'Στάλθηκε. Ελέγξτε τον εκτυπωτή.', errorRefused: 'Η σύνδεση απορρίφθηκε — ελέγξτε IP και θύρα', errorGeneric: 'Αποτυχία αποστολής ZPL', httpsWarning: 'Η σελίδα χρησιμοποιεί HTTPS — η άμεση εκτύπωση μέσω IP ενδέχεται να αποκλειστεί από τον φυλλομετρητή (μεικτό περιεχόμενο).', diff --git a/src/locales/en.ts b/src/locales/en.ts index 50f66c42..2caa32c2 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -135,6 +135,7 @@ const en = { noPrinters: 'No printers found', agentNotFound: 'Zebra Browser Print agent not running. Download it from zebra.com.', success: 'ZPL sent successfully', + sentNoResponse: 'Sent. Verify on the printer.', errorRefused: 'Connection refused — check IP and port', errorGeneric: 'Failed to send ZPL', httpsWarning: 'Page is on HTTPS — direct IP printing may be blocked by the browser (Mixed Content).', diff --git a/src/locales/es.ts b/src/locales/es.ts index bd3e57b2..89a51ecc 100644 --- a/src/locales/es.ts +++ b/src/locales/es.ts @@ -423,6 +423,7 @@ const es = { noPrinters: 'No se encontraron impresoras', agentNotFound: 'Agente Zebra Browser Print no activo. Descárgalo en zebra.com.', success: 'ZPL enviado correctamente', + sentNoResponse: 'Enviado. Verifica en la impresora.', errorRefused: 'Conexión rechazada — verifica IP y puerto', errorGeneric: 'Error al enviar ZPL', httpsWarning: 'La página está en HTTPS — la impresión directa por IP puede ser bloqueada por el navegador (contenido mixto).', diff --git a/src/locales/et.ts b/src/locales/et.ts index 6e76eff6..6d4915fc 100644 --- a/src/locales/et.ts +++ b/src/locales/et.ts @@ -423,6 +423,7 @@ const et = { noPrinters: 'Printereid ei leitud', agentNotFound: 'Zebra Browser Print agent ei tööta. Laadige alla aadressilt zebra.com.', success: 'ZPL edukalt saadetud', + sentNoResponse: 'Saadetud. Kontrolli printerit.', errorRefused: 'Ühendus keeldutud — kontrollige IP-d ja porti', errorGeneric: 'ZPL saatmine ebaõnnestus', httpsWarning: 'Leht kasutab HTTPS-i — otsene IP-printimistöö võib olla brauseri poolt blokeeritud (segasisaldus).', diff --git a/src/locales/fa.ts b/src/locales/fa.ts index 382c30ff..ea3f6843 100644 --- a/src/locales/fa.ts +++ b/src/locales/fa.ts @@ -423,6 +423,7 @@ const fa = { noPrinters: 'چاپگری یافت نشد', agentNotFound: 'عامل Zebra Browser Print در حال اجرا نیست. از zebra.com دانلود کنید.', success: 'ZPL با موفقیت ارسال شد', + sentNoResponse: 'ارسال شد. روی چاپگر بررسی کنید.', errorRefused: 'اتصال رد شد — IP و پورت را بررسی کنید', errorGeneric: 'ارسال ZPL ناموفق بود', httpsWarning: 'صفحه روی HTTPS است — چاپ مستقیم از طریق IP ممکن است توسط مرورگر مسدود شود (محتوای مختلط).', diff --git a/src/locales/fi.ts b/src/locales/fi.ts index 43c24da9..ac5acb81 100644 --- a/src/locales/fi.ts +++ b/src/locales/fi.ts @@ -423,6 +423,7 @@ const fi = { noPrinters: 'Tulostimia ei löydy', agentNotFound: 'Zebra Browser Print -agentti ei ole käynnissä. Lataa osoitteesta zebra.com.', success: 'ZPL lähetetty onnistuneesti', + sentNoResponse: 'Lähetetty. Tarkista tulostimelta.', errorRefused: 'Yhteys evätty — tarkista IP ja portti', errorGeneric: 'ZPL:n lähetys epäonnistui', httpsWarning: 'Sivu on HTTPS:llä — suora IP-tulostus saattaa olla selaimen estämä (sekasisältö).', diff --git a/src/locales/fr.ts b/src/locales/fr.ts index 736cefde..c31dcd95 100644 --- a/src/locales/fr.ts +++ b/src/locales/fr.ts @@ -423,6 +423,7 @@ const fr = { noPrinters: 'Aucune imprimante trouvée', agentNotFound: 'Agent Zebra Browser Print non détecté. Téléchargez-le sur zebra.com.', success: 'ZPL envoyé avec succès', + sentNoResponse: 'Envoyé. Vérifie sur l\'imprimante.', errorRefused: 'Connexion refusée — vérifiez IP et port', errorGeneric: 'Échec de l’envoi ZPL', httpsWarning: 'La page est en HTTPS — l\'impression directe par IP peut être bloquée par le navigateur (contenu mixte).', diff --git a/src/locales/he.ts b/src/locales/he.ts index 4102d696..7b2df6b8 100644 --- a/src/locales/he.ts +++ b/src/locales/he.ts @@ -423,6 +423,7 @@ const he = { noPrinters: 'לא נמצאו מדפסות', agentNotFound: 'סוכן Zebra Browser Print אינו פועל. הורד מזברא.com.', success: 'ZPL נשלח בהצלחה', + sentNoResponse: 'נשלח. בדוק במדפסת.', errorRefused: 'החיבור סורב — בדוק IP ופורט', errorGeneric: 'שליחת ZPL נכשלה', httpsWarning: 'הדף נמצא על HTTPS — הדפסה ישירה דרך IP עלולה להיחסם על ידי הדפדפן (תוכן מעורב).', diff --git a/src/locales/hr.ts b/src/locales/hr.ts index 3a50ce9a..ee5ba20d 100644 --- a/src/locales/hr.ts +++ b/src/locales/hr.ts @@ -423,6 +423,7 @@ const hr = { noPrinters: 'Nisu pronađeni pisači', agentNotFound: 'Agent Zebra Browser Print nije pokrenut. Preuzmite sa zebra.com.', success: 'ZPL uspješno poslan', + sentNoResponse: 'Poslano. Provjerite na pisaču.', errorRefused: 'Veza odbijena — provjerite IP i port', errorGeneric: 'Slanje ZPL-a nije uspjelo', httpsWarning: 'Stranica koristi HTTPS — izravno ispisivanje putem IP-a može biti blokirano od preglednika (mješoviti sadržaj).', diff --git a/src/locales/hu.ts b/src/locales/hu.ts index 12b5d8bf..8022762c 100644 --- a/src/locales/hu.ts +++ b/src/locales/hu.ts @@ -423,6 +423,7 @@ const hu = { noPrinters: 'Nem találhatók nyomtatók', agentNotFound: 'A Zebra Browser Print ügynök nem fut. Töltse le a zebra.com oldalról.', success: 'ZPL sikeresen elküldve', + sentNoResponse: 'Elküldve. Ellenőrizze a nyomtatón.', errorRefused: 'Kapcsolat megtagadva — ellenőrizze az IP-t és a portot', errorGeneric: 'ZPL küldése sikertelen', httpsWarning: 'Az oldal HTTPS-en fut — az IP-n keresztüli közvetlen nyomtatást a böngésző blokkolhatja (vegyes tartalom).', diff --git a/src/locales/it.ts b/src/locales/it.ts index b34c4b3b..c9a127eb 100644 --- a/src/locales/it.ts +++ b/src/locales/it.ts @@ -423,6 +423,7 @@ const it = { noPrinters: 'Nessuna stampante trovata', agentNotFound: 'Agente Zebra Browser Print non attivo. Scaricalo su zebra.com.', success: 'ZPL inviato con successo', + sentNoResponse: 'Inviato. Verifica sulla stampante.', errorRefused: 'Connessione rifiutata — verifica IP e porta', errorGeneric: 'Invio ZPL non riuscito', httpsWarning: 'La pagina è in HTTPS — la stampa diretta tramite IP potrebbe essere bloccata dal browser (contenuto misto).', diff --git a/src/locales/ja.ts b/src/locales/ja.ts index 711a3ecb..af4e9f50 100644 --- a/src/locales/ja.ts +++ b/src/locales/ja.ts @@ -423,6 +423,7 @@ const ja = { noPrinters: 'プリンターが見つかりません', agentNotFound: 'Zebra Browser Print エージェントが起動していません。zebra.com からダウンロードしてください。', success: 'ZPL を送信しました', + sentNoResponse: '送信しました。プリンターで確認してください。', errorRefused: '接続が拒否されました — IP とポートを確認してください', errorGeneric: 'ZPL の送信に失敗しました', httpsWarning: 'ページが HTTPS 上にあります — ブラウザが直接 IP 印刷をブロックする場合があります(混在コンテンツ)。', diff --git a/src/locales/ko.ts b/src/locales/ko.ts index b6f454a6..5ed4edf0 100644 --- a/src/locales/ko.ts +++ b/src/locales/ko.ts @@ -423,6 +423,7 @@ const ko = { noPrinters: '프린터를 찾을 수 없습니다', agentNotFound: 'Zebra Browser Print 에이전트가 실행 중이 아닙니다. zebra.com에서 다운로드하세요.', success: 'ZPL이 전송되었습니다', + sentNoResponse: '전송됨. 프린터에서 확인하세요.', errorRefused: '연결이 거부되었습니다 — IP와 포트를 확인하세요', errorGeneric: 'ZPL 전송에 실패했습니다', httpsWarning: '페이지가 HTTPS 상에 있습니다 — 브라우저가 직접 IP 인쇄를 차단할 수 있습니다(혼합 콘텐츠).', diff --git a/src/locales/lt.ts b/src/locales/lt.ts index ab89239f..b6d3d3b2 100644 --- a/src/locales/lt.ts +++ b/src/locales/lt.ts @@ -423,6 +423,7 @@ const lt = { noPrinters: 'Spausdintuvų nerasta', agentNotFound: 'Zebra Browser Print agentas neveikia. Atsisiųskite iš zebra.com.', success: 'ZPL sėkmingai išsiųsta', + sentNoResponse: 'Išsiųsta. Patikrinkite spausdintuvą.', errorRefused: 'Ryšys atmestas — patikrinkite IP ir prievadą', errorGeneric: 'ZPL siuntimas nepavyko', httpsWarning: 'Puslapis naudoja HTTPS — tiesioginis spausdinimas per IP gali būti užblokuotas naršyklės (mišrus turinys).', diff --git a/src/locales/lv.ts b/src/locales/lv.ts index 7e9c013f..c18c7d0e 100644 --- a/src/locales/lv.ts +++ b/src/locales/lv.ts @@ -423,6 +423,7 @@ const lv = { noPrinters: 'Printeri nav atrasti', agentNotFound: 'Zebra Browser Print aģents nedarbojas. Lejupielādējiet no zebra.com.', success: 'ZPL veikmīgi nosūtīts', + sentNoResponse: 'Nosūtīts. Pārbaudiet printerī.', errorRefused: 'Savienojums atteikts — pārbaudiet IP un portu', errorGeneric: 'ZPL nosūtīšana neizdevās', httpsWarning: 'Lapa izmanto HTTPS — tiešā IP drukāšana var tikt bloķēta pārlūkprogrammā (jaukts saturs).', diff --git a/src/locales/nl.ts b/src/locales/nl.ts index 1a2a5b99..e89847a0 100644 --- a/src/locales/nl.ts +++ b/src/locales/nl.ts @@ -423,6 +423,7 @@ const nl = { noPrinters: 'Geen printers gevonden', agentNotFound: 'Zebra Browser Print-agent niet actief. Download op zebra.com.', success: 'ZPL succesvol verzonden', + sentNoResponse: 'Verzonden. Controleer op de printer.', errorRefused: 'Verbinding geweigerd — controleer IP en poort', errorGeneric: 'ZPL verzenden mislukt', httpsWarning: 'Pagina gebruikt HTTPS — direct afdrukken via IP kan worden geblokkeerd door de browser (gemengde inhoud).', diff --git a/src/locales/no.ts b/src/locales/no.ts index 3291ca55..c754541c 100644 --- a/src/locales/no.ts +++ b/src/locales/no.ts @@ -423,6 +423,7 @@ const no = { noPrinters: 'Ingen skrivere funnet', agentNotFound: 'Zebra Browser Print-agenten kjører ikke. Last ned fra zebra.com.', success: 'ZPL sendt', + sentNoResponse: 'Sendt. Sjekk på skriveren.', errorRefused: 'Tilkobling nektet — sjekk IP og port', errorGeneric: 'Sending av ZPL mislyktes', httpsWarning: 'Siden bruker HTTPS — direkte utskrift via IP kan bli blokkert av nettleseren (blandet innhold).', diff --git a/src/locales/pl.ts b/src/locales/pl.ts index 770f8731..cad41431 100644 --- a/src/locales/pl.ts +++ b/src/locales/pl.ts @@ -423,6 +423,7 @@ const pl = { noPrinters: 'Nie znaleziono drukarek', agentNotFound: 'Agent Zebra Browser Print nie działa. Pobierz ze strony zebra.com.', success: 'ZPL wysłany pomyślnie', + sentNoResponse: 'Wysłano. Sprawdź na drukarce.', errorRefused: 'Odmowa połączenia — sprawdź IP i port', errorGeneric: 'Błąd wysyłania ZPL', httpsWarning: 'Strona używa HTTPS — bezpośrednie drukowanie przez IP może zostać zablokowane przez przeglądarkę (mieszana treść).', diff --git a/src/locales/pt.ts b/src/locales/pt.ts index 4d51a728..d272e54a 100644 --- a/src/locales/pt.ts +++ b/src/locales/pt.ts @@ -423,6 +423,7 @@ const pt = { noPrinters: 'Nenhuma impressora encontrada', agentNotFound: 'Agente Zebra Browser Print não está em execução. Baixe em zebra.com.', success: 'ZPL enviado com sucesso', + sentNoResponse: 'Enviado. Verifique na impressora.', errorRefused: 'Conexão recusada — verifique IP e porta', errorGeneric: 'Falha ao enviar ZPL', httpsWarning: 'A página está em HTTPS — a impressão direta por IP pode ser bloqueada pelo navegador (conteúdo misto).', diff --git a/src/locales/ro.ts b/src/locales/ro.ts index 93ffa9b8..4404a6e1 100644 --- a/src/locales/ro.ts +++ b/src/locales/ro.ts @@ -423,6 +423,7 @@ const ro = { noPrinters: 'Nu s-au găsit imprimante', agentNotFound: 'Agentul Zebra Browser Print nu rulează. Descărcați de pe zebra.com.', success: 'ZPL trimis cu succes', + sentNoResponse: 'Trimis. Verifică pe imprimantă.', errorRefused: 'Conexiune refuzată — verificați IP şi portul', errorGeneric: 'Trimiterea ZPL a eşuat', httpsWarning: 'Pagina este pe HTTPS — imprimarea directă prin IP poate fi blocată de browser (conținut mixt).', diff --git a/src/locales/sk.ts b/src/locales/sk.ts index a097910e..f39a2dbb 100644 --- a/src/locales/sk.ts +++ b/src/locales/sk.ts @@ -423,6 +423,7 @@ const sk = { noPrinters: 'Neboli nájdené žiadne tlačiarne', agentNotFound: 'Agent Zebra Browser Print nie je spustený. Stiahnite zo zebra.com.', success: 'ZPL úspšne odoslané', + sentNoResponse: 'Odoslané. Skontrolujte na tlačiarni.', errorRefused: 'Pripojenie odmietnuté — skontrolujte IP a port', errorGeneric: 'Odoslanie ZPL zlyhalo', httpsWarning: 'Stránka beží cez HTTPS — priama tlač cez IP môže byť prehliadačom zablokovaná (zmiešaný obsah).', diff --git a/src/locales/sl.ts b/src/locales/sl.ts index 1038be7e..fee60b09 100644 --- a/src/locales/sl.ts +++ b/src/locales/sl.ts @@ -423,6 +423,7 @@ const sl = { noPrinters: 'Ni najdenih tiskalnikov', agentNotFound: 'Agent Zebra Browser Print ne deluje. Prenesite s zebra.com.', success: 'ZPL uspešno poslan', + sentNoResponse: 'Poslano. Preverite na tiskalniku.', errorRefused: 'Povezava zavrnjena — preverite IP in vrata', errorGeneric: 'Pošiljanje ZPL ni uspelo', httpsWarning: 'Stran uporablja HTTPS — neposredno tiskanje prek IP-ja je morda blokirano s strani brskalnika (mešana vsebina).', diff --git a/src/locales/sr.ts b/src/locales/sr.ts index 1a0774e8..88078a15 100644 --- a/src/locales/sr.ts +++ b/src/locales/sr.ts @@ -423,6 +423,7 @@ const sr = { noPrinters: 'Nisu pronađeni štampači', agentNotFound: 'Agent Zebra Browser Print nije pokrenut. Preuzmite sa zebra.com.', success: 'ZPL uspešno poslat', + sentNoResponse: 'Poslato. Proverite na štampaču.', errorRefused: 'Veza odbijena — proverite IP i port', errorGeneric: 'Slanje ZPL-a nije uspelo', httpsWarning: 'Stranica koristi HTTPS — direktno štampanje putem IP može biti blokirano od strane pregledača (mešoviti sadržaj).', diff --git a/src/locales/sv.ts b/src/locales/sv.ts index db3cf45b..f88859ab 100644 --- a/src/locales/sv.ts +++ b/src/locales/sv.ts @@ -423,6 +423,7 @@ const sv = { noPrinters: 'Inga skrivare hittades', agentNotFound: 'Zebra Browser Print-agenten körs inte. Ladda ner från zebra.com.', success: 'ZPL skickades', + sentNoResponse: 'Skickat. Verifiera på skrivaren.', errorRefused: 'Anslutning nekad — kontrollera IP och port', errorGeneric: 'Det gick inte att skicka ZPL', httpsWarning: 'Sidan använder HTTPS — direktutskrift via IP kan blockeras av webbläsaren (blandat innehåll).', diff --git a/src/locales/tr.ts b/src/locales/tr.ts index b07ac490..b375eb63 100644 --- a/src/locales/tr.ts +++ b/src/locales/tr.ts @@ -423,6 +423,7 @@ const tr = { noPrinters: 'Yazıcı bulunamadı', agentNotFound: 'Zebra Browser Print aracısı çalışmıyor. zebra.com adresinden indirin.', success: 'ZPL başarıyla gönderildi', + sentNoResponse: 'Gönderildi. Yazıcıdan doğrulayın.', errorRefused: 'Bağlantı reddedildi — IP ve portu kontrol edin', errorGeneric: 'ZPL gönderilemedi', httpsWarning: 'Sayfa HTTPS üzerinde — doğrudan IP yazdırma tarayıcı tarafından engellenebilir (karma içerik).', diff --git a/src/locales/zh-hans.ts b/src/locales/zh-hans.ts index 781826f7..8ed5a2be 100644 --- a/src/locales/zh-hans.ts +++ b/src/locales/zh-hans.ts @@ -423,6 +423,7 @@ const zhHans = { noPrinters: '未找到打印机', agentNotFound: 'Zebra Browser Print 代理未运行。请从 zebra.com 下载。', success: 'ZPL 发送成功', + sentNoResponse: '已发送。请在打印机上确认。', errorRefused: '连接被拒绝 — 检查 IP 和端口', errorGeneric: '发送 ZPL 失败', httpsWarning: '页面在 HTTPS 上 — 浏览器可能阻止直接 IP 打印(混合内容)。', diff --git a/src/locales/zh-hant.ts b/src/locales/zh-hant.ts index 3d4ffe2d..ea7acfc3 100644 --- a/src/locales/zh-hant.ts +++ b/src/locales/zh-hant.ts @@ -423,6 +423,7 @@ const zhHant = { noPrinters: '未找到印表機', agentNotFound: 'Zebra Browser Print 代理程式未執行。請從 zebra.com 下載。', success: 'ZPL 傳送成功', + sentNoResponse: '已傳送。請在印表機上確認。', errorRefused: '連線遭拒 — 請確認 IP 和連接埠', errorGeneric: '傳送 ZPL 失敗', httpsWarning: '頁面在 HTTPS 上 — 瀏覽器可能封鎖直接 IP 列印(混合內容)。', diff --git a/src/test/zebraPrint.test.ts b/src/test/zebraPrint.test.ts index 47d24130..5e656af4 100644 --- a/src/test/zebraPrint.test.ts +++ b/src/test/zebraPrint.test.ts @@ -133,30 +133,45 @@ describe("sendViaNetwork", () => { expect(init.body).toBe("^XA^XZ"); }); - it("swallows a generic TypeError (printer gives no HTTP response)", async () => { + it("returns no_response on a generic TypeError (raw-socket printer's typical case)", async () => { vi.stubGlobal("fetch", mockFetchThrow(new TypeError("network error"))); - await expect(sendViaNetwork("192.168.1.50", 9100, "^XA^XZ")).resolves.toBeUndefined(); + await expect(sendViaNetwork("192.168.1.50", 9100, "^XA^XZ")).resolves.toEqual({ + kind: "no_response", + }); }); - it("swallows an AbortError (timeout — printer never responds)", async () => { + it("returns no_response on AbortError (timeout — host unreachable or printer silent)", async () => { const abort = new DOMException("signal timed out", "AbortError"); vi.stubGlobal("fetch", mockFetchThrow(abort)); - await expect(sendViaNetwork("192.168.1.50", 9100, "^XA^XZ")).resolves.toBeUndefined(); + await expect(sendViaNetwork("192.168.1.50", 9100, "^XA^XZ")).resolves.toEqual({ + kind: "no_response", + }); }); - it("re-throws TypeError with 'refused' in message", async () => { + it("returns refused on a TypeError with 'refused' in the message", async () => { vi.stubGlobal( "fetch", mockFetchThrow(new TypeError("Connection refused")), ); - await expect(sendViaNetwork("192.168.1.50", 9100, "^XA^XZ")).rejects.toThrow( - "Connection refused", - ); + await expect(sendViaNetwork("192.168.1.50", 9100, "^XA^XZ")).resolves.toEqual({ + kind: "refused", + }); }); - it("swallows a successful response (printer accepts data)", async () => { + it("returns responded with status when fetch resolves (e.g. print server)", async () => { vi.stubGlobal("fetch", mockFetch({})); - await expect(sendViaNetwork("192.168.1.50", 9100, "^XA^XZ")).resolves.toBeUndefined(); + await expect(sendViaNetwork("192.168.1.50", 9100, "^XA^XZ")).resolves.toEqual({ + kind: "responded", + status: 200, + }); + }); + + it("preserves a non-2xx status so the caller can flag it as an error", async () => { + vi.stubGlobal("fetch", mockFetch({}, false)); + await expect(sendViaNetwork("192.168.1.50", 9100, "^XA^XZ")).resolves.toEqual({ + kind: "responded", + status: 500, + }); }); });