fix: oprava parsování TechTower po změně jejich webu
CI / Generate TypeScript types (push) Successful in 11s
CI / Server unit tests (push) Successful in 30s
CI / Build server (push) Successful in 29s
CI / Build client (push) Successful in 41s
CI / Playwright E2E tests (push) Successful in 2m0s
CI / Build and push Docker image (push) Successful in 47s
CI / Notify (push) Successful in 2s

This commit is contained in:
mates committed 2026-10-09 14:37:09 +02:00
1 parent 7cda7cfdb6
commit 9fee4a1538
4 files changed
+370 -1

No files matched your search

+25 -1
View File
@@ -31,6 +31,11 @@ const SOUP_NAMES = [
'bramboračka',
'dýňový krém',
'ovarová',
'fazolačka',
'kyselica',
'rajčatová s ',
'hrášková s ',
'hrachová s ',
];
const DAYS_IN_WEEK = ['pondělí', 'úterý', 'středa', 'čtvrtek', 'pátek', 'sobota', 'neděle'];
@@ -334,6 +339,13 @@ export const getMenuTechTower = async (firstDayOfWeek: Date, mock: boolean = fal
if (!font) {
throw new Error('Chyba: nenalezen <font> pro obědy v HTML Techtower.');
}
// Šestý pokus - formát z 10/2026: hlavička je <p><strong><font class="wsw-41">,
// jednotlivé dny a položky jsou sourozenecké <p> v témže bloku. Třetí pokus sice najde
// hlavičku, ale <font> nemá žádné sourozenecké <p>, proto se použije parsing pátého pokusu.
if (thirdTry && $(font).parent().siblings('p').length === 0) {
thirdTry = false;
fifthTry = true;
}
const result: Food[][] = [];
@@ -371,7 +383,11 @@ export const getMenuTechTower = async (firstDayOfWeek: Date, mock: boolean = fal
if (fifthTry) {
let parsing = false;
let currentDayIndex = 0;
const container = $(font).parent().parent();
let container = $(font).parent().parent();
if (container.find('p').length === 0) {
// Formát 10/2026 - hlavička je přímo v <p>, kontejnerem je jeho rodič
container = $(font).closest('p').parent();
}
container.find('p').each((_, p) => {
const pHtml = $(p).html() ?? '';
const lines = pHtml.split(/<br\s*\/?>/i)
@@ -379,7 +395,15 @@ export const getMenuTechTower = async (firstDayOfWeek: Date, mock: boolean = fal
.filter(line => line.length > 0);
for (const text of lines) {
const lower = text.toLocaleLowerCase();
// Za aktuálním týdnem může následovat menu na další týden - to již nezpracováváme
if (parsing && lower.startsWith('následující týden')) {
return false;
}
if (DAYS_IN_WEEK.includes(lower)) {
if (result[DAYS_IN_WEEK.indexOf(lower)]) {
// Opakující se den = začátek dalšího týdne
return false;
}
currentDayIndex = DAYS_IN_WEEK.indexOf(lower);
parsing = true;
result[currentDayIndex] ??= [];
+305
View File
@@ -0,0 +1,305 @@
<!DOCTYPE html>
<html class="no-js" prefix="og: https://ogp.me/ns#" lang="cs">
<head><link rel="preconnect" href="https://duyn491kcolsw.cloudfront.net" crossorigin><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><meta charset="utf-8"><link rel="shortcut icon" href="https://duyn491kcolsw.cloudfront.net/files/1x/1xh/1xh0pi.ico?ph=59d3cce388"><link rel="apple-touch-icon" href="https://duyn491kcolsw.cloudfront.net/files/1x/1xh/1xh0pi.ico?ph=59d3cce388"><link rel="icon" href="https://duyn491kcolsw.cloudfront.net/files/1x/1xh/1xh0pi.ico?ph=59d3cce388">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Restaurace :: Equifarm</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="msapplication-tap-highlight" content="no">
<link href="https://duyn491kcolsw.cloudfront.net/files/0r/0rk/0rklmm.css?ph=59d3cce388" media="print" rel="stylesheet">
<link href="https://duyn491kcolsw.cloudfront.net/files/4f/4fk/4fkxao.css?ph=59d3cce388" media="screen and (min-width:100000em)" rel="stylesheet" data-type="cq" disabled>
<link rel="stylesheet" href="https://duyn491kcolsw.cloudfront.net/files/01/018/018gum.css?ph=59d3cce388"><link rel="stylesheet" href="https://duyn491kcolsw.cloudfront.net/files/0k/0k1/0k1ucs.css?ph=59d3cce388" media="screen and (min-width:37.5em)"><link rel="stylesheet" href="https://duyn491kcolsw.cloudfront.net/files/0o/0on/0onzbj.css?ph=59d3cce388" data-wnd_color_scheme_file=""><link rel="stylesheet" href="https://duyn491kcolsw.cloudfront.net/files/34/34q/34qmjb.css?ph=59d3cce388" data-wnd_color_scheme_desktop_file="" media="screen and (min-width:37.5em)" disabled=""><link rel="stylesheet" href="https://duyn491kcolsw.cloudfront.net/files/1j/1jo/1jorv9.css?ph=59d3cce388" data-wnd_additive_color_file=""><link rel="stylesheet" href="https://duyn491kcolsw.cloudfront.net/files/48/48g/48gira.css?ph=59d3cce388" data-wnd_typography_file=""><link rel="stylesheet" href="https://duyn491kcolsw.cloudfront.net/files/2b/2b9/2b9a9p.css?ph=59d3cce388" data-wnd_typography_desktop_file="" media="screen and (min-width:37.5em)" disabled=""><script>(()=>{let e=!1;const t=()=>{if(!e&&window.innerWidth>=600){for(let e=0,t=document.querySelectorAll('head > link[href*="css"][media="screen and (min-width:37.5em)"]');e<t.length;e++)t[e].removeAttribute("disabled");e=!0}};t(),window.addEventListener("resize",t),"container"in document.documentElement.style||fetch(document.querySelector('head > link[data-type="cq"]').getAttribute("href")).then((e=>{e.text().then((e=>{const t=document.createElement("style");document.head.appendChild(t),t.appendChild(document.createTextNode(e)),import("https://duyn491kcolsw.cloudfront.net/client/js.polyfill/container-query-polyfill.modern.js").then((()=>{let e=setInterval((function(){document.body&&(document.body.classList.add("cq-polyfill-loaded"),clearInterval(e))}),100)}))}))}))})()</script>
<link rel="preload stylesheet" href="https://duyn491kcolsw.cloudfront.net/files/2m/2m8/2m8msc.css?ph=59d3cce388" as="style"><meta name="description" content="Otevírací dobapo – pá 10.00 - 14.00obědy 10.00 - 13:45"><meta name="keywords" content=""><meta name="generator" content="Webnode 2"><meta name="apple-mobile-web-app-capable" content="no"><meta name="apple-mobile-web-app-status-bar-style" content="black"><meta name="format-detection" content="telephone=no">
<meta property="og:url" content="https://www.equifarm.cz/restaurace-techtower/"><meta property="og:title" content="Restaurace :: Equifarm"><meta property="og:type" content="article"><meta property="og:description" content="Otevírací dobapo – pá 10.00 - 14.00obědy 10.00 - 13:45"><meta property="og:site_name" content="Equifarm"><meta property="og:article:published_time" content="2026-10-05 00:00:00"><meta name="robots" content="index,follow"><link rel="canonical" href="https://www.equifarm.cz/restaurace-techtower/"><script>window.checkAndChangeSvgColor=function(c){try{var a=document.getElementById(c);if(a){c=[["border","borderColor"],["outline","outlineColor"],["color","color"]];for(var h,b,d,f=[],e=0,m=c.length;e<m;e++)if(h=window.getComputedStyle(a)[c[e][1]].replace(/\s/g,"").match(/^rgb[a]?\(([0-9]{1,3}),([0-9]{1,3}),([0-9]{1,3})/i)){b="";for(var g=1;3>=g;g++)b+=("0"+parseInt(h[g],10).toString(16)).slice(-2);"0"===b.charAt(0)&&(d=parseInt(b.substr(0,2),16),d=Math.max(16,d),b=d.toString(16)+b.slice(-4));f.push(c[e][0]+"="+b)}if(f.length){var k=a.getAttribute("data-src"),l=k+(0>k.indexOf("?")?"?":"&")+f.join("&");a.src!=l&&(a.src=l,a.outerHTML=a.outerHTML)}}}catch(n){}};</script></head>
<body class="l wt-page ac-i l-default l-d-none b-btn-sq b-btn-s-l b-btn-dn b-btn-bw-1 img-d-n img-t-o img-h-z line-solid b-e-ds lbox-d c-s-s wnd-fe"><noscript>
<iframe
src="https://www.googletagmanager.com/ns.html?id=GTM-542MMSL"
height="0"
width="0"
style="display:none;visibility:hidden"
>
</iframe>
</noscript>
<div class="wnd-page l-page cs-gray ac-none t-t-fs-l t-t-fw-l t-t-sp-n t-t-d-n t-s-fs-m t-s-fw-l t-s-sp-n t-s-d-n t-p-fs-s t-p-fw-m t-p-sp-n t-h-fs-m t-h-fw-l t-h-sp-n t-bq-fs-s t-bq-fw-l t-bq-sp-n t-bq-d-q t-btn-fw-l t-nav-fw-l t-pd-fw-s t-nav-tt-u">
<div class="l-w t cf t-30">
<div class="l-bg cf">
<div class="s-bg-l">
</div>
</div>
<header class="l-h cf">
<div class="sw cf">
<div class="sw-c cf"><section data-space="true" class="s s-hn s-hn-default wnd-mt-classic wnd-na-c logo-classic sc-ml wnd-background-pattern wnd-w-wider wnd-nh-m hm-hidden wnd-nav-border menu-default-underline">
<div class="s-w">
<div class="s-o">
<div class="s-bg">
<div class="s-bg-l wnd-background-pattern bgpos-center-center bgatt-scroll" style="background-image:url('https://duyn491kcolsw.cloudfront.net/files/17/17i/17ib2g.png?ph=59d3cce388')">
</div>
</div>
<div class="h-w h-f wnd-fixed">
<div class="n-l">
<div class="s-c menu-nav">
<div class="logo-block">
<div class="b b-l logo logo-default logo-nb proxima-nova logo-32 wnd-logo-with-text wnd-iar-1-1 b-ls-l" id="wnd_LogoBlock_193721444" data-wnd_mvc_type="wnd.fe.LogoBlock">
<div class="b-l-c logo-content">
<a class="b-l-link logo-link" href="/">
<div class="b-l-image logo-image">
<div class="b-l-image-w logo-image-cell">
<picture><source type="image/webp" srcset="https://59d3cce388.clvaw-cdnwnd.com/bd8e4bd40b5bb1412d0aee3843c4e306/200000384-5e4ab5e4ae/450/EQF_Logo%20%28orig.%29.webp?ph=59d3cce388 366w, https://59d3cce388.clvaw-cdnwnd.com/bd8e4bd40b5bb1412d0aee3843c4e306/200000384-5e4ab5e4ae/700/EQF_Logo%20%28orig.%29.webp?ph=59d3cce388 366w, https://59d3cce388.clvaw-cdnwnd.com/bd8e4bd40b5bb1412d0aee3843c4e306/200000384-5e4ab5e4ae/EQF_Logo%20%28orig.%29.webp?ph=59d3cce388 366w" sizes="(min-width: 600px) 450px, (min-width: 360px) calc(100vw * 0.8), 100vw" ><img src="https://59d3cce388.clvaw-cdnwnd.com/bd8e4bd40b5bb1412d0aee3843c4e306/200000003-2ad852ad86/EQF_Logo%20%28orig.%29.png?ph=59d3cce388" alt="" width="366" height="356" class="wnd-logo-img" ></picture>
</div>
</div>
<div class="b-l-br logo-br"></div>
<div class="b-l-text logo-text-wrapper">
<div class="b-l-text-w logo-text">
<span class="b-l-text-c logo-text-cell">Equifarm, s.r.o.</span>
</div>
</div>
</a>
</div>
</div>
</div>
<div id="menu-slider">
<div id="menu-block">
<nav id="menu"><div class="menu-font menu-wrapper">
<a href="#" class="menu-close" rel="nofollow" title="Close Menu"></a>
<ul role="menubar" aria-label="Menu" class="level-1">
<li role="none" class="wnd-homepage">
<a class="menu-item" role="menuitem" href="/"><span class="menu-item-text">Úvod</span></a>
</li><li role="none" class="wnd-with-submenu">
<a class="menu-item" role="menuitem" href="/firemni-stravovani/"><span class="menu-item-text">Firemní stravování</span></a>
<ul role="menubar" aria-label="Menu" class="level-2">
<li role="none">
<a class="menu-item" role="menuitem" href="/specialiste-na-japonskou-kuchyni/"><span class="menu-item-text">Specialisté na japonskou kuchyni</span></a>
</li><li role="none">
<a class="menu-item" role="menuitem" href="/vlastni-cukrarska-vyroba/"><span class="menu-item-text">Vlastní cukrářská výroba</span></a>
</li><li role="none">
<a class="menu-item" role="menuitem" href="/reference/"><span class="menu-item-text">Reference</span></a>
</li><li role="none">
<a class="menu-item" role="menuitem" href="/kontakty2/"><span class="menu-item-text">Kontakty </span></a>
</li>
</ul>
</li><li role="none">
<a class="menu-item" role="menuitem" href="/catering-a-eventy/"><span class="menu-item-text">Catering</span></a>
</li><li role="none" class="wnd-with-submenu">
<a class="menu-item" role="menuitem" href="/rekreacni-areal2/"><span class="menu-item-text">Rekreační areál</span></a>
<ul role="menubar" aria-label="Menu" class="level-2">
<li role="none">
<a class="menu-item" role="menuitem" href="/areal/"><span class="menu-item-text">Areál</span></a>
</li><li role="none">
<a class="menu-item" role="menuitem" href="/kontakty/"><span class="menu-item-text">Kontakty</span></a>
</li><li role="none">
<a class="menu-item" role="menuitem" href="/cenik/"><span class="menu-item-text">Ceník</span></a>
</li><li role="none">
<a class="menu-item" role="menuitem" href="/kalendar/"><span class="menu-item-text">Kalendář</span></a>
</li><li role="none">
<a class="menu-item" role="menuitem" href="/fotogalerie/"><span class="menu-item-text">Fotogalerie</span></a>
</li><li role="none">
<a class="menu-item" role="menuitem" href="/vylety-do-okoli/"><span class="menu-item-text">Výlety do okolí</span></a>
</li>
</ul>
</li><li role="none" class="wnd-active-path wnd-with-submenu">
<a class="menu-item" role="menuitem" href="/techtower/"><span class="menu-item-text">TechTower</span></a>
<ul role="menubar" aria-label="Menu" class="level-2">
<li role="none">
<a class="menu-item" role="menuitem" href="/kavarna-techtower/"><span class="menu-item-text">SeedUp Space</span></a>
</li><li role="none" class="wnd-active wnd-active-path">
<a class="menu-item" role="menuitem" href="/restaurace-techtower/"><span class="menu-item-text">Restaurace </span></a>
</li><li role="none">
<a class="menu-item" role="menuitem" href="/coffee-breaks/"><span class="menu-item-text">Coffee breaks</span></a>
</li>
</ul>
</li><li role="none">
<a class="menu-item" role="menuitem" href="/kontakt/"><span class="menu-item-text">Kontakt</span></a>
</li>
</ul>
<span class="more-text">Více</span>
</div></nav>
</div>
</div>
<div class="cart-and-mobile">
<div id="menu-mobile">
<a href="#" id="menu-submit"><span></span>Menu</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section></div>
</div>
</header>
<main class="l-m cf">
<div class="sw cf">
<div class="sw-c cf"><section class="s s-hm s-hm-hidden wnd-h-hidden cf sc-w hn-default"><div></div></section><section class="s s-basic cf sc-w wnd-w-default wnd-s-normal wnd-h-auto">
<div class="s-w cf">
<div class="s-o s-fs cf">
<div class="s-bg cf">
<div class="s-bg-l">
</div>
</div>
<div class="s-c s-fs cf">
<div class="ez cf wnd-no-cols">
<div class="ez-c"><div class="b b-text cf">
<div class="b-c b-text-c b-s b-s-t60 b-s-b60 b-cs cf"><h1 class="wnd-align-center"><strong><font class="wsw-31">Restaurace&nbsp;</font></strong></h1>
</div>
</div><div class="b b-text cf">
<div class="b-c b-text-c b-s b-s-t60 b-s-b60 b-cs cf"></div>
</div><div class="b b-s b-hr-line line-auto">
<hr class="line-style line-color">
</div><div class="b b-text cf">
<div class="b-c b-text-c b-s b-s-t60 b-s-b60 b-cs cf"><h3 class="wnd-align-center"><font class="wsw-02"><p class=""><strong>Otevírací doba</strong><br></p><p class="">po – pá 10.00 - 14.00</p></font><p class=""><font class="wsw-41">obědy 10.00 - 13:45</font></p></h3></div>
</div><div class="b b-text cf">
<div class="b-c b-text-c b-s b-s-t60 b-s-b60 b-cs cf"><p class="wnd-align-center"><strong><font class="wsw-41 wnd-font-size-110">Jídelní lístek 5. 10.– 9. 10.</font></strong></p><p class="wnd-align-center"><strong>Pondělí</strong></p><p class="wnd-align-center">Mexická fazolačka s kukuřicí a masem 1 — 45 Kč</p><p class="wnd-align-center">Špagety s kuřecím masem ve smetanové omáčce, pórek, sýr 1,7 — 140 Kč</p><p class="wnd-align-center">Wrap se zeleninou a grilovaným halloumi sýrem 1,7</p><p class="wnd-align-center">Vepřové medailonky na zeleném pepři, fazolky se slaninou, šťouchané brambory 1,7</p><p class="wnd-align-center">Kuřecí paličky se sladkokyselou omáčkou, jasmínová rýže, barevný sezam</p><p class="wnd-align-center"><strong>Úterý</strong></p><p class="wnd-align-center">Rajčatová s cizrnou a bazalkou 1 — 45 Kč</p><p class="wnd-align-center">Maďarský hovězí guláš, houskový knedlík 1,3,7 — 140 Kč</p><p class="wnd-align-center">Tagliatelle s dýňovou omáčkou a semínky, trhaná burrata 1,7</p><p class="wnd-align-center">Dušená šunka od kosti s čerstvým křenem s jablky, hrubozrnná hořčice, podmáslový chléb 1,10</p><p class="wnd-align-center">Cordon bleu, hranolky, pikantní dip 1,3,7</p><p class="wnd-align-center"><strong>Středa</strong></p><p class="wnd-align-center">Uzený vývar s rýží a zeleninou 9 — 45 Kč</p><p class="wnd-align-center">Rozlítaný vepřový ptáček, rýže 1,3 — 140 Kč</p><p class="wnd-align-center">Halušky s pečeným ajvarem a feta sýrem, bylinkový olej 1,7</p><p class="wnd-align-center">Krůtí medailonky s grilovanou zeleninou, silná omáčka 1</p><p class="wnd-align-center">Smažený karbanátek, bramborové pyré, řepový salát s jablky 1,3,7</p><p class="wnd-align-center"><strong>Čtvrtek</strong></p><p class="wnd-align-center">Valašská kyselica s klobásou 1,7 — 45 Kč</p><p class="wnd-align-center">Rizoto z vepřového masa se zeleninou, sypané sýrem Gouda 1,7 — 140 Kč</p><p class="wnd-align-center">Žemlovka s jablky a tvarohem, cukr, máslo 1,3,7</p><p class="wnd-align-center">Zapečené bramborové plátky s kuřecím masem a smetanovo-máslovou omáčkou, mozzarella 1,3,7</p><p class="wnd-align-center">Hovězí roštěná na česneku s jasmínovou rýží 1</p><p class="wnd-align-center"><strong>Pátek</strong></p><p class="wnd-align-center">Hovězí vývar se zeleninou a masem, vaječné kapání 1,3,7,9 — 45 Kč</p><p class="wnd-align-center">Zapečené těstoviny s uzeným masem, okurka 1,3,7 — 140 Kč</p><p class="wnd-align-center">Houbový kuba, naše čalamáda 1</p><p class="wnd-align-center">Pečené kachní stehýnko s dušeným zelím, bramborové knedlíky s bylinkami a špekem 1,3,7</p><p class="wnd-align-center">Smažený sýr se šunkou v bulce, hranolky, tatarská omáčka 1,3,7</p><p class="wnd-align-center"><br></p><p class="wnd-align-center"><strong><font class="wsw-41 wnd-font-size-110">Následující týden</font></strong></p><p class="wnd-align-center"><strong>Pondělí</strong></p><p class="wnd-align-center">Hrášková s krutonem 1,7 — 45 Kč</p><p class="wnd-align-center">Čevabčiči, brambory, cibule, hořčice 1,3,7 — 140 Kč</p><p class="wnd-align-center">Sýrová pizza, čerstvá bazalka 1,7</p><p class="wnd-align-center">Vepřová panenka s žampionovou omáčkou, jasmínová rýže 1,7</p><p class="wnd-align-center">Pečený kuřecí gyros, hranolky, tzatziki 7</p><p class="wnd-align-center"><strong>Úterý</strong></p><p class="wnd-align-center">Telecí vývar se zeleninou a játrovými knedlíčky 1,3,7,9 — 45 Kč</p><p class="wnd-align-center">Francouzské brambory, okurka 1,3,7 — 140 Kč</p><p class="wnd-align-center">Halušky s brynzou a řepou, smažená cibulka 1,7</p><p class="wnd-align-center">Quesadilla s kuřecím masem a jalapeňos, červené fazole, salát coleslaw 1,3</p><p class="wnd-align-center">Pečená selečí roláda, baby mrkev na másle, bramborový knedlík 1,3,7</p><p class="wnd-align-center"><strong>Středa</strong></p><p class="wnd-align-center">Krémová slepičí polévka se zeleninou 1,3,7,9 — 45 Kč</p><p class="wnd-align-center">Játra po anglicku, opečené brambory 1 — 140 Kč</p><p class="wnd-align-center">Těstoviny Alfredo, pažitka 1,3,7</p><p class="wnd-align-center">Hovězí roštěná po cikánsku, jasmínová rýže 1,7</p><p class="wnd-align-center">Smažený sekaný řízek s cheddarem, bramborové pyré 1,3,7</p><p class="wnd-align-center"><strong>Čtvrtek</strong></p><p class="wnd-align-center">Hrachová s klobásou 1,7 — 45 Kč</p><p class="wnd-align-center">Houbová omáčka, hovězí maso, houskový knedlík 1,3,7 — 140 Kč</p><p class="wnd-align-center">Tvarohové knedlíky s ovocem, cukr, máslo, tvaroh 1,3,7</p><p class="wnd-align-center">Vepřové plátky na japonský způsob, jasmínová rýže, barevný sezam 1,6,11</p><p class="wnd-align-center">Steak z tuňákLine truncated
</div><div class="b b-text cf">
<div class="b-c b-text-c b-s b-s-t60 b-s-b60 b-cs cf"><p id="wnd_TextBlock_76217_inner_1" data-wnd_is_separable="1" data-wnd_separable_index="1" data-wnd_separable_id="wnd_TextBlock_76217"></p></div>
</div><div class="b b-text cf">
<div class="b-c b-text-c b-s b-s-t60 b-s-b60 b-cs cf"><p class="wnd-align-center"><a href="https://www.equifarm.cz" target="_blank">www.equifarm.cz</a></p><p class="wnd-align-center"><font class="wsw-31">techtower@equifarm.cz</font></p><p class="wnd-align-center">+420 608 180 311</p></div>
</div></div>
</div>
</div>
</div>
</div>
</section></div>
</div>
</main>
<footer class="l-f cf">
<div class="sw cf">
<div class="sw-c cf"><section data-wn-border-element="s-f-border" class="s s-f s-f-basic s-f-simple sc-w wnd-w-default wnd-s-higher">
<div class="s-w">
<div class="s-o">
<div class="s-bg">
<div class="s-bg-l">
</div>
</div>
<div class="s-c s-f-l-w s-f-border">
<div class="s-f-l b-s b-s-t0 b-s-b0">
<div class="s-f-l-c s-f-l-c-first">
<div class="s-f-cr"><span class="it b link">
<span class="it-c">© 2022 Equifarm, s.r.o. Všechna práva vyhrazena.</span>
</span></div>
<div class="s-f-sf">
<span class="sf b">
<span class="sf-content sf-c link">Vytvořeno službou <a href="https://www.webnode.cz?utm_source=text&utm_medium=footer&utm_campaign=free3&utm_content=wnd2" rel="nofollow noopener" target="_blank">Webnode</a></span>
</span>
<span class="sf-cbr link">
<a href="#" rel="nofollow">Cookies</a>
</span>
</div>
</div>
<div class="s-f-l-c s-f-l-c-last">
<div class="s-f-lang lang-select cf">
</div>
</div>
<div class="s-f-l-c s-f-l-c-currency">
<div class="s-f-ccy ccy-select cf">
</div>
</div>
</div>
</div>
</div>
</div>
</section></div>
</div>
</footer>
</div>
</div>
<section class="cb cb-dark" id="cookiebar" style="display:none;" id="cookiebar" style="display:none;">
<div class="cb-bar cb-scrollable">
<div class="cb-bar-c">
<div class="cb-bar-text">Používáme cookies, abychom zajistili správné fungování a bezpečnost našich stránek. Tím vám můžeme zajistit tu nejlepší zkušenost při jejich návštěvě.</div>
<div class="cb-bar-buttons">
<button class="cb-button cb-close-basic" data-action="accept-necessary">
<span class="cb-button-content">Přijmout nezbytné</span>
</button>
<button class="cb-button cb-close-basic" data-action="accept-all">
<span class="cb-button-content">Přijmout vše</span>
</button>
</div>
</div>
<div class="cb-close cb-close-basic" data-action="accept-necessary"></div>
</div>
<div class="cb-popup cb-light close">
<div class="cb-popup-c">
<div class="cb-popup-head">
<h3 class="cb-popup-title">Pokročilá nastavení</h3>
<p class="cb-popup-text">Zde můžete upravit své preference ohledně cookies. Následující kategorie můžete povolit či zakázat a svůj výběr uložit.</p>
</div>
<div class="cb-popup-options cb-scrollable">
<div class="cb-option">
<input class="cb-option-input" type="checkbox" id="necessary" name="necessary" readonly="readonly" disabled="disabled" checked="checked">
<div class="cb-option-checkbox"></div>
<label class="cb-option-label" for="necessary">Nezbytné krátkodobé cookies</label>
<div class="cb-option-text"></div>
</div>
</div>
<div class="cb-popup-footer">
<button class="cb-button cb-save-popup" data-action="advanced-save">
<span class="cb-button-content">Uložit</span>
</button>
</div>
<div class="cb-close cb-close-popup" data-action="close"></div>
</div>
</div>
</section>
<script src="https://duyn491kcolsw.cloudfront.net/files/35/35w/35wjn2.js?ph=59d3cce388" crossorigin="anonymous" type="module"></script><script>document.querySelector(".wnd-fe")&&[...document.querySelectorAll(".c")].forEach((e=>{const t=e.querySelector(".b-text:only-child");t&&""===t.querySelector(".b-text-c").innerText&&e.classList.add("column-empty")}))</script>
<script src="https://duyn491kcolsw.cloudfront.net/client.fe/js.compiled/lang.cz.a9c1a985e49aad81.js?ph=59d3cce388" crossorigin="anonymous"></script><script src="https://duyn491kcolsw.cloudfront.net/client.fe/js.compiled/compiled.multi.64ecbadac2103be4.js?ph=59d3cce388" crossorigin="anonymous"></script><script>var wnd = wnd || {};wnd.$data = {"image_content_items":{"wnd_ThumbnailBlock_1":{"id":"wnd_ThumbnailBlock_1","type":"wnd.pc.ThumbnailBlock"},"wnd_HeaderSection_header_main_412360230":{"id":"wnd_HeaderSection_header_main_412360230","type":"wnd.pc.HeaderSection"},"wnd_ImageBlock_793396992":{"id":"wnd_ImageBlock_793396992","type":"wnd.pc.ImageBlock"},"wnd_Section_default_762442558":{"id":"wnd_Section_default_762442558","type":"wnd.pc.Section"},"wnd_LogoBlock_193721444":{"id":"wnd_LogoBlock_193721444","type":"wnd.pc.LogoBlock"},"wnd_FooterSection_footer_306617015":{"id":"wnd_FooterSection_footer_306617015","type":"wnd.pc.FooterSection"}},"svg_content_items":{"wnd_ImageBlock_793396992":{"id":"wnd_ImageBlock_793396992","type":"wnd.pc.ImageBlock"},"wnd_LogoBlock_193721444":{"id":"wnd_LogoBlock_193721444","type":"wnd.pc.LogoBlock"}},"content_items":[],"eshopSettings":{"ESHOP_SETTINGS_DISPLAY_PRICE_WITHOUT_VAT":false,"ESHOP_SETTINGS_DISPLAY_ADDITIONAL_VAT":false,"ESHOP_SETTINGS_DISPLAY_SHIPPING_COST":false},"project_info":{"isMultilanguage":false,"isMulticurrency":false,"eshop_tax_enabled":"1","country_code":"","contact_state":null,"eshop_tax_type":"VAT","eshop_discounts":false,"graphQLURL":"https:\/\/equifarm.cz\/servers\/graphql\/","iubendaSettings":{"cookieBarCode":"","cookiePolicyCode":"","privacyPolicyCode":"","termsAndConditionsCode":""}}};</script><script>wnd.$system = {"fileSystemType":"aws_s3","localFilesPath":"https:\/\/www.equifarm.cz\/_files\/","awsS3FilesPath":"https:\/\/59d3cce388.clvaw-cdnwnd.com\/bd8e4bd40b5bb1412d0aee3843c4e306\/","staticFiles":"https:\/\/duyn491kcolsw.cloudfront.net\/files","isCms":false,"staticCDNServers":["https:\/\/duyn491kcolsw.cloudfront.net\/"],"fileUploadAllowExtension":["jpg","jpeg","jfif","png","gif","bmp","ico","svg","webp","tiff","pdf","doc","docx","ppt","pptx","pps","ppsx","odt","xls","xlsx","txt","rtf","mp3","wma","wav","ogg","amr","flac","m4a","3gp","avi","wmv","mov","mpg","mkv","mp4","mpeg","m4v","swf","gpx","stl","csv","xml","txt","dxf","dwg","iges","igs","step","stp"],"maxUserFormFileLimit":4194304,"frontendLanguage":"cz","backendLanguage":"cz","frontendLanguageId":"1","page":{"id":200005119,"identifier":"restaurace-techtower","template":{"id":200000048,"styles":{"typography":"t-30_new","scheme":"cs-gray","additiveColor":"ac-none","acHeadings":false,"acSubheadings":false,"acIcons":true,"acOthers":false,"acMenu":false,"imageStyle":"img-d-n","imageHover":"img-h-z","imageTitle":"img-t-o","buttonStyle":"b-btn-sq","buttonSize":"b-btn-s-l","buttonDecoration":"b-btn-dn","buttonBorders":"b-btn-bw-1","lineStyle":"line-solid","eshopGridItemStyle":"b-e-ds","formStyle":"default","menuType":"","menuStyle":"menu-default-underline","lightboxStyle":"lbox-d","columnSpaces":"c-s-s","sectionWidth":"wnd-w-default","sectionSpace":"wnd-s-normal","layoutType":"l-default","layoutDecoration":"l-d-none","background":{"default":null},"backgroundSettings":{"default":""},"typoTitleSizes":"t-t-fs-l","typoTitleWeights":"t-t-fw-l","typoTitleSpacings":"t-t-sp-n","typoTitleDecorations":"t-t-d-n","typoHeadingSizes":"t-h-fs-m","typoHeadingWeights":"t-h-fw-l","typoHeadingSpacings":"t-h-sp-n","typoSubtitleSizes":"t-s-fs-m","typoSubtitleWeights":"t-s-fw-l","typoSubtitleSpacings":"t-s-sp-n","typoSubtitleDecorations":"t-s-d-n","typoParagraphSizes":"t-p-fs-s","typoParagraphWeights":"t-p-fw-m","typoParagraphSpacings":"t-p-sp-n","typoBlockquoteSizes":"t-bq-fs-s","typoBlockquoteWeights":"t-bq-fw-l","typoBlockquoteSpacings":"t-bq-sp-n","typoBlockquoteDecorations":"t-bq-d-q","buttonWeight":"t-btn-fw-l","menuWeight":"t-nav-fw-l","productWeight":"t-pd-fw-s","menuTextTransform":"t-nav-tt-u"}},"layout":"default","name":"Restaurace ","html_title":"","language":"cz","langId":1,"isHomepage":false,"meta_description":"","meta_keywords":"","header_code":"","footer_code":"","styles":{"pageBased":{"navline":{"style":{"sectionWidth":"wnd-w-wider","sectionHeight":"wnd-nh-m","sectionPosition":"wnd-na-c"}}}},"countFormsEntries":[]},"listingsPrefix":"\/l\/","productPrefix":"\/p\/","cartPrefix":"\/cart\/","checkoutPrefix":"\/checkout\/","searchPrefix":"\/search\/","isCheckout":false,"isEshop":false,"hasBlog":false,"isProductDetail":false,"isListingDetail":false,"listing_page":[],"hasEshopAnalytics":false,"gTagId":null,"gAdsId":null,"format":{"be":{"DATE_TIME":{"mask":"%d.%m.%Y %H:%M","regexp":"^(((0?[1-9]|[1,2][0-9]|3[0,1])\\.(0?[1-9]|1[0-2])\\.[0-9]{1,4})(( [0-1][0-9]| 2[0-3]):[0-5][0-9])?|(([0-9]{4}(0[1-9]|1[0-2])(0[1-9]|[1,2][0-9]|3[0,1])(0[0-9]|1[0-9]|2[0-3])[0-5][0-9][0-5][0-9])))?$"},"DATE":{"mask":"%d.%m.%Y","regexp":"^((0?[1-9]|[1,2][0-9]|3[0,1])\\.(0?[1-9]|1[0-2])\\.[0-9]{1,4})$"},"CURRENCY":{"mask":{"point":",","tLine truncated
events: {"error":{"name":"Error"},"publish":{"name":"Publish page"},"open_premium_popup":{"name":"Open premium popup"},"publish_from_premium_popup":{"name":"Publish from premium content popup"},"upgrade_your_plan":{"name":"Upgrade your plan"},"ml_lock_page":{"name":"Lock access to page"},"ml_unlock_page":{"name":"Unlock access to page"},"ml_start_add_page_member_area":{"name":"Start - add page Member Area"},"ml_end_add_page_member_area":{"name":"End - add page Member Area"},"ml_show_activation_popup":{"name":"Show activation popup"},"ml_activation":{"name":"Member Login Activation"},"ml_deactivation":{"name":"Member Login Deactivation"},"ml_enable_require_approval":{"name":"Enable approve registration manually"},"ml_disable_require_approval":{"name":"Disable approve registration manually"},"ml_fe_member_registration":{"name":"Member Registration on FE"},"ml_fe_member_login":{"name":"Login Member"},"ml_fe_member_recovery":{"name":"Sent recovery email"},"ml_fe_member_change_password":{"name":"Change Password"},"undoredo_click_undo":{"name":"Undo\/Redo - click Undo"},"undoredo_click_redo":{"name":"Undo\/Redo - click Redo"},"add_anchor":{"name":"Anchor adding completed"},"add_page":{"name":"Page adding completed"},"change_page_order":{"name":"Change of page order"},"delete_page":{"name":"Page deleted"},"background_options_change":{"name":"Background setting completed"},"add_content":{"name":"Content adding completed"},"delete_content":{"name":"Content deleting completed"},"change_text":{"name":"Editing of text completed"},"add_image":{"name":"Image adding completed"},"add_photo":{"name":"Adding photo to galery completed"},"change_logo":{"name":"Logo changing completed"},"open_pages":{"name":"Open Pages"},"show_page_cms":{"name":"Show Page - CMS"},"new_section":{"name":"New section completed"},"delete_section":{"name":"Section deleting completed"},"add_video":{"name":"Video adding completed"},"add_maps":{"name":"Maps adding completed"},"add_button":{"name":"Button adding completed"},"add_file":{"name":"File adding completed"},"add_hr":{"name":"Horizontal line adding completed"},"delete_cell":{"name":"Cell deleting completed"},"delete_microtemplate":{"name":"Microtemplate deleting completed"},"add_blog_page":{"name":"Blog page adding completed"},"new_blog_post":{"name":"New blog post created"},"new_blog_recent_posts":{"name":"Blog recent posts list created"},"e_show_products_popup":{"name":"Show products popup"},"e_show_add_product":{"name":"Show add product popup"},"e_show_edit_product":{"name":"Show edit product popup"},"e_show_collections_popup":{"name":"Show collections manager popup"},"e_show_eshop_settings":{"name":"Show eshop settings popup"},"e_add_product":{"name":"Add product"},"e_edit_product":{"name":"Edit product"},"e_remove_product":{"name":"Remove product"},"e_bulk_show":{"name":"Bulk show products"},"e_bulk_hide":{"name":"Bulk hide products"},"e_bulk_remove":{"name":"Bulk remove products"},"e_move_product":{"name":"Order products"},"e_add_collection":{"name":"Add collection"},"e_rename_collection":{"name":"Rename collection"},"e_remove_collection":{"name":"Remove collection"},"e_add_product_to_collection":{"name":"Assign product to collection"},"e_remove_product_from_collection":{"name":"Unassign product from collection"},"e_move_collection":{"name":"Order collections"},"e_add_products_page":{"name":"Add products page"},"e_add_procucts_section":{"name":"Add products list section"},"e_add_products_content":{"name":"Add products list content block"},"e_change_products_zone_style":{"name":"Change style in products list"},"e_change_products_zone_collection":{"name":"Change collection in products list"},"e_show_products_zone_collection_filter":{"name":"Show collection filter in products list"},"e_hide_products_zone_collection_filter":{"name":"Hide collection filter in products list"},"e_show_product_detail_page":{"name":"Show product detail page"},"e_add_to_cart":{"name":"Add product to cart"},"e_remove_from_cart":{"name":"Remove product from cart"},"e_checkout_step":{"name":"From cart to checkout"},"e_finish_checkout":{"name":"Finish order"},"welcome_window_play_video":{"name":"Welcome window - play video"},"e_import_file":{"name":"Eshop - products import - file info"},"e_import_upload_time":{"name":"Eshop - products import - upload file duration"},"e_import_result":{"name":"Eshop - products import result"},"e_import_error":{"name":"Eshop - products import - errors"},"e_promo_blogpost":{"name":"Eshop promo - blogpost"},"e_promo_activate":{"name":"Eshop promo - activate"},"e_settings_activate":{"name":"Online store - activate"},"e_promo_hide":{"name":"Eshop promo - close"},"e_activation_popup_step":{"name":"Eshop activation popup - step"},"e_activation_popup_activate":{"name":"Eshop activation popup - activate"},"e_activation_popup_hide":{"name":"Eshop activation popup - close"},"e_deactivation":{"name":"Eshop deactivation"},"e_reactivation":{"name":"Eshop reactivation"},"e_variant_create_first":Line truncated
data: {"user":{"u":0,"p":44019905,"lc":"CZ","t":"1"},"action":{"identifier":"","name":"","category":"project","platform":"WND2"},"browser":{"url":"https:\/\/www.equifarm.cz\/restaurace-techtower","ua":"axios\/1.20.0","referer_url":"","resolution":"","ip":"90.181.238.210"}},
urlPrefix: "https://events.webnode.com/projects/-/events/",
collection: "PROD",
}</script></body>
</html>
+37
View File
@@ -129,6 +129,43 @@ describe('TechTower parser – nový formát 07/2026', () => {
});
});
describe('TechTower parser – nový formát 10/2026', () => {
// Pondělí 5.10.2026, stránka obsahuje i menu na následující týden
const MONDAY_2026_10 = new Date('2026-10-05');
beforeEach(() => {
mockedAxios.get = jest.fn().mockResolvedValue({ data: loadFixture('techtower-2026-10.html') });
});
test('vrátí pole o délce 5 s jídly pro každý den', async () => {
const menu = await getMenuTechTower(MONDAY_2026_10);
expect(menu).toHaveLength(5);
for (const den of menu) {
expect(den).toHaveLength(5);
}
});
test('nezahrne menu následujícího týdne', async () => {
const menu = await getMenuTechTower(MONDAY_2026_10);
expect(menu[0][0].name).toBe('Mexická fazolačka s kukuřicí a masem');
expect(menu.flat().some(f => f.name.startsWith('Hrášková'))).toBe(false);
});
test('každý den začíná polévkou s cenou a alergeny', async () => {
const menu = await getMenuTechTower(MONDAY_2026_10);
for (const den of menu) {
expect(den[0].isSoup).toBe(true);
expect(den[0].price).toBe('45\xA0Kč');
expect(den[0].allergens?.length).toBeGreaterThan(0);
expect(den.slice(1).some(f => f.isSoup)).toBe(false);
}
});
test('hodí StaleWeekError pro jiný týden', async () => {
await expect(getMenuTechTower(new Date('2026-10-12'))).rejects.toBeInstanceOf(StaleWeekError);
});
});
describe('SenkSerikova parser', () => {
beforeEach(() => {
// SenkSerikova parsuje arraybuffer – musíme vrátit Buffer, ne string