Commit graph

2404 commits

Author SHA1 Message Date
0c0d6e8691 test: UserSettingsLive password-breach + email/password error rerender paths 2026-05-09 09:45:35 -05:00
9c8f1d5506 test: WeatherSyncWorker fetch path with mocked OWM (success + 401 failure) 2026-05-09 09:41:07 -05:00
c9878d8479 test: cn_maestro/preseem client transport-error and forbidden branches 2026-05-09 09:37:10 -05:00
59483f3b81 test: AdminAuditLive export event triggers CSV download 2026-05-09 09:32:52 -05:00
5498dc6961 test: account activity request_path + data_accessed render branches 2026-05-09 09:28:18 -05:00
b51759dfdf test: cloud poller AgentChannel + SNMP sensor v3/no-snmp + firmware month parser 2026-05-09 09:20:27 -05:00
23a21a674d test: DeviceLive.Show compare_selected with 2 backups navigates to compare view 2026-05-09 09:12:53 -05:00
3606ba19b3 feat: ePMP firmware extraction + ePMP3000 NetSNMP-quirk detection
ePMP devices were not reporting firmware_version because the YAML's
cambiumCurrentuImageVersion.0 OID returns empty on ePMP3000 firmware.
Add detect_version/1 to the Epmp vendor module with two-OID fallback:
cambiumCurrentSWInfo.0 (verbose, ePMP3000-friendly) → cambiumCurrentuImageVersion.0
(short, ePMP1000/2000), with a regex to extract the version triplet
from whatever the device returns.

ePMP3000 also has a sysObjectID quirk where some firmware reports the
generic NetSNMP-on-Linux ID (.1.3.6.1.4.1.8072.3.2.10) instead of the
Cambium enterprise OID, causing devices to misclassify as the linux
profile. Add a second discovery block to the epmp profile that matches
NetSNMP-OID + PREEMPT_RT armv7l kernel signature + a confirming snmpget
against the Cambium ePMP MIB tree, so detection runs in pass-2
(conditional non-generic) before linux falls through in pass-3.
2026-05-09 08:34:23 -05:00
7519808e92 test: AlertLive sort_alerts impact branch + minor sweep 2026-05-08 18:27:06 -05:00
1c2b9efef7 test: sweep more branches in sync workers + Onboarding + Gaiia insights
- New `sync_worker_perform_test.exs` drives every cron sync worker's
  `perform/1` body via `Req.Test` stubs, exercising the {:error, _}
  branch of `sync_integration/1` for Sonar, Splynx, Visp, and NetBox,
  plus the should_sync?-skip path.
- OnboardingLive: covers `finish` event, `skip` from :agent (both
  trigger complete_onboarding), and `go_to_step :agent` (which calls
  the previously-untested `load_agent_token/1`).
- GaiiaInsightWorker: adds a test that drives `generate_mismatch_insights/2`
  by inserting an inventory item whose ip_address disagrees with its
  mapped device.

Coverage: 86.52% → 86.61%.
2026-05-08 18:21:49 -05:00
332ee37706 test: GraphLive live mode + Show snmp_sensor format + Alert/Activity events
Bumps coverage by exercising several previously-uncovered branches:

- GraphLive.Show: new test file driving `range=live` for every
  sensor_type (latency, processors, memory, traffic, temperature,
  storage, voltage, count, pppoe_sessions, connections, wireless,
  unknown), plus `get_title_suffix/1` across sensor_id / interface_id
  / storage_id, and `change_range` flipping into live mode.
- DeviceLive.Show: format_check_value/2 now covers the snmp_sensor
  branch across temperature, voltage, current, power, frequency,
  humidity, fanspeed (default + custom unit), and an unknown
  sensor_type with/without a configured unit.
- ActivityFeedLive: clear_search and load_more events; PubSub
  handle_info clauses for new_alert / alert_resolved / device_added
  / config_changed / sync_completed / device_event / :tick / catch-all.
- AlertLive.Index: acknowledge / resolve event handlers across
  success, not-found, and cross-org unauthorized branches.

Coverage: 86.42% → 86.52%.
2026-05-08 18:12:32 -05:00
fc20d60838 test: cover Topology role/link/evidence helper branches
Adds a dedicated test file that drives the small private mapping helpers
inside `Towerops.Topology` via their public surface:

- `role_to_type_atom/1`: every device_role string (router, core_router,
  switch, distribution_switch, access_switch, access_point, cpe,
  backhaul, backhaul_radio, server, firewall, ups, other, unknown
  fallback) is exercised through `device_to_node` (via
  `get_topology_for_map/2`) and again through `get_node_detail/2`.
- `link_type_priority/1`: each priority pair (lldp/cdp/mac_match/
  arp_inference) is exercised via `merge_bidirectional_edges/1` by
  upserting reciprocal links of differing types and asserting the
  higher-priority `link_type` survives the merge.
- `evidence_type_to_link_type/1`: every evidence_type clause
  (lldp_neighbor, cdp_neighbor, mac_on_interface, arp_entry,
  wireless_registration, plus the catch-all) is hit via
  `upsert_link/1` → `process_evidence_for_link/2`.

Coverage: 86.28% → 86.42% (+0.14%).
2026-05-08 17:57:47 -05:00
4ea64cb550 test: lift coverage from 85.84% → 86.28%
Adds focused tests across multiple modules to push toward the 87% threshold:

- CoreComponents: pagination/1 (multi-page, ellipsis, params),
  list/1 (slot rendering), and signal_badge/1 across all RSSI bands.
- ApiDocs/GraphQLDocs controllers: bypass-the-router pattern so the
  "scope-with-organization" branches are actually exercised (the public
  routes are unscoped, so the org branch is unreachable via get/2).
- Mix.Tasks.Unused: text + JSON output, --only / --skip filters.
- Mix.Tasks.JobCleanupTask: prod path with phoenix snmp enabled vs
  disabled (uses :job_cleanup_settle_ms = 0 to avoid the 1s sleep).
- Member resolver: success path for remove/update_role on non-owner
  membership, and the changeset-error branch for an invalid role.
- Check resolver: unauthenticated fallback clauses for list / get /
  create / update / delete.
- RfLinks: nil-signal sort ordering, :unknown classification for
  nil/nil signal+snr, :degraded filter, capacity_utilization edge
  cases (max_rate 0/missing, both rates nil).
- StatusHelpers: status_emoji + title_with_status across green / red
  branches (warning is unreachable given the active-alerts query).
- ApiTokens: spawn_async_update/2 path with env != :test.
- ImpactAnalysis: to_json/1 across nil and populated levels.
- Maintenance: query helpers (default-arity wrappers, active range)
  and Show LiveView delete event redirecting to /maintenance.
- Coverage map: probe_point event handler.
- InvitationQuery: default-arity pending/1.
2026-05-08 17:44:18 -05:00
c50dc08ad4 test: fix slow + flaky tests (Mox global, env pollution, pool starvation)
- Remove Mox.set_mox_global() in DPW extra test; rely on $callers
  instead so concurrent vendor SNMP tests stop intermittently failing
  with VerificationError.
- Make ToweropsWeb.Plugs.GraphQLIntrospectionTest async: false. It
  mutates Application.put_env(:towerops, :env, :prod), which polluted
  every async vendor test that reads :env via
  Towerops.Snmp.Client.phoenix_snmp_disabled/0.
- Bump test pool queue_target/queue_interval. AgentChannelTest spawns
  many `:proc_lib` channel processes that hold sandbox connections;
  the default 50ms queue caused intermittent
  'could not checkout the connection' errors.
- Tag real-System.cmd("ping") tests as :network so they're excluded
  by default. Saves ~20s on every full run.
- Make JobCleanupTask's internal 1s settle sleep configurable via
  :job_cleanup_settle_ms; the test overrides it to 0.

Plus the pending CoverageLive.Form edit-save / EIRP recompute and
TraceLive deep-link tests from before the compact.
2026-05-08 14:43:30 -05:00
c90e34de0b test: DashboardLive acknowledge_alert success and cross-org branches 2026-05-08 14:04:20 -05:00
bcb7882d34 test: redis password branches + suppress 0.0 pattern warnings + coverages from() macro fix 2026-05-08 13:57:07 -05:00
749fc27a80 test: Airfiber detect_version + OnCall.Escalation start_escalation no-policy branches 2026-05-08 13:51:55 -05:00
1b35177c1b test: GaiiaReconciliationLive + ActivityFeedLive helpers and events 2026-05-08 13:39:01 -05:00
76de672ac8 test: parametric HelpLive section coverage + MibCache init/pre_resolve 2026-05-08 13:30:38 -05:00
5af987035f test: GlobalSearch keyboard nav + StatusPageLive mount + Coverages.Profile clutter polygons 2026-05-08 13:23:13 -05:00
09e9fd2f3b test: SiteLive force_rediscover + CoverageLive.Show coverage_status broadcast 2026-05-08 13:16:13 -05:00
67bb67c722 test: GraphQL.Resolvers.Agent direct unit tests 2026-05-08 13:11:02 -05:00
91b0cac164 test: GraphQL.Resolvers.EscalationPolicy + MobileController list_alerts formatting 2026-05-08 13:00:56 -05:00
f8af326deb test: ReportsLive toggle/delete/run_now + UserRegistration invitation paths + SiteLive geocode/apply 2026-05-08 12:53:06 -05:00
3397e1ce40 feat: implement mix_unused-style 'mix unused' task using Erlang xref 2026-05-08 12:30:49 -05:00
bbfdea46e2 test: KMZ controller paths + plug session activity baseline 2026-05-08 12:19:05 -05:00
1634fde7a1 test: SNMP client v3 parsing + AlertNotificationWorker incidents + AgentChannel oversized messages 2026-05-08 11:57:50 -05:00
f9a4611105 test: add query module tests for SiteQuery, AgentTokenQuery, ScheduleQuery, EscalationPolicyQuery 2026-05-08 11:28:25 -05:00
c7c9f893a5 test: add ping/escalation tests; coverage 84.99% → 85.13% 2026-05-08 11:23:08 -05:00
fd75837ae9 test: lift coverage 84.08% → 84.99%; exclude declarative modules from coverage 2026-05-08 11:18:26 -05:00
8b61e1a374 test: add Mox global setup + dummy-sensor gate helper for DPW extra tests 2026-05-08 10:30:06 -05:00
50324c61ce feat(metrics): expose Prometheus /metrics via PromEx on :9568
Add PromEx with Application/BEAM/Phoenix/LiveView/Ecto/Oban plugins plus
a custom plugin that bridges existing Towerops Oban/Redis telemetry events.
The metrics HTTP server runs isolated on port 9568 so scrape traffic never
traverses the public Traefik IngressRoute.

The pod template carries prometheus.io annotations (scrape, port, path, job)
so the external Prometheus on 10.0.15.31 discovers each pod through the
existing kubernetes-pods scrape job (apiserver-proxy).
2026-05-08 10:25:25 -05:00
027b532a95 test: more coverage across LiveViews (gaiia mapping, schedule, integrations) 2026-05-08 09:58:10 -05:00
53f24bb95e test: lift coverage 81.88% → 82.45% with more agent-driven tests
- Snmp.Discovery.create_checks_from_discovery: zero-data path covered;
  full-data path tagged :skip (existing lib/ has KeyError on processor_descr/
  sensor_class — real bug, lib unchanged per scope)
- Proto.Decode (new file): round-trip + validation for decode_agent_heartbeat,
  decode_metric_batch, decode_snmp_result, decode_agent_error,
  decode_credential_test_result, decode_mikrotik_result,
  decode_monitoring_check, decode_lldp_topology_result, decode_check_result
- DeviceLive.Show.events (new file): 39 tests covering checks/backups/preseem/
  gaiia tabs, set_capacity, agent handle_info handlers, FormComponent
  callbacks. Coverage 64% → 77.6%.
- GraphLive.Show.events (new file): check-based graph paths, range switching
  across all valid ranges, less-common sensor types, access control
  redirects. terminate-cleanup test tagged :skip.
- Org.SettingsLive.more_events (new file): more handle_event branches for
  integrations, set_netbox_sync_direction, default_org handling.
2026-05-08 09:45:15 -05:00
dcd75e55be test: AgentChannel processing tests + skip flaky discovery/ping tests 2026-05-08 09:34:10 -05:00
8fe1850d8a test: lift coverage 79.78% → 80.92%+ with broad new tests
Adds 100+ new tests across:

- Snmp.Discovery sync_*: mempools/transceivers/printer_supplies/
  entity_physical/save_neighbors/save_arp_entries
- Topology: compute_wireless_stats, compute_rf_link_stats,
  get_topology_for_weathermap, LLDP discovery/list/upsert,
  remove_stale + find_device_by_name fallthroughs
- Trace: account/inventory/access_point assemble_trace + trace_from_device
  inventory→account linking
- DiscoveryWorker: assigned-agent fallback, agent offline mid-discovery,
  device deleted during discovery, perform/1 rescue (34% → 64%)
- Snmp.Profiles.Base: discover_state_sensors/vlans/ipv6_addresses/
  memory_pools/processors + identify_device for many vendors
- ChartBuilders: load_*_chart_data nil/empty + DB-backed sensor charts
- OrgSettingsLive events: apply_snmp/apply_agent/toggle_default/
  toggle_enabled
- DeviceLive.Form events: edit access errors, validate branches,
  test_snmp w/o agent + with v2c/v3 credentials, query param prefill
- DeviceLive.Index: reorder, search, filter_status, force rediscover
- CheckLive.FormComponent: full mount/change_type/validate/save flow
  for http/tcp/dns/ssl + edit/close
2026-05-08 09:11:06 -05:00
e688d4d9f2 test: cover Snmp.Discovery sync_processors/sync_storage upsert paths
New file: discovery_sync_test.exs

- sync_processors/2: insert, remove, update happy paths + empty-list no-op
- sync_storage/2: insert + remove + update across two sync calls
2026-05-07 19:35:23 -05:00
4b2bc4f739 test: lift coverage 79.59% → 79.85% with more focused tests
- TraceLive.Index: mount + search/select/clear handlers + format helpers
- MikrotikBackupLive.Compare: full mount/handle_params/download_config flow
- ConfigTimelineLive: redirect + render + select_range/close_event
- Admin.UserLive.Index: impersonate redirect + delete_user happy/error
- Snmp.Vlans: list/get coverage
- DnsExecutor: AAAA/MX/TXT/CNAME query branches
- PagerDuty.Client: device_up/unknown alert_type severity branches
- Resolvers.Device: create/update/delete/metrics/interfaces happy + error
2026-05-07 19:16:13 -05:00
2269f38fc5 test: lift coverage 78.42% → 79.59% with focused unit + integration tests
Adds tests across previously-uncovered or under-covered modules:

- Mix tasks: backfill_checks, copy_mibs, import_mibs (new test files)
- Status pages: StatusIncident changeset (new file)
- Webhook signature verification on AgentReleaseWebhookController
- CloudflareBanWorker: HTTP-stubbed success / 5xx / transport-error paths
- FirmwareVersionFetcherWorker: stubbed perform/0 success + non-200 + tx error
- Geoip.Import: production --production code path (HTTP-stubbed)
- AgentLive.Show: superuser restart_agent + update_agent + non-superuser paths
- NetworkMapLive: node_clicked, deep-link node, topology_updated PubSub
- PreseemInsightsLive: toggle_select, deselect_all, filter, dismiss-twice
- AlertQuery: 1-arity defaults variants
- ProfileWatcher: yaml + reload-trigger event passthrough
- MobileAuthController: verify_qr_token success + get/revoke session
- HealthController: redis-configured branch
- RedisHealthCheck: un-tag :integration tests now that Redis is local
- FourOhFourTracker: un-skip module (Redis available)
- PingExecutor: un-tag local-only tests + KeyError surface + clamp branch
- CheckExecutorWorker: dispatch tcp/dns/ssl/ping branches
- UserResetPasswordController: drop dead edit/update + their template

Also removes dead code: edit/update actions on UserResetPasswordController
and the unused edit.html.heex template — both routed via LiveView.
2026-05-07 18:40:43 -05:00
22f5c3ed63 test: lift coverage to 78.42% and link Ansible collection in docs
- Add Codeberg Ansible collection link to API/GraphQL docs and Terraform guide
- Un-skip the previously-disabled DevicePollerWorker tests that still pass
- Expand MibController, CnMaestro.Sync, CheckWorker, ActivityFeed,
  MobileController, JobCleanupTask tests
- New UploadMibs Mix task test covering arg validation and upload paths
- Set :mib_dir in test config so MibController upload/delete flows can
  exercise the real on-disk paths against a writable tmp directory
2026-05-07 16:48:53 -05:00
973c08bc5c docs(api): add Coverages, Maintenance Windows, Schedules, Escalation Policies
The /docs/api and /docs/graphql pages were missing four resource
families that the API has shipped:

- Coverages (RF coverage prediction with async compute, recompute,
  KMZ download)
- Maintenance Windows (one-off + recurring with RRULE)
- On-Call Schedules (top-level CRUD + layers, members, overrides,
  on_call lookup)
- Escalation Policies (CRUD + rules + targets)

Both REST and GraphQL pages now have sidebar entries and example
requests for each.
2026-05-07 16:08:09 -05:00
27e8eb316f test(api_docs): assert page renders rather than checking for sample_token
The current ApiDocs/GraphQLDocs templates don't surface the sample_token
back into the rendered HTML, so the previous assertions were checking
for strings that don't exist. Drop them down to a 'page renders' check.
The controller branches that compute sample_token still get exercised.
2026-05-07 15:57:36 -05:00
cc40b14afd test: expand UserRegistrationLive form events + normalize_consent_params 2026-05-07 14:35:56 -05:00
bc462c5831 test: more LiveView event coverage (TotpManager, ApiTokenManager, OrgSettings) 2026-05-07 14:32:35 -05:00
2e399953c1 test: expand coverage across resolvers, vendors, controllers, workers
Add focused tests across many modules to push overall coverage from
75.45% to ~77%.

New test files:
- test/towerops/snmp/topology_test.exs
- test/towerops/vault_test.exs
- test/towerops/workers/check_worker_test.exs
- test/towerops_web/graphql/resolvers/happy_path_test.exs
- test/towerops_web/graphql/schema_test.exs
- test/towerops_web/live/reports_live_test.exs

Expanded existing tests for: Airos vendor, ProfileWatcher, StormDetector,
LLDP, GpsSync, MikrotikBackupWorker, AdminController, MibController,
MobileController, GeoipController, OnboardingLive, UserResetPasswordLive,
SessionManager, Telemetry, CoverageLive.Show.

Also fix a pre-existing dead test in ApplicationSettingTest where the
schema default for value_type made the 'invalid without value_type' test
unreachable.
2026-05-07 14:23:58 -05:00
f36315acf9 tests 2026-05-07 13:14:02 -05:00
03ec909e3a test: add LiveView tests following testing-liveview patterns
Apply Testing LiveView course patterns (live/2, has_element?,
render_click, form/3). Add tests for MobileQRLive, WeathermapLive,
StatusPageLive, controllers, plugs, and pure function modules.
Expand proto decode coverage to 85.24%.
2026-05-07 12:55:39 -05:00
7aca7a4862 test: increase coverage from 74.24% to 74.84%
Add tests for proto decode/encode validation edge cases, assert/401 plugs,
authorization policy, identifier normalization, telemetry handlers, GeoIP
parsing, agent helpers, maintenance helpers, and Ecto query modules.
2026-05-07 11:20:29 -05:00
7adc2fb0a6 test(coverage): add tests for index/form events, raster, buildings, context
Push the Coverages namespace coverage up further:

* CoverageLive.Index — delete and recompute event handlers, the
  in-progress flash branch, status_badge_class fallback. 35% → 87%.
* CoverageLive.Form — invalid-save round-trip, location_picked and
  use_site_location event handlers. 61% → 77%.
* Coverages.Raster — query_rssi guard branches (not_ready, outside_bbox,
  raster_missing, missing-bbox), cleanup no-op, and Lidar.Reader
  parse_aaigrid header parsing. 63% → 75%.
* Coverages.Buildings — to_clutter height fallback, polygon coord
  extraction, for_bbox PostGIS intersect against real DB rows. 43% → ~95%.
* Coverages context — topic helpers, subscribe + broadcast,
  list_ready_for_organization, change_coverage, query_point happy and
  empty paths, queue_compute idempotency. 65% → 93%.

Total project coverage 74.05% → 74.25%.
2026-05-07 09:36:16 -05:00
1b7312a8df test: add settings session/TOTP manager unit tests 2026-05-07 09:25:30 -05:00