⚙ AS26 · DAY 8 AFTERNOON LAB

Hardening Sprint:
Edge Cases & Stress Testing

Break your app on purpose. Find every edge case, every failure point, every crash. Then fix them all before tomorrow's final presentations.

📅 Wednesday, June 17, 2026 🕒 14:00 - 16:00 📍 ISU, Strasbourg ⚙ Hands-on Lab
Lab Overview

Goal: Break It, Then Fix It

Your app works for the "happy path" (the ideal user doing exactly what you expect). But real users are unpredictable: they paste emojis into search boxes, they have terrible internet, and they click buttons 47 times in a row.

Today's Mission

  • Systematically test every feature of your application
  • Try to break it with weird inputs, slow connections, and invalid API keys
  • Log every failure in a structured testing log
  • Fix the critical bugs before tomorrow's presentations
⚠️
Mindset shift: Finding a bug today is a win. Finding it during your presentation tomorrow is a disaster. Be your own worst enemy right now.
💡
Netflix engineers built an entire tool called Chaos Monkey that randomly kills production servers to test resilience. You are the Chaos Monkey of your own project today.1
🎯 Sprint Focus

Today's Sprint: Apply to Your Project

Test your specific project pipeline end-to-end: from satellite data ingestion to AI analysis to dashboard output.

🛰
Insurance Track
NDVI/soil moisture thresholds for automated payouts
🍇
CubeSat Track
Localized Alsace monitoring dashboard
🏭
ESG Track
EU Green New Deal compliance monitoring
💡
Your Own Idea
Apply today's concepts to your custom project
Lab Overview

The Chaos Engineering Mindset

Chaos engineering is the discipline of experimenting on a system to build confidence in its ability to withstand turbulent conditions in production.2 For your project, this means deliberately causing failures to discover weaknesses before your users (or your instructor) do.

Three Principles for Today

1

Hypothesize Failure Modes

Before you test, ask: "What could go wrong?" List every scenario: empty inputs, network timeouts, invalid API keys, browser differences, and mobile screens.

2

Introduce Controlled Failures

Use Chrome DevTools throttling to simulate slow networks. Pass intentionally bad data. Revoke API keys. Test on your phone.

3

Observe, Record, Fix

Document what happened. Was there a graceful error message? Did the app crash? Fix the worst issues first, using a triage approach: critical bugs before cosmetic ones.

Pro tip: Swap with a classmate and test each other's apps. Fresh eyes catch bugs that you are blind to after staring at your own code for days.
Testing Protocol

Step 1: The Happy Path Test

Start with the baseline: does the core feature work end-to-end when everything goes perfectly?

What to verify

  • Open your deployed GitHub Pages URL (not localhost!)
  • Enter a normal, expected query into your AI chat
  • Verify the AI response appears correctly and is relevant
  • Check that the map loads and displays data properly
  • Click every button, link, and interactive element once
  • Verify the entire flow from landing to final output
🚨
If the happy path is broken, stop everything and fix it first. Nothing else matters if your core feature does not work. This is a "stop the line" moment.

Common Happy Path Failures

  • API key is hardcoded but expired or rate-limited
  • Map tiles fail to load due to CORS or missing attribution
  • JavaScript errors prevent the page from loading at all (check the Console!)
  • CSS file path is wrong after deploying to GitHub Pages
Testing Protocol

Step 2 & 3: Edge Cases & Network Stress

Edge Case Inputs to Try

  • Empty string: submit with nothing typed
  • Very long text: paste 5,000 characters
  • Special characters: <script>alert('xss')</script>
  • Emojis: 🌎🌍🛰 as input
  • Numbers only: "12345678"
  • SQL injection attempt: '; DROP TABLE users;--
  • Rapid repeated clicks: click submit 20 times fast
  • Non-English text: Arabic, Chinese, or Cyrillic characters

Network Stress Tests

Open Chrome DevTools (F12), go to the Network tab:

  • Slow 3G: simulates 2,000ms RTT latency, ~400 kbps throughput
  • Offline: toggle the "Offline" checkbox
  • Custom throttle: create a profile with 2G speeds
💡
Does your app show a loading spinner while waiting? Or does the user stare at a blank screen for 30 seconds wondering if anything happened?

Step 5: Cross-Browser

Test on at least two different browsers (Chrome + Firefox or Safari). CSS features like backdrop-filter may behave differently.

Testing Protocol

Step 4: API Failure Simulation

What happens when external services fail? Your Gemini API call, your map tile provider, your satellite data source: any of these can go down at any time.3

Tests to Run

A

Invalid API Key

Temporarily change your Gemini API key to "INVALID_KEY_12345". Does your app show a helpful error, or does it silently fail?

B

Rate Limit Exceeded

Send 20 rapid requests. The free Gemini API tier has rate limits. Does your app handle 429 "Too Many Requests" responses gracefully?

C

Malformed API Response

What if the AI returns an unexpected format? Does your code use try/catch around JSON parsing?

D

CORS Errors on Deployment

Some API calls that work on localhost fail when deployed to GitHub Pages due to CORS restrictions. Always test the deployed version.

⚠️
Remember: After testing with an invalid API key, restore the correct one before committing!
Testing Protocol

Testing Log Template

Use this structured template to record every test you run. Copy it into a Google Doc or a Markdown file in your repo. This becomes evidence of your testing process.

Feature Input / Action Expected Result Actual Result Status
AI Chat Ask "What is NDVI?" Correct explanation appears Response shows in chat ✔ PASS
AI Chat Submit empty string Error or placeholder message API returns 400 error, no UI feedback ✘ FAIL
Map Zoom to max level Tiles load smoothly Grey tiles appear ✘ FAIL
Map Click marker Popup with info appears Popup displays correctly ✔ PASS
Mobile Open on iPhone Safari Layout adapts, all features work Chat input hidden by keyboard ✘ FAIL
💡
Aim for at least 15 rows in your testing log. Cover every major feature with both "happy" and "unhappy" inputs. A thorough log shows professionalism and rigor.
Code

Adding Debug Logging

Console logging is your best friend during testing. Use a structured logging wrapper so you can easily turn debug output on and off, and so every log message has a category tag for quick filtering.

JavaScript
// Debug logging wrapper
// Set to false before final deployment to silence logs
const DEBUG = true;

function log(category, message, data) {
  if (DEBUG) {
    console.log(`[${category}] ${message}`, data || '');
  }
}

// Usage examples:
log('AI', 'Sending prompt', { prompt, model: 'gemini-2.0-flash' });
log('MAP', 'Adding marker', { lat, lng });
log('ERROR', 'API call failed', { status, error });
log('UI', 'Button clicked', { buttonId: 'send-btn' });
log('NETWORK', 'Fetch started', { url });
💡
Chrome DevTools tip: In the Console panel, use the Filter box to type a category tag like [ERROR] to see only error logs. This makes debugging much faster when you have many log entries.
⚠️
Before your final deployment: Set DEBUG = false to prevent console noise for end users. Never log sensitive data like full API keys.
Fixing Issues

Issue: API Response Takes Too Long

🔴 Problem
The user clicks "Send" and nothing happens for 10+ seconds. No spinner, no feedback. The user thinks the app is broken and clicks again, spawning duplicate requests.
✅ Solution: Add a Timeout + Loading State
Use the AbortController API to set a maximum wait time, and show a visual loading indicator while the request is in progress.
JavaScript
// Show loading state
const sendBtn = document.getElementById('send-btn');
sendBtn.disabled = true;
sendBtn.textContent = 'Thinking...';

// Set up a 15-second timeout using AbortController
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 15000);

try {
  const response = await fetch(url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload),
    signal: controller.signal
  });
  const data = await response.json();
  // Handle successful response...
} catch (err) {
  if (err.name === 'AbortError') {
    showError('Request timed out. Please try again.');
  } else {
    showError('Something went wrong: ' + err.message);
  }
} finally {
  clearTimeout(timeout);
  sendBtn.disabled = false;
  sendBtn.textContent = 'Send';
}
💡
The AbortController is a native browser API (no library needed). The finally block ensures the button is always re-enabled, whether the request succeeded, failed, or timed out.4
Fixing Issues

Issues: Map Markers & Chat Scrolling

🔴 Markers Pile Up
Every new query adds more markers without clearing old ones. The map becomes a mess of overlapping pins.
JavaScript
// Track all markers in an array
const markers = [];

function addMarker(lat, lng, label) {
  const m = L.marker([lat, lng])
    .addTo(map)
    .bindPopup(label);
  markers.push(m);
}

function clearMarkers() {
  markers.forEach(m =>
    map.removeLayer(m)
  );
  markers.length = 0;
}

// Call clearMarkers() before adding
// new results from a fresh query
🔴 Chat Scrolls to Wrong Position
New messages appear below the visible area. The user has to manually scroll down to see the latest response.
JavaScript
// Auto-scroll chat to bottom
function scrollToBottom() {
  const container = document
    .getElementById('chat-messages');
  container.scrollTop =
    container.scrollHeight;
}

// Call after adding every message
function addMessage(text, sender) {
  const div = document
    .createElement('div');
  div.className =
    `message ${sender}`;
  div.textContent = text;
  container.appendChild(div);
  scrollToBottom();
}
Fixing Issues

Issue: App Crashes on Mobile

🔴 Problem
The layout overflows, text is unreadably small, and interactive elements are too close together to tap accurately on a phone screen.

The Essential Mobile Fix

First, make sure your HTML <head> includes the viewport meta tag. Without it, mobile browsers render the page at desktop width and then scale it down.

HTML
<!-- This MUST be in your <head> -->
<meta name="viewport"
      content="width=device-width, initial-scale=1.0">

Responsive CSS Essentials

CSS
/* Stack columns on small screens */
@media (max-width: 768px) {
  .app-layout {
    grid-template-columns: 1fr;  /* single column */
    grid-template-rows: auto 1fr auto;
  }

  .sidebar {
    display: none;  /* hide on mobile */
  }

  .chat-input {
    font-size: 16px;  /* prevents iOS zoom on focus */
  }

  /* Make tap targets at least 44x44pt (Apple HIG); 1pt = 1px at 1x density */
  button, .clickable {
    min-height: 44px;
    min-width: 44px;
  }
}
💡
Quick mobile test: In Chrome DevTools, click the device toggle toolbar (Ctrl+Shift+M) and select "iPhone 14" or "Pixel 7". This simulates mobile viewport, touch events, and device pixel ratio.5
Quiz

Knowledge Check: Testing & Debugging

1. You set a 15-second timeout using AbortController, but the API responds in 3 seconds. What happens to the timeout?

A It fires anyway at 15 seconds and aborts the already-completed request
B It causes a memory leak because it was never cleared
C The finally block calls clearTimeout(), cancelling the pending timer
D The browser automatically cancels it when the fetch resolves
✅ Correct! The finally block runs whether the fetch succeeds or fails, and it calls clearTimeout() to cancel the pending timer. Without this cleanup, the timer would still fire (option A), though it would not cause a crash since the controller's signal is already used.
❌ Not quite. The key is the finally block: it always runs and calls clearTimeout(timeout), which cancels the timer before it fires. The browser does not cancel timers automatically.

2. What CSS property value prevents iOS Safari from auto-zooming when a user taps on a text input?

A zoom: none
B font-size: 16px (or larger)
C touch-action: none
D user-scalable=no in the viewport meta
✅ Correct! iOS Safari auto-zooms on inputs with font-size below 16px. Setting font-size to 16px or larger prevents this behavior. While user-scalable=no also prevents zoom, it is an accessibility anti-pattern because it blocks intentional pinch-zoom.
❌ The answer is font-size: 16px. iOS Safari zooms in on inputs with a font-size smaller than 16px. Setting it to 16px or larger prevents this auto-zoom without sacrificing accessibility.
Automated Workflows

Automating the Chaos (CI/CD Basics)

In enterprise projects like TERRA, manual testing is not enough. You cannot rely on developers to manually run every test before deploying. You need Continuous Integration and Continuous Deployment (CI/CD).

What is CI/CD?

  • Continuous Integration (CI): Every time you push code to GitHub, an automated server runs your tests and checks for errors. If it fails, the code is blocked from merging.
  • Continuous Deployment (CD): If all tests pass, the code is automatically deployed to the live server (like GitHub Pages).
💡
Why it matters: CI/CD eliminates human error. It guarantees that broken code never reaches your users.
Automated Workflows

GitHub Actions Pipeline

We use GitHub Actions to build our CI/CD pipeline. It uses YAML files to define automated jobs.

The Enterprise Starter Workflow

We have provided a starter template for your project. Copy it to .github/workflows/main.yml in your repository.

YAML
# A simplified look at what the pipeline does:
jobs:
  lint-and-scan:
    # 1. Runs your tests and checks for syntax errors
  build:
    # 2. Builds your application bundle if tests pass
  deploy:
    # 3. Automatically deploys to GitHub Pages
Automated Workflows

Security Scanning & Code Quality

Real-world applications have strict security constraints. A pipeline doesn't just test if the code works, it tests if the code is safe.

  • Static Analysis (Linting): Tools check your code against formatting rules and catch common errors before they run.
  • Dependency Scanning (Dependabot): Automatically checks if any libraries you use have known vulnerabilities.
  • CodeQL: A semantic code analysis engine that finds security vulnerabilities in your codebase.
⚠️
Security Constraint: In TERRA, if the security scan fails, the deployment is hard-blocked. You cannot deploy until the vulnerabilities are fixed.
Checklist

Quality Checklist Before Final Presentations

Go through every item on this list. Click to check off items as you verify them. Every checked box is one less thing that can go wrong during your presentation tomorrow.

  • Core feature works end-to-end on the deployed URL
  • Error messages are user-friendly (not raw stack traces)
  • Loading states are visible (spinners, disabled buttons, "Thinking..." text)
  • App works on mobile (viewport meta tag, responsive CSS)
  • No console errors in the browser Developer Tools
  • All navigation links and buttons work correctly
  • Deployed to GitHub Pages and the live URL loads correctly
  • Map loads with correct tile layer and attribution
  • API key is valid and not exceeding rate limits
  • Tested on at least two different browsers
  • Empty and edge-case inputs are handled gracefully
  • README.md is up to date with project description and screenshots
⚠️
Tomorrow: Presentation coaching and final polish session. You will practice your 5-minute demo and get feedback from peers. The app must be fully deployed and working before that session begins.
Quiz

Knowledge Check: Hardening Best Practices

3. Your app makes an API call, but you forgot to wrap it in try/catch. The API returns a 500 error. What happens in the browser?

A The browser automatically shows a "Server Error" alert dialog
B The fetch promise rejects, throwing an unhandled exception that crashes the page
C The fetch resolves normally (no error thrown); you must check response.ok manually
D The browser retries the request three times before failing
✅ Correct! The Fetch API only rejects on network failures (DNS errors, offline). HTTP error status codes like 400 or 500 still resolve the promise normally. You must check response.ok or response.status to detect server errors. This is a very common source of bugs!4
❌ Tricky one! The Fetch API does not reject on HTTP errors (400, 500, etc.). It only rejects on network-level failures. A 500 response resolves the promise, so you must manually check response.ok to detect server errors.
Summary

Summary of Big Ideas

💣
Break It On Purpose
Chaos engineering means deliberately introducing failures to build confidence in your system. Test with bad inputs, slow networks, and invalid keys before your users encounter them.
📋
Test Systematically
Use a structured testing log. Cover the happy path first, then edge cases, network stress, API failures, and cross-browser compatibility. Document every result.
Timeouts and Loading States
Never leave users staring at a blank screen. Use AbortController for timeouts, disable buttons during requests, and show loading indicators for every async operation.
📱
Mobile is Not Optional
The viewport meta tag, responsive CSS media queries, and 44-point (44px at 1x density) minimum tap targets (per Apple HIG) are non-negotiable. Test on actual mobile devices or the DevTools device simulator.
🔎
Debug Logging
A structured logging wrapper with categories (AI, MAP, ERROR, UI) makes debugging faster. Use Chrome Console filters to isolate specific log categories.
✔️
Checklists Save Demos
A pre-flight quality checklist ensures nothing is forgotten before going live. Check core features, error handling, deployment, and cross-browser support.
Reference

Glossary & References

Glossary of Key Terms

Edge Case
An input or condition that occurs at the extreme boundaries of expected behavior: empty strings, maximum lengths, special characters, or unusual user interactions that developers often overlook.
Chaos Engineering
The discipline of experimenting on a system by deliberately introducing controlled failures to uncover weaknesses and build confidence in the system's resilience under real-world conditions.
Throttling
Artificially slowing down network speed (using Chrome DevTools or similar tools) to simulate poor connectivity conditions such as 3G, 2G, or intermittent connections during testing.
Timeout
A predetermined maximum waiting period for an asynchronous operation (such as an API call). If the operation does not complete within this period, it is cancelled and an error is shown to the user.
AbortController
A built-in browser API that provides a signal object used to abort web requests (e.g., Fetch calls). It allows developers to cancel in-progress network requests programmatically.
Debug Logging
The practice of adding structured console output (with categories and contextual data) to trace application behavior during development and testing. Typically disabled in production builds.
Cross-Browser Testing
The process of verifying that a web application functions correctly across multiple browsers (Chrome, Firefox, Safari, Edge) and rendering engines, ensuring consistent behavior for all users.

References

  • [1] Basiri, A., et al. (2016). "Chaos Engineering." IEEE Software, 33(3), 35-41. doi:10.1109/MS.2016.60
  • [2] Rosenthal, C., & Jones, N. (2020). Chaos Engineering: System Resiliency in Practice. O'Reilly Media. O'Reilly
  • [3] Google. (2026). "Gemini API: Error Handling." Google AI for Developers. ai.google.dev
  • [4] MDN Web Docs. (2026). "AbortController." Mozilla Developer Network. developer.mozilla.org
  • [5] Google Chrome Developers. (2026). "Simulate Mobile Devices with Device Mode." Chrome DevTools. developer.chrome.com
  • [6] MDN Web Docs. (2026). "Using the Fetch API." Mozilla Developer Network. developer.mozilla.org
  • [7] Apple. (2026). "Human Interface Guidelines: Tap Targets." Apple Developer. developer.apple.com
🌟 Pioneer Profile
πŸ‘€

Kent Beck

Software Engineering Visionary

Kent Beck created Test-Driven Development (TDD) and Extreme Programming (XP), two practices that transformed how software teams build reliable code. His philosophy of 'make it work, make it right, make it fast' remains a guiding principle for developers worldwide.

🌍 Local to Global

Global Data, Local Impact

Applying EO to Community Challenges

Earth Observation provides a macroscopic view of environmental trends, but its true power lies in downscaling this data to affect local policy and design, such as urban planning and sustainable workplaces.

πŸ“
Texas Connection: In Texas, EO data is used to monitor the Edwards Aquifer depletion and track the expansion of urban heat islands across the Dallas-Fort Worth metroplex.
πŸ—ΊοΈ
πŸ€” Geographic Inquiry

Regional Decisions Scenario

Scenario: Sustainable Workspace Siting

Your startup needs to establish a new hybrid work hub. You must balance employee commute times, environmental impact (using the IPAT equation), and existing green infrastructure.

Your Task:

  • Identify 3 potential sites using EO vegetation indices.
  • Calculate the estimated carbon footprint of hybrid commuting.
  • Propose a Placemaking strategy for the hub.
πŸ“š Summary

Big Ideas & Glossary

Summary of Big Ideas

  • Data is only as valuable as its application.
  • Space technology has direct terrestrial benefits.

Glossary of Terms

Earth Observation
Gathering information about Earth via remote sensing.
πŸ“ Knowledge Check

Auto-Graded Quiz

What is the primary benefit of remote sensing in sustainability?
A
It replaces the need for local governance.
B
It provides continuous, objective data over large, inaccessible areas.
C
It lowers the cost of launching rockets.
βœ… Correct! Remote sensing allows for consistent monitoring of remote regions without expensive on-the-ground surveys.
❌ Incorrect. The right answer was B. Remote sensing allows for consistent monitoring of remote regions without expensive on-the-ground surveys.

πŸ“ Daily Reflection

What was your biggest takeaway from this session, and how does it apply to the TERRA project? Write your response below. Your instructor will review this to track your progress.