Case study · Design QA

Education Center: five QA rounds, 132 findings, before launch

How I designed the QA of a new learning module to break it the way a first-time learner, a plain member and a team admin would, and turned a 132-item report into tickets engineering could close one at a time.

Senior Product Designer · Design QA lead · 21–24 Sep 2026, follow-up through Oct · Happly, white-label platform

Role

Senior Product Designer, design QA lead

Team

Front-end and back-end developers; product decisions and retests on the company side

Timeframe

Five rounds, 21–24 Sep 2026; follow-up through Oct 2026

Tools

Figma, Jira, and AI agents driving the browser and the API

In 30 seconds

What it was

QA of the Education Center, the learning module of a white-label platform, before launch: member side and back office, from courses to certificates.

What I owned

I designed and led the QA; AI agents ran the test passes. I set the matrix and the rules, decided what counted as a finding, removed duplicates, and wrote every ticket.

Key decisions

01

Rounds built to break it, run with three accounts: admin, plain member and team role.

02

Split the report by impact: 21 bugs got tickets of their own.

03

Where the PRD was silent on “Skip for now”, a decision question instead of a guess.

Outcome

132 findings logged, 129 stand after 3 withdrawals; 21 bug tickets with acceptance criteria; the skip rule is now in the PRD. Fixes were in progress as of October 2026.

In 30 seconds

What it was

QA of the Education Center, the learning module of a white-label platform, before launch: member side and back office, from courses to certificates.

What I owned

I designed and led the QA; AI agents ran the test passes. I set the matrix and the rules, decided what counted as a finding, removed duplicates, and wrote every ticket.

Key decisions

01

Rounds built to break it, run with three accounts: admin, plain member and team role.

02

Split the report by impact: 21 bugs got tickets of their own.

03

Where the PRD was silent on “Skip for now”, a decision question instead of a guess.

Outcome

132 findings logged, 129 stand after 3 withdrawals; 21 bug tickets with acceptance criteria; the skip rule is now in the PRD. Fixes were in progress as of October 2026.

Hero image: an Education Center course page on demo data (to come)

What the Education Center is

The Education Center is the learning module of the white-label platform: organizations publish courses made of video, audio, reading, quiz, survey and assignment lessons, learners enroll, and a certificate is issued at the end.

Courses are either Structured, where lessons unlock in order, or Self-paced.

Where a review by eye stops

When the build reached the dev environment, the main path worked: create, publish, enroll, finish, get a certificate. That is exactly when a review by eye says “looks good”.

But a learning module carries money, access and credentials. A quiz counted as passed when nobody took it, or a certificate issued without the work, is not a visual bug.

The problem was not to find ugly things. It was to find the places where the screen says one thing and the system does another.

Then write each one so a developer can fix it without a meeting, and prove it’s fixed. I designed and led the QA; AI agents ran the test passes.

What the QA tested against

The brief for this body of work, condensed. Every finding had to trace back to one of these lines.

Goal

Release the Education Center with behavior that matches its PRD, on both sides, in both languages.

Rules (PRD v4)

In Structured courses only surveys can be skipped, and quizzes must be passed.

In Self-paced courses, completion and the certificate need at least 70% of the non-survey lessons actually completed.

Draft content stays hidden from members until it is published.

Success criteria

Every finding is reproducible, tied to a PRD rule or a measured value, and has an expected state. Nothing is filed twice. Nothing is called fixed without a retest.

Non-goals

Redesigning the module, or changing the PRD inside a ticket. Where the PRD was silent, the finding became a decision question with a recommendation, not a bug.

Constraints

A dev environment that changed mid-session, four days, and one designer leading the whole loop.

By the numbers

The report, counted

Counted 13 Oct 2026

132

findings logged: 62 bugs, 50 UI, 20 newcomer

QA report, ID ranges

129

stand after 3 were withdrawn

Withdrawal noted in the report

21

bug tickets with acceptance criteria

Jira, 24 Sep 2026

Findings by stage

129 standing, in order

45

7

47

9

8

13

01

First pass

45

02

Extra tests

7

03

Rounds 3 and 4, three reviewer roles

47

04

Plain member, roles and phone

9

05

“Skip for now” focus

8

06

Round 5

13

5

QA rounds in 4 days, 21–24 Sep 2026

Report updates

3

Test accounts: admin, plain member, team role

The report

22 · 25 · 12

High, Medium and Low among the 59 rated bugs; one bug added later is unrated

Priority headings in the QA subtasks

82

Front-end and UI items scoped into implementation

Jira comment, 7 Oct 2026

Most findings came from rounds 3 and 4, when three reviewer roles ran at once; the last round still added 13.

Challenge 1 of 6

Rounds built to break it, run with three accounts

Situation

The first pass confirmed the core flow worked. The worst bugs only appeared in states, not screens: “Save draft” right after publishing took a live course offline.

Decision

Rounds, each with a different job: I designed them, AI agents ran them. In rounds 3 and 4, three reviewer roles ran at once, and a finding stayed only if it was seen twice. Round 5 tried to break it on purpose.

Which account saw it

Marked where the report records it

Bug

Admin

Plain member

Team role

8 bugs found with the admin

A course limited to a membership plan opened to members without it

“Admin review required” was ignored

A view-only team member edited other admins’ courses by link

Read down the last column: one admin account would have shipped all three access bugs.

Outcome

Eight bugs found with the admin reproduced identically for a plain member, so developers knew they weren’t admin-only edge cases.

What made it hard

None of these show up in a screenshot. They show up with two editor tabs open, an old tab, a direct link, a double click. And a newcomer’s problems (can’t find the certificate again) never show up for someone who already knows the product.

Options

One careful pass against the PRD; the PRD pass plus passes designed to break it; or wait for users to report.

More detail

The passes used three accounts, because different roles show different bugs: an admin, a plain member and a custom team role.

Another state bug: saving a quiz lesson deleted and recreated every answer option, so a learner who had already opened the quiz scored 0% for correct answers.

The three reviewer roles: a product review that checked every PRD rule, a senior design review that measured the UI (spacing, type, contrast, states), and a first-time user who knows nothing. The second of the two rounds re-checked every finding of the first.

Round 5 was two passes on purpose: strictly against the PRD, then “try to break it” with two editors at once, old tabs, direct links, double clicks and odd input.

Challenge 2 of 6

Three kinds of finding, three shapes, so nobody has to ask

Situation

Developers had a spec and a Figma file, but no way to tell “a bug” from “polish” from “the PRD being silent”.

Decision

Three kinds, three shapes. A bug (B) has Current, Steps and Expected. A UI finding (U) has Where, Current and Change, with exact copy and measured values, like a status chip’s proposed 5.6:1 text contrast. A newcomer finding (N) has what a newcomer expects and what the screen says.

Three shapes

Blank templates

Bug

B1–B62

Current

Steps

Expected

Dev notes

UI finding

U1–U50

Where

Current

Change: current → new

Measured values

Newcomer

N1–N20

Where

What a newcomer expects

What the screen says

Change

The shape says what kind of work it is: a state to fix, a value to change, or a sentence to rewrite.

Outcome

The front-end work could be cut into lanes that don’t share files: 82 front-end and UI items went into implementation in that shape.

What made it hard

A long report is only as useful as its weakest entry. If a developer has to message me to reproduce something, the finding costs me and them.

Options

A free-form report; a tracker row per finding; or a fixed shape per kind of finding.

More detail

Bugs carried dev notes where there was a concrete lead: for the “Save draft” bug, the editor was sending the course status from its own memory.

UI copy is written as “current → new” so it can be searched in code, with pixel sizes, hex colors and contrast ratios where they apply.

Every finding carries a screenshot where it helps and names its source: PRD section, product decision, admin UI copy or general quality. The PRD-over-Figma rule sat at the top of the report, so nobody had to re-argue it item by item.

Where the PRD and Figma disagreed, the PRD won and I updated Figma.

Challenge 3 of 6

Withdraw false findings in the open: 132 logged, 129 stand

Situation

On the second day I withdrew four findings: B13, B14, U5 and the sidebar part of U17. They came from the test browser the agents drove, which slows down timers, not from the app.

Decision

Remove them in the open, in the report, with the cause. A false finding costs a developer an afternoon and costs the next real finding some trust.

The count

From the report’s ID ranges

Bugs

B1–B62

62

UI findings

U1–U50

50

Newcomer findings

N1–N20

20

Logged

132

Withdrawn, test-browser artifacts

B13 · B14 · U5

−3

Stand

129

The number on the page is the one left after the withdrawals, not the bigger one that came first.

Outcome

Three IDs were withdrawn (the fourth removal was part of an item), so 129 stand. I’d rather publish “132 logged, 3 withdrawn” than a round number.

What made it hard

Removing them made the report smaller, and a smaller number looks worse.

Options

Leave them in as “needs investigation”; quietly delete them; or remove them in writing with the reason.

More detail

The same discipline ran the other way: the report also lists what works (the certificate opens right after the last lesson, quiz retries keep the highest score, comments are escaped), so developers know what not to touch.

Challenge 4 of 6

Split the report by impact: 21 bugs got tickets of their own

Situation

After rounds 1–4 the work lived in four large checklist tickets. A developer can’t “close 30% of a ticket”, and a manager can’t see which bug is blocking a release.

Decision

On 24 Sep I split by impact. Each high-impact logic or access finding got its own ticket: 17 from the first rounds plus 4 from “Skip for now”, 21 in all. Small UI and copy fixes and newcomer items stayed as grouped checklists.

The split

24 Sep 2026

The QA report

Four checklist tickets after rounds 1–4

21 tickets of their own

Full report, screenshot, acceptance criteria and a retest label each.

17 from the first rounds

4 for “Skip for now”

Grouped checklists

Small UI and copy fixes and the newcomer items stayed together.

2 duplicates closed

Each points to the ticket that kept the full repro.

Each ring is a bug someone can close on its own.

Outcome

Each serious bug could be fixed, retested and closed on its own. As of October 2026, the tickets were still being fixed.

What made it hard

The worst bugs (a quiz completes without being taken, a live course goes offline) were buried between small copy fixes in the same list.

Options

Keep one checklist; one ticket per finding, over a hundred tickets and mostly noise; or split by impact.

More detail

The round-5 items each got acceptance criteria the next day. Two duplicates were closed with a pointer to the ticket that kept the full repro.

Challenge 5 of 6

A decision question, not a guess, for “Skip for now”

Situation

In a Self-paced course, “Skip for now” on a quiz completed it: a course with a certificate could be finished without taking its quiz.

Decision

I set up a focused pass on “Skip for now” with all three accounts and wrote four bugs, each with screenshots, a video and acceptance criteria.

Product then locked the intent: a skip is not a completion, a skipped survey stays retakeable, and some surveys must be mandatory. That became a separate story for an admin control.

What a skip does

Self-paced course

Before: what the build did

Skip for now

→

Completed

→

Course complete

→

Certificate issued

Now: the locked rule

Skip for now

→

Skipped

Not a completion · a skipped survey stays retakeable

The button was never the bug; the missing rule was. Once “Skipped” existed as its own state, every screen could be checked against it.

Outcome

The skip rule is now written in the PRD, and “Skipped” is its own status everywhere.

What made it hard

This was not a plain bug: the PRD didn’t say what a skip should do to progress. If I’d just logged “wrong”, someone would have guessed.

Options

Pick a behavior in the ticket; leave it as a PRD gap; or turn it into a decision question with a recommendation.

More detail

The four bugs: skip completes the course and issues the certificate; “Allow skip = No” isn’t enforced; admin views disagree about skipped lessons; the skipped state has no way back.

The same defect existed on surveys, and the survey had no way back.

Challenge 6 of 6

Write the loop down, so the next feature starts at step one

Situation

A retest on 25 Sep showed an Education Center fix working, and found the same class of problem in other modules.

Decision

A cross-module rule followed: draft content stays hidden from members until published, in every module. Those findings became their own tickets.

And I wrote the loop down, so it can run on any feature.

The loop, written down

Reused on the next feature

01

Read the PRD and list every rule it contains

02

Read the known items, so nothing is filed twice

03

Set up the three accounts

04

Build the test matrix

05

Collect annotated evidence

06

Triage

07

Report

08

Write tickets

09

Retest

None of the steps is new. Writing them down meant the next feature’s QA started at step one instead of from scratch.

Outcome

The loop became the template for the next feature’s QA. A design-system sweep a few days later found that two of six Education Center fixes had defects of their own after a merge: the argument for retesting every fix.

What I learned

Test states, not screens.

The bugs that mattered needed a second tab, a role, or a double click. A screenshot review would have shipped them.

Fewer, sharper tickets win.

Splitting by impact made the serious bugs visible and closable.

Withdraw what you got wrong.

Taking four findings back in the open made the other 129 easier to believe.

A decision question beats a guess.

Where the PRD was silent, asking with a recommendation got a locked rule in a day.

Next time, measure it.

Tie each finding to a release metric so design QA shows up as a number, and run the loop before a feature reaches dev instead of on it.

Bugs found by design QA before release versus reported by users after; time from “reported” to “Final check ready”; how many findings reopen after a retest; and learner completion where a skip or a bypass used to count as done.