Skip to content

test: deprecation middleware unit tests, admin course/badge E2E coverage - #744

Merged
DeFiVC merged 3 commits into
ChainLearnOfficial:mainfrom
Kinkytech:test/chainlearn-kinkytech-batch-582-583-612-613
Oct 21, 2026
Merged

DeFiVC merged 3 commits into
ChainLearnOfficial:mainfrom
Kinkytech:test/chainlearn-kinkytech-batch-582-583-612-613

Conversation

@Kinkytech

@Kinkytech Kinkytech commented Oct 21, 2026 •

Copy link
Copy Markdown

closes #583
closes #612
closes #613
closes #582

Note: #582 (unit tests for timeout middleware) is not included. tests/unit/middleware/timeout.test.ts already exists at exactly the path the issue asks for and covers default timeout, per-route override, and the timeout response (408, not the 504 the issue's acceptance criteria names, matching what registerRequestTimeout actually sends). 4/4 passing, confirmed, not claiming it here.

Infra fix (required before #612/#613 could even boot a server)

Same repo-wide breakage already reported in full in #689: every E2E test crashes before buildApp() finishes, confirmed on a clean clone of main. Since #612 and #613 both ask for new E2E coverage, fixed it here too rather than write tests against a server that cannot boot. Full detail is in the first commit's message and mirrors #689: the logger.ts/config/index.ts circular import, the Fastify logger vs loggerInstance option, process-webhook-retries.ts's two concatenated implementations, dead NestJS-style scaffold code bolted onto several real files (course.service.ts, credential.controller.ts, credential.service.ts, reward.controller.ts, plus three fully-dead files and the whole src/modules/quizes/ directory), duplicate route registrations in course.routes.ts/admin-course.routes.ts, and a ReferenceError in webhook-dispatcher.ts's sendWebhook().

New bug found while writing #612's content-management tests: admin-course.routes.ts's POST .../modules/:moduleId/content route had a Fastify-level JSON Schema (body: { content: string, contentType, videoUrl }) that doesn't match course.types.ts's createContentSchema at all, a Zod discriminated union keyed on a required type field, with content as an object shaped per type (text/video/quiz/exercise). Fastify validates the route's own JSON Schema before the Zod preHandler ever runs, so any request shaped for the real schema was rejected with FST_ERR_VALIDATION, this endpoint could not succeed with any input. Rewrote the route schema to match createContentSchema's actual shape.

What's added

  • tests/unit/middleware/deprecation.test.ts (Add unit tests for deprecation middleware #583): deprecationHeader() is a preHandler factory attaching RFC 8594 Deprecation/Sunset/Link headers. It isn't currently attached to any route (confirmed via a repo-wide search), so there's no endpoint-matching logic beyond the factory's own header construction to test; covered that: the Deprecation: true header, the Sunset header as a valid RFC 7231 HTTP-date, the Link header's successor-version computation, and that all three are set independent of request contents.
  • tests/e2e/admin-courses.test.ts (Add E2E tests for admin course management #612): course CRUD, module management (create/update/delete), content management (create/list/delete, the bug above was found and fixed writing these), and course publishing (publish-check correctly reporting a module-less course as not ready, and publish itself rejecting that same course).
  • tests/e2e/admin-badges.test.ts (Add E2E tests for admin badge management #613): badge CRUD. For "assignment" and "progress tracking": there's no admin assignment endpoint; badges are evaluated and auto-awarded against a user's real activity on every call to GET /users/me/badges (badge.service.ts's evaluateUserBadges). Covered that end to end: seeding real enrollment data against an admin-created badge's criteria, confirming its progress before it's earned, and confirming it gets auto-awarded once the criteria are met.

30 tests, all passing. Also confirmed courses.test.ts, credentials.test.ts, rewards.test.ts, and quizzes.test.ts all still pass (no regressions from the scaffold cleanup).

Disclosure: course-modules.test.ts has 3 pre-existing failures unrelated to anything touched here, confirmed present before this PR too.

…ntent-creation bug (ChainLearnOfficial#612, ChainLearnOfficial#613)

Same repo-wide breakage already reported in full in PR ChainLearnOfficial#689: every
E2E test crashes before buildApp() finishes, confirmed on a clean
clone of main. ChainLearnOfficial#612 and ChainLearnOfficial#613 ask for new E2E coverage against two of
the affected route files, so fixed it here too rather than write
tests against a server that cannot boot:

- utils/logger.ts and config/index.ts had a circular import that left
  config undefined mid-evaluation, crashing every logger.ts import.
- server.ts passed a pre-built pino instance via Fastify's logger
  option (object or boolean only); switched to loggerInstance.
- jobs/process-webhook-retries.ts had two incompatible
  implementations of startWebhookRetryProcessor concatenated
  together with a stray mid-file import; kept the one server.ts
  actually calls.
- Several files (course.service.ts, course-publish.controller.ts,
  credential.controller.ts, credential.service.ts,
  reward.controller.ts, admin-reward.controller.ts, and all of
  src/modules/quizes/, the real module is modules/quizzes/) had dead
  NestJS style scaffold code bolted onto or alongside the real
  Fastify implementations, causing duplicate export and duplicate
  class compile errors. None of it was registered with the app;
  removed it.
- course.routes.ts and admin-course.routes.ts each registered the
  same method and path twice (quiz-history, quiz archive, quiz
  analytics); kept whichever registration's schema matched what the
  controller method actually implements.
- services/webhook-dispatcher.ts's sendWebhook() called
  clearTimeout(timer) in its finally block, but the AbortController
  timeout handle is named timeout, not timer, a ReferenceError on
  every webhook send.

Also fixed, found while writing ChainLearnOfficial#612's content-management tests:
admin-course.routes.ts's POST .../modules/:moduleId/content route had
a Fastify-level JSON Schema (body: content as a string, plus
contentType and videoUrl) that doesn't match course.types.ts's
createContentSchema at all, a Zod discriminated union keyed on a
required type field, with content as an object shaped per type:
text/video/quiz/exercise. Fastify validates the route's own JSON
Schema before the Zod preHandler ever runs, so any request shaped for
the real schema was rejected with FST_ERR_VALIDATION; this endpoint
could not succeed with any input. Rewrote the route schema to match
createContentSchema's actual shape.
…admin course/badge management (ChainLearnOfficial#583, ChainLearnOfficial#612, ChainLearnOfficial#613)

Note: ChainLearnOfficial#582 (unit tests for timeout middleware) is not included;
tests/unit/middleware/timeout.test.ts already exists at exactly the
path the issue asks for and covers default timeout, per-route
override, and the timeout response, 408, not the 504 the issue's
acceptance criteria names, matching what registerRequestTimeout
actually sends (4/4 passing). Confirmed, not claiming it here.

tests/unit/middleware/deprecation.test.ts (ChainLearnOfficial#583): deprecationHeader()
is a preHandler factory that attaches RFC 8594 Deprecation/Sunset/Link
headers. It is not currently attached to any route (confirmed via a
repo-wide search), so there is no endpoint-matching logic beyond the
factory's own header construction to test; covers that: the
Deprecation: true header, the Sunset header as a valid RFC 7231
HTTP-date, the Link header's successor-version computation, and that
all three headers are set independent of request contents.

tests/e2e/admin-courses.test.ts (ChainLearnOfficial#612): course CRUD, module management
(create/update/delete), content management (create/list/delete), and
course publishing (publish-check correctly reporting a module-less
course as not ready, and publish itself rejecting that same course).

tests/e2e/admin-badges.test.ts (ChainLearnOfficial#613): badge CRUD. For 'assignment' and
'progress tracking', there is no admin assignment endpoint; badges are
evaluated and auto-awarded against a user's real activity on every
call to GET /users/me/badges (badge.service.ts's evaluateUserBadges).
Covered that end to end: seeding real enrollment data against an
admin-created badge's criteria, confirming its progress before it's
earned, and confirming it gets auto-awarded once the criteria are met.

30 tests total, all passing.
@drips-wave

drips-wave Bot commented Oct 21, 2026

Copy link
Copy Markdown

@Kinkytech Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@DeFiVC
DeFiVC merged commit 2176990 into ChainLearnOfficial:main Oct 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants