Skip to content

Repository files navigation

quiz_app

A quiz app for creating and taking quizzes, built in Dart/Flutter for Android. Quizzes consist of a text prompt, three wrong answers and one correct answer (all open text). Quizzes can be saved and accessed locally (implemented with SQLite and Floor), or in the cloud (Firebase Data Connect and PostgreSQL). In order to access the cloud features, users must sign up and authenticate (Firebase Auth). This project uses Firebase Emulator rather than a live Firebase project.

Prerequisites

This app uses the Firebase Auth, Data Connect, and Cloud Functions emulators for local development. No live Firebase project is required. Note: the Firebase Installations SDK (a dependency of Cloud Functions) always contacts real Firebase servers; using placeholder credentials will log a warning but the app functions normally for Auth and Data Connect. Cloud Function calls require a valid google-services.json to fully authenticate. Because of this design, there is no need to have a .firebaserc file, and firebase.json only holds emulator-specific data and no API keys.

Development Setup Steps

  1. Install Flutter dependencies:
flutter pub get
  1. Verify your environment:
flutter doctor

All items should show [✓] before running the app.

  1. Build the Cloud Functions (required before starting the emulator)
cd functions && npm install && npm run build && cd ..
  1. Start the emulators

From the quiz_app/ directory (where firebase.json lives):

firebase emulators:start --only auth,dataconnect,functions --project demo-quiz-app

The emulator UI will be available at http://127.0.0.1:4000 where you can inspect created accounts and query the local database.

  1. Configure the app for your mobile emulator or device

Copy local.env.example to local.env and set EMULATOR_HOST for your target:

Target EMULATOR_HOST
Android emulator (AVD) 10.0.2.2
Physical device via USB localhost (see note below)
Physical device via Wi-Fi your Mac's LAN IP (e.g. 192.168.x.x)

Note — physical device via USB: The Firebase Auth SDK auto-remaps localhost for AVDs but Data Connect and Cloud Functions do not. Using adb reverse tunnels all three ports over the USB cable so localhost works for everything:

~/Library/Android/sdk/platform-tools/adb reverse tcp:9099 tcp:9099
~/Library/Android/sdk/platform-tools/adb reverse tcp:9399 tcp:9399
~/Library/Android/sdk/platform-tools/adb reverse tcp:5001 tcp:5001

Add platform-tools to your PATH (see below) to use adb directly.

Note — Wi-Fi: your device and development machine must be on the same network. Find your Mac's IP with ipconfig getifaddr en0. Both emulators bind to 0.0.0.0 so they accept LAN connections.

  1. Run the app:
flutter run --dart-define-from-file=local.env

local.env is gitignored so your settings are never committed.

Optional: add adb to your PATH

# Add to ~/.zshrc
export PATH="$PATH:$HOME/Library/Android/sdk/platform-tools"

Then source ~/.zshrc.

Features

  • Create quizzes — add a title, description, optional time limit, and multiple-choice questions
  • Take quizzes — timed or untimed, with an immediate score summary on completion
  • Rate quizzes — after completing a cloud quiz, rate it 1–5 stars from the results screen
  • View past attempts — see score, time taken, and per-question results for each attempt
  • Local storage — quizzes and attempts saved to an on-device SQLite database (no account needed)
  • Cloud storage — sign in to save quizzes and attempts to Firebase Data Connect (PostgreSQL); cloud attempts are filtered to the signed-in user
  • Save toggle — when signed in, the New Quiz page shows a "Save to Cloud" toggle to choose where the quiz is stored
  • Username / attribution — set a display name on your Profile; it appears on any cloud quiz you create
  • Creator dashboard — the Profile screen doubles as a creator dashboard for signed-in users: it lists every quiz you've published to the cloud and shows, for each quiz, the title, publish date, total number of attempts, average score across all attempts, and average star rating

Authorization

Rule How it's enforced
Anyone can read cloud quizzes @auth(level: PUBLIC) on ListQuizzes and GetQuiz
Nobody can modify a quiz after creation No quiz_update/quiz_delete mutation is exposed to clients
Only the author sees their quiz stats GetMyPublishedQuizzes filters by creatorUserId: { eq_expr: "auth.uid" } server-side
Nobody sees each other's attempt results GetAttemptsForQuiz filters by userId: { eq_expr: "auth.uid" } server-side

Testing

Unit + widget tests (no emulator needed)

flutter test test/

Integration tests (requires running emulators)

# Android emulator (AVD)
flutter test integration_test/app_test.dart --dart-define=EMULATOR_HOST=10.0.2.2

# Physical device via USB (run adb reverse first — see Setup)
flutter test integration_test/app_test.dart --dart-define=EMULATOR_HOST=localhost -d <device-id>

Test coverage

# macOS — install lcov first if needed: brew install lcov
flutter test test/ --coverage
genhtml coverage/lcov.info -o coverage/html
open coverage/html/index.html

Regenerating mocks

After adding or changing methods on QuizRepository or DataConnectQuizRepository, regenerate the Mockito mocks:

dart run build_runner build --delete-conflicting-outputs

Regenerating the Data Connect SDK

After editing any .gql file under dataconnect/, regenerate the Dart connector:

firebase dataconnect:sdk:generate

Manual Feature Verification

These steps confirm the key features work end-to-end with the emulator running.

Username / attribution

  1. Sign up with a new account (drawer → Sign Up)
  2. Open the drawer → tap Profile
  3. Enter a display name and tap Save
  4. Confirm the drawer now shows that name instead of the email address

Cloud quiz creation (transactional)

  1. Sign in and open the drawer → New Quiz
  2. Fill in a title, description, and at least one question; enable Save to Cloud
  3. Tap Save — the app should return to the quiz list
  4. Confirm the quiz appears in Community Quizzes with a chip showing your username
  5. To verify the transaction, check the emulator Postgres state at http://127.0.0.1:4000 — the quiz and all its questions should appear together, or neither should appear

Star rating

  1. Take any cloud quiz through to completion
  2. Confirm the results dialog shows a 1–5 star row labelled "Rate this quiz"
  3. Tap a star — the selection should highlight immediately
  4. Each attempt lets you submit a new rating; subsequent ratings replace the previous one for your account

Creator dashboard (Profile screen)

  1. Sign in as the user who created one or more cloud quizzes
  2. Open the drawer → Profile
  3. Below the username field, confirm a My Published Quizzes section appears
  4. For each quiz you published, verify the card shows:
    • Quiz title
    • Publish date
    • Number of attempts
    • Average score (as a percentage)
    • Average star rating (shown as filled stars)
  5. Have a second account take one of your quizzes; refresh the Profile screen and confirm the attempt count and average score update

Emulator Debug

If any of the SQL schema changes, the emulator may crash because of stale data. Clear the emulator's cached Postgres state and restart:

rm -rf dataconnect/.dataconnect
firebase emulators:start

(optional) Persist emulator state across restarts

By default, the Auth emulator loses all accounts when stopped. To keep your test accounts between sessions:

# First run — save state on exit
firebase emulators:start --only auth,dataconnect,functions --project demo-quiz-app --export-on-exit=./emulator-data

# Subsequent runs — restore and save
firebase emulators:start --only auth,dataconnect,functions --project demo-quiz-app --import=./emulator-data --export-on-exit=./emulator-data

Add emulator-data/ to .gitignore to avoid committing it.

Note: If you restart the emulator without --import, you must sign out and sign back in — the Flutter app caches your token locally but the emulator no longer recognizes it.

About

A Flutter quiz app for creating and taking quizzes. Uses SQLite & Floor for local storage or Firebase Data Connect with PostgreSQL to save in cloud. Users authenticate via Firebase Auth in order to use cloud storage.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages