Development
Requirements: Flutter 3.47.9 (Dart 3.13.7), pinned in pubspec.yaml: flutter pub get refuses another release, and
the worker bundle, the formatter output and the CanvasKit build depend on it. No native dependencies.
git clone https://github.com/videjunior/opencadirrigation.git
cd opencadirrigation
flutter pub get
flutter run -d chrome # development in the browser
flutter test # about 3,000 tests: engine, model, formats, interface
flutter analyze # lints
tool/build_worker.sh # recompiles web/design_worker.js after changing lib/core (the app falls
# back to the interface thread when the file is missing)
tool/build_web.sh # release build: worker + flutter build web with the git commit and date
# baked into the version (welcome, status bar, Help → About, console),
# CanvasKit served by the site and the offline service worker filled in
# (tool/gen_sw.dart); OCI_WEB_OUT=<folder> writes the build elsewhere
flutter build web --release # a plain build (no commit/date, CanvasKit from Google's CDN, no offline
# start: its sw.js removes itself; build/web, web/CNAME holds the domain)
dart run bin/oci.dart --help # command line: import, new, set, pack add, design, analyze, check, validate,
# export, bom and schema of .oci.json projects (docs/API.md)
dart tool/engine_package.dart build/engine # the engine as a package without Flutter (needs only the Dart SDK)
dart run tool/gen_version.dart # regenerates lib/app/version.dart after changing `version:` in pubspec.yaml
dart run tool/gen_site.dart # site pages (English index, /pt/, /es/, /de/, … sitemap, 404, robots, llms.txt)
dart run tool/indexnow.dart # after a deploy: ask IndexNow engines (Bing…) to crawl the pages again
dart run tool/gen_catalogs.dart # validates and normalises catalogs/*.oci.cat and rebuilds index.json
dart run tool/gen_examples.dart # regenerates examples/<lang>/*.oci.json from lib/app/examples.dart
dart run tool/gen_brand.dart # icons and brand assets from web/brand
python3 tool/formats/make_fixtures.py # rewrites test/fixtures/formats with ezdxf, pyshp, tifffile, Pillow, openpyxl and LibreDWG
python3 tool/formats/check_exports.py # validates build/formats (written by flutter test) with independent readers
python3 tool/fonts/build_fonts.py # rebuilds the Noto subsets of assets/fonts from the interface strings
python3 tool/fonts/gen_unicode_data.py # regenerates lib/core/io/fonts/unicode_data.dart from the Unicode Character Database
python3 tool/fonts/make_shaping_fixtures.py # rewrites test/fixtures/shaping with HarfBuzz (uharfbuzz)
UPDATE_AI_TOOLS_DOC=1 flutter test test/widget_ai_coverage_test.dart # regenerates docs/AI_TOOLS.md from the coverage map
flutter test --platform chrome test/web # the *_web.dart code in a real Chrome
flutter test --update-goldens test/goldens # rewrites the golden images
dart run tool/release.dart status # the release checklist (prepare, build, publish, live, verify-build)
dart run tool/i18n_review.dart export <code> # a language as a spreadsheet for native speakers (and import)
git config core.hooksPath tool/hooks # the pre-commit hook: formatting, forbidden names, stale worker
npm ci --prefix tool/e2e # once: the end-to-end smoke test and its playwright-core
npm exec --prefix tool/e2e -- playwright-core install webkit firefox # once: the pinned WebKit and Firefox builds
node tool/e2e/smoke.mjs build/web --browser chromium,webkit,firefox # the smoke test of a production build
The command line runs the engine of the app in the Dart VM, without Flutter or a browser:
design sizes and analyses a project (and writes the designed project, the results and every
report table), analyze keeps the sizes as drawn, check lists the problems and exits with 1 on an
error, validate says what reading the file had to repair, export writes any drawing format, bom
prints the bill of materials and schema the JSON Schema of the project file, in any of the 20
languages (--lang); import, new, set and pack add make and change projects, and the
commands that read projects take several files or folders at once, with --out-dir
(docs/API.md).
The committed outputs of most generators have guard tests (the site pages, the service worker
template, the examples, the catalogues, the version and the AI tools table): when one drifts from its
source, the matching test fails and says which command to run. Rebuild the design worker
(tool/build_worker.sh) after changing lib/core or the string table, and the PDF font subsets
(tool/fonts/build_fonts.py) after adding characters, where no guard reminds you. Desktop builds (flutter run -d macos|windows|linux) use the
isolate for the calculation. The android/ and ios/ folders are the project templates Flutter
generated; native mobile builds have not been built or tested, and phones and tablets use the web
app (installable as a PWA).
How to extend
- New entity: class in
entities.dart(JSON, clone, transform, grips, distance, bounds),EntityType, default layer, painting inpainter.dart, properties inproperties_panel.dart, tool intools.dartand alias inshortcuts.dart, export inplot.dart/cad_export.dart. - New report: table in
report_tables.dart(the CSV/TXT/XLSX/PDF exporters and the panel pick it up automatically) and texts ini18n.dart. - New format: reader or writer in
lib/core/io, entry in the controller'simportFileor inDrawingFormat/ReportFormat, and a round-trip test. - New formula: in
lib/core/hydraulics, with a test against a reference value. - New AI tool: a tool in
lib/app/ai/agent_tools*.dart(sent with every request) or an operation inlib/app/ai/ops_*.dart(found withfind_operations), over the controller, with its input schema and its effect (read, change, export or a request to another service), and its route inlib/app/ai/ai_coverage.dart.test/widget_ai_tools_test.dartchecks names and schemas,test/widget_ai_coverage_test.dartfails when a command, tool, menu item or dialog has no route, andtest/widget_ai_manual_test.dartwhen the manual misses an item key, a design parameter or a message code. - Interface colours: take them from
Cad.*(lib/app/theme.dart), adding a token to both palettes when none fits;test/widget_theme_test.dartchecks the contrast of the light text tokens (4.5:1 on every light surface).
Tests
flutter test runs about 3,000 tests in a few minutes (the number grows with every version). What each
group guarantees:
| File | Coverage |
|---|---|
core/hydraulics_test.dart |
Hazen-Williams against a textbook value; Darcy-Weisbach ≈ Hazen-Williams on smooth PVC; laminar factor; Swamee-Jain ≈ Colebrook; continuity and slope match at the transition; Christiansen F table and Scaloppi adjustment; equivalent diameter; emitter law and fit; application rate; overlap CU; CU/DU and the Keller-Karmeli EU (the worked example of the technical study); pump curve fit, operating point, CRF; K → flow form; PVC celerity; number formatting without scientific notation |
core/network_test.dart |
Sparse solver; single pipe; loops; mass conservation; pressure-dependent emitters; pump; PRV; device curve; Darcy-Weisbach convergence; large branched network is fast; comparison with Christiansen; laterals on slopes; maximum length; feed positions; emitters above the available head stay closed (no backflow) |
core/network_robustness_test.dart |
A pump near its shutoff head feeding a hundred emitters near zero pressure (against an independent bisection); a pump that one bad step used to lock closed; pressure-compensating emitters on a hill, dry above the grade line and starved below it; a pressure-reducing valve just above its setting stays open; a check valve fitted as a device stops reverse flow; 300 random tree networks (pumps, check valves, demands, every emitter exponent) converge to solutions that satisfy continuity and the head-loss laws; a line at rest behind an idle pump |
core/valves_formulas_test.dart, core/pressure_class_test.dart, core/minor_fittings_test.dart, core/mains_frequency_test.dart |
Scobey and Manning laws in the solver; a pressure-sustaining valve holds its upstream setting and a flow-control valve its flow, hydrant flow limiters in a project; a variable-speed pump holds its outlet pressure flow after flow, with NPSH and efficiency curves; PVC and PE derating with temperature and the class as a sizing constraint (a 95 m supply never gets PN 80 PVC, warm water fails a pipe that passes at 20 °C); the losses of the drawn fittings; a 60 Hz pump on 50 Hz mains and the pump selection at the mains speed |
core/invariance_test.dart |
Moving a project (also to UTM coordinates), drawing its pipes the other way round, saving and reopening it or changing the language leave the design as it was; inverse-distance terrain counts every spot height once |
core/regressions_1017_test.dart |
Defects fixed in the 2026-10-17 sweep: pump and device curves typed with repeated flows, a pump with a shutoff head only, feed positions of laterals that need more than three times the nominal pressure |
core/lp_test.dart |
Simplex: ≤/≥, equalities, infeasible, unbounded, a problem shaped like the sizing one |
core/design_test.dart, core/sizing_features_test.dart, core/gaps_test.dart |
Block generator; connected graph; full analysis and sizing; LP no worse than greedy; telescoping; fittings; flushing; water hammer; overlap CU and emitters per plant; agronomy and controller programme; pump and motor selection; GeoTIFF DEM; pivot (spans, costs); looped mainline |
core/transient_test.dart, core/transient_analysis_test.dart, core/air_valves_test.dart, core/eps_test.dart |
Method of characteristics: the steady state does not move without an event, Joukowsky surge and the 4L/a period, Michaud's surge for a slow stop, friction damping, column separation, a combination air valve, a pump trip with its check valve, inertia and an air vessel, merged and lumped pipes; every example's mainline runs every scenario with the steady state inside the envelopes; air valve placement by AWWA M51 practice and orifice sizing; extended period with tanks, schedules, patterns and controls, and the energy, against analytic curves and hand calculations |
core/terrain_pivot_test.dart, core/breakline_test.dart, core/slope_map_test.dart |
Delaunay TIN exact on planes; TIN vs IDW; contour generation; segment chaining; alignment and clipping geometry; guided blocks; pivot hydraulics (including sector pivots); design check; Excel catalogue and packs; breaklines forced into the triangulation; slope and aspect maps |
core/advisor_test.dart |
Unconnected items joined (valve back at its zone), impossible settings restored, emitter pressure outside the nozzle range, zones left out of the flows, surface pump in a deep well → submersible, booster for a short public supply, flows split to the supply flow, fix automatically on a project with several mistakes, optimisation never raising the annual cost |
widget_advice_test.dart |
Messages tab explains and fixes in one click (one undo step), design with errors opens Messages, fix automatically in one history step, optimisation and menu entries, missing supply with its one-click fix |
core/auto_layout_test.dart, core/zoning_test.dart, core/routing_test.dart, core/templates_test.dart, core/field_subdivision_test.dart, core/tree_rings_test.dart, core/pivot_fit_test.dart, core/auto_design_test.dart, core/vegetation_test.dart |
Head layouts of rectangles, L-shapes, curved beds and lawns round a house with their CU, matched part circles; zones within the flow that never mix precipitation classes; zone and mainline trees round buildings; pitch, track, green, tee and fairway templates; blocks of equal area with roads; rings joined to their laterals; the largest circle and the best sector of a field; laid-out, zoned and routed lawns, fields and orchards that design without errors; vegetation of a synthetic aerial scene (lawns, crowns, shade, pool, paving) within a few per cent; each in well under a second for thousands of heads |
core/climate_test.dart, core/climate_online_test.dart, core/crops_test.dart, core/soils_test.dart, core/effective_rain_test.dart, core/irrigation_requirement_test.dart, core/solar_pumping_test.dart, core/wetted_bulb_test.dart, core/water_budget_test.dart |
FAO-56 worked examples (pressure, vapour pressure, radiation, ETo in Bangkok, Uccle and Lyon), Kc curves, Annex 7 and sparse cover; FAO-29 leaching and the drip-irrigated citrus of FAO Module 9; NEH 623 effective rain and the FAO formulas; the soil table against NEH 652, Rawls et al., FAO-56 Table 19 and the SWAT/EPA table; solar geometry against Duffie & Beckman and FAO-56 Example 8; Schwartzman & Zur; MWELO budgets and cycle and soak; Open-Meteo and NASA POWER requests, parsing, pacing, retries and normals |
core/mechanised_test.dart, core/pivot_package_test.dart, core/corner_arm_test.dart, core/vri_test.dart, core/pivot_electrical_test.dart, core/traveller_test.dart, core/surface_irrigation_test.dart, core/gated_pipe_test.dart |
NEH 623 sample calculation 11-18 (system capacity, outlet flow, end gun, friction, revolution and booster), regulated packages with numbered or catalogue nozzles, timer chart from the drive train; corner arm against analytic cases; variable rate from sectors and zones; tower motors and cable drop by IEC 60364-5-52, generator size; traveller sample calculation 11-17; the furrow, border and basin examples of FAO 45; gated pipe outlets |
core/network_ops_test.dart, core/on_demand_test.dart, core/tariff_test.dart, core/energy_grouping_test.dart, core/criticality_test.dart, core/calibration_test.dart, core/fertigation_test.dart |
Clément flows against FAO 59 Box 1 and the random-configuration check (AS 241 quantiles, MRG32k3a reference sequence); the Brazilian discount rule and the scheduler exact against brute force; energy grouping 30 % below first fit by flow; N−1 on trees and loops; golden section and Levenberg–Marquardt recovering C; fertigation travel times, plan and venturi; all of them on a designed project |
core/valve_in_head_test.dart, core/two_wire_test.dart, core/wire_routing_test.dart, core/round_1025_test.dart, widget_valve_in_head_test.dart |
Valve-in-head stations scheduled by the flows (pressures, 24 hours, wiring, two-wire, EPANET, pump static lift, controller programme, transients, fertigation) and the results of projects that never scheduled them; two-wire voltage by hand, decoders and grounding; routes along the trenches (shortest paths, Steiner-like tree), master valves and pump relays; master valve and accessories in the BOM, compressed browser storage, a device on every selected lateral, share links, comments and revision clouds, nozzle curves fitted to pasted tables |
core/dwg_test.dart, core/dwg_writer_test.dart, core/cad_export_test.dart |
Reading R2000–R2018 and R2007 samples, with blocks and dimensions expanded; rejection of unknown versions; CRC; writer round trip; LibreDWG validation when installed; R2000 DXF and DWG with native entities, dimension blocks, layers with true colours and linetypes, attribute definitions and user blocks, for every gallery example, read back alike |
core/formats_test.dart, core/formats_app_test.dart |
Every import format against files written by other programs (ezdxf, LibreDWG, pyshp, tifffile, Pillow, openpyxl and Google Earth style KML; fixtures in test/fixtures/formats, generated by tool/formats/make_fixtures.py) with positions, elevations, names and layers checked; every export re-read by our own readers and written to build/formats for tool/formats/check_exports.py, which validates them with ezdxf, LibreDWG, lxml, openpyxl and pypdf; the new formats through the app (GeoJSON, GPX, LAS, DGN, EPANET, zips of shapefiles) |
core/epanet_inp_test.dart, core/shp_writer_test.dart, core/gpx_test.dart, core/landxml_test.dart, core/ifc_test.dart, core/geojson_reader_test.dart, core/las_test.dart, core/dgn_test.dart, core/datum_test.dart |
EPANET files of designed projects matching our analysis zone by zone and flow by flow, and the reader; shapefiles, GPX, LandXML and IFC by their specifications and read back; GeoJSON with every geometry and crs; LAS formats 0–10, decimation and refusals; DGN V7 2D and 3D; transverse Mercator, the IBGE datum shifts and CRS recognition |
core/pdf_reader_test.dart, core/pdf_import_test.dart, core/pdf_fonts_test.dart, core/pdf_images_test.dart, core/text_shaping_test.dart, core/sheets_test.dart, widget_sheets_test.dart |
The PDF reader on our own files and on file structures, filters, colours, texts, images and layers of other writers, plans imported to scale; TrueType reading and subsetting, bidirectional order, embedded fonts in every interface script; shaping identical to HarfBuzz on the interface strings (fixtures by tool/fonts/make_shaping_fixtures.py); images in PDF and SVG; sheet sets, details, charts and the revision table; PNG of a sheet |
core/export_test.dart, core/kml_test.dart |
UTM round trip; georeference; KML round trip; GeoJSON; plot scene; SVG; valid compressed PDF; sheet and report pages; same tables in CSV/TXT/XLSX |
core/catalog_packs_test.dart |
Every pack in catalogs/ loads, unique ids not colliding with the default catalogue, normalised files and consistent index; pack format; loaders (assets and URL) |
core/examples_test.dart |
Every example, in the 20 languages, builds, is connected, passes the check, designs with zones inside the window and no deficit, prints every report cell as a plain number, and matches the files in examples/ |
core/spatial_index_test.dart |
Index against brute force, drawing order, degenerate cases, invalidation in the controller, selection and snap, entities by id and counts per layer |
core/painter_test.dart, core/scene_cache_test.dart |
Result overlays (the same emitter dots in every overlay, recoloured by pressure), drawing entities, texts over the linework, the hover colour, hairlines in a view packed with linework on a 2× screen; one recording per scene, a heavy scene moved with the view and drawn sharp once it rests |
core/geo_parse_test.dart, core/i18n_lang_test.dart |
Pasted coordinates (decimals, comma, hemispheres, DMS, links); contour interval; language choice from the system and the URL |
core/i18n_packs_test.dart |
Every language pack covers every key of the table, the tutorial and the catalogue names with the same placeholders and is mostly not English; installed packs reach the strings, the tutorial and the catalogue; setLanguage loads a pack on demand with English meanwhile and retries a failed load |
core/editing_test.dart, core/model_test.dart, core/workspace_test.dart, core/design_job_test.dart, core/app_io_test.dart, core/entities_roundtrip_test.dart |
Editing (grips, transformations, trim, extend, cut), entity JSON, tabs and clipboard (pivot catalogue items and wiring included), worker protocol, local HTTP, project storage, camera and snap |
core/blocks_test.dart, core/label_rules_test.dart, core/snapping_extra_test.dart, core/gps_test.dart, core/auto_analysis_test.dart, core/selection_bom_test.dart, core/proposal_test.dart, core/finame_test.dart, core/licensing_test.dart, core/works_schedule_test.dart, core/limits_test.dart |
User blocks in the file and the history; conditional labels; intersection, perpendicular, tangent, quadrant, extension snaps and polar tracking, also on long contours crossing by the cursor; GPS walks, marks and stake-out; automatic analysis after edits; materials of the selection; the quote (margin to freight, trenches, payback, NPV and IRR, sectors, alternatives); FINAME codes; CONAMA categories; construction schedule; the limits the app tells the user (BigTIFF, the raster cap, TIN thinning, a PDF dropped without the dialog) |
core/cli_test.dart, core/api_examples_test.dart |
test/core/cli_test.dart runs the command line on a shipped example; test/core/api_examples_test.dart runs every snippet of docs/API.md and fails when the documents show code it does not run |
core/ai_agent_test.dart, core/ai_openai_test.dart, core/ai_formats_test.dart, core/ai_context_test.dart |
Requests follow each API: Anthropic (endpoint, headers, streaming, adaptive thinking, always on for Fable 5.1, effort, caching, refusal fallback, task budgets, compaction, clearing of old tool results; no browser header on desktop) and OpenAI (Responses API, bearer key, instructions, function tools, reasoning effort, no storage, compaction, older pictures dropped); tool turns, invalid inputs as error results, the four modes and plan approval, confirmed exports, the step limit and the spending cap, messages written while it works, Stop, retries and errors that never show a key, the data-retention refusal of Fable 5.1, refusals and fallbacks priced at the model that answered, list prices with the long-prompt rules; both formats convert to each other without loss; the project context is deterministic, bounded and never holds a key |
widget_ai_agent_test.dart, widget_ai_assistant_test.dart, widget_ai_tools_test.dart, widget_ai_vision_test.dart |
GPT with the OpenAI key, a new conversation when the company changes and neither key reaching the other company, one Claude model taking over another's conversation; a whole small project done by the agent (questions, plan, drawing, design, check, fixes, report, to-do list); messages typed while it works, rewind, the spending cap and Continue, quick commands, compaction notices, pictures, the Markdown transcript, the docked panel, its button and the phone sheet; keys in memory unless remembered, nothing sent before Send, data sheets checked before they enter the catalogue; the pixel-to-world mapping, the satellite picture taken off screen with the user's view and map unchanged, Google imagery with a key, proposed geometry, terrain pictures and profiles against exact values |
widget_ai_coverage_test.dart, widget_ai_manual_test.dart, widget_ai_ops_cad_test.dart, widget_ai_ops_eng_test.dart |
Every action, tool, alias, menu item and dialog has a route for the AI and every route exists, and docs/AI_TOOLS.md is the table of the map; every manual topic reads on an empty and on a designed project, every item key, design parameter and message code has its explanation, and the worked example replays; the drawing-side and engineering operations (editing, annotation, blocks, view and history, files, terrain and site, imports; calculators, network analyses, catalogue and packs, exports, automatic design), each with its approvals and undo steps. Scripted fakes of both APIs (test/support/fake_claude.dart, test/support/fake_openai.dart) stand in for the companies: no test reaches the network |
densogram_test.dart, electrical_test.dart, electrical_io_test.dart, management_test.dart (in core/) |
Every spray profile returns the whole flow, part circles, areas against their own mean, measured profiles and wind; routes, stations, solenoid voltage by hand, cheapest wires against brute force, wire catalogue, BOM and Electrical report, design check codes, DXF/DWG/GeoJSON/plot output; demands and automatic system flows with pivots and stations |
core/import_curves_test.dart |
Rational and clamped NURBS; DXF SPLINE by control points or fit points, HATCH with polyline, line, arc (both senses), ellipse and spline edges and islands, SOLID/TRACE, hatches inside blocks; DWG R2000–R2018 splines, hatches, solids and the ellipse matching LibreDWG |
core/controller_extra_test.dart |
Opening a file or an example drops the old marks, profile, check and history; dialog edits as one undo step (mutations folded in, units keep the results); undo with nothing to undo; grips drag wires with pipe nodes; painter for the new entities and the densogram |
core/regressions_test.dart |
Every defect fixed in the 2026-09-22 sweep, each failing without its fix: a lateral cut on an outlet keeps it once; generated contours stay generated; files without the id counter; mirrored part-circle sprinklers and full-circle heads with a part-circle nozzle (plot and canvas too); survey files with spaces and decimal commas; rasters too large to decode; damaged files reported as such; psi, kPa and bar; grid CU with close heads; blocks on L and U fields and guided rows clipped in two; telescoping drawn either way; numbers with thousands separators, prices and pump curves; spacings of 0 and NaN values that used to hang or break the saving; GPS tracks in KML |
core/hotkeys_dispatch_test.dart |
The keyboard dispatcher on its own: application, editing and canvas keys, typed coordinates, what dialogs and menus block, every typed command alias |
core/engine_speed_test.dart |
The faster engine gives the very same results: the elimination plan of the network solver bit for bit against the map-based solver, and the indexed lookups of links and catalogue items following every edit of their lists |
core/hydraulics_extra_test.dart, core/pump_devices_test.dart |
Friction helpers (gradients, Reynolds number, Blasius against Colebrook, Hazen C as a roughness), minor losses, devices and emitter flags; every mainline device of the catalogue in series between a tank and a zone: each splits the pipe and reports its own loss, a PRV regulates only above its setting, the pump follows its curve and the affinity laws, a calculated supply never runs below zero, suction lift |
core/design_extra_test.dart, core/area_water_test.dart, core/auto_fix_test.dart |
Design paths the other tests do not reach (empty and missing zones, the zone variation limit, devices inside a zone, unreachable valves, missing fittings, fixed-hour schedules, Darcy-Weisbach pivots); the defects found by checking the example gallery (heads on an area's outline, matched-precipitation uniformity, flushing convergence, staggered programme days, pivots in the water table); every correction of the design assistant on its case and on a case where it has nothing to do |
core/model_extra_test.dart, core/io_extra_test.dart, core/currency_test.dart |
Geometry, units, terrain and TIN edge cases, split, extend and offset on every entity type; importers and exporters on the inputs the format tests do not reach (catalogue lists, UTM zone exceptions, GeoTIFF transforms, KMZ variants, DBF encodings, DXF blocks and curves, PDF report pages); currencies by language and region, reference rates and the conversion of every price |
core/basemap_layer_test.dart, core/dem_online_test.dart |
Map tiles against a fake server: cache and eviction, a coarser zoom instead of a blank map, the nearest ancestor of a missing tile, the ArcGIS tilemap and the Google Map Tiles session; the online elevation grid, batches, concurrent downloads with retries and pacing, and the datum check of the user's own data |
core/region_trace_test.dart |
Field outlines on synthetic aerial pictures: crop rows traced to the field edges, trees inside filled and reported, fields cut by the picture edge flagged, every field of a picture found |
core/ai_api_fixes_test.dart, core/ai_transport_io_test.dart, core/ai_image_prep_test.dart |
The assistant against scripted failures of the APIs (refused and oversized requests, service errors, timeouts and dropped streams, each with what is kept and sent again); the desktop transport against a server on the machine (upload, streaming, a cancel closes the connection); attached pictures typed by their bytes, turned upright, scaled into the model limits and re-encoded within the size |
core/app_logic_test.dart |
App logic without widgets: command aliases, translated action labels, tutorial navigation, the route observer, the design runner without workers, desktop files and language assets |
widget_ai_*.dart (the files not named above) |
The assistant's start screen, beginner help, chat behaviour and Markdown, error messages, marks on the map, voice, field photos, paste and drop, saved conversations, /review, the sheet preview and the pictures it sends |
editorial_names_test.dart |
The editorial rule: no competing product anywhere in the repository and no CAD product in the interface, the site and the documentation, checked by SHA-256 against the one list tool/hooks/banned-names.sha256 (shared with the pre-commit hook) so that the test names none of them |
widget_*.dart |
Real interface: welcome screen and tutorial, gallery, menus and dialogs, panels, canvas editing, shortcuts, history, terrain and compact layout; management with pivots and automatic flows, dialogs closed outside, densogram, controller and wire tools with the Electrical tab, ordinate and diameter dimensions, the Wires tab of the catalogue, numeric fields that reject a value; the properties of every entity type, batch editing and the results of the selection; the profile chart readout; wheel, trackpad, middle-button and two-finger navigation; georeference and plot dialogs; mainline and phone menus; the system flows dialog; the dialogs of automatic design, agronomy, mechanised machines, network operation, transients, PDF import, sheets and blocks and vegetation, each applying as one undo step and laying out on a 390 × 844 phone; the right-to-left layout of Arabic and Urdu, conditional labels, the GPS chip, the breakline tool and the materials of the selection |
widget_theme_test.dart |
The dark palette is the original look, colour for colour; the light palette keeps WCAG AA contrast for the text on its surfaces; View → Theme switches in place (same shell, project and selection), also from the phone menu, and the sheets build in light; a white layer draws near-black on the light canvas while plots stay unchanged; the choice is saved and applied at start-up; Follow the system tracks the platform brightness live; the pictures for the AI assistant keep the dark canvas |
web_metadata_test.dart, version_test.dart, web_offline_test.dart |
Generated site pages, SEO, JSON-LD, manifest, icons, robots, sitemap, 404, llms.txt; the entry pages load the app on demand; app version consistent with pubspec.yaml, the generator and the site; test/web_offline_test.dart covers the service worker generator, the templates and the build script |
flutter_test_config.dart |
Runs around every test file: the file fails when the interface asked for a string key the table does not have, and no test reaches the network (only the loopback interface) |
seams/agronomy_programme_test.dart, seams/paste_merge_test.dart, seams/storage_full_app_test.dart |
Tests that cross modules: for the 15 gallery examples the water table, the crop requirement, the FAO-56 table and the controller programme give the same requirement per area; a whole project pasted into a neighbour's tab with another currency and georeference lands in place, priced in the target's currency, designs alike and undoes in one step; the app with the browser storage full makes room with versions and projects saved to a file, never with unsaved work, and keeps the warning until a copy fits |
guards/*_test.dart |
The engine package holds everything it reaches; lib/core imports no Flutter; the generated brand images and the date of the site; the hooks and the one list of forbidden names; no network; every character of every PDF text has a font; the release tool; the design worker rebuilt byte for byte |
core/pump_station_test.dart, core/real_operation_test.dart, core/reservoir_vessel_test.dart, core/sizing_plus_test.dart, core/analysis_control_test.dart, widget_mot_plus_test.dart |
Pump stations in parallel or in series, on duty or on standby, staged by the flow, with the duty, energy and bill of every pump; the real operation of the zones and the valve pilots; the reservoir curve, its days of demand and its level over 24 hours, the air vessel in the transients; the surge in the class of every pipe, the grade line over the high points, the loops; analyses a step at a time with the same results, cancelled, and the ageing and clogging scenarios; their dialogs on a phone |
core/soil_water_balance_test.dart, core/agr_plan_test.dart, core/agr_runoff_capacity_test.dart, core/agr_programme_test.dart, core/agr_catch_cans_fert_test.dart, core/inmet_csv_test.dart, widget_agr_plus_test.dart |
A water balance done by hand, rainfed with Ky, regulated deficit, fixed interval and partial refill; the agronomy plan in the file; NRCS intake families, runoff per pass, capacity in 24 h and in a window; cycle and soak, a short window and a typed seasonal adjustment; catch cans, CU and DU, fertigation by stage; INMET hourly and BDMEP files; the six dialogs on a phone, in Arabic and with the text twice as big |
core/agb_pump_house_test.dart, core/agb_solar_water_test.dart, core/agb_field_machines_test.dart, widget_agb_test.dart |
The pump house electrics and the pivots' supply in the design, the report and the bill; solar pumping and its energy cost; water quality and treatment; two-wire in the bill; several pivots with their mainline; traveller lanes and furrows as demands; every dialog one undo step |
core/prd_*_test.dart, core/permit_test.dart, core/memorial_om_test.dart, core/budget_lcc_test.dart, core/tech_doc_test.dart, core/prb_packages_test.dart, widget_prd_test.dart, widget_deliverables_test.dart |
The title block, the datum named by the user or by the site, the coordinate grid, the slope sheet and classes, the standards under every table, the document packages; the permit regime month by month, the memorial and the O&M plan the same for the same project, the budget and the life-cycle cost; the writers of the documents (Markdown, CSV, XLSX, PDF) |
core/cad_plus_core_test.dart, core/cad_plus_model_test.dart, core/cad_plus_controller_test.dart, widget_cad_plus_test.dart |
Trim with cuts at the ends only, Lengthen, the outline by a click inside; typed field coordinates, kgf/cm², the dimension style and layer states in the file, block references with attributes, the comparison of copies; text edited in place, the magnifier, the dynamic input, the snaps one by one |
core/formats_1102_test.dart, core/projections_1102_test.dart, widget_fmt_1102_test.dart |
Large and cloud-optimised GeoTIFFs block by block, KMZ ground overlays, survey blocks, XDATA round trips, CJK code pages, PDF/A-2b and layers, custom sheets; Albers, Lambert and polyconic against the worked examples of Snyder (1987); the points wizard, stake-out points, the downloads kept and the question before a large link |
core/area_holes_test.dart, core/area_holes_editor_test.dart, core/project_merge_test.dart, core/pipe_standards_test.dart, core/catalog_units_test.dart, core/new_project_prefs_test.dart, core/cli_projects_test.dart, core/tin_order_test.dart, guards/engine_package_test.dart |
Islands left out of the area, the water, the layout and the pictures and carried by the exports; Insert project; the packs by standard and their prices; the catalogue in the units of the project; what new projects start with; the command line making and changing projects; a TIN independent of the order of the items; the engine as a package |
core/automation_wave2_test.dart, widget_aut_wave2_test.dart, core/ai_ia_plus_test.dart, widget_ai_ia_plus_test.dart, core/ui_wave2_test.dart, widget_ui_wave2_test.dart |
One self-crossing detector and one offset, the longest lateral, the item-by-item review of Fix and Optimise, tracing on imagery against synthetic tiles; the costs by step, Apply the rest of this task, the effort by stage, the conversations of a project; the unnamed tab, the command palette, the manual and its chapters, What's new, the report of a problem |
site_manual_test.dart, site_fonts_test.dart, web_js_test.dart, launch_actions_test.dart, data_credits_test.dart, field_map_test.dart, i18n_review_test.dart, web_docs_test.dart |
The user guide pages (anchors, links, text, metadata, sitemap), the fonts served by the site, the service worker and bootstrap scripts in Node, opening files with the installed app, the credits of third-party data, the map kept for the field, the translation review files, the links and headings of the documentation |
Checks beyond the test suite
- CI (GitHub Actions,
.github/workflows/ci.yml, actions pinned by commit, Flutter read frompubspec.yaml): analysis without any issue, formatting, the design worker byte for byte, the generators without differences, the suite in four slices with coverage floors by folder (the timing tests, taggedperf, apart with a slack), the browser tests in Chrome, a production build checked bytool/release.dart verify-buildwith the end-to-end smoke test, and a formats job with pinned Python packages and LibreDWG; a matrix job runs the same smoke test in WebKit and Firefox on that build. Dependabot proposes updates of the packages and of the actions. - End-to-end smoke test (
tool/e2e/smoke.mjs, pinnedplaywright-core): on a production build (sh tool/build_web.sh), the app opens an example and designs it in the Web Worker, prints the version of the build, installs its service worker and starts again offline, sends a message of the AI assistant with the user's key to a fake of the API (nothing leaves the machine), notices a design worker of another build and loads this build's, and shows no page error.--browser chromium,webkit,firefoxuses the installed Chrome and the WebKit and Firefox builds the pinned version fixes; a check a browser cannot run is reported as skipped, never as passed. - Golden images (
test/goldens, taggolden): the drawing board light and dark, dense hairlines on a 2× screen, a dialog on a phone and the SVG of a sheet, compared with a tolerance for the anti-aliasing of other platforms. - Hooks (
git config core.hooksPath tool/hooks): the pre-commit hook refuses staged Dart files that are not formatted and any forbidden name in the lines a commit adds (the one listtool/hooks/banned-names.sha256, plus a local plain list in.git/info/banned-words) and warns about a design worker not rebuilt. test/seams/holds the tests that cross modules (agronomy and programme, paste between projects, the browser storage full), beside the tests of each module.
Known pitfalls when writing widget tests: the calculation is truly asynchronous and must run inside
tester.runAsync; dialog titles may be upper-case; the canvas needs a defined window size; asset
loading (catalogues) uses rootBundle and works in flutter test.
Open the app