Movatterモバイル変換


[0]ホーム

URL:


Skip to main content
⌘K
Up or down tonavigateEnter toselectEscape toclose
On this page

Testing web apps

Deno is a JavaScript runtime that operates outside of the browser, as such, youcannot directly manipulate the Document Object Model in Deno as you would in abrowser. However you can use a library likedeno-dom,JSDom orLinkeDOM to work with the DOM. Thistutorial will guide you through how to effectively test your web applicationsusing Deno.

Testing UI components and DOM manipulationJump to heading

Let's say you have a website that shows a uers's profile, you can set up a testfunction to verify that the DOM element creation works correctly. This code setsup a basic card element then tests whether the created DOM structure matcheswhat was expected.

import{ assertEquals}from"jsr:@std/assert";import{ DOMParser, Element}from"jsr:@b-fuze/deno-dom";// Component or function that manipulates the DOMfunctioncreateUserCard(user:{ name:string; email:string}): Element{const doc=newDOMParser().parseFromString("<div></div>","text/html")!;const card= doc.createElement("div");  card.className="user-card";const name= doc.createElement("h2");  name.textContent= user.name;  card.appendChild(name);const email= doc.createElement("p");  email.textContent= user.email;  email.className="email";  card.appendChild(email);return card;}Deno.test("DOM manipulation test",()=>{// Create a test userconst testUser={ name:"Test User", email:"test@example.com"};// Call the functionconst card=createUserCard(testUser);// Assert the DOM structure is correctassertEquals(card.className,"user-card");assertEquals(card.children.length,2);assertEquals(card.querySelector("h2")?.textContent,"Test User");assertEquals(card.querySelector(".email")?.textContent,"test@example.com");});

Testing Event HandlingJump to heading

Web applications often handle user interactions through events. Here's how totest event handlers. This code sets up a button that tracks its active/inactivestate and updates its appearance when clicked. The accompanying test verifiesthe toggle functionality by creating a button, checking its initial state,simulating clicks, and asserting that the button correctly updates its stateafter each interaction:

import{ DOMParser}from"jsr:@b-fuze/deno-dom";import{ assertEquals}from"jsr:@std/assert";// Component with event handlingfunctioncreateToggleButton(text:string){const doc=newDOMParser().parseFromString("<div></div>","text/html")!;const button= doc.createElement("button");  button.textContent= text;  button.dataset.active="false";  button.addEventListener("click",()=>{const isActive= button.dataset.active==="true";    button.dataset.active= isActive?"false":"true";    button.classList.toggle("active",!isActive);});return button;}Deno.test("event handling test",()=>{// Create buttonconst button=createToggleButton("Toggle Me");// Initial stateassertEquals(button.dataset.active,"false");assertEquals(button.classList.contains("active"),false);// Simulate click event  button.dispatchEvent(newEvent("click"));// Test after first clickassertEquals(button.dataset.active,"true");assertEquals(button.classList.contains("active"),true);// Simulate another click  button.dispatchEvent(newEvent("click"));// Test after second clickassertEquals(button.dataset.active,"false");assertEquals(button.classList.contains("active"),false);});

Testing Fetch RequestsJump to heading

Testing components that make network requests requires mocking the fetch API.

In the below example we willmock thefetch APIto test a function that retrieves user data from an external API. The testcreates a spy function that returns predefined responses based on the requestedURL, allowing you to test both successful requests and error handling withoutmaking actual network calls:

import{ assertSpyCalls, spy}from"jsr:@std/testing/mock";import{ assertEquals}from"jsr:@std/assert";// Component that fetches dataasyncfunctionfetchUserData(  userId:string,):Promise<{ name:string; email:string}>{const response=awaitfetch(`https://api.example.com/users/${userId}`);if(!response.ok){thrownewError(`Failed to fetch user:${response.status}`);}returnawait response.json();}Deno.test("fetch request test",async()=>{// Mock fetch responseconst originalFetch= globalThis.fetch;const mockFetch=spy(async(input: RequestInfo|URL):Promise<Response>=>{const url= input.toString();if(url==="https://api.example.com/users/123"){returnnewResponse(JSON.stringify({ name:"John Doe", email:"john@example.com"}),{ status:200, headers:{"Content-Type":"application/json"}},);}returnnewResponse("Not found",{ status:404});});// Replace global fetch with mock  globalThis.fetch= mockFetch;try{// Call the function with a valid IDconst userData=awaitfetchUserData("123");// Assert the resultsassertEquals(userData,{ name:"John Doe", email:"john@example.com"});assertSpyCalls(mockFetch,1);// Test error handling (optional)try{awaitfetchUserData("invalid");thrownewError("Should have thrown an error for invalid ID");}catch(error){assertEquals((erroras Error).message,"Failed to fetch user: 404");}assertSpyCalls(mockFetch,2);}finally{// Restore the original fetch    globalThis.fetch= originalFetch;}});

Using Testing Steps to set up and teardownJump to heading

For complex tests, you can use steps to organize test logic into discretesections, making tests more readable and maintainable. Steps also enable betterisolation between different parts of your test. Using step naming you canimplement a setup and teardown of the test conditions.

import{ DOMParser}from"jsr:@b-fuze/deno-dom";import{ assertEquals, assertExists}from"jsr:@std/assert";Deno.test("complex web component test",async(t)=>{const doc=newDOMParser().parseFromString("<!DOCTYPE html><html></html>","text/html",);const body= doc.createElement("body");const container= doc.createElement("div");  body.appendChild(container);await t.step("initial rendering",()=>{    container.innerHTML=`<div></div>`;const app= container.querySelector("#app");assertExists(app);assertEquals(app.children.length,0);});await t.step("adding content",()=>{const app= container.querySelector("#app");assertExists(app);const header= doc.createElement("header");    header.textContent="My App";    app.appendChild(header);assertEquals(app.children.length,1);assertEquals(app.firstElementChild?.tagName.toLowerCase(),"header");});await t.step("responding to user input",()=>{const app= container.querySelector("#app");assertExists(app);const button= doc.createElement("button");    button.textContent="Click me";    button.id="test-button";    app.appendChild(button);let clickCount=0;    button.addEventListener("click",()=> clickCount++);    button.dispatchEvent(newEvent("click"));    button.dispatchEvent(newEvent("click"));assertEquals(clickCount,2);});await t.step("removing content",()=>{const app= container.querySelector("#app");assertExists(app);const header= app.querySelector("header");assertExists(header);    header.remove();assertEquals(app.children.length,1);// Only the button should remain});});

Best Practices for Web Testing in DenoJump to heading

  1. Maintain isolation - Each test should be self-contained and not depend onother tests.

  2. Use names to show intent - descriptive names for tests make it clear what isbeing tested and give more readable output in the console

  3. Clean up after your tests - remove any DOM elements created during tests toprevent test pollution.

  4. Mock external services (such as APIs) to make tests faster and more reliable.

  5. Organize tests into logical steps usingt.step() for complex components.

Running Your TestsJump to heading

Execute your tests with the Deno test command:

denotest

For web tests, you might need additional permissions:

denotest --allow-net --allow-read --allow-env

🦕 By following the patterns in this tutorial, you can write comprehensive testsfor your web applications that verify both functionality and user experience.

Remember that effective testing leads to more robust applications and helpscatch issues before they reach your users.

Did you find what you needed?

What can we do to improve this page?

If provided, you'll be @mentioned in the created GitHub issue

Privacy policy

[8]ページ先頭

©2009-2025 Movatter.jp