Skip to content

Front-End application Troubleshooting

At the end of this class, you should be able to…

  • Identify and troubleshoot common front-end issues, including JavaScript errors, broken layouts, and slow performance.
  • Use browser developer tools to inspect the DOM, console errors, and network activity.
  • Debug JavaScript using breakpoints and step-through execution.
  • Analyze network requests to identify issues with API calls.

In-Class Demo Jan 2026 term

To run the coding demo, you need to have your Student Workbook open in Visual Studio Code.

  1. Open the terminal window and paste in the following.

    Run from the root of your repository
    pnpm dlx tiged --disable-cache --force DG-InClass/SDEV-1150-A04-Jan-2026/sk/lesson-25 ./src/lesson-25
  2. Walk through the steps in the ReadMe.md of the new lesson.


  • Identify and diagnose common issues in web components using DevTools and automated tests
  • Apply debugging techniques including inspecting Shadow DOM, analyzing events, and verifying component state
  • Write targeted tests that reveal broken behaviour in components
  • Fix failing behaviour by correcting attribute handling, slot rendering, and event detail propagation

The example user-card component and main.js script include a few intentional bugs for you to discover and fix. These are designed so that your tests (and DevTools) will help you identify what is wrong.

Bug 1: Avatar attribute does not update the image

Section titled “Bug 1: Avatar attribute does not update the image”
Symptom:

Setting the avatar attribute on <user-card> does not change the image src, even though observedAttributes includes avatar.

Cause: attributeChangedCallback checks for the wrong attribute name.

static get observedAttributes() {
return ['avatar'];
}
attributeChangedCallback(name, oldValue, newValue) {
// Bug: name check does not match the observed attribute
if (name === 'avatars' && this.shadowRoot) {
const img = this.shadowRoot.querySelector('img');
if (img) {
img.src = newValue;
}
}
}

Fix: Update the condition to check for 'avatar' so it matches the observed attribute.

attributeChangedCallback(name, oldValue, newValue) {
if (name === 'avatar' && this.shadowRoot) {
const img = this.shadowRoot.querySelector('img');
if (img) {
img.src = newValue;
}
}
}

Writing a test that sets element.setAttribute('avatar', 'some-url.png') and then asserts on the img.src will expose this bug immediately.

Bug 2: Description does not render from the user property

Section titled “Bug 2: Description does not render from the user property”
Symptom:

When setting the <code>user</code> property (e.g., <code>card.user = { id: 'u1', name: 'Zelda', description: 'Princess of Hyrule' }</code>), the name appears correctly, but the description does not show up in the card.

Cause: The selector for the description slot is slightly wrong.

_renderFromUser() {
if (this.#user) {
// ... avatar and name logic ...
const descSlot = this.shadowRoot.querySelector('[name="descriptions"]');
if (descSlot) {
descSlot.textContent = this.#user.description || '';
}
}
}

Fix:

  • Correct the selector so it matches the slot name in the template (name="description").
const descSlot = this.shadowRoot.querySelector('[name="description"]');
if (descSlot) {
descSlot.textContent = this.#user.description || '';
}

A test that sets the user property and then asserts that the rendered description text matches the expected value will fail until this bug is fixed.

Bug 3: Follow counter does not update correctly in main.js

Section titled “Bug 3: Follow counter does not update correctly in main.js”
Symptom:

Clicking the Follow button on a card toggles its visual state, but the #follow-counter text does not change as expected.

Cause: The event listener in main.js is reading the wrong property from the custom event detail object.

main.addEventListener('follow-change', (e) => {
// Bug: uses e.detail.isFollowed, but the event detail uses "followed"
followedCount += e.detail.isFollowed ? 1 : -1;
const counterEl = document.querySelector('#follow-counter');
counterEl.textContent = `Followed: ${followedCount}`;
console.log('follow-change:', e.detail);
});

The component dispatches the event like this:

this.dispatchEvent(new CustomEvent('follow-change', {
detail: { id: this.getAttribute('user-id') || null, followed: this.followed },
bubbles: true,
composed: true,
}));

Fix: Update the listener to use the correct property name (followed).

main.addEventListener('follow-change', (e) => {
followedCount += e.detail.followed ? 1 : -1;
const counterEl = document.querySelector('#follow-counter');
counterEl.textContent = `Followed: ${followedCount}`;
console.log('follow-change:', e.detail);
});

You can also write a test for the follow-change event (or manually trigger it in DevTools) to confirm that the detail payload matches what your listener expects.


These intentional bugs are meant to be discovered via failing tests and by inspecting the DOM and events in DevTools:

  • Write tests first for the expected behaviour.
  • Run the tests and observe which assertions fail.
  • Use the failures to guide you to the corresponding bug in the component or script.

NOTE: if you’ve already completed the following from the previous lesson, use those tests to help diagnose and fix the errors described above.

  • Add a test for the avatar attribute, specifically, that setting this attribute will udpate the img src attribute.
  • Add a test for the user property, specifically, that setting this attribute will update the expected slots and image elements.
Terminal window
git add .
  1. Commit the changes:
Terminal window
git commit -m 'Lesson 25 Example'
  1. Push your changes to the remote workbook repository:
Terminal window
git push origin main