Skip to content

test: add unit tests for authorization, boot, booter-lb3app, context, express, core and metadata - #11854

Open
pranesh-sridhar wants to merge 6 commits into
loopbackio:masterfrom
pranesh-sridhar:test/core-packages-unit-coverage
Open

pranesh-sridhar wants to merge 6 commits into
loopbackio:masterfrom
pranesh-sridhar:test/core-packages-unit-coverage

Conversation

@pranesh-sridhar

@pranesh-sridhar pranesh-sridhar commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Add unit tests to cover code paths in five core packages and two additional packages that the existing suites did not exercise. Gaps were identified from measured nyc coverage of each package's dist/ output. Only test files are changed; there are no source changes.

@loopback/authentication is covered separately in #11853.

Package Tests before Tests after Statements before Statements after
authorization 24 27 98.00% 100%
booter-lb3app 15 18 96.87% 98.43% (100% lines/functions)
boot 78 92 see note src/ gaps closed except model.booter.ts 52-53
context 708 753 97.32% 98.98%
express 50 78 92.30% 99.11%
core 346 355 95.47% 98.74%
metadata 162 171 96.18% 98.09%

Note on boot: the baseline report also counted compiled fixtures under dist/, so a single before/after percentage is not comparable. The uncovered src/ lines it reported are now covered, apart from the model.booter.ts lines noted above.

Tests added

  • authorization: voter functions declared in @authorize metadata (allow and deny); @authorize on a property throws
  • booter-lb3app: Lb3AppBooter constructor guard, option merging, configure() path resolution
  • boot: ModelBooter, ModelApiBooter.getApiBuilderForPattern, BaseArtifactBooter (artifactName, empty options, discover with and without debug logging), Bootstrapper context reuse, BootMixin bindings
  • context: binding/view/subscription edge cases, findByTag with unknown or intersecting tags, hasInjections, inspectInjections, @inject.setter/@inject.binding rejecting filters, @config.getter/@config.view, stacked @intercept, interception proxy, invokeMethod with skipInterceptors
  • express: ExpressServer (basePath, settings, start/stop, url), toMiddleware, invokeExpressMiddleware, getMiddlewareContext, MiddlewareMixin guards, MiddlewareView, InvokeMiddlewareProvider, sortListOfGroups
  • core: assertInStates() — throws when the application is not in the expected state; setMetadata() — stores and overwrites CoreBindings.APPLICATION_METADATA; mountComponent() self-reference guard; getObserverGroupsByOrder() debug-logging branch; @service() without design-time type metadata; createServiceBinding() with a DynamicValueProvider class
  • metadata: base-class abstract-method guards (mergeWithInherited(), mergeWithOwn(), create()); getTarget() returning undefined for non-object specs; MethodMultiDecoratorFactory.mergeWithOwn on a standalone class; MetadataInspector.defineMetadata(); getMethodMetadata() with methodName omitted

Verification

Run locally on this branch, per package (lb-tsc build, then lb-mocha): all passing, 0 failing. ESLint (--report-unused-disable-directives) and Prettier are clean on all changed files.

Remaining uncovered code is mostly defensive or compiler-generated, for example the namespace merge blocks and debug-only logging.

