MyLittleSuite / data_fixture_dart

MIT License
6 stars 0 forks source link

Request to add multiple factory "traits" simultaneously and have object creation similar to Mirage JS #2

Open aashir-khan opened 3 years ago

aashir-khan commented 3 years ago

In Mirage JS over here, traits are demonstrated (which in data_fixture_dart are similar to those custom factory functions that redefine the default definition) as being able to be combined, which is very useful to create custom objects with varying "traits" very quickly. Also part of the Mirage JS syntax is that you can call const customStudent = server.create('student', 'withNoLastName', { firstName: 'Bob' }) to quickly create objects, built in this order:

  1. Create default student -> same as calling server.create('student')
  2. Add in effects of withNoLastName trait to this default student, overriding whichever fields are necessary to override to acccomplish this
  3. Override the object created in step 2 with firstName being Bob

and by doing this, not only would it return you the object (not directly but in a wrapped form with functions available on the returned object), but it will persist that object in the database for later retrieval (e.g. server.db.students[0]) which is useful for later accessing inside for example tests (e.g. end-to-end tests) either directly or with DOM assertions as seen here

I was wondering if it is possible to port over something like the above features to this package, or at least some of these features. It would be very useful!

ibrahim-mubarak commented 2 years ago

You could achieve this using FixtureRedefinitionBuilder

class EmployeeFixtureFactory extends FixtureFactory<Employee> {
  @override
  FixtureDefinition<Employee> definition() =>
      define((faker) => Employee(name: faker.person.name()));

  /// Do not call redefine here
  FixtureRedefinitionBuilder<Employee> region(String region) =>
      (employee) => employee.copyWith(region: region);

  FixtureRedefinitionBuilder<Employee> ready() =>
      (employee) => employee.copyWith(isReady: true);

  /// This method calls redefine for all the above states
  FixtureDefinition<Employee> states(
    List<FixtureRedefinitionBuilder<Employee>> definitions,
  ) {
    return redefine((employee) {
      return definitions.fold(
        employee,
        (previousState, redefinitionBuilder) => redefinitionBuilder(previousState),
      );
    });
  }
}

Usage

// Call multiple states
employeeFactory.states([
  employeeFactory.region("AU"),
  employeeFactory.ready(),
  /// Manually setting some values
  (employee) => employee.copyWith(name: "John"),
]).makeMany(2);

// Call single state using redefine
employeeFactory.redefine(employeeFactory.region('AU')).makeMany(5);

// Call single state using states
employeeFactory.states([
  employeeFactory.region("AU"),
]).makeMany(10);

I'm sure the API can be simplified much further by making necessary changes and using something similar to callable classes. I might work on this if I get some time