Release v0.2.0 - #76
Merged
Merged
Conversation
Moved here from @fleetbase/ember-core, where it had been importing ../models/waypoint — a path that does not exist in that package, so the module threw for anyone who imported it. This is its natural home: the Waypoint model lives here, so the import is a plain relative one. It could not stay in ember-core, because ember-core cannot depend on fleetops-data (fleetops-data already depends on ember-core), leaving only an undeclared cross-package import or an optional peer dependency, both worse than putting the util beside the model it checks. No package used it in source, so nothing needs updating alongside this. The matches that show up elsewhere are in built dist bundles, which is ember-core's own code inlined into consumers' vendor files rather than real usage. Tested against a real waypoint, the place model waypoint extends, an unrelated record, a proxy, and plain and nullish values. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Ember test suite could not boot at all: `@ember/string` is only a peer dependency of ember-data, so it was never linked at the top level and the vendor bundle could not resolve it. CI only ran `pnpm run build`, so this went unnoticed. Declare it explicitly, along with the other pieces the dummy application needs to stand up the addon: - `ember-fetch`, which `@fleetbase/ember-core`'s fetch service imports and host applications supply. - `API.host` / `API.namespace` in the dummy config, read at module scope by the ember-core application adapter. - Stub models for the 11 types Fleet-Ops relates to but does not define (file, user, company, comment, custom-field-value, ...). - `EXTEND_PROTOTYPES: true`, matching the Fleetbase console, which Fleet-Ops models rely on for `pushObjects`/`objectAt` on plain arrays. Coverage is provided by ember-cli-code-coverage, instrumenting only the addon's own trees so the report contains first-party source and nothing else. `scripts/check-coverage.js` enforces 100% globally and per file, and derives the eligible file list from disk so a module that never gets instrumented fails the gate instead of vanishing from the denominator. `tests/helpers/load-addon-modules.js` force-loads every addon module and rethrows any import failure rather than swallowing it. Baseline: 175 tests / 131 pass / 44 fail. Now: 556 tests / 556 pass, 40.69% statements, 39.05% branches, 33.57% functions, 39.81% lines. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Replace the generated "look up a serializer, serialize an empty record, assert truthy" stubs with tests of the actual wire contract: the exact `attrs` map (so an added or removed embed fails), `uuid` as the primary key, attribute round trips through normalize and serialize, embedded relationships travelling inline, and non-embedded ones linked by `<key>_uuid`. The driver serializer gets its own treatment: user, vendor, current_job, fleets and jobs are server-owned and must never be echoed back, while the assigned vehicle is embedded — and the defensive path that reduces an already-collected `vehicle` to an identifier is exercised directly. Also move the Codecov upload ahead of the coverage gate so a shortfall is still reported on the pull request instead of being hidden behind a failed step, and fix the Feature test that was asserting the wrong constructor branch (a Point carries type and coordinates, so it never reaches the `instanceof GeoJson` path — a GeometryCollection does). 644 tests, 644 pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Replace the remaining generated "create a record, assert it exists" model stubs with the structural contract each model actually declares: - the full relationship map, including async, polymorphic and inverse options, so a mis-wired relationship fails loudly rather than surfacing as a runtime error in a consumer; - configured attribute defaults, and separately that image defaults resolve through `defaultValues` configuration rather than being hard-coded; - every `date-fns` formatting getter family, asserted against literal expected strings for a fixed local instant and against a relative instant for the distance getters, plus null/undefined/Invalid Date on both sides of the `isValidDate` guard; - the shared GeoJSON point accessors on place, driver and vehicle, including null island, zero components and the coordinate extremes. The three models whose date getters have no `isValidDate` guard (payload, integrated-vendor, service-rate) are asserted only on the happy path, with a comment recording that a missing date throws there rather than rendering as null — documenting real behaviour instead of an aspiration. 766 tests, 766 pass. Coverage 80.18% statements, 78.75% branches, 76.59% functions, 80.30% lines; 40 of 130 files still below 100%. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Completes the campaign: the coverage gate now passes with every eligible addon file at 100% statements, branches, functions and lines. Behavioural coverage for the parts the structural generators deliberately left alone: the service-rate fee ranking, dedup and rule builders; manifest and manifest-stop status lifecycles and progress arithmetic; position speed and timestamp conversion; device, sensor and attachable display fallbacks; the driver, vehicle, fuel-report and issue relationship loaders; zone and service-area geography; and the custom serialize / normalize / serializePolymorphicType overrides on the order, waypoint, maintenance, work-order, maintenance-schedule, entity, device and service-rate serializers. Fifteen defensive clauses cannot be reached through any supported use — a `rankFee` rank for a record state Ember Data cannot produce, `?? []` guards on relationships that always expose `toArray`, and guards already implied by the check above them. Rather than weaken the gate or edit production code, `scripts/unreachable-code.js` lists each one by its exact Istanbul location with the reason it is unreachable. The gate counts those locations as covered, prints them on every run, and fails if one becomes reachable or disappears — so an exemption cannot outlive its cause. Nothing else is excluded. DEFECTS.md records all fifteen findings: four production defects fixed earlier in the campaign, six behavioural issues left alone with the test that pins each one, and the five unreachable-code entries. 986 tests, 986 pass, 0 skip. Lint, production build and the 38 coverage-gate self-tests all pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Points at the default branch, so it reports the repository's coverage once this branch merges. Also records, in DEFECTS.md, that the README claims MIT while package.json and LICENSE.md say AGPL-3.0-or-later. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`package.json` declares `AGPL-3.0-or-later` and `LICENSE.md` carries the GNU Affero General Public License v3 text; only the README said MIT. It now names the licence the project actually ships under. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Declare attachment_state and vehicle_id on the Trailer model; the console never received the attachment state because the attribute was missing. - Add displayName, isAttached, isOnline, and formatted last-online/attached-at projections to Trailer, and formatted timing plus duration to AssetConnection. - Add the attachable-driver model so equipment issued to a driver normalizes instead of failing on an unknown model. - Set explicit inverses on the vehicle trailer/equipment relationships and embed the trailer category. - Cover query and single-record envelope normalization, the new projections, and the driver mapping.
The live map feed now sends each vehicle's currently coupled trailers alongside its devices so map popovers can list both. Declare the relationship as embedded so normalization pushes the trailer records instead of treating the objects as ids, and cover it with a normalizeResponse test.
Bump package.json to 0.2.0 and seed RELEASE.md so the release-tag workflow can validate the version once this branch merges to main.
…-rate Their date-fns getters formatted updated_at/created_at without the isValidDate guard every sibling model uses, so reading them on an unsaved record threw RangeError: Invalid time value. They now return null like the rest of the addon, and the guarded: false escape hatch in the shared test helper is gone so no model can opt out again.
serializeBelongsTo special-cased a vehicle that was already an array in the outgoing json and wrote vehicle_uuid from get(array, 'uuid'), which is always undefined. The branch could never run during record.serialize() either, because the embedded records mixin writes json.vehicle after this hook, and nothing in the monorepo calls the hook directly. Removed rather than repaired: correcting the type test would have left it just as dead.
The four @Not macros referenced camelCase getters the model never declared, so missing_tracking_number, missing_purchase_rate, missing_tracking_statuses and missing_payload were always true. They now negate the has_* presence macros declared directly above them. No consumer in the monorepo reads the flags, so nothing had adapted to the always-true values.
The shim re-exported a default the barrel never declares, so anything resolving it through the app tree got undefined. It now re-exports the barrel's named surface, matching the module it points at.
The post-save reconciliation keyed persisted fees by id and drafts by shape, so the two key spaces never intersected and per-drop and fixed-distance drafts were never removed once the backend returned their saved counterparts, leaving duplicate rows in the editor until reload. Both sides are now keyed by shape; genuinely different fees still do not collapse.
driver.loadVehicle/loadVendor, fuelReport.loadVehicle/loadDriver and issue.loadVehicle/loadDriver guarded their fetch with ember-core's isRelationMissing, which passes an empty path to its second isset and so never consults the relationship: every call re-fetched. They now use a local isRelationMissing that is the exact negation of shouldNotLoadRelation. shouldNotLoadRelation itself now reads a declared relationship through its Ember Data reference rather than the property: the driver's and fuel report's relationships are async, and an async belongsTo hands back a promise proxy that is never blank, so a plain property check would have made those loaders never fetch at all. Every relationship the order loaders check is async: false, so their behaviour is unchanged. The upstream ember-core util is still broken for its other consumers; fixing it there is out of scope here and noted in DEFECTS.md.
serializePolymorphicType read belongsTo.modelName before its own null guard, so an unset customer threw a TypeError and the guard could never run. The read now sits inside the else branch like every sibling serializer, an unset customer writes customer_type: null, and the coverage exemption for the formerly dead branch is removed.
… above loadPayload's second early return needed a payload whose waypoints was neither a ManyArray nor an array, which Ember Data cannot produce, and the _index_resource flag existed only to feed it. loadCustomer repeated the exact condition shouldNotLoadRelation had just returned false for. Both are gone, along with their coverage exemptions.
… relationship Ember Data never lets a hasMany be anything but a ManyArray, so the branch returning this.waypoints when it lacked toArray could not run. The getter now materializes the relationship unconditionally and the exemption and the tests that documented the dead branch are removed.
… fallbacks rankFee had a middle rank for a fee that is neither new nor has an id, which an Ember Data record cannot be, and was copied into three getters. It is now one module-level helper with two ranks. The ?? [] fallbacks guarded rate_fees and parcel_fees against having no toArray, which a hasMany always has. Their coverage exemptions go with them.
super resolves lexically against the prototype chain and JSONSerializer always provides the hook, so the typeof guard and its bare return could never run. With this last entry gone scripts/unreachable-code.js exports an empty map; the gate test now checks that an empty map prints no exemption block, and the file keeps its header as the documented home for any future exemption.
…report keys A file the report showed with all-zero totals skipped every metric and counted as fully covered, so an empty entry could stand in for a module that was never instrumented. Zero branches or functions are still skipped, but a file with zero statements is now parsed and must genuinely contain none (a bare subclass, a class of decorated fields, a re-export barrel); anything with executable code fails, and every declaration-only file is listed in the gate output. Two report keys normalizing onto the same addon path used to overwrite each other silently, so a dummy-app fixture with the same name as an addon module could substitute its trivial coverage for the real thing. A collision now fails the gate and names both keys.
…the build pull_request.branches filters on the base branch and both triggers listed only main, so pull requests retargeted at release/v0.2.0 ran no lint, tests, coverage gate or build, and pushes to the release branch triggered nothing. Both triggers now include release/**. fail_ci_if_error turned a rate-limited tokenless Codecov upload from a forked pull request into a failed test job even when everything else had passed; the upload is reporting and the gate is enforcement, so it is now false. The unused test:ci script, a second definition of what CI runs that could drift from the workflow, is removed.
Every recorded defect is now fixed, so the document records what was wrong, what changed and the covering test for each, and adds the coverage-gate and CI problems fixed in the same series.
Test coverage campaign: 100% coverage gate, CI and Codecov
…grade Add inspection data models
Add is-waypoint-record util (moved from ember-core)
Add first-class Trailer data models
Merging the four v0.2.0 pull requests left @ember/optional-features and @ember/string keyed without their (supports-color@8.1.1) suffix in the importer section while the package section still carried it, so pnpm install --frozen-lockfile failed with ERR_PNPM_LOCKFILE_MISSING_DEPENDENCY. The two lines are restored from the last consistent lockfile.
… serializer's dead guard The device tests used trailer as their unsupported attachable type, which the trailer work made supported; they now use place and assert trailer resolves. The equipment contract test still expected no embedded attrs. The is-waypoint-record test resolved its util through the dummy app tree, where ember-core's same-named shim wins and imports a waypoint model ember-core does not have; it now imports the addon module directly. The equipment serializer carried the same unreachable typeof super.serializePolymorphicType guard removed from the device serializer, with its domain-type restore folded into normalize. It now mirrors the device serializer's structure so every branch is testable.
The inspection form, submission and item-result models and serializers had no tests; several trailer and asset-connection getters were never read. DEFECTS.md records the merge findings, including the ember-core is-waypoint-record shim collision this repository cannot fix.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #76 +/- ##
========================================
Coverage ? 100.00%
========================================
Files ? 114
Lines ? 2899
Branches ? 687
========================================
Hits ? 2899
Misses ? 0
Partials ? 0
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report in Codecov by Harness.
🚀 New features to boost your workflow:
|
Every defect it recorded is fixed and covered by tests, and the working notes are not something to ship in the package. The three comments that pointed at it now carry their explanation inline.
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.
Release branch for v0.2.0. Feature PRs targeting this release are retargeted here and merge into this branch; merging this PR into
maintriggers the release-tag workflow, which tagsv0.2.0frompackage.json.Included
Release prep in this branch
package.jsonbumped0.1.40→0.2.0RELEASE.mdseeded with the v0.2.0 header and highlights (placeholders removed so the tag job passes)Update
RELEASE.mdbefore merging if the included set changes.