Saturday, April 19, 2025
Home Blog Page 1350

Why Home of the Dragon Modified One of many Most Ugly Moments From the Guide

0

Final evening’s second season premiere of Sport of Thrones’ spinoff Home of the Dragon tackled one in every of George R.R. Martin’s most notorious deaths—in a brand new means that shocked the fandom.

Image for article titled Why House of the Dragon Changed One of the Most Gruesome Moments From the Book

In an interview with Selection, showrunner Ryan Condal defined the reasoning for the Max present’s departure from Martin’s authentic recollection of an occasion identified by readers of Hearth and Blood—the creator’s historic rationalization of Targaryen historical past in Westeros— as “Blood and Cheese,” named for 2 assassins who’re chargeable for the homicide of Jaehaerys Targayren. In “A Son for a Son” Blood and Cheese take middle stage, employed by Daemon (Matt Smith) to retaliate for the dying of Rhaenyra’s (Emma D’Arcy) son Lucerys on the finish of final season. We choose up on the duo’s journey to do the dastardly deed which, within the present, is far more instantly orchestrated than in Hearth & Blood, having Rhaenyra name for Aemond’s (Ewan Mitchell) dying. 

“One of many issues that’s difficult about adapting Hearth & Blood is that there’s this deliberately conflicting narrative within the e-book the place there are sometimes these three totally different viewpoints on the historical past that don’t line up with each other,” Condal defined, “so it’s our job as adapters to attempt to discover the target line by means of this to carry the viewers into the narrative as we see it having been laid out.” Within the e-book, it’s a complete lot extra messy—Blood and Cheese weren’t given a selected goal, simply Daemon’s orders for “an eye fixed for an eye fixed, a son for a son,” and so attempt to kill the primary boy they discover.

“It felt like Rhaenyra, regardless of being in grief, she’s searching for vengeance, however she would select a goal that will have some form of strategic or army benefit,” Condal continued. “In fact, should you did take out Aemond, not solely would he be punished instantly for his betrayal and homicide of Luke, however it might remove the rider of the most important dragon on this planet, and instantly create a bonus for his or her aspect.” Jaehaerys nonetheless dies in Home of the Dragon, but it surely’s introduced extra as because of Blood and Cheese’s incompetence—as a substitute of discovering Aemond, the assassins bump into his sister and spouse, Queen Helaena, in her room together with her twin youngsters.

Within the books, Helaena really provides up her youngest son, Maelor (who isn’t included in Home of the Dragon because of how the present has condensed the timeline of Hearth and Blood), just for Jaehaerys to be killed by Blood and Cheese anyway—however within the present, Helaena is compelled as a substitute to sacrifice him to avoid wasting her daughter. “We knew it might be horrifying and brutal—we didn’t need it to be gratuitous or excessive,” Condal stated of the homicide. “The thought of that sequence was to dramatize a heist gone improper. So we transfer off the middle narrative of Daemon, Rhaenyra, Alicent and Aegon’s world, and abruptly, we’re following these two characters that we’ve simply met in an alley in Flea Backside. Daemon’s given them an task to go in and discover Aemond Targaryen, and we’re following them, and we’re following them, and we’re not chopping away and we’re not going again to the opposite narratives—‘oh, God, what’s going to occur?’”

Home of the Dragon airs Sundays on HBO and Max.


Need extra io9 information? Take a look at when to anticipate the most recent Marvel, Star Wars, and Star Trek releases, what’s subsequent for the DC Universe on movie and TV, and the whole lot it’s worthwhile to find out about the way forward for Physician Who.

Apple Pay Later is already being shut down, after solely launching final yr

0

Apple Pay Later lets customers cut up Apple Pay funds into 4 installments unfold over six weeks with no curiosity or charges, with a mortgage worth of between $50 and $1,000. It is a related type of set as much as Klarna or Affirm. You may apply on-line and within the Apple Retailer app for loans in opposition to purchases of iPhones and iPad with retailers that settle for Apple Pay. Or no less than you used to have the ability to.

The Cupertino big has determined to drag the plug on its “purchase now, pay later” service, which solely launched final yr. So, if you happen to had been hoping to make use of it for a bit longer, powerful luck. As of at this time, Apple Pay Later isn’t any extra.


HONOR MagicBook Professional 16 Evaluate: Someplace within the center

0

Fast Hyperlinks

Earlier than diving into this assessment, I need to make one factor clear — I have been utilizing MacBooks for the higher a part of the final decade and have been utilizing the MacBook Professional 13-inch (M1) because it debuted in 2020. So, after I bought my arms on the HONOR MagicBook Professional 16, the massive query on my thoughts was — can this laptop computer change my Mac? For any laptop computer to tackle Apple’s laptops, particularly their new M-series MacBooks, it should excel in 5 areas: portability, construct high quality, show and audio high quality, uncooked efficiency, and battery life.



HONOR’s new MagicBook Professional 16 comes ever so near matching Apple’s requirements, however the machine makes one factor clear — there’s nonetheless an extended solution to go. With its 16-inch 165Hz display, a robust mixture of Intel Core Extremely 7 CPU and RTX 4060 Laptop computer GPU, and a few of the greatest audio system on a Home windows laptop computer, the HONOR MagicBook Professional 16 gives a stable general expertise. Nevertheless, there are some areas the place it falls brief. Hold studying for my detailed assessment to search out out why and the place it misses the mark.


HONOR MagicBook Pro 16 pbi

HONOR MagicBook Professional 16

Editor’s Choose

The MagicBook Professional 16 is a smooth and highly effective laptop computer by HONOR. It has loads of horsepower, a giant 16-inch show with a 165Hz refresh fee, a devoted laptop computer GPU, and a complete load of AI options.

Working System
Home windows 11

CPU
Intel Core Extremely 7 Processor 155H

GPU
NVIDIA GeForce RTX 4060

RAM
32GB

Storage
1TB

Battery
75Wh

Show (Dimension, Decision)
16-inch, 500 nits, 3072×1920 pixels, matte end

Audio system
6x Audio system and 2x Constructed-in Microphones

Colours
White

Ports
2 x USB-C, 1 x HDMI, 1 x 3.5mm headphone jack

Weight
1.86kg

Connectivity
Wi-Fi 5, Bluetooth 5.1

Safety
Fingerprint Energy Button

Execs

  • Spectacular construct high quality
  • Wonderful audio system and show for multimedia
  • Snappy fingerprint scanner
  • Loads of RAM and storage
  • Succesful CPU
Cons

  • White physique will get soiled shortly
  • Gaming efficiency may’ve been higher
  • Cumbersome charger

Pricing and Availability

The HONOR MagicBook Professional 16 was unveiled on the firm’s grand keynote at MWC 2024. Nevertheless, within the typical HONOR style, the corporate hasn’t introduced the worldwide pricing or availability simply but. Within the dwelling nation China, the HONOR MagicBook Professional 16 begins at CNY 8,999 ($1,250 / €1,160) for the bottom mannequin with Intel Core Extremely 5. We bought our arms on the top-tier variant with the Intel Core Extremely 7, which is priced at CNY 9,999 ($1,400 / €1,290). We’ll hold you posted on international availability as quickly as we obtain extra information from the model.

Design and Construct

HONOR MagicBook Pro 16 Review 4

Sanuj Bhatia / Pocketnow

Beginning off with the design, which has been a standout function of HONOR’s merchandise. Their Magic V2 was a “groundbreaking” foldable smartphone, and the Magic6 Professional introduced its distinctive design to Android flagships. The MagicBook Professional 16 follows go well with — it carries on this custom with its personal aptitude.


The MagicBook Professional 16 comes with a pure white end, with the outer shell given a rainbow hue. Once I took out this machine out of the field, I used to be left amazed by this coloration. However, as anticipated, it will get soiled actual quick. The truth is, when you look intently, you will see that my unit has already picked up just a few everlasting stains. When you’re a cleansing freak, I’d relatively suggest you to get the outer floor laminated as quickly as potential. As a result of white end, I’ve been hesitant to eat close to it, which is a disgrace given its audio system and show are distinctive for the value.

However, when you can overlook the colour, it is a fairly solidly constructed laptop computer. You may get a reasonably smooth design for a laptop computer with top-end, gaming-capable {hardware}. It weighs 1.86kg and measures 17.9mm in thickness — solely about 1mm thicker than the 16-inch MacBook Professional. The physique encompasses a gentle brushed metallic end and is free from any overly flashy design components. Even the outer shell options solely the HONOR brand.


HONOR MagicBook Pro 16 Review 7

Sanuj Bhatia / Pocketnow

The location of ports on the MagicBook Professional 16 can also be thoughtfully executed. There are six ports in whole, with probably the most regularly used ones, like the three.5mm headphone jack and two USB-C ports (one supporting PD charging), conveniently positioned on the left aspect. The precise aspect has been left clean, whereas the again aspect of the laptop computer options the opposite ports, such because the HDMI port, two USB-A ports, and the proprietary charging port, making them much less obtrusive.

To maintain this factor cool, since this laptop computer can get a bit heat, HONOR has included air vents on all sides, together with the again, backside, and sides. Nevertheless, the underside line concerning the MagicBook Professional 16’s construct high quality is that it is stable — and this comes from somebody who has been utilizing Apple’s MacBook for greater than a decade. The hinge can also be well-designed, opening easily with one hand, and with the physique made principally out of metallic, the laptop computer feels sturdy and premium.


Keyboard and Trackpad

HONOR MagicBook Pro 16 Review 3

Sanuj Bhatia / Pocketnow

The MagicBook Professional 16 encompasses a full keyboard, full with a numeric pad on the appropriate aspect. This structure is nice for many who worth having a numeric pad, however as somebody like me who’s accustomed to centered keyboards, it took me some time to adapt. The truth that the keyboard has pretty small “Enter” and “Shift” buttons did not assist both.

Nonetheless, the general responsiveness and really feel of the keys are wonderful. The keys are generously sized, supply good journey, and are comparatively quiet. As soon as accustomed to this structure, you will love typing on this machine. The keyboard even has backlighting. Nevertheless, I discovered the lighting uneven and poorly seen in opposition to the white keys, and I switched off this function on the primary boot itself.


HONOR MagicBook Pro 16 Review 5

Sanuj Bhatia / Pocketnow

The keyboard is surrounded by the laptop computer’s sound system on either side. The highest proper key of the keyboard doubles as an influence/wake button and the fingerprint scanner. The fingerprint scanner on this machine might be the quickest I’ve used on a Home windows laptop computer, unlocking the laptop computer virtually immediately upon contact.

Transferring to the trackpad, the MagicBook Professional 16 gives a big trackpad with ample floor space, however that is one other key space the place this laptop computer falls wanting different rivals. The trackpad feels plastic-y, and the press suggestions is inconsistent, with the highest half feeling stiff and the underside overly versatile. HONOR positively has room for enchancment on this space.


Show and Audio

HONOR MagicBook Pro 16 Review 8

Sanuj Bhatia / Pocketnow

Transferring onto the show, the MagicBook Professional comes with a big 16-inch “FullView” IPS LCD show with as much as a 165Hz refresh fee and a decision of 3072×1920 pixels. The show has a 16:10 facet ratio, a matte end, and may attain as much as 500 nits of brightness. Even for somebody like me who loves the shiny and colourful show of the Mac, the HONOR MagicBook Professional 16’s show does a fantastic job in sustaining wonderful coloration copy and vibrancy, regardless of it being a matte show.


The excessive refresh fee makes certain Home windows and general UI look buttery clean. And oh, did I point out the bezels? The bezels on three sides are nearly negligible and it makes for a fantastic viewing expertise when watching TV reveals, films, and sports activities. The display can also be TUV Rheinland licensed for Low Blue Gentle and Flicker Free, much like HONOR’s different merchandise. The one factor I’d enhance about this show is the brightness. The low 500 nits brightness means the colours take successful when checked out from the aspect angles and in out of doors settings the place the matte end doesn’t assist both. Nonetheless, the general expertise is excellent, particularly contemplating the value.

