DwRecordingServerTransport class
A DwServerTransport that answers reads from what the test prepared and keeps every write that left, for a test to assert on afterwards.
Hand it to DwCore instead of a client, and nothing has to stand up a
Serverpod client to render a widget or watch it save:
final transport = DwRecordingServerTransport(
classNames: {Task: 'Task'},
);
setUpAll(() {
DwCore<ServerpodClientShared, Task>(
config: const DwConfig(),
transport: transport,
dwAlerts: DwAlerts.init(logErrors: false, logFunction: (_) {}),
getUserId: (_) => null,
);
});
testWidgets('the button saves the task', (tester) async {
await tester.pumpWidget(/* the feature */);
await tester.tap(find.byIcon(Icons.check));
await tester.pumpAndSettle();
expect(transport.saves, hasLength(1));
expect((transport.saves.single.model as Task).isDone, isTrue);
});
Reads must be prepared, writes need not be. A read nobody answered throws DwUnpreparedServerCall, because the test does not know what its subject fetches. A save answers by echoing the model back and a delete by succeeding, because there the assertion is about what left, and forcing a canned response for it would be ceremony with nothing behind it. Override either with answerSave / answerDelete when the response matters — an id assigned on insert, a rejected write.
One instance per core, and reset between tests: the core keeps the
transport it was built with for its whole life, and DwCore can be built
only once per process.
- Implemented types
Constructors
-
DwRecordingServerTransport({Map<
Type, String> classNames = const {}, SerializationManager? serializationManager}) -
An application passes
serializationManager, and passes its own generatedProtocol()— the same object its Serverpod client carries. It already names every model of the project correctly, and it is the only thing that can: a generated model is an abstract class with a private implementation, so itsruntimeTypeis_NewsPostImpland never the name the wire uses. It is also what a test needs to read a model back — a local snapshot rebuilds its response from stored JSON.
Properties
-
answerDelete
↔ Future<
DwApiResponse< Function(DwRecordedDelete delete)?bool> > -
Answers
delete. Unset reports success.getter/setter pair -
answerGetAll
↔ Future<
DwApiResponse< Function(DwRecordedRead read)?List< >DwModelWrapper> > -
Answers
getAll. Unset means everygetAllthrows.getter/setter pair -
answerGetCount
↔ Future<
DwApiResponse< Function(DwRecordedRead read)?int> > -
Answers
getCount. Unset means everygetCountthrows.getter/setter pair -
answerGetOne
↔ Future<
DwApiResponse< Function(DwRecordedRead read)?DwModelWrapper> > -
Answers
getOne. Unset means everygetOnethrows.getter/setter pair -
answerSave
↔ Future<
DwApiResponse< Function(DwRecordedSave save)?DwModelWrapper> > -
Answers
saveModel. Unset echoes the saved model back, as a server that accepted it unchanged would.getter/setter pair -
answerSubscribe
↔ Stream<
SerializableModel> Function(String channel)? -
Answers
subscribeOnUpdates. Unset opens a stream that never emits and never ends.getter/setter pair -
answerUploadDescription
↔ Future<
DwUploadTicket?> Function(String? folder, String fileExtension, String? fileName)? -
Answers
getUploadDescription. Unset means it throws.getter/setter pair -
answerVerifyUpload
↔ Future<
DwCloudFile?> Function(int fileId)? -
Answers
verifyUpload. Unset means it throws.getter/setter pair -
deletes
→ List<
DwRecordedDelete> -
Every delete that left, oldest first.
final
- hashCode → int
-
The hash code for this object.
no setterinherited
-
reads
→ List<
DwRecordedRead> -
Every read that left, oldest first — including the ones that then threw
DwUnpreparedServerCall, so a failing test can be told what was asked.
final
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
-
saves
→ List<
DwRecordedSave> -
Every save that left, oldest first.
final
- serializationManager → SerializationManager
-
How models are named and rebuilt on the wire this transport speaks.
final
Methods
-
delete(
{required String className, required int modelId, String? apiGroup}) → Future< DwApiResponse< bool> > -
Deletes row
modelIdofclassName.override -
getAll(
{required String className, DwBackendFilter? filter, List< DwOrderBy> ? orderByList, int? limit, int? offset, String? apiGroup}) → Future<DwApiResponse< List< >DwModelWrapper> > -
Reads the
classNamerows matchingfilter, ordered and paginated.override -
getCount(
{required String className, DwBackendFilter? filter, String? apiGroup}) → Future< DwApiResponse< int> > -
Counts the
classNamerows matchingfilter, server-side.override -
getOne(
{required String className, required DwBackendFilter filter, String? apiGroup}) → Future< DwApiResponse< DwModelWrapper> > -
Reads the single
classNamerow matchingfilter.override -
getUploadDescription(
{String? folder, required String fileExtension, String? fileName}) → Future< DwUploadTicket?> -
Asks the server to reserve a key and sign a one-shot upload for it.
override
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
reset(
) → void - Forgets everything recorded and every prepared answer.
-
saveModel(
{required DwModelWrapper wrappedModel, String? apiGroup}) → Future< DwApiResponse< DwModelWrapper> > -
Creates or updates
wrappedModel; answers with the persisted model.override -
subscribeOnUpdates(
{required String channel}) → Stream< SerializableModel> -
Opens the server-side update stream for
channel.override -
toString(
) → String -
A string representation of this object.
inherited
-
verifyUpload(
{required int fileId}) → Future< DwCloudFile?> -
Confirms with the server that the bytes for reservation
fileIdarrived, and answers with the stored file —nullwhen the upload cannot be verified or the reservation is not the caller's.override
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited