Files
doormile_customer_app/test/map_config_test.dart
Thiru-tenext 0d66627c3c Replace the customer app with Doormile CX
Book a pickup, track it to delivery — the rebuilt customer app.

- Design language from doormile-screens.html: brand #8F0F06, Manrope +
  Geist Mono (variable fonts), bordered cards instead of shadows, crimson
  brand headers, sliding tab indicator, mono for anything read digit by digit.
- lib/data (one live API implementation, plus a debug-only offline fake),
  lib/state, lib/ui (tokens, widgets, screens).
- 84 tests, plus a design snapshot harness that renders every screen with the
  real fonts: flutter test test/design_snapshot_test.dart --run-skipped
  --update-goldens

This replaces the previous app (pubspec 'doormile', app id
com.doormile.customer). That tree remains in history at 6c7d656; note its
android/app/google-services.json is not carried over, and the application id
here is in.doormile.customer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 16:07:33 +05:30

97 lines
3.5 KiB
Dart

import 'dart:io';
import 'package:doormile_cx/data/map_config.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
group('tile provider', () {
test('CARTO serves anonymously and takes a key when one is supplied', () {
const anonymous = MapTileProvider.carto;
expect(anonymous.usable, isTrue);
expect(anonymous.hasKey, isFalse);
expect(anonymous.urlFor(DmMapStyle.streets), isNot(contains('api_key')));
final keyed = anonymous.withKey('abc123');
expect(keyed.hasKey, isTrue);
expect(
keyed.urlFor(DmMapStyle.streets),
endsWith('?api_key=abc123'),
);
// Nothing else about the source changes when the key arrives.
expect(keyed.attribution, anonymous.attribution);
expect(keyed.subdomains, anonymous.subdomains);
});
test('the two styles are distinct sources', () {
expect(
MapTileProvider.carto.urlFor(DmMapStyle.streets),
isNot(MapTileProvider.carto.urlFor(DmMapStyle.muted)),
);
});
test('a key-only provider reports itself unusable without one', () {
expect(MapTileProvider.maptiler.usable, isFalse);
expect(MapTileProvider.maptiler.withKey('k').usable, isTrue);
expect(
MapTileProvider.maptiler.withKey('k').urlFor(DmMapStyle.streets),
endsWith('?key=k'),
);
expect(MapTileProvider.stadia.usable, isFalse);
});
test('every preset credits its data source', () {
for (final provider in MapTileProvider.presets.values) {
expect(
provider.attribution,
contains('OpenStreetMap'),
reason: '${provider.id} must credit OpenStreetMap',
);
expect(provider.attributionUrl, startsWith('https://'));
expect(provider.templates[DmMapStyle.streets], isNotNull);
}
});
});
group('resolved configuration', () {
test('defaults to CARTO and identifies the app to the provider', () {
final config = DmMapConfig.fromEnvironment();
expect(config.provider.id, 'carto');
expect(config.warning, isNull);
expect(config.userAgent, contains('Doormile/'));
expect(config.userAgent, contains(DmMapConfig.packageName));
expect(config.attribution, contains('CARTO'));
});
test('is swappable without touching a screen', () {
final original = DmMapConfig.instance;
addTearDown(() => DmMapConfig.instance = original);
DmMapConfig.instance = DmMapConfig(
provider: MapTileProvider.osm,
userAgent: 'test/1.0',
);
expect(DmMapConfig.instance.attribution, '© OpenStreetMap contributors');
expect(DmMapConfig.instance.retina, isFalse);
expect(DmMapConfig.instance.maxNativeZoom, 19);
});
});
test('no tile URL, subdomain list or map key lives in the UI layer', () {
// The whole point of the provider layer: swapping CARTO for a keyed plan or
// another vendor must never mean editing a map screen.
final offenders = <String>[];
for (final entry in Directory('lib/ui').listSync(recursive: true)) {
if (entry is! File || !entry.path.endsWith('.dart')) continue;
final source = entry.readAsStringSync();
if (source.contains('cartocdn') ||
source.contains('tile.openstreetmap.org') ||
source.contains('api.maptiler.com') ||
source.contains('tiles.stadiamaps.com') ||
source.contains('{z}/{x}/{y}')) {
offenders.add(entry.path);
}
}
expect(offenders, isEmpty, reason: 'tile URLs belong in map_config.dart');
});
}