What enhances this show fantastically is the laptop computer’s sound system. The MagicBook Professional 16 might properly have the most effective audio system of any Home windows laptop computer at the moment available on the market. For the primary time shortly, I didn’t miss the sound system of my MacBook Professional — which has turn out to be the business normal at this level. The audio system ship punchy, detailed sound throughout low, mid-range, and excessive frequencies, making for among the finest audio experiences I’ve had on a Home windows laptop computer in a very long time.

Software program, Efficiency, and Battery Life

HONOR MagicBook Pro 16 Review 2

Sanuj Bhatia / Pocketnow


Now, shifting onto efficiency, however let’s first get the uncooked specs out of the best way. The HONOR MagicBook Professional 16 is powered by Intel’s Core Extremely 7 155H processor coupled with 32GB DDR5 RAM and 1TB SSD storage. For graphics, it features a devoted NVIDIA GeForce RTX 4060 laptop computer GPU with 8GB of reminiscence and an Intel Arc built-in GPU, although it primarily depends on the RTX 4060 for graphic-intensive duties. And, with HONOR calling this laptop computer an AI PC, because of the inclusion of two Gen3 compute engines NPU for dealing with AI-based duties.

As you’d count on from a laptop computer with this succesful {hardware}, Home windows runs quick and fluid on this gadget. From launching functions and booting up, to switching between browser tabs and modifying paperwork or photographs, the efficiency is steady and fast. The one enchancment I might counsel is streamlining Home windows updates, however that is a job for Microsoft, not HONOR. However apart from that, this factor flies proper off the bat. Proper from the second you activate this machine, you’ll really feel it being buttery clean and quick.


Nevertheless, the graphics efficiency doesn’t meet the expectations for a gaming laptop computer. Regardless of setting it to efficiency mode and conserving it plugged in, the MagicBook Professional struggles to keep up a constant 60fps in FIFA 23, with body charges usually dropping to between 40-43fps. I additionally tried to play Microsoft’s Forza Horizon 5 on this machine, however discovered related outcomes with the machine failing to ship clean gameplay.

HONOR has built-in a number of Apple-like cross-platform options. The MagicBook Professional comes geared up with HONOR PC Supervisor and HONOR WorkStation apps. PC Supervisor means that you can handle the laptop computer, together with updating BIOS and drivers, backing up information, enabling spatial audio, and configuring HONOR Share.

HONOR MagicBook Pro 16 Review 1

Sanuj Bhatia / Pocketnow


WorkStation, alternatively, improves interoperability amongst HONOR units, permitting for clipboard sharing, file transfers, display sharing, and even utilizing the laptop computer’s enter units along with your cellphone. You may also immediately allow the cellphone’s hotspot by means of the WorkStation app. Whereas HONOR guarantees extra AI options like doc summarization, AI video subtitles, and extra, these weren’t out there on the time of assessment.

Relating to battery life, the MagicBook Professional 16 falls brief. The battery life is disappointing, with the laptop computer usually working out earlier than noon even underneath mild use, which incorporates doc writing and modifying, internet looking, video streaming, and emailing. Moreover, the laptop computer comes with a cumbersome charger, which is cumbersome regardless of the choice to cost by way of USB-C.


Verdict

So, is the HONOR MagicBook Professional 16 value it? In equity to HONOR, it is a commendable try at creating a conveyable powerhouse. The MagicBook Professional 16 is provided with a few of the greatest {hardware} out there, boasts wonderful construct high quality, a show + sound combo that is unmatched on any Home windows laptop computer, and delivers nice efficiency, all for round $1000. Whereas there are some shortcomings that make this laptop computer inferior in opposition to a few of the rivals, these drawbacks are usually manageable for many customers (even probably the most energy customers).

Adobe’s hidden cancellation charge is illegal, FTC go well with says

0

Adobe’s hidden cancellation fee is unlawful, FTC suit says

Adobe prioritized earnings whereas spending years ignoring quite a few complaints from customers struggling to cancel expensive subscriptions with out incurring hefty hidden charges, the US Federal Commerce Fee (FTC) alleged in a lawsuit Monday.

In line with the FTC, Adobe knew that canceling subscriptions was laborious however decided that it could damage income to make canceling any simpler, so Adobe by no means modified the “convoluted” course of. Even when the FTC launched a probe in 2022 particularly indicating that Adobe’s practices could also be unlawful, Adobe did nothing to deal with the alleged hurt to customers, the FTC grievance famous. Adobe additionally “gives no refunds or solely partial refunds to some subscribers who incur expenses after an tried, unsuccessful cancellation.”

Adobe “repeatedly determined in opposition to rectifying a few of Adobe’s illegal practices due to the income implications,” the FTC alleged, asking a jury to completely block Adobe from persevering with the seemingly misleading practices.

Dana Rao, Adobe’s common counsel and chief belief officer, supplied a assertion confirming to Ars that Adobe plans to defend its enterprise practices in opposition to the FTC’s claims.

“Subscription providers are handy, versatile, and cost-effective to permit customers to decide on the plan that most closely fits their wants, timeline, and funds,” Rao stated. “Our precedence is to at all times guarantee our prospects have a optimistic expertise. We’re clear with the phrases and situations of our subscription agreements and have a easy cancellation course of. We’ll refute the FTC’s claims in courtroom.”

Cancellation charge allegedly used as retention device

The federal government’s closely redacted grievance laid out Adobe’s alleged scheme, which begins with “manipulative enrollment practices.”

To lock subscribers into recurring month-to-month funds, Adobe would sometimes pre-select by default its hottest “annual paid month-to-month” plan, the FTC alleged. That subscription possibility locked customers into an annual plan regardless of paying month to month. In the event that they canceled after a two-week interval, they’d owe Adobe an early termination charge (ETF) that prices 50 p.c of their remaining annual subscription. The “materials phrases” of this charge are hidden throughout enrollment, the FTC claimed, solely showing in “disclosures which can be designed to go unnoticed and that the majority customers by no means see.”

For particular person customers, accessing Adobe’s suite of apps can value greater than $700 yearly, Bloomberg reported. For a lot of customers all of the sudden confronted with paying an ETF value a whole lot whereas dropping entry to providers immediately, the choice to cancel just isn’t as simple because it may be with out the hidden charge. the FTC alleged.

As a result of Adobe allegedly solely alerted customers to the ETF in effective print—by hovering over a small icon or clicking a hyperlink in small textual content—whereas the corporate’s cancellation flows made it laborious to finish recurring funds, the FTC is suing and accusing Adobe of misleading practices beneath the FTC Act.

Moreover, Adobe’s “stealth ETF” could violate the Restore On-line Consumers’ Confidence Act (ROSCA), the FTC alleged.

Beneath ROSCA, Adobe’s ETF might be thought-about a “adverse function possibility” as a result of Adobe allegedly doesn’t clearly disclose the ETF throughout subscription sign-ups. Subsequently, Adobe solely will get a buyer to comply with pay the ETF by way of their “silence or failure to take an affirmative motion to reject items or providers or to cancel the settlement.”

ROSCA solely permits on-line companies to cost for items or providers by way of a adverse function possibility beneath sure situations. In Adobe’s case, the ETF would’ve wanted to be clearly disclosed previous to gathering billing data. In any other case, the shopper ought to have been requested to offer knowledgeable consent, or Adobe ought to have supplied “easy mechanisms to cease recurring expenses.”

Adobe did none of that, the FTC alleged, failing to offer “a easy means” to finish subscriptions and harming prospects who have been “ambushed” by ETFs that “can typically be a number of hundred {dollars}.”

Scattered Spider Boss Cuffed in Spain Boarding a Flight to Italy

0

The ringleader of brazen cybercrime ring Scattered Spider led profitable cyberattacks that introduced US powerhouse corporations like MGM Resorts and Caesars Leisure to a standstill. Extra not too long ago, he spent the previous couple of weeks dwelling in Spain. Nevertheless, the celebration, it appears, has abruptly ended.

The 22-year-old British nationwide is now within the custody of Spanish police after being arrested on the Palma Airport in Palma de Mallorca as he was attempting to board a flight to Italy, in keeping with stories from Murica Information. Police advised the outlet they imagine the suspect arrived in Barcelona on the finish of Might.

On the time of the arrest, the accused cybercriminal was in possession of a laptop computer, a cell phone, and maintained management of a $27 million Bitcoin fortune, the Spanish police added.

He’s accused of greater than 45 cyberattacks towards US corporations and a warrant for his arrest was issued by the FBI in Los Angeles, the stories added.

Profitable World Cybercrime Arrests Proceed

Worldwide legislation enforcement has been cracking down on cybercriminals over the previous few weeks.

On June 3 Europol introduced Operation Endgame, a coordinated legislation enforcement effort throughout the globe to trace down particular person cybercriminals, and added 5 Russian nationals to the checklist of Europe’s most wished fugitives. On June 12, Operation Endgame introduced the arrest of LockBit and Conti Ransomware developer in Ukraine.

Whereas the arrests ship an necessary message that searching down cybercriminals is a precedence for legislation enforcement, cybercrime teams proceed to function and adapt.

Simply days in the past, as an example, researchers at Mandiant mentioned they noticed Scattered Spider increasing into cyberattacks towards software-as-a-service (SaaS) purposes to ship ransomware.


Introducing Databricks LakeFlow: A unified, clever resolution for information engineering

0

At present, we’re excited to announce Databricks LakeFlow, a brand new resolution that incorporates every thing it is advisable to construct and function manufacturing information pipelines. It consists of new native, extremely scalable connectors for databases together with MySQL, Postgres, SQL Server and Oracle and enterprise purposes like Salesforce, Microsoft Dynamics, NetSuite, Workday, ServiceNow and Google Analytics. Customers can remodel information in batch and streaming utilizing customary SQL and Python. We’re additionally saying Actual Time Mode for Apache Spark, permitting stream processing at orders of magnitude quicker latencies than microbatch. Lastly, you possibly can orchestrate and monitor workflows and deploy to manufacturing utilizing CI/CD. Databricks LakeFlow is native to the Knowledge Intelligence Platform, offering serverless compute and unified governance with Unity Catalog.

LakeFlow
LakeFlow is the one unified information engineering resolution for ingestion, transformation and orchestration

On this weblog submit we talk about the the explanation why we consider LakeFlow will assist information groups meet the rising demand of dependable information and AI in addition to LakeFlow’s key capabilities built-in right into a single product expertise.

Challenges in constructing and working dependable information pipelines

Knowledge engineering – accumulating and getting ready contemporary, high-quality and dependable information – is a vital ingredient for democratizing information and AI in your small business. But reaching this stays filled with complexity and requires stitching collectively many various instruments.

 

First, information groups have to ingest information from a number of methods every with their very own codecs and entry strategies. This requires constructing and sustaining in-house connectors for databases and enterprise purposes. Simply maintaining with enterprise purposes’ API modifications is usually a full-time job for a complete information group. Knowledge then must be ready in each batch and streaming, which requires writing and sustaining complicated logic for triggering and incremental processing. When latency spikes or a failure happens, it means getting paged, a set of sad information shoppers and even disruptions to the enterprise that have an effect on the underside line. Lastly, information groups have to deploy these pipelines utilizing CI/CD and monitor the standard and lineage of knowledge property. This usually requires deploying, studying and managing one other solely new instrument like Prometheus or Grafana.

 

That is why we determined to construct LakeFlow, a unified resolution for information ingestion, transformation, and orchestration powered by information intelligence. Its three key elements are: LakeFlow Join, LakeFlow Pipelines and LakeFlow Jobs.

LakeFlow Join: Easy and scalable information ingestion 

LakeFlow Join supplies point-and-click information ingestion from databases reminiscent of MySQL, Postgres, SQL Server and Oracle and enterprise purposes like Salesforce, Microsoft Dynamics, NetSuite, Workday, ServiceNow and Google Analytics. LakeFlow Join can even ingest unstructured information reminiscent of PDFs and Excel spreadsheets from sources like SharePoint.

 

It extends our widespread native connectors for cloud storage (e.g. S3, ADLS Gen2 and GCS) and queues (e.g. Kafka, Kinesis, Occasion Hub and Pub/Sub connectors), and associate options reminiscent of Fivetran, Qlik and Informatica.

LakeFlow Connector
Setup an ingestion pipeline in a couple of straightforward steps with LakeFlow Join

We’re notably enthusiastic about database connectors, that are powered by our acquisition of Arcion. An unbelievable quantity of precious information is locked away in operational databases. As an alternative of naive approaches to load this information, which hit operational and scaling points, LakeFlows makes use of change information seize (CDC) know-how to make it easy, dependable and operationally environment friendly to deliver this information to your lakehouse.

 

Databricks prospects who’re utilizing LakeFlow Join discover {that a} easy ingestion resolution improves productiveness and lets them transfer quicker from information to insights. Insulet, a producer of a wearable insulin administration system, the Omnipod, makes use of the Salesforce ingestion connector to ingest information associated to buyer suggestions into their information resolution which is constructed on Databricks. This information is made obtainable for evaluation by means of Databricks SQL to achieve insights relating to high quality points and monitor buyer complaints. The group discovered vital worth in utilizing the brand new capabilities of LakeFlow Join.

“With the brand new Salesforce ingestion connector from Databricks, we have considerably streamlined our information integration course of by eliminating fragile and problematic middleware. This enchancment permits Databricks SQL to straight analyze Salesforce information inside Databricks. In consequence, our information practitioners can now ship up to date insights in near-real time, lowering latency from days to minutes.”

— Invoice Whiteley, Senior Director of AI,  Analytics, and Superior Algorithms, Insulet

LakeFlow Pipelines: Environment friendly declarative information pipelines

LakeFlow Pipelines decrease the complexity of constructing and managing environment friendly batch and streaming information pipelines. Constructed on the declarative Delta Stay Tables framework, they free you as much as write enterprise logic in SQL and Python whereas Databricks automates information orchestration, incremental processing and compute infrastructure autoscaling in your behalf. Furthermore, LakeFlow Pipelines provides built-in information high quality monitoring and its Actual Time Mode helps you to allow persistently low-latency supply of time-sensitive datasets with none code modifications.

LakeFlow Pipelines simplifies data pipeline automation
LakeFlow Pipelines simplifies information pipeline automation

LakeFlow Jobs: Dependable orchestration for each workload

LakeFlow Jobs reliably orchestrates and displays manufacturing workloads. Constructed on the superior capabilities of Databricks Workflows, it orchestrates any workload, together with ingestion, pipelines, notebooks, SQL queries, machine studying coaching, mannequin deployment and inference. Knowledge groups can even leverage triggers, branching and looping to satisfy complicated information supply use circumstances.

 

LakeFlow Jobs additionally automates and simplifies the method of understanding and monitoring information well being and supply. It takes a data-first view of well being, giving information groups full lineage together with relationships between ingestion, transformations, tables and dashboards. Moreover, it tracks information freshness and high quality, permitting information groups so as to add displays by way of Lakehouse Monitoring with the press of a button.

Constructed on the Knowledge Intelligence Platform

Databricks LakeFlow is natively built-in with our Knowledge Intelligence Platform, which brings these capabilities:

  • Knowledge intelligence: AI-powered intelligence is not only a characteristic of LakeFlow, it’s a foundational functionality that touches each facet of the product. Databricks Assistant powers the invention, authoring and monitoring of knowledge pipelines, so you possibly can spend extra time constructing dependable information.
  • Unified governance: LakeFlow can be deeply built-in with Unity Catalog, which powers lineage and information high quality. 
  • Serverless compute: Construct and orchestrate pipelines at scale and assist your group concentrate on work with out having to fret about infrastructure.

The way forward for information engineering is easy, unified and clever

We consider that LakeFlow will allow our prospects to ship brisker, extra full and higher-quality information to their companies. LakeFlow will enter preview quickly beginning with LakeFlow Join. If you need to request entry, join right here. Over the approaching months, search for extra LakeFlow bulletins as further capabilities turn into obtainable.

Mastering Nutanix Hyperconverged Infrastructure on Cisco’s Black Belt Academy

0

The digital panorama witnessed a big milestone on August 28, 2023, when Cisco and Nutanix unveiled a world strategic partnership that guarantees to be a game-changer within the realm of hybrid multi-cloud computing. This alliance is about to fast-track and streamline the hybrid multi-cloud expedition for purchasers, all whereas redefining the core rules of knowledge middle modernization. With the mixing of Nutanix’s premier software program platform and Cisco’s cutting-edge server portfolio, this collaboration has produced what’s arguably the business’s most sturdy and complete hyperconverged infrastructure resolution so far.

When Cisco introduced the Finish-of-Life for Cisco HyperFlex Information Platform (HXDP) on September 12, 2023; it left our prospects and companions equally overwhelmed. So, when Cisco proposed that the Nutanix Software program, working on Cisco’s {Hardware} can be a direct substitute of HyperFlex; we at Cisco Black Belt Academy made certain that our companions get immediate steerage on the brand new resolution with thorough particulars on its enhanced HCI capabilities topped with a path on transitioning or migrating from HyperFlex to Cisco’s HCI Answer with Nutanix.

The ”Chronicle” of Nutanix on Cisco Black Belt Academy

The Nutanix Stage 1 & 2 tracks on Cisco Black Belt Academy are launched for each Presales and Deployment roles. These tracks cowl:

1. Cisco’s Hyperconverged Technique

Explains how the partnership of Cisco and Nutanix is solid on their mixed edge on utility, information and infrastructure administration.

2. Introduction to the Hyper Converged Infrastructure

Makes our companions acquainted with Subsequent Era HCI, Advantages of HCI, Sustained improvements and HCI Vendor Panorama.

3. Answer Overview

Particulars Cisco Compute Hyperconverged resolution with Nutanix and covers it’s cloud infrastructure, broad Information Providers portfolio, Nutanix Cloud Supervisor, Nutanix Unified Storage and Prism, the Cloud Administration interface.

4. Structure Deep Dive

Elucidates why Nutanix Structure is totally different from different HCI options; Reveals how Cisco servers, storage, networking, and SaaS operations are mixed with the Nutanix Cloud Platform; explains how the controller VM’s are working to get a excessive efficiency construction; introduces resiliency and functioning of the storage layer.

5. Configuration & Deployment

In-depth demonstrations and methods surrounding Nutanix Deployment, protecting:

  • Preliminary Configurations/Information to getting began
  • Deploying the Nutanix Basis installer VM to a VMware ESX 7 cluster.
  • Deploying a Nutanix cluster on UCS servers managed by UCS Supervisor and including these hosts to vCenter.
  • Increasing a Nutanix cluster with a node that has been beforehand provisioned.
  • Deploying Prism Central from Prism Factor and registering the cluster with the newly created Prism Central.
  • Updating the UCS Server Firmware with Nutanix Life Cycle Supervisor (LCM) with out disrupting general cluster operations.

6. Migration from HyperFlex

Study the assorted choices emigrate current HyperFlex platforms to the brand new Nutanix Platform. Achieve an understanding of how Migrations of digital machines between clusters of VMware ESXi servers is most simply completed by way of “shared nothing” vMotion. As well as, be taught in regards to the a free software program software known as Transfer that Nutanix presents, which acts as an middleman agent and coordinator to maneuver VMs between two methods.

7. Sizing Cisco HCI with Nutanix

Discusses the Cisco HCI with Nutanix sizing primarily based on:

  • Output recordsdata from RVTools and Nutanix Collector instruments
  • Present HyperFlex and Nutanix Invoice Of Supplies (BOM)
  • VM-based and Capability-based sizing of the Cisco HCI with Nutanix utilizing Nutanix Sizer software.

8. Successful with Nutanix

Purchase a information of Nutanix differentiators available in the market, Insights on the aggressive surroundings and edge over VMware, HPE & Lenovo while protecting the methods to efficiently navigate CI and HCI buyer conversations.

9. Dcloud/Seize the Flag (CTF)

Arms on demo with entry to a easy Nutanix deployment on Cisco UCS, with Cisco Intersight, Nutanix Prism Factor, Nutanix AHV, Prism Central and Cisco UCS Supervisor. The Seize the Flag (CTF) missions present a gamified method of understanding what the brand new Cisco & Nutanix Partnership brings to the desk.

The Nutanix Stage 1 & 2 tracks on Cisco Black Belt Academy for both Presales and Deployment roles.

The place to be taught extra?

With the fashionable enterprise challenges and the ever-changing Market Dynamics, functions have develop into the middle for each buyer and these functions are rising at a quick tempo. IT groups are required to deploy these functions quicker and that too with a cloud working mannequin in place. Therefore, it turns into very important to be taught and perceive how the partnership of Cisco and Nutanix can assist ship the infrastructure and functions globally whereas utilizing the best-in-class cloud working fashions, that too with added resiliency and adaptability. The curriculum of “Cisco HCI resolution with Nutanix” on Cisco Black Belt Academy, can instill confidence to deal with buyer conversations and carry out a profitable PoC/PoV as a Presales SE or navigate thorough deployments of the Nutanix Answer as a subject engineer whereas migrating from the older HyperFlex base.

 

So, begin at the moment and get licensed! Go to our

 

 


We’d love to listen to what you suppose. Ask a Query, Remark Under, and Keep Related with #CiscoPartners on social!

Cisco Companions Fb  |  @CiscoPartners X/Twitter  |  Cisco Companions LinkedIn

Share:


Check-Driving HTML Templates

After a decade or extra the place Single-Web page-Purposes generated by
JavaScript frameworks have
grow to be the norm
, we see that server-side rendered HTML is turning into
widespread once more, additionally due to libraries corresponding to HTMX or Turbo. Writing a wealthy net UI in a
historically server-side language like Go or Java is not simply attainable,
however a really enticing proposition.

We then face the issue of how you can write automated exams for the HTML
elements of our net functions. Whereas the JavaScript world has advanced highly effective and subtle methods to check the UI,
ranging in dimension from unit-level to integration to end-to-end, in different
languages we would not have such a richness of instruments accessible.

When writing an internet software in Go or Java, HTML is usually generated
by way of templates, which include small fragments of logic. It’s actually
attainable to check them not directly by way of end-to-end exams, however these exams
are sluggish and costly.

We will as a substitute write unit exams that use CSS selectors to probe the
presence and proper content material of particular HTML components inside a doc.
Parameterizing these exams makes it simple so as to add new exams and to obviously
point out what particulars every take a look at is verifying. This method works with any
language that has entry to an HTML parsing library that helps CSS
selectors; examples are offered in Go and Java.

Degree 1: checking for sound HTML

The primary factor we wish to examine is that the HTML we produce is
principally sound. I do not imply to examine that HTML is legitimate in accordance with the
W3C; it will be cool to do it, but it surely’s higher to start out with a lot less complicated and quicker checks.
As an example, we wish our exams to
break if the template generates one thing like

<div>foo</p> 

Let’s examine how you can do it in levels: we begin with the next take a look at that
tries to compile the template. In Go we use the usual html/template bundle.

Go

  func Test_wellFormedHtml(t *testing.T) {     templ := template.Should(template.ParseFiles("index.tmpl"))     _ = templ   }

In Java, we use jmustache
as a result of it is quite simple to make use of; Freemarker or
Velocity are different frequent selections.

Java

  @Check   void indexIsSoundHtml() {       var template = Mustache.compiler().compile(               new InputStreamReader(                       getClass().getResourceAsStream("/index.tmpl")));   }

If we run this take a look at, it can fail, as a result of the index.tmpl file does
not exist. So we create it, with the above damaged HTML. Now the take a look at ought to move.

Then we create a mannequin for the template to make use of. The applying manages a todo-list, and
we are able to create a minimal mannequin for demonstration functions.

Go

  func Test_wellFormedHtml(t *testing.T) {     templ := template.Should(template.ParseFiles("index.tmpl"))     mannequin := todo.NewList()     _ = templ     _ = mannequin   }

Java

  @Check   void indexIsSoundHtml() {       var template = Mustache.compiler().compile(               new InputStreamReader(                       getClass().getResourceAsStream("/index.tmpl")));       var mannequin = new TodoList();   }

Now we render the template, saving the leads to a bytes buffer (Go) or as a String (Java).

Go

  func Test_wellFormedHtml(t *testing.T) {     templ := template.Should(template.ParseFiles("index.tmpl"))     mannequin := todo.NewList()     var buf bytes.Buffer     err := templ.Execute(&buf, mannequin)     if err != nil {       panic(err)     }   }

Java

  @Check   void indexIsSoundHtml() {       var template = Mustache.compiler().compile(               new InputStreamReader(                       getClass().getResourceAsStream("/index.tmpl")));       var mannequin = new TodoList();          var html = template.execute(mannequin);   }

At this level, we wish to parse the HTML and we count on to see an
error, as a result of in our damaged HTML there’s a div component that
is closed by a p component. There’s an HTML parser within the Go
customary library, however it’s too lenient: if we run it on our damaged HTML, we do not get an
error. Fortunately, the Go customary library additionally has an XML parser that may be
configured to parse HTML (due to this Stack Overflow reply)

Go

  func Test_wellFormedHtml(t *testing.T) {     templ := template.Should(template.ParseFiles("index.tmpl"))     mannequin := todo.NewList()          // render the template right into a buffer     var buf bytes.Buffer     err := templ.Execute(&buf, mannequin)     if err != nil {       panic(err)     }        // examine that the template may be parsed as (lenient) XML     decoder := xml.NewDecoder(bytes.NewReader(buf.Bytes()))     decoder.Strict = false     decoder.AutoClose = xml.HTMLAutoClose     decoder.Entity = xml.HTMLEntity     for {       _, err := decoder.Token()       change err {       case io.EOF:         return // We're carried out, it is legitimate!       case nil:         // do nothing       default:         t.Fatalf("Error parsing html: %s", err)       }     }   }

supply

This code configures the HTML parser to have the appropriate stage of leniency
for HTML, after which parses the HTML token by token. Certainly, we see the error
message we needed:

--- FAIL: Test_wellFormedHtml (0.00s)     index_template_test.go:61: Error parsing html: XML syntax error on line 4: surprising finish component </p> 

In Java, a flexible library to make use of is jsoup:

Java

  @Check   void indexIsSoundHtml() {       var template = Mustache.compiler().compile(               new InputStreamReader(                       getClass().getResourceAsStream("/index.tmpl")));       var mannequin = new TodoList();          var html = template.execute(mannequin);          var parser = Parser.htmlParser().setTrackErrors(10);       Jsoup.parse(html, "", parser);       assertThat(parser.getErrors()).isEmpty();   }

supply

And we see it fail:

java.lang.AssertionError:  Anticipating empty however was:<[<1:13>: Unexpected EndTag token [</p>] when in state [InBody], 

Success! Now if we copy over the contents of the TodoMVC
template
to our index.tmpl file, the take a look at passes.

The take a look at, nevertheless, is simply too verbose: we extract two helper features, in
order to make the intention of the take a look at clearer, and we get

Go

  func Test_wellFormedHtml(t *testing.T) {     mannequin := todo.NewList()        buf := renderTemplate("index.tmpl", mannequin)        assertWellFormedHtml(t, buf)   }

supply

Java

  @Check   void indexIsSoundHtml() {       var mannequin = new TodoList();          var html = renderTemplate("/index.tmpl", mannequin);          assertSoundHtml(html);   }

supply

Degree 2: testing HTML construction

What else ought to we take a look at?

We all know that the seems of a web page can solely be examined, in the end, by a
human how it’s rendered in a browser. Nonetheless, there may be usually
logic in templates, and we wish to have the ability to take a look at that logic.

One may be tempted to check the rendered HTML with string equality,
however this method fails in apply, as a result of templates include lots of
particulars that make string equality assertions impractical. The assertions
grow to be very verbose, and when studying the assertion, it turns into troublesome
to grasp what it’s that we’re attempting to show.

What we want
is a method to say that some elements of the rendered HTML
correspond to what we count on, and to ignore all the main points we do not
care about.
A method to do that is by operating queries with the CSS selector language:
it’s a highly effective language that enables us to pick out the
components that we care about from the entire HTML doc. As soon as now we have
chosen these components, we (1) rely that the variety of component returned
is what we count on, and (2) that they include the textual content or different content material
that we count on.

The UI that we’re speculated to generate seems like this:

Check-Driving HTML Templates

There are a number of particulars which can be rendered dynamically:

  1. The variety of gadgets and their textual content content material change, clearly
  2. The model of the todo-item modifications when it is accomplished (e.g., the
    second)
  3. The “2 gadgets left” textual content will change with the variety of non-completed
    gadgets
  4. One of many three buttons “All”, “Lively”, “Accomplished” might be
    highlighted, relying on the present url; as an illustration if we resolve that the
    url that reveals solely the “Lively” gadgets is /lively, then when the present url
    is /lively, the “Lively” button ought to be surrounded by a skinny purple
    rectangle
  5. The “Clear accomplished” button ought to solely be seen if any merchandise is
    accomplished

Every of this issues may be examined with the assistance of CSS selectors.

It is a snippet from the TodoMVC template (barely simplified). I
haven’t but added the dynamic bits, so what we see right here is static
content material, offered for example:

index.tmpl

  <part class="todoapp">     <ul class="todo-list">       <!-- These are right here simply to point out the construction of the record gadgets -->       <!-- Listing gadgets ought to get the category `accomplished` when marked as accomplished -->       <li class="accomplished">           <div class="view">           <enter class="toggle" kind="checkbox" checked>           <label>Style JavaScript</label>            <button class="destroy"></button>         </div>       </li>       <li>         <div class="view">           <enter class="toggle" kind="checkbox">           <label>Purchase a unicorn</label>            <button class="destroy"></button>         </div>       </li>     </ul>     <footer class="footer">       <!-- This ought to be `0 gadgets left` by default -->       <span class="todo-count"><sturdy>0</sturdy> merchandise left</span>        <ul class="filters">         <li>           <a class="chosen" href="#/">All</a>          </li>         <li>           <a href="#/lively">Lively</a>         </li>         <li>           <a href="#/accomplished">Accomplished</a>         </li>       </ul>       <!-- Hidden if no accomplished gadgets are left ↓ -->       <button class="clear-completed">Clear accomplished</button>      </footer>   </part>  

supply

By wanting on the static model of the template, we are able to deduce which
CSS selectors can be utilized to determine the related components for the 5 dynamic
options listed above:

function CSS selector
All of the gadgets ul.todo-list li
Accomplished gadgets ul.todo-list li.accomplished
Gadgets left span.todo-count
Highlighted navigation hyperlink ul.filters a.chosen
Clear accomplished button button.clear-completed

We will use these selectors to focus our exams on simply the issues we wish to take a look at.

Testing HTML content material

The primary take a look at will search for all of the gadgets, and show that the info
arrange by the take a look at is rendered accurately.

func Test_todoItemsAreShown(t *testing.T) {   mannequin := todo.NewList()   mannequin.Add("Foo")   mannequin.Add("Bar")   buf := renderTemplate(mannequin)   // assert there are two <li> components contained in the <ul class="todo-list">    // assert the primary <li> textual content is "Foo"   // assert the second <li> textual content is "Bar" } 

We’d like a approach to question the HTML doc with our CSS selector; an excellent
library for Go is goquery, that implements an API impressed by jQuery.
In Java, we maintain utilizing the identical library we used to check for sound HTML, specifically
jsoup. Our take a look at turns into:

Go

  func Test_todoItemsAreShown(t *testing.T) {     mannequin := todo.NewList()     mannequin.Add("Foo")     mannequin.Add("Bar")        buf := renderTemplate("index.tmpl", mannequin)        // parse the HTML with goquery     doc, err := goquery.NewDocumentFromReader(bytes.NewReader(buf.Bytes()))     if err != nil {       // if parsing fails, we cease the take a look at right here with t.FatalF       t.Fatalf("Error rendering template %s", err)     }        // assert there are two <li> components contained in the <ul class="todo-list">     choice := doc.Discover("ul.todo-list li")     assert.Equal(t, 2, choice.Size())        // assert the primary <li> textual content is "Foo"     assert.Equal(t, "Foo", textual content(choice.Nodes[0]))        // assert the second <li> textual content is "Bar"     assert.Equal(t, "Bar", textual content(choice.Nodes[1]))   }      func textual content(node *html.Node) string {     // A bit of mess on account of the truth that goquery has     // a .Textual content() methodology on Choice however not on html.Node     sel := goquery.Choice{Nodes: []*html.Node{node}}     return strings.TrimSpace(sel.Textual content())   }

supply

Java

  @Check   void todoItemsAreShown() throws IOException {       var mannequin = new TodoList();       mannequin.add("Foo");       mannequin.add("Bar");          var html = renderTemplate("/index.tmpl", mannequin);          // parse the HTML with jsoup       Doc doc = Jsoup.parse(html, "");          // assert there are two <li> components contained in the <ul class="todo-list">       var choice = doc.choose("ul.todo-list li");       assertThat(choice).hasSize(2);          // assert the primary <li> textual content is "Foo"       assertThat(choice.get(0).textual content()).isEqualTo("Foo");          // assert the second <li> textual content is "Bar"       assertThat(choice.get(1).textual content()).isEqualTo("Bar");   }

supply

If we nonetheless have not modified the template to populate the record from the
mannequin, this take a look at will fail, as a result of the static template
todo gadgets have completely different textual content:

Go

  --- FAIL: Test_todoItemsAreShown (0.00s)       index_template_test.go:44: First record merchandise: need Foo, bought Style JavaScript       index_template_test.go:49: Second record merchandise: need Bar, bought Purchase a unicorn

Java

  IndexTemplateTest > todoItemsAreShown() FAILED       org.opentest4j.AssertionFailedError:       Anticipating:        <"Style JavaScript">       to be equal to:        <"Foo">       however was not.

We repair it by making the template use the mannequin information:

Go

  <ul class="todo-list">     {{ vary .Gadgets }}       <li>         <div class="view">           <enter class="toggle" kind="checkbox">           <label>{{ .Title }}</label>           <button class="destroy"></button>         </div>       </li>     {{ finish }}   </ul>

supply

Java – jmustache

  <ul class="todo-list">     {{ #allItems }}     <li>       <div class="view">         <enter class="toggle" kind="checkbox">         <label>{{ title }}</label>         <button class="destroy"></button>       </div>     </li>     {{ /allItems }}   </ul>

supply

Check each content material and soundness on the identical time

Our take a look at works, however it’s a bit verbose, particularly the Go model. If we’ll have extra
exams, they’ll grow to be repetitive and troublesome to learn, so we make it extra concise by extracting a helper perform for parsing the html. We additionally take away the
feedback, because the code ought to be clear sufficient

Go

  func Test_todoItemsAreShown(t *testing.T) {     mannequin := todo.NewList()     mannequin.Add("Foo")     mannequin.Add("Bar")        buf := renderTemplate("index.tmpl", mannequin)        doc := parseHtml(t, buf)     choice := doc.Discover("ul.todo-list li")     assert.Equal(t, 2, choice.Size())     assert.Equal(t, "Foo", textual content(choice.Nodes[0]))     assert.Equal(t, "Bar", textual content(choice.Nodes[1]))   }      func parseHtml(t *testing.T, buf bytes.Buffer) *goquery.Doc {     doc, err := goquery.NewDocumentFromReader(bytes.NewReader(buf.Bytes()))     if err != nil {       // if parsing fails, we cease the take a look at right here with t.FatalF       t.Fatalf("Error rendering template %s", err)     }     return doc   } 

Java

  @Check   void todoItemsAreShown() throws IOException {       var mannequin = new TodoList();       mannequin.add("Foo");       mannequin.add("Bar");          var html = renderTemplate("/index.tmpl", mannequin);          var doc = parseHtml(html);       var choice = doc.choose("ul.todo-list li");       assertThat(choice).hasSize(2);       assertThat(choice.get(0).textual content()).isEqualTo("Foo");       assertThat(choice.get(1).textual content()).isEqualTo("Bar");   }      non-public static Doc parseHtml(String html) {       return Jsoup.parse(html, "");   } 

A lot better! At the least in my view. Now that we extracted the parseHtml helper, it is
a good suggestion to examine for sound HTML within the helper:

Go

  func parseHtml(t *testing.T, buf bytes.Buffer) *goquery.Doc {     assertWellFormedHtml(t, buf)     doc, err := goquery.NewDocumentFromReader(bytes.NewReader(buf.Bytes()))     if err != nil {       // if parsing fails, we cease the take a look at right here with t.FatalF       t.Fatalf("Error rendering template %s", err)     }     return doc   }

supply

Java

  non-public static Doc parseHtml(String html) {       var parser = Parser.htmlParser().setTrackErrors(10);       var doc = Jsoup.parse(html, "", parser);       assertThat(parser.getErrors()).isEmpty();       return doc;   }

supply

And with this, we are able to do away with the primary take a look at that we wrote, as we are actually testing for sound HTML on a regular basis.

The second take a look at

Now we’re in an excellent place for testing extra rendering logic. The
second dynamic function in our record is “Listing gadgets ought to get the category
accomplished when marked as accomplished”. We will write a take a look at for this:

Go

  func Test_completedItemsGetCompletedClass(t *testing.T) {     mannequin := todo.NewList()     mannequin.Add("Foo")     mannequin.AddCompleted("Bar")        buf := renderTemplate("index.tmpl", mannequin)        doc := parseHtml(t, buf)     choice := doc.Discover("ul.todo-list li.accomplished")     assert.Equal(t, 1, choice.Measurement())     assert.Equal(t, "Bar", textual content(choice.Nodes[0]))   }

supply

Java

  @Check   void completedItemsGetCompletedClass() {       var mannequin = new TodoList();       mannequin.add("Foo");       mannequin.addCompleted("Bar");          var html = renderTemplate("/index.tmpl", mannequin);          Doc doc = Jsoup.parse(html, "");       var choice = doc.choose("ul.todo-list li.accomplished");       assertThat(choice).hasSize(1);       assertThat(choice.textual content()).isEqualTo("Bar");   }

supply

And this take a look at may be made inexperienced by including this little bit of logic to the
template:

Go

  <ul class="todo-list">     {{ vary .Gadgets }}       <li class="{{ if .IsCompleted }}accomplished{{ finish }}">         <div class="view">           <enter class="toggle" kind="checkbox">           <label>{{ .Title }}</label>           <button class="destroy"></button>         </div>       </li>     {{ finish }}   </ul>

supply

Java – jmustache

  <ul class="todo-list">     {{ #allItems }}     <li class="{{ #isCompleted }}accomplished{{ /isCompleted }}">       <div class="view">         <enter class="toggle" kind="checkbox">         <label>{{ title }}</label>         <button class="destroy"></button>       </div>     </li>     {{ /allItems }}   </ul>

supply

So little by little, we are able to take a look at and add the assorted dynamic options
that our template ought to have.

Make it simple so as to add new exams

The primary of the 20 ideas from the superb discuss by Russ Cox on Go
Testing
is “Make it simple so as to add new take a look at circumstances“. Certainly, in Go there
is a bent to make most exams parameterized, for this very cause.
Alternatively, whereas Java has
good assist
for parameterized exams
with JUnit 5, they aren’t used as a lot.

Since our present two exams have the identical construction, we
may issue them right into a single parameterized take a look at.

A take a look at case for us will encompass:

  • A reputation (in order that we are able to produce clear error messages when the take a look at
    fails)
  • A mannequin (in our case a todo.Listing)
  • A CSS selector
  • A listing of textual content matches that we anticipate finding once we run the CSS
    selector on the rendered HTML.

So that is the info construction for our take a look at circumstances:

Go

  var testCases = []struct {     title     string     mannequin    *todo.Listing     selector string     matches  []string   }{     {       title: "all todo gadgets are proven",       mannequin: todo.NewList().         Add("Foo").         Add("Bar"),       selector: "ul.todo-list li",       matches:  []string{"Foo", "Bar"},     },     {       title: "accomplished gadgets get the 'accomplished' class",       mannequin: todo.NewList().         Add("Foo").         AddCompleted("Bar"),       selector: "ul.todo-list li.accomplished",       matches:  []string{"Bar"},     },   }

supply

Java

  file TestCase(String title,                   TodoList mannequin,                   String selector,                   Listing<String> matches) {       @Override       public String toString() {           return title;       }   }      public static TestCase[] indexTestCases() {       return new TestCase[]{               new TestCase(                       "all todo gadgets are proven",                       new TodoList()                               .add("Foo")                               .add("Bar"),                       "ul.todo-list li",                       Listing.of("Foo", "Bar")),               new TestCase(                       "accomplished gadgets get the 'accomplished' class",                       new TodoList()                               .add("Foo")                               .addCompleted("Bar"),                       "ul.todo-list li.accomplished",                       Listing.of("Bar")),       };   }

supply

And that is our parameterized take a look at:

Go

  func Test_indexTemplate(t *testing.T) {     for _, take a look at := vary testCases {       t.Run(take a look at.title, func(t *testing.T) {         buf := renderTemplate("index.tmpl", take a look at.mannequin)            assertWellFormedHtml(t, buf)         doc := parseHtml(t, buf)         choice := doc.Discover(take a look at.selector)         require.Equal(t, len(take a look at.matches), len(choice.Nodes), "surprising # of matches")         for i, node := vary choice.Nodes {           assert.Equal(t, take a look at.matches[i], textual content(node))         }       })     }   }

supply

Java

  @ParameterizedTest   @MethodSource("indexTestCases")   void testIndexTemplate(TestCase take a look at) {       var html = renderTemplate("/index.tmpl", take a look at.mannequin);          var doc = parseHtml(html);       var choice = doc.choose(take a look at.selector);       assertThat(choice).hasSize(take a look at.matches.dimension());       for (int i = 0; i < take a look at.matches.dimension(); i++) {           assertThat(choice.get(i).textual content()).isEqualTo(take a look at.matches.get(i));       }   }

supply

We will now run our parameterized take a look at and see it move:

Go

  $ go take a look at -v   === RUN   Test_indexTemplate   === RUN   Test_indexTemplate/all_todo_items_are_shown   === RUN   Test_indexTemplate/completed_items_get_the_'accomplished'_class   --- PASS: Test_indexTemplate (0.00s)       --- PASS: Test_indexTemplate/all_todo_items_are_shown (0.00s)       --- PASS: Test_indexTemplate/completed_items_get_the_'accomplished'_class (0.00s)   PASS   okay    tdd-html-templates  0.608s

Java

  $ ./gradlew take a look at      > Activity :take a look at      IndexTemplateTest > testIndexTemplate(TestCase) > [1] all todo gadgets are proven PASSED   IndexTemplateTest > testIndexTemplate(TestCase) > [2] accomplished gadgets get the 'accomplished' class PASSED

Be aware how, by giving a reputation to our take a look at circumstances, we get very readable take a look at output, each on the terminal and within the IDE:

Having rewritten our two outdated exams in desk type, it is now tremendous simple so as to add
one other. That is the take a look at for the “x gadgets left” textual content:

Go

  {     title: "gadgets left",     mannequin: todo.NewList().       Add("One").       Add("Two").       AddCompleted("Three"),     selector: "span.todo-count",     matches:  []string{"2 gadgets left"},   },

supply

Java

  new TestCase(       "gadgets left",       new TodoList()               .add("One")               .add("Two")               .addCompleted("Three"),       "span.todo-count",       Listing.of("2 gadgets left")),

supply

And the corresponding change within the html template is:

Go

  <span class="todo-count"><sturdy>{{len .ActiveItems}}</sturdy> gadgets left</span>

supply

Java – jmustache

  <span class="todo-count"><sturdy>{{activeItemsCount}}</sturdy> gadgets left</span>

supply

The above change within the template requires a supporting methodology within the mannequin:

Go

  kind Merchandise struct {     Title       string     IsCompleted bool   }      kind Listing struct {     Gadgets []*Merchandise   }      func (l *Listing) ActiveItems() []*Merchandise {     var end result []*Merchandise     for _, merchandise := vary l.Gadgets {       if !merchandise.IsCompleted {         end result = append(end result, merchandise)       }     }     return end result   } 

supply

Java

  public class TodoList {       non-public last Listing<TodoItem> gadgets = new ArrayList<>();       // ...       public lengthy activeItemsCount() {           return gadgets.stream().filter(TodoItem::isActive).rely();       }   }

supply

We have invested slightly effort in our testing infrastructure, in order that including new
take a look at circumstances is simpler. Within the subsequent part, we’ll see that the necessities
for the following take a look at circumstances will push us to refine our take a look at infrastructure additional.

Making the desk extra expressive, on the expense of the take a look at code

We are going to now take a look at the “All”, “Lively” and “Accomplished” navigation hyperlinks at
the underside of the UI (see the image above),
and these depend upon which url we’re visiting, which is
one thing that our template has no approach to discover out.

Presently, all we move to our template is our mannequin, which is a todo-list.
It is not appropriate so as to add the at the moment visited url to the mannequin, as a result of that’s
consumer navigation state, not software state.

So we have to move extra info to the template past the mannequin. A straightforward method
is to move a map, which we assemble in our
renderTemplate perform:

Go

  func renderTemplate(mannequin *todo.Listing, path string) bytes.Buffer {     templ := template.Should(template.ParseFiles("index.tmpl"))     var buf bytes.Buffer     information := map[string]any{       "mannequin": mannequin,       "path":  path,     }     err := templ.Execute(&buf, information)     if err != nil {       panic(err)     }     return buf   }

Java

  non-public String renderTemplate(String templateName, TodoList mannequin, String path) {       var template = Mustache.compiler().compile(               new InputStreamReader(                       getClass().getResourceAsStream(templateName)));       var information = Map.of(               "mannequin", mannequin,               "path", path       );       return template.execute(information);   }

And correspondingly our take a look at circumstances desk has yet another area:

Go

  var testCases = []struct {     title     string     mannequin    *todo.Listing     path     string     selector string     matches  []string   }{     {       title: "all todo gadgets are proven",       mannequin: todo.NewList().         Add("Foo").         Add("Bar"),       selector: "ul.todo-list li",       matches:  []string{"Foo", "Bar"},     },   // ... the opposite circumstances     {       title:     "highlighted navigation hyperlink: All",       path:     "/",       selector: "ul.filters a.chosen",       matches:  []string{"All"},     },     {       title:     "highlighted navigation hyperlink: Lively",       path:     "/lively",       selector: "ul.filters a.chosen",       matches:  []string{"Lively"},     },     {       title:     "highlighted navigation hyperlink: Accomplished",       path:     "/accomplished",       selector: "ul.filters a.chosen",       matches:  []string{"Accomplished"},     },   }

Java

  file TestCase(String title,                   TodoList mannequin,                   String path,                   String selector,                   Listing<String> matches) {       @Override       public String toString() {           return title;       }   }      public static TestCase[] indexTestCases() {       return new TestCase[]{               new TestCase(                       "all todo gadgets are proven",                       new TodoList()                               .add("Foo")                               .add("Bar"),                       "/",                       "ul.todo-list li",                       Listing.of("Foo", "Bar")),               // ... the earlier circumstances               new TestCase(                       "highlighted navigation hyperlink: All",                       new TodoList(),                       "/",                       "ul.filters a.chosen",                       Listing.of("All")),               new TestCase(                       "highlighted navigation hyperlink: Lively",                       new TodoList(),                       "/lively",                       "ul.filters a.chosen",                       Listing.of("Lively")),               new TestCase(                       "highlighted navigation hyperlink: Accomplished",                       new TodoList(),                       "/accomplished",                       "ul.filters a.chosen",                       Listing.of("Accomplished")),       };   }

We discover that for the three new circumstances, the mannequin is irrelevant;
whereas for the earlier circumstances, the trail is irrelevant. The Go syntax permits us
to initialize a struct with simply the fields we’re occupied with, however Java doesn’t have
the same function, so we’re pushed to move additional info, and this makes the take a look at circumstances
desk tougher to grasp.

A developer may take a look at the primary take a look at case and marvel if the anticipated conduct relies upon
on the trail being set to "/", and may be tempted so as to add extra circumstances with
a unique path. In the identical method, when studying the
highlighted navigation hyperlink take a look at circumstances, the developer may marvel if the
anticipated conduct relies on the mannequin being set to an empty todo record. In that case, one may
be led so as to add irrelevant take a look at circumstances for the highlighted hyperlink with non-empty todo-lists.

We wish to optimize for the time of the builders, so it is worthwhile to keep away from including irrelevant
information to our take a look at case. In Java we’d move null for the
irrelevant fields, however there’s a greater method: we are able to use
the builder sample,
popularized by Joshua Bloch.
We will rapidly write one for the Java TestCase file this manner:

Java

  file TestCase(String title,                   TodoList mannequin,                   String path,                   String selector,                   Listing<String> matches) {       @Override       public String toString() {           return title;       }          public static last class Builder {           String title;           TodoList mannequin;           String path;           String selector;           Listing<String> matches;              public Builder title(String title) {               this.title = title;               return this;           }              public Builder mannequin(TodoList mannequin) {               this.mannequin = mannequin;               return this;           }              public Builder path(String path) {               this.path = path;               return this;           }              public Builder selector(String selector) {               this.selector = selector;               return this;           }              public Builder matches(String ... matches) {               this.matches = Arrays.asList(matches);               return this;           }              public TestCase construct() {               return new TestCase(title, mannequin, path, selector, matches);           }       }   }

Hand-coding builders is slightly tedious, however doable, although there are
automated methods to jot down them.
Now we are able to rewrite our Java take a look at circumstances with the Builder, to
obtain larger readability:

Java

  public static TestCase[] indexTestCases() {       return new TestCase[]{               new TestCase.Builder()                       .title("all todo gadgets are proven")                       .mannequin(new TodoList()                               .add("Foo")                               .add("Bar"))                       .selector("ul.todo-list li")                       .matches("Foo", "Bar")                       .construct(),               // ... different circumstances               new TestCase.Builder()                       .title("highlighted navigation hyperlink: Accomplished")                       .path("/accomplished")                       .selector("ul.filters a.chosen")                       .matches("Accomplished")                       .construct(),       };   }

So, the place are we with our exams? At current, they fail for the unsuitable cause: null-pointer exceptions
as a result of lacking mannequin and path values.
So as to get our new take a look at circumstances to fail for the appropriate cause, specifically that the template does
not but have logic to focus on the right hyperlink, we should
present default values for mannequin and path. In Go, we are able to do that
within the take a look at methodology:

Go

  func Test_indexTemplate(t *testing.T) {     for _, take a look at := vary testCases {       t.Run(take a look at.title, func(t *testing.T) {         if take a look at.mannequin == nil {           take a look at.mannequin = todo.NewList()         }         buf := renderTemplate(take a look at.mannequin, take a look at.path)         // ... identical as earlier than        })     }   }

supply

In Java, we are able to present default values within the builder:

Java

  public static last class Builder {       String title;       TodoList mannequin = new TodoList();       String path = "/";       String selector;       Listing<String> matches;       // ...   }

supply

With these modifications, we see that the final two take a look at circumstances, those for the highlighted hyperlink Lively
and Accomplished fail, for the anticipated cause that the highlighted hyperlink doesn’t change:

Go

  === RUN   Test_indexTemplate/highlighted_navigation_link:_Active       index_template_test.go:82:              Error Hint:  .../tdd-templates/go/index_template_test.go:82             Error:        Not equal:                            anticipated: "Lively"                           precise  : "All"   === RUN   Test_indexTemplate/highlighted_navigation_link:_Completed       index_template_test.go:82:              Error Hint:  .../tdd-templates/go/index_template_test.go:82             Error:        Not equal:                            anticipated: "Accomplished"                           precise  : "All" 

Java

  IndexTemplateTest > testIndexTemplate(TestCase) > [5] highlighted navigation hyperlink: Lively FAILED       org.opentest4j.AssertionFailedError:       Anticipating:        <"All">       to be equal to:        <"Lively">       however was not.      IndexTemplateTest > testIndexTemplate(TestCase) > [6] highlighted navigation hyperlink: Accomplished FAILED       org.opentest4j.AssertionFailedError:       Anticipating:        <"All">       to be equal to:        <"Accomplished">       however was not.

To make the exams move, we make these modifications to the template:

Go

  <ul class="filters">     <li>       <a class="{{ if eq .path "/" }}chosen{{ finish }}" href="#/">All</a>     </li>     <li>       <a class="{{ if eq .path "/lively" }}chosen{{ finish }}" href="#/lively">Lively</a>     </li>     <li>       <a class="{{ if eq .path "/accomplished" }}chosen{{ finish }}" href="#/accomplished">Accomplished</a>     </li>   </ul>

supply

Java – jmustache

  <ul class="filters">     <li>       <a class="{{ #pathRoot }}chosen{{ /pathRoot }}" href="#/">All</a>     </li>     <li>       <a class="{{ #pathActive }}chosen{{ /pathActive }}" href="#/lively">Lively</a>     </li>     <li>       <a class="{{ #pathCompleted }}chosen{{ /pathCompleted }}" href="#/accomplished">Accomplished</a>     </li>   </ul>

supply

For the reason that Mustache template language doesn’t enable for equality testing, we should change the
information handed to the template in order that we execute the equality exams earlier than rendering the template:

Java

  non-public String renderTemplate(String templateName, TodoList mannequin, String path) {       var template = Mustache.compiler().compile(               new InputStreamReader(                       getClass().getResourceAsStream(templateName)));       var information = Map.of(               "mannequin", mannequin,               "pathRoot", path.equals("/"),               "pathActive", path.equals("/lively"),               "pathCompleted", path.equals("/accomplished")       );       return template.execute(information);   }

supply

And with these modifications, all of our exams now move.

To recap this part, we made the take a look at code slightly bit extra difficult, in order that the take a look at
circumstances are clearer: it is a excellent tradeoff!

Degree 3: testing HTML behaviour

Within the story to this point, we examined the behaviour of the HTML
templates
, by checking the construction of the generated HTML.
That is good, however what if we needed to check the behaviour of the HTML
itself, plus any CSS and JavaScript it could use?

The behaviour of HTML by itself is often fairly apparent, as a result of
there may be not a lot of it. The one components that may work together with the
consumer are the anchor (<a>), <type> and
<enter> components, however the image modifications utterly when
we add CSS, that may disguise, present, transfer round issues and much extra, and
with JavaScript, that may add any behaviour to a web page.

In an software that’s primarily rendered server-side, we count on
that the majority behaviour is applied by returning new HTML with a
round-trip to the consumer, and this may be examined adequately with the
strategies we have seen to this point, however what if we needed to hurry up the
software behaviour with a library corresponding to HTMX? This library works by way of particular
attributes which can be added to components so as to add Ajax behaviour. These
attributes are in impact a DSL that we’d wish to
take a look at.

How can we take a look at the mixture of HTML, CSS and JavaScript in
a unit take a look at?

Testing HTML, CSS and JavaScript requires one thing that is ready to
interpret and execute their behaviours; in different phrases, we want a
browser! It’s customary to make use of headless browsers in end-to-end exams;
can we use them for unitary exams as a substitute? I believe that is attainable,
utilizing the next strategies, though I have to admit I’ve but to attempt
this on an actual mission.

We are going to use the Playwright
library, that’s accessible for each Go and
Java. The exams we
are going to jot down might be slower, as a result of we must wait a couple of
seconds for the headless browser to start out, however will retain among the
vital traits of unit exams, primarily that we’re testing
simply the HTML (and any related CSS and JavaScript), in isolation from
some other server-side logic.

Persevering with with the TodoMVC
instance, the following factor we’d wish to take a look at is what occurs when the
consumer clicks on the checkbox of a todo merchandise. What we might prefer to occur is
that:

  1. A POST name to the server is made, in order that the applying is aware of
    that the state of a todo merchandise has modified
  2. The server returns new HTML for the dynamic a part of the web page,
    specifically the entire part with class “todoapp”, in order that we are able to present the
    new state of the applying together with the rely of remaining “lively”
    gadgets (see the template above)
  3. The web page replaces the outdated contents of the “todoapp” part with
    the brand new ones.

Loading the web page within the Playwright browser

We begin with a take a look at that may simply load the preliminary HTML. The take a look at
is slightly concerned, so I present the whole code right here, after which I’ll
remark it little by little.

Go

  func Test_toggleTodoItem(t *testing.T) {     // render the preliminary HTML     mannequin := todo.NewList().       Add("One").       Add("Two")     initialHtml := renderTemplate("index.tmpl", mannequin, "/")        // open the browser web page with Playwright     web page := openPage()     defer web page.Shut()     logActivity(web page)        // stub community calls     err := web page.Route("**", func(route playwright.Route) {       if route.Request().URL() == "http://localhost:4567/index.html" {         // serve the preliminary HTML         stubResponse(route, initialHtml.String(), "textual content/html")       } else {         // keep away from surprising requests         panic("surprising request: " + route.Request().URL())       }     })     if err != nil {       t.Deadly(err)     }        // load preliminary HTML within the web page     response, err := web page.Goto("http://localhost:4567/index.html")     if err != nil {       t.Deadly(err)     }     if response.Standing() != 200 {       t.Fatalf("surprising standing: %d", response.Standing())     }   }

supply

Java

  public class IndexBehaviourTest {       static Playwright playwright;       static Browser browser;          @BeforeAll       static void launchBrowser() {           playwright = Playwright.create();           browser = playwright.chromium().launch();       }          @AfterAll       static void closeBrowser() {           playwright.shut();       }          @Check       void toggleTodoItem() {           // Render the preliminary html           TodoList mannequin = new TodoList()                   .add("One")                   .add("Two");           String initialHtml = renderTemplate("/index.tmpl", mannequin, "/");                      attempt (Web page web page = browser.newPage()) {               logActivity(web page);                  // stub community calls               web page.route("**", route -> {                   if (route.request().url().equals("http://localhost:4567/index.html")) {                       // serve the preliminary HTML                       route.fulfill(new Route.FulfillOptions()                               .setContentType("textual content/html")                               .setBody(initialHtml));                   } else {                       // we do not need surprising calls                       fail(String.format("Sudden request: %s %s", route.request().methodology(), route.request().url()));                   }               });                          // load preliminary html               web page.navigate("http://localhost:4567/index.html");           }       }   }

supply

Firstly of the take a look at, we initialize the mannequin with two todo
gadgets “One” and “Two”, then we render the template as earlier than:

Go

  mannequin := todo.NewList().     Add("One").     Add("Two")   initialHtml := renderTemplate("index.tmpl", mannequin, "/") 

Java

  TodoList mannequin = new TodoList()           .add("One")           .add("Two");   String initialHtml = renderTemplate("/index.tmpl", mannequin, "/");

Then we open the Playwright “web page”, which can begin a headless
browser

Go

  web page := openPage()   defer web page.Shut()   logActivity(web page) 

Java

  attempt (Web page web page = browser.newPage()) {       logActivity(web page);

The openPage perform in Go returns a Playwright
Web page object,

Go

  func openPage() playwright.Web page {     pw, err := playwright.Run()     if err != nil {       log.Fatalf("couldn't begin playwright: %v", err)     }     browser, err := pw.Chromium.Launch()     if err != nil {       log.Fatalf("couldn't launch browser: %v", err)     }     web page, err := browser.NewPage()     if err != nil {       log.Fatalf("couldn't create web page: %v", err)     }     return web page   }

and the logActivity perform gives suggestions on what
the web page is doing

Go

  func logActivity(web page playwright.Web page) {     web page.OnRequest(func(request playwright.Request) {       log.Printf(">> %s %sn", request.Methodology(), request.URL())     })     web page.OnResponse(func(response playwright.Response) {       log.Printf("<< %d %sn", response.Standing(), response.URL())     })     web page.OnLoad(func(web page playwright.Web page) {       log.Println("Loaded: " + web page.URL())     })     web page.OnConsole(func(message playwright.ConsoleMessage) {       log.Println("!  " + message.Textual content())     })   }

Java

  non-public void logActivity(Web page web page) {       web page.onRequest(request -> System.out.printf(">> %s %spercentn", request.methodology(), request.url()));       web page.onResponse(response -> System.out.printf("<< %s %spercentn", response.standing(), response.url()));       web page.onLoad(page1 -> System.out.println("Loaded: " + page1.url()));       web page.onConsoleMessage(consoleMessage -> System.out.println("!  " + consoleMessage.textual content()));   }

Then we stub all community exercise that the web page may attempt to do

Go

  err := web page.Route("**", func(route playwright.Route) {     if route.Request().URL() == "http://localhost:4567/index.html" {       // serve the preliminary HTML       stubResponse(route, initialHtml.String(), "textual content/html")     } else {       // keep away from surprising requests       panic("surprising request: " + route.Request().URL())     }   }) 

Java

  // stub community calls   web page.route("**", route -> {       if (route.request().url().equals("http://localhost:4567/index.html")) {           // serve the preliminary HTML           route.fulfill(new Route.FulfillOptions()                   .setContentType("textual content/html")                   .setBody(initialHtml));       } else {           // we do not need surprising calls           fail(String.format("Sudden request: %s %s", route.request().methodology(), route.request().url()));       }   });

and we ask the web page to load the preliminary HTML

Go

  response, err := web page.Goto("http://localhost:4567/index.html") 

Java

  web page.navigate("http://localhost:4567/index.html");

With all this equipment in place, we run the take a look at; it succeeds and
it logs the stubbed community exercise on customary output:

Go

  === RUN   Test_toggleTodoItem   >> GET http://localhost:4567/index.html   << 200 http://localhost:4567/index.html   Loaded: http://localhost:4567/index.html   --- PASS: Test_toggleTodoItem (0.89s)

Java

  IndexBehaviourTest > toggleTodoItem() STANDARD_OUT       >> GET http://localhost:4567/index.html       << 200 http://localhost:4567/index.html       Loaded: http://localhost:4567/index.html      IndexBehaviourTest > toggleTodoItem() PASSED

So with this take a look at we are actually capable of load arbitrary HTML in a
headless browser. Within the subsequent sections we’ll see how you can simulate consumer
interplay with components of the web page, and observe the web page’s
behaviour. However first we have to resolve an issue with the shortage of
identifiers in our area mannequin.

Figuring out todo gadgets

Now we wish to click on on the “One” checkbox. The issue now we have is
that at current, now we have no approach to determine particular person todo gadgets, so
we introduce an Id area within the todo merchandise:

Go – up to date mannequin with Id

  kind Merchandise struct {     Id          int     Title       string     IsCompleted bool   }      func (l *Listing) AddWithId(id int, title string) *Listing {     merchandise := Merchandise{       Id:    id,       Title: title,     }     l.Gadgets = append(l.Gadgets, &merchandise)     return l   }      // Add creates a brand new todo.Merchandise with a random Id   func (l *Listing) Add(title string) *Listing {     merchandise := Merchandise{       Id:    generateRandomId(),       Title: title,     }     l.Gadgets = append(l.Gadgets, &merchandise)     return l   }      func generateRandomId() int {     return abs(rand.Int())   }

Java – up to date mannequin with Id

  public class TodoList {       non-public last Listing<TodoItem> gadgets = new ArrayList<>();          public TodoList add(String title) {           gadgets.add(new TodoItem(generateRandomId(), title, false));           return this;       }          public TodoList addCompleted(String title) {           gadgets.add(new TodoItem(generateRandomId(), title, true));           return this;       }          public TodoList add(int id, String title) {           gadgets.add(new TodoItem(id, title, false));           return this;       }          non-public static int generateRandomId() {           return new Random().nextInt(0, Integer.MAX_VALUE);       }   }      public file TodoItem(int id, String title, boolean isCompleted) {       public boolean isActive() {           return !isCompleted;       }   }

And we replace the mannequin in our take a look at so as to add express Ids

Go – including Id within the take a look at information

  func Test_toggleTodoItem(t *testing.T) {     // render the preliminary HTML     mannequin := todo.NewList().       AddWithId(101, "One").       AddWithId(102, "Two")     initialHtml := renderTemplate("index.tmpl", mannequin, "/")     // ...    }

Java – including Id within the take a look at information

  @Check   void toggleTodoItem() {       // Render the preliminary html       TodoList mannequin = new TodoList()               .add(101, "One")               .add(102, "Two");       String initialHtml = renderTemplate("/index.tmpl", mannequin, "/");   }

We are actually prepared to check consumer interplay with the web page.

Clicking on a todo merchandise

We wish to simulate consumer interplay with the HTML web page. It may be
tempting to proceed to make use of CSS selectors to determine the particular
checkbox that we wish to click on, however there’s a greater method: there’s a
consensus amongst front-end builders that one of the best ways to check
interplay with a web page is to make use of it
the identical method that customers do
. As an example, you do not search for a
button by way of a CSS locator corresponding to button.purchase; as a substitute,
you search for one thing clickable with the label “Purchase”. In apply,
this implies figuring out elements of the web page by way of their
ARIA
roles.

To this finish, we add code to our take a look at to search for a checkbox labelled
“One”:

Go

  func Test_toggleTodoItem(t *testing.T) {     // ...     // click on on the "One" checkbox     checkbox := web page.GetByRole(*playwright.AriaRoleCheckbox, playwright.PageGetByRoleOptions{Identify: "One"})     if err := checkbox.Click on(); err != nil {       t.Deadly(err)     }   }

Java

  @Check   void toggleTodoItem() {           // ...           // click on on the "One" checkbox           var checkbox = web page.getByRole(AriaRole.CHECKBOX, new Web page.GetByRoleOptions().setName("One"));           checkbox.click on();       }   }

We run the take a look at, and it fails:

Go

  >> GET http://localhost:4567/index.html   << 200 http://localhost:4567/index.html   Loaded: http://localhost:4567/index.html   --- FAIL: Test_toggleTodoItem (32.74s)       index_behaviour_test.go:50: playwright: timeout: Timeout 30000ms exceeded.

Java

  IndexBehaviourTest > toggleTodoItem() STANDARD_OUT       >> GET http://localhost:4567/index.html       << 200 http://localhost:4567/index.html       Loaded: http://localhost:4567/index.html      IndexBehaviourTest > toggleTodoItem() FAILED       com.microsoft.playwright.TimeoutError: Error {         message="hyperlink the label to the checkbox correctly: 

generated HTML with dangerous accessibility

  <li>     <div class="view">       <enter class="toggle" kind="checkbox">       <label>One</label>       <button class="destroy"></button>     </div>   </li>

We repair it through the use of the for attribute within the
template,

index.tmpl – Go

  <li>     <div class="view">       <enter id="checkbox-{{.Id}}" class="toggle" kind="checkbox">       <label for="checkbox-{{.Id}}">{{.Title}}</label>       <button class="destroy"></button>     </div>   </li>

index.tmpl – Java

  <li>     <div class="view">       <enter id="checkbox-{{ id }}" class="toggle" kind="checkbox">       <label for="checkbox-{{ id }}">{{ title }}</label>       <button class="destroy"></button>     </div>   </li>

In order that it generates correct, accessible HTML:

generated HTML with higher accessibility

  <li>     <div class="view">       <enter id="checkbox-101" class="toggle" kind="checkbox">       <label for="checkbox-101">One</label>       <button class="destroy"></button>     </div>   </li>

We run once more the take a look at, and it passes.

On this part we noticed how testing the HTML in the identical was as customers
work together with it led us to make use of ARIA roles, which led to enhancing
accessibility of our generated HTML. Within the subsequent part, we'll see
how you can take a look at that the clicking on a todo merchandise triggers a distant name to the
server, that ought to lead to swapping part of the present HTML with
the HTML returned by the XHR name.

Spherical-trip to the server

Now we’ll prolong our take a look at. We inform the take a look at that if name to
POST /toggle/101 is obtained, it ought to return some
stubbed HTML.

Go

  } else if route.Request().URL() == "http://localhost:4567/toggle/101" && route.Request().Methodology() == "POST" {     // we count on {that a} POST /toggle/101 request is made once we click on on the "One" checkbox     const stubbedHtml = `       <part class="todoapp">         <p>Stubbed html</p>       </part>`     stubResponse(route, stubbedHtml, "textual content/html")

Java

  } else if (route.request().url().equals("http://localhost:4567/toggle/101") && route.request().methodology().equals("POST")) {       // we count on {that a} POST /toggle/101 request is made once we click on on the "One" checkbox       String stubbedHtml = """           <part class="todoapp">               <p>Stubbed html</p>           </part>           """;       route.fulfill(new Route.FulfillOptions()               .setContentType("textual content/html")               .setBody(stubbedHtml));

And we stub the loading of the HTMX library, which we load from a
native file:

Go

  } else if route.Request().URL() == "https://unpkg.com/htmx.org@1.9.12" {     // serve the htmx library     stubResponse(route, readFile("testdata/htmx.min.js"), "software/javascript")

Go

  } else if (route.request().url().equals("https://unpkg.com/htmx.org@1.9.12")) {       // serve the htmx library       route.fulfill(new Route.FulfillOptions()               .setContentType("textual content/html")               .setBody(readFile("/htmx.min.js")));

Lastly, we add the expectation that, after we click on the checkbox,
the part of the HTML that incorporates many of the software is
reloaded.

Go

  // click on on the "One" checkbox   checkbox := web page.GetByRole(*playwright.AriaRoleCheckbox, playwright.PageGetByRoleOptions{Identify: "One"})   if err := checkbox.Click on(); err != nil {     t.Deadly(err)   }   // examine that the web page has been up to date   doc := parseHtml(t, content material(t, web page))   components := doc.Discover("physique > part.todoapp > p")   assert.Equal(t, "Stubbed html", components.Textual content(), should(web page.Content material())) 

java

  // click on on the "One" checkbox   var checkbox = web page.getByRole(AriaRole.CHECKBOX, new Web page.GetByRoleOptions().setName("One"));   checkbox.click on();   // examine that the web page has been up to date   var doc = parseHtml(web page.content material());   var components = doc.choose("physique > part.todoapp > p");   assertThat(components.textual content())           .describedAs(web page.content material())           .isEqualTo("Stubbed html");

We run the take a look at, and it fails, as anticipated. So as to perceive
why precisely it fails, we add to the error message the entire HTML
doc.

Go

  assert.Equal(t, "Stubbed html", components.Textual content(), should(web page.Content material())) 

Java

  assertThat(components.textual content())           .describedAs(web page.content material())           .isEqualTo("Stubbed html");

The error message may be very verbose, however we see that the explanation it
fails is that we do not see the stubbed HTML within the output. This implies
that the web page didn’t make the anticipated XHR name.

Go – Java is analogous

  --- FAIL: Test_toggleTodoItem (2.75s)   === RUN   Test_toggleTodoItem   >> GET http://localhost:4567/index.html   << 200 http://localhost:4567/index.html   Loaded: http://localhost:4567/index.html       index_behaviour_test.go:67:             Error Hint:  .../index_behaviour_test.go:67             Error:        Not equal:                           anticipated: "Stubbed html"                           precise  : ""                           ...             Check:         Test_toggleTodoItem             Messages:     <!DOCTYPE html><html lang="en"><head>                               <meta charset="utf-8">                               <meta title="viewport" content material="width=device-width, initial-scale=1">                               <title>Template • TodoMVC</title>                               <script src="https://unpkg.com/htmx.org@1.9.12"></script>                             <physique>                               <part class="todoapp">                           ...                                     <li class="">                                       <div class="view">                                         <enter id="checkbox-101" class="toggle" kind="checkbox">                                         <label for="checkbox-101">One</label>                                         <button class="destroy"></button>                                       </div>                                     </li>                           ...

We will make this take a look at move by altering the HTML template to make use of HTMX
to make an XHR name again to the server. First we load the HTMX
library:

index.tmpl

  <title>Template • TodoMVC</title>   <script src="https://unpkg.com/htmx.org@1.9.12"></script> 

Then we add the HTMX attributes to the checkboxes:

index.tmpl

  <enter       data-hx-post="/toggle/{{.Id}}"       data-hx-target="part.todoapp"       id="checkbox-{{.Id}}"       class="toggle"       kind="checkbox">

The data-hx-post annotation will make HTMX do a POST
name to the required url. The data-hx-target tells HTMX
to repeat the HTML returned by the decision, to the component specified by the
part.todoapp CSS locator.

We run once more the take a look at, and it nonetheless fails!

Go – Java is analogous

  --- FAIL: Test_toggleTodoItem (2.40s)   === RUN   Test_toggleTodoItem   >> GET http://localhost:4567/index.html   << 200 http://localhost:4567/index.html   >> GET https://unpkg.com/htmx.org@1.9.12   << 200 https://unpkg.com/htmx.org@1.9.12   Loaded: http://localhost:4567/index.html   >> POST http://localhost:4567/toggle/101   << 200 http://localhost:4567/toggle/101       index_behaviour_test.go:67:             Error Hint:  .../index_behaviour_test.go:67             Error:        Not equal:                           anticipated: "Stubbed html"                           precise  : ""                           ...             Check:         Test_toggleTodoItem             Messages:     <!DOCTYPE html><html lang="en"><head>                               <meta charset="utf-8">                               <meta title="viewport" content material="width=device-width, initial-scale=1">                               <title>Template • TodoMVC</title>                               <script src="https://unpkg.com/htmx.org@1.9.12"></script>                           ...                             <physique>                               <part class="todoapp"><part class="todoapp">                                     <p>Stubbed html</p>                                   </part></part>                           ...                           </physique></html>

The log strains present that the POST name occurred as anticipated, however
examination of the error message reveals that the HTML construction we
anticipated just isn’t there: now we have a part.todoapp nested
inside one other. Because of this we aren’t utilizing the HTMX annotations
accurately, and reveals why this type of take a look at may be beneficial. We add the
lacking annotation

index.tmpl

  <enter       data-hx-post="/toggle/{{.Id}}"       data-hx-target="part.todoapp"       data-hx-swap="outerHTML"       id="checkbox-{{.Id}}"       class="toggle"       kind="checkbox">

The default behaviour of HTMX is to switch the internal HTML of the
goal component. The data-hx-swap="outerHTML" annotation
tells HTMX to switch the outer HTML as a substitute.

and we take a look at once more, and this time it passes!

Go

  === RUN   Test_toggleTodoItem   >> GET http://localhost:4567/index.html   << 200 http://localhost:4567/index.html   >> GET https://unpkg.com/htmx.org@1.9.12   << 200 https://unpkg.com/htmx.org@1.9.12   Loaded: http://localhost:4567/index.html   >> POST http://localhost:4567/toggle/101   << 200 http://localhost:4567/toggle/101   --- PASS: Test_toggleTodoItem (1.39s)

Java

  IndexBehaviourTest > toggleTodoItem() STANDARD_OUT       >> GET http://localhost:4567/index.html       << 200 http://localhost:4567/index.html       >> GET https://unpkg.com/htmx.org@1.9.12       << 200 https://unpkg.com/htmx.org@1.9.12       Loaded: http://localhost:4567/index.html       >> POST http://localhost:4567/toggle/101       << 200 http://localhost:4567/toggle/101      IndexBehaviourTest > toggleTodoItem() PASSED

On this part we noticed how you can write a take a look at for the behaviour of our
HTML that, whereas utilizing the difficult equipment of a headless browser,
nonetheless feels extra like a unit take a look at than an integration take a look at. It’s in
truth testing simply an HTML web page with any related CSS and JavaScript,
in isolation from different elements of the applying corresponding to controllers,
companies or repositories.

The take a look at prices 2-3 seconds of ready time for the headless browser to return up, which is often an excessive amount of for a unit take a look at; nevertheless, like a unit take a look at, it is rather secure, as it’s not flaky, and its failures are documented with a comparatively clear error message.

See the ultimate model of the take a look at in Go and in Java.

Bonus stage: Stringly asserted

Esko Luontola, TDD skilled and writer of the net course tdd.mooc.fi, recommended an alternate to testing HTML with CSS selectors: the concept is to rework HTML right into a human-readable canonical type.

Let’s take for instance this snippet of generated HTML:

<ul class="todo-list">   <li class="">     <div class="view">       <enter id="checkbox-100" class="toggle" kind="checkbox">       <label for="checkbox-100">One</label>       <button class="destroy"></button>     </div>   </li>   <li class="">     <div class="view">       <enter id="checkbox-200" class="toggle" kind="checkbox">       <label for="checkbox-200">Two</label>       <button class="destroy"></button>     </div>   </li>   <li class="accomplished">     <div class="view">       <enter id="checkbox-300" class="toggle" kind="checkbox">       <label for="checkbox-300">Three</label>       <button class="destroy"></button>     </div>   </li> </ul> 

We may visualize the above HTML by:

  1. deleting all HTML tags
  2. decreasing each sequence of whitespace characters to a single clean

to reach at:

One Two Three

This, nevertheless, removes an excessive amount of of the HTML construction to be helpful. As an example, it doesn’t allow us to distinguish between lively and accomplished gadgets. Some HTML component symbolize seen content material: as an illustration

<enter worth="foo" />

reveals a textual content field with the phrase “foo” that is a crucial a part of the method we understand HTML. To visualise these components, Esko suggests so as to add a data-test-icon attribute that provides some textual content for use instead of the component when visualizing it for testing. With this,

<enter worth="foo" data-test-icon="[foo]" />

the enter component is visualized as [foo], with the sq. brackets hinting that the phrase “foo” sits inside an editable textual content field. Now if we add test-icons to our HTML template,

Go — Java is analogous

  <ul class="todo-list">       {{ vary .mannequin.AllItems }}       <li class="{{ if .IsCompleted }}accomplished{{ finish }}">           <div class="view">               <enter data-hx-post="/toggle/{{ .Id }}"                      data-hx-target="part.todoapp"                      data-hx-swap="outerHTML"                      id="checkbox-{{ .Id }}"                      class="toggle"                      kind="checkbox"                      data-test-icon="{{ if .IsCompleted }}✅{{ else }}⬜{{ finish }}">               <label for="checkbox-{{ .Id }}">{{ .Title }}</label>               <button class="destroy" data-test-icon="❌️"></button>           </div>       </li>       {{ finish }}   </ul>

we are able to assert in opposition to its canonical visible illustration like this:

Go

  func Test_visualize_html_example(t *testing.T) {     mannequin := todo.NewList().       Add("One").       Add("Two").       AddCompleted("Three")        buf := renderTemplate("todo-list.tmpl", mannequin, "/")        anticipated := `       ⬜ One ❌️       ⬜ Two ❌️       ✅ Three ❌️       `     assert.Equal(t, normalizeWhitespace(anticipated), visualizeHtml(buf.String()))   }

Java

  @Check   void visualize_html_example() {       var mannequin = new TodoList()               .add("One")               .add("Two")               .addCompleted("Three");          var html = renderTemplate("/todo-list.tmpl", mannequin, "/");          assertThat(visualizeHtml(html))               .isEqualTo(normalizeWhitespace("""                       ⬜ One ❌️                       ⬜ Two ❌️                       ✅ Three ❌️                       """));   }

Right here is Esko Luontola’s Java implementation of the 2 features that make this attainable, and my translation to Go of his code.

Go

  func visualizeHtml(html string) string abbr      func normalizeWhitespace(s string) string {     return strings.TrimSpace(replaceAll(s, "s+", " "))   }      func replaceAll(src, regex, repl string) string {     re := regexp.MustCompile(regex)     return re.ReplaceAllString(src, repl)   }

supply

Java

  public static String visualizeHtml(String html) tt)b.*?>", "") // inline components              .replaceAll("<[^>]*>", " ");  // block components      // substitute HTML character entities      html = html.replaceAll("&nbsp;", " ")              .replaceAll("&lt;", "<") // have to be after stripping HTML tags, to keep away from creating unintended components              .replaceAll("&gt;", ">")              .replaceAll("&quot;", """)              .replaceAll("&apos;", "'")              .replaceAll("&amp;", "&"); // have to be final, to keep away from creating unintended character entities      return normalizeWhitespace(html);         public static String normalizeWhitespace(String s) {      return s.replaceAll("s+", " ").trim();   }

supply

On this part, now we have seen a method for asserting HTML content material that’s an alternative choice to the CSS selector-based approach utilized in the remainder of the article. Esko Luontola has reported nice success with it, and I hope readers have success with it too!

This method of asserting in opposition to giant, difficult information constructions corresponding to HTML pages by decreasing them to a canonical string model has no title that I do know of. Martin Fowler recommended “stringly asserted”, and from his suggestion comes the title of this part.

Modeling Extraordinarily Giant Photos with xT – The Berkeley Synthetic Intelligence Analysis Weblog


As laptop imaginative and prescient researchers, we consider that each pixel can inform a narrative. Nonetheless, there appears to be a author’s block settling into the sector with regards to coping with giant photos. Giant photos are not uncommon—the cameras we feature in our pockets and people orbiting our planet snap photos so massive and detailed that they stretch our present greatest fashions and {hardware} to their breaking factors when dealing with them. Typically, we face a quadratic improve in reminiscence utilization as a operate of picture dimension.

In the present day, we make one among two sub-optimal decisions when dealing with giant photos: down-sampling or cropping. These two strategies incur vital losses within the quantity of data and context current in a picture. We take one other take a look at these approaches and introduce $x$T, a brand new framework to mannequin giant photos end-to-end on up to date GPUs whereas successfully aggregating international context with native particulars.



Structure for the $x$T framework.

BVLOS Pipeline Inspections: Avisight, Occasion 38 and Elsight

0

New Connectivity Options Drive Effectivity in Difficult Terrains

Occasion 38 Unmanned Programs, a number one producer of unmanned aerial automobiles, and AviSight, a important infrastructure inspection supplier, have introduced their collaboration with Elsight to combine its AI-based UAV connectivity answer, Halo, into their operations. This partnership goals to reinforce past visual-line-of-sight (BVLOS) inspections for intensive oil and fuel pipeline monitoring over troublesome terrain.

Elsight’s Halo is a light-weight and dependable communications system. Halo makes use of AI-based software program to combination a number of IP hyperlinks right into a safe bond utilizing private and non-private mobile, satellite tv for pc, and RF applied sciences. This ensures uninterrupted drone communications even in probably the most difficult environments, facilitating steady transmission of high-bandwidth video and information to the command-and-control heart (C2).

Elsight Halo

AviSight’s CEO, Suzanne Herring, emphasised the significance of connectivity of their operations: “AviSight’s repute relies on our potential to supply correct, well timed and constantly important infrastructure inspections by the usage of unmanned ariel methods in an economical method. In a know-how market that’s quickly creating, it’s important to stay progressive in our methods methodology whereas additionally embodying the challenges of an environment friendly execution of the mission. With C2 linkage being a main precedence for our BVLOS missions, it was important to discover a companion with the capabilities to take care of communications all through our risky terrains. Elsight has offered us with the flexibility to take care of C2 by huge wetlands, mountainous areas, and distant areas. Whereas Occasion 38’s E455 has given us the flexibility to fly intensive linear inspections effectively and extra affordably.”

The E455, Occasion 38’s newest VTOL drone, is a fixed-wing, vertical takeoff and touchdown plane weighing 55lbs. It presents a 2.5-hour flight endurance on battery energy alone and is able to carrying numerous payloads, together with mapping sensors, LiDAR, and EO/IR surveillance sensors. This versatility meets the strict calls for of assorted purposes, together with prolonged pipeline inspections.

BVLOS Pipeline Inspections: Avisight, Occasion 38 and Elsight

Jeff Taylor, CEO of Occasion 38 Unmanned Programs, highlighted the importance of this integration: “The excessive bandwidth and low energy utilization of the Elsight Halo paired with the E455 open infinite prospects of inspections over lengthy distances and rugged terrain that weren’t doable beforehand. Our E455 VTOL was capable of get nearer to the pipelines with the assistance of Elsight.”

Yoav Amitai, CEO of Elsight, commented on the collaboration: “Working with Occasion 38 and AviSight has been very fulfilling from each technological and enterprise views. Our Halo was designed for mission-critical objectives, significantly, in troublesome conditions. Elsight optimizes the usage of drones in lots of industries with dependable BVLOS connectivity for operational effectiveness. On the identical time, we allow trade progress by utilizing just one operator to regulate a drone fleet from distant areas anyplace. That is how we see our Halo as a market catalyst for drones in pipelines, and inspections in lots of industries, through which eradicating the human component delivers higher and safer outcomes.”

Learn extra: