Conversation
…shots Add a test-utils workspace crate that serves the real application router against a fresh MySQL database per test, with tables generated from the sea-orm entities and an optional deterministic seed data set. - Entities now match the production column types (unsigned ids, string lengths, DATE post dates). sqlx needs this to decode the resolvers' u32/u16 fields, and the generated test schema relies on it. - Integration tests cover posts, search, preview tokens, the archive, canteen, events, pages, the menu, colleagues, authors, labels, HTTP behaviour and Apollo persisted queries. - The operations website_frontend2 sends are copied into tests/frontend/ and snapshot-tested with insta. - Nine more bugs are recorded as #[ignore = "bug: ..."] tests. - compose.yaml gets healthchecks, and CI starts MySQL and Redis for tests. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: TwoDCube The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
TwoDCube
marked this pull request as draft
September 14, 2026 18:06
This was referenced Sep 14, 2026
CI serialized the aliased root fields of the canteen query in a different order than local runs, which failed its snapshot. JSON object key order carries no meaning, so take response snapshots with assert_response_snapshot!, which sorts object keys before comparing and keeps array order. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Sep 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Step 2 of 3 in adding a test suite. Stacked on #246, so the base is
test/unit-tests. Once #246 merges and its branch is deleted, GitHub retargets this PR tomaster.What changes
New
test-utilsworkspace crate, modelled on matverseny-backend's:TestApp::seeded()/TestApp::empty()serve the realwebsite_backend2::approuter, middleware included, on127.0.0.1:0. The persisted-query cache is the real Redis-backed one.TestDatabasecreates a freshtest_<uuid>MySQL database for each test and generates every table from the sea-orm entities (Schema::create_table_from_entity). It drops the database when the test ends, so tests are independent and run in parallel.seed.rsis a small, deterministic data set: published, featured, unpublished and backdated posts; authors and labels with and without posts; a nested menu; soft-deleted rows; canteen days around the ISO year boundary; events around a month's calendar grid; colleague names that need Hungarian collation. Named constants identify the rows tests use.assert_response_snapshot!isinsta::assert_json_snapshot!with object keys sorted. The order of sibling fields in responses is not stable between runs, while array order, which the tests rely on, is kept.TEST_MYSQL_URL/TEST_REDIS_URLconfigure it, with defaults that matchcompose.yaml. If a service is unreachable, the failure says how to start it.Entities aligned with production (
src/entity/):type/categorycolumns are now unsignedposts_data.dateisDATEevents_data.colorisNOT NULLOnly schema generation and seeding use these types; the resolvers select their own columns into their own structs, so runtime queries are unchanged. The unsigned types matter because sqlx only decodes
u32/u16fromUNSIGNEDcolumns. On a signed schema,Maybeswallows the decode error and the resolvers' ids would come back asnull.Integration tests (
tests/: 44 tests + 18 insta snapshots, plus 12 unit tests for the harness itself):frontend_queries.rstests/frontend/), snapshot-testedposts.rsfeatured, search (case- and accent-insensitive), unpublished posts never leaking, preview tokens, archive, author/label filters, paginationcalendar.rscontent.rshttp.rs/metricscounters, CORS, gzip, complexity limit, GraphiQL, introspection, routingpersisted_queries.rsRedisCacheround-trip and eviction of undecodable entriesCI:
Testjob startsdatabaseandrediswithdocker compose up --wait, then runscargo nextest run --workspace.FormatandClippycover the workspace.compose.yamlgains healthchecks and--max-connections=500, and drops the obsoleteversionkey.Docs:
docs/testing.mdexplains the harness, the seed data, how to update snapshots, and why entity changes must mirror migrations.Bugs found (ignored tests; each gets its own fix PR)
paging_through_posts_visits_every_published_post_oncedate <= d AND id < i, so posts with a higher id but an older date are skipped: paging stops after[1, 2].page_info_of_a_filtered_list_reflects_the_filterhasPreviousPage/hasNextPageof author, label, featured and search lists are computed over all published posts.listing_posts_without_published_posts_returns_an_empty_listCould not get min valueinstead of an empty list.nonexistent_canteen_week_is_a_graphql_errorcanteen(week: 0)panics onunwrap()and returns HTTP 500.operation_named_introspection_query_can_select_dataoperationName: "IntrospectionQuery"skip the transaction and context data, so selecting data panics (HTTP 500).trailing_slash_is_ignoredtrim_trailing_slashis added withRouter::layer, which runs after routing, soPOST /graphql/returns 404.soft_deleted_page_is_not_servedpage(slug)ignoresdeleted_at.soft_deleted_menu_items_are_not_listedmenuignoresdeleted_at.menu_slug_does_not_depend_on_selecting_linkpage_idis only loaded whenlinkis selected, so{ menu { slug } }returnsnullslugs. The frontend always selectslink, so the site isn't affected today.events_include_the_last_day_of_the_calendar_gridcovers the events bug from #246 at the API level.Snapshots record current behaviour, so each fix PR also updates the affected snapshots.
Verification
cargo fmt --all --checkpasses;cargo clippy --locked --workspace --all-targets -- -D warningsis clean.cargo test --workspaceagainst MySQL 8.4.11 and Redis 6.2.24 in local containers: 109 passed, 14 ignored.CI=true, so insta refuses to write, passes.--ignoredand fails the way its description says.test_*databases are left behind after a run.canteen_page: CI serialized the query's aliased root fields in a different order than local runs. Snapshots now compare with sorted object keys (ced400b). Ajq -Scomparison confirmed all 18 regenerated snapshots are semantically unchanged.podman build -f Containerfilefrom a clean worktree of this branch succeeds. cargo-chef compiled none of the test-only crates, and the image's binary starts on ubi-micro, exiting with the expectedEnvVarMissing { name: "DATABASE_URL" }when unconfigured.🤖 Generated with Claude Code