Checklist

  • DCO (Developer Certificate of Origin) signed in all commits
  • npm test passes on your machine (ran each affected package's build and tests, plus lint on changed files; full monorepo npm test not run)
  • New tests added or existing tests modified to cover all changes
  • Code conforms with the style guide
  • API Documentation in code was updated (n/a, tests only)
  • Documentation in /docs/site was updated (n/a)
  • Affected artifact templates in packages/cli were updated (n/a)
  • Affected example projects in examples/* were updated (n/a)

- Interceptor: invoke voter functions declared directly in the
  @authorize metadata, for both allow and deny decisions
- @authorize: throws when applied to a property

Statement, function and line coverage of the package is now 100%.

Signed-off-by: Pranesh Sridhar <68075088+pranesh-sridhar@users.noreply.github.com>
…configure

Cover the guard for applications without mountExpressRouter, option
merging with defaults, and appPath resolution.

Signed-off-by: Pranesh Sridhar <68075088+pranesh-sridhar@users.noreply.github.com>
…ixin bindings

- ModelBooter: default and custom options, binding of model classes
- ModelApiBooter: getApiBuilderForPattern lookup and error messages
- BaseArtifactBooter: artifactName, empty dirs/extensions, discover with
  and without debug logging
- Bootstrapper: reuse booter instances when a context is passed to boot()
- BootMixin: PROJECT_ROOT and BOOT_OPTIONS dynamic bindings

Signed-off-by: Pranesh Sridhar <68075088+pranesh-sridhar@users.noreply.github.com>
…tion and interceptors

Add unit tests for code paths that were not covered by the existing suites:

- Binding: refresh without cache, unconfigured bindings, server scope
  resolution failures, once()
- ContextView: singleValue(), open() reuse, once()
- Context: findByTag with unknown or intersecting tags, observer
  subscribe/unsubscribe/close edge cases
- Injection: hasInjections, inspectInjections, @inject.setter and
  @inject.binding rejecting binding filters, @config.getter/@config.view
  without a current binding
- Interceptors: stacked @intercept on classes and methods, registering
  provider classes and grouped global interceptors, interception proxy
- InvocationContext.toString(), invokeMethod with skipInterceptors,
  BindingKey.validate, isBindingAddress, uuid

Signed-off-by: Pranesh Sridhar <68075088+pranesh-sridhar@users.noreply.github.com>
…d invoke provider

- ExpressServer: basePath normalization, Express settings, listening and
  url lifecycle, serving under basePath, parent context
- toMiddleware and invokeExpressMiddleware: single/chained handlers and the
  empty-handler error
- getMiddlewareContext: missing request and bound context
- MiddlewareMixin: non-Context super class and empty handler list
- MiddlewareView: group ordering, refresh, validate callback, debug logging
- InvokeMiddlewareProvider: handler arrays, default and custom chains
- sortListOfGroups: debug logging and short group lists

Signed-off-by: Pranesh Sridhar <68075088+pranesh-sridhar@users.noreply.github.com>
Add unit tests to cover code paths in `@loopback/core` and
`@loopback/metadata` that the existing suites did not exercise.
Coverage was measured with `nyc` over each package's `dist/` output.
Only test files are changed; there are no source changes.

`@loopback/authentication` is covered in loopbackio#11853.
`@loopback/authorization`, `boot`, `booter-lb3app`, `context`,
and `express` are covered in loopbackio#11854.

| Package | Tests before | Tests after | Stmts before | Stmts after |
|---|---|---|---|---|
| `core` | 346 | 355 | 95.47% | 98.74% |
| `metadata` | 162 | 171 | 96.18% | 98.09% |

### Tests added

**`@loopback/core`**

- `application-lifecycle.unit.ts`: `assertInStates()` — throws when the
  application is not in the expected state; does not throw when it is
- `application.unit.ts`: `setMetadata()` — stores metadata under
  `CoreBindings.APPLICATION_METADATA`; overwrites on a second call
- `component.unit.ts`: `mountComponent()` self-reference guard —
  skips a component instance placed directly in its own `components` array
- `lifecycle-registry.unit.ts`: `getObserverGroupsByOrder()` — debug
  logging branch exercised by enabling the `loopback:core:lifecycle`
  namespace temporarily
- `service.unit.ts`: `@service()` without design-time type metadata —
  throws "No design-time type metadata found" when `design:type` is
  absent; `createServiceBinding()` with a `DynamicValueProvider` class —
  trims the `Provider` suffix from the name; preserves a custom name

**`@loopback/metadata`**

- `decorator-factory.unit.ts`: Base-class abstract-method guards —
  `mergeWithInherited()`, `mergeWithOwn()`, and `create()` each throw
  "not implemented" when the subclass does not override them; `getTarget()`
  returns `undefined` for non-object specs; `MethodMultiDecoratorFactory`
  `mergeWithOwn` exercised on a standalone class with no base
- `inspector.unit.ts`: `MetadataInspector.defineMetadata()` — stores and
  overwrites class-level metadata; `getMethodMetadata()` with `methodName`
  omitted defaults to the constructor key

### Verification

All tests pass (`npm test` per package, `lb-tsc` build + `lb-mocha`).
ESLint (`--report-unused-disable-directives`) and Prettier clean on all
changed files.

Signed-off-by: Pranesh Sridhar <Pranesh.Sridhar@ibm.com>
@pranesh-sridhar pranesh-sridhar changed the title test: add unit tests for authorization, boot, booter-lb3app, context and express test: add unit tests for authorization, boot, booter-lb3app, context, express, core and metadata Oct 22, 2026

@dhmlau dhmlau left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pranesh-sridhar, thanks for your PR. Your PR LGTM.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants