transactionTests method

dynamic transactionTests()

Implementation

transactionTests() {
  group('Transaction', () {
    late Cursor cursor;
    late Connection otherConnection;

    setUp(() async {
      connection = await connector.connect(_initDb);
      otherConnection = await connector.connect();
      cursor = await connection.cursor();
    });

    tearDown(() async {
      await connection.close();
      await otherConnection.close();
    });

    test('autocommit defaults to true', () {
      expect(connection.autocommit, true);
    });

    test('autocommit can be set to false', () async {
      expect(connection.autocommit, true);
      await connection.setAutocommit(false);
      expect(connection.autocommit, false);
    });

    test('autocommit is true after commit', () async {
      expect(connection.autocommit, true);
      await connection.setAutocommit(false);
      await connection.commit();

      expect(connection.autocommit, true);
    });

    test('autocommit is true after rollback', () async {
      expect(connection.autocommit, true);
      await connection.setAutocommit(false);
      await connection.rollback();

      expect(connection.autocommit, true);
    });

    test('closing connection rolls back open transactions', () async {});

    group('on single collection', () {
      test('single operation can be commited', () async {
        final entity = {
          "id": 1,
          "name": "first!",
        };
        await connection.setAutocommit(false);
        await cursor.execute(
          Insert(userSchema, [entity]),
        );
        await connection.commit();

        await cursor.execute(Query(from: userSchema));
        var result = await cursor.fetchone();

        expect(result, entity);
      });

      test('single operation can be rolled back', () async {
        final entity = {
          "id": 1,
          "name": "first!",
        };
        await connection.setAutocommit(false);
        await cursor.execute(
          Insert(userSchema, [entity]),
        );
        await connection.rollback();

        await cursor.execute(Query(from: userSchema));
        var result = await cursor.fetchone();

        expect(result, isNull);
      });

      test('multiple operations can be commited', () async {
        final entity = {
          "id": 1,
          "name": "first!",
        };
        final entity2 = {
          "id": 2,
          "name": "second!",
        };
        await connection.setAutocommit(false);
        await cursor.execute(
          Insert(userSchema, [entity]),
        );
        await cursor.execute(
          Insert(userSchema, [entity2]),
        );
        await connection.commit();

        await cursor.execute(Query(from: userSchema));
        var results = await cursor.fetchall();

        expect(results, hasLength(2));
      });

      test('multiple operation can be rolled back', () async {
        final entity = {
          "id": 1,
          "name": "first!",
        };
        final entity2 = {
          "id": 2,
          "name": "second!",
        };
        await connection.setAutocommit(false);
        await cursor.execute(
          Insert(userSchema, [entity]),
        );
        await cursor.execute(
          Insert(userSchema, [entity2]),
        );
        await connection.rollback();

        await cursor.execute(Query(from: userSchema));
        var result = await cursor.fetchone();

        expect(result, isNull);
      });

      test('read after write in transaction', () async {
        final entity = {
          "id": 1,
          "name": "first!",
        };

        await connection.setAutocommit(false);
        await cursor.execute(
          Insert(userSchema, [entity]),
        );
        await cursor.execute(Query(from: userSchema));
        final fromDb = await cursor.fetchone();
        expect(fromDb, entity);
      });

      test('write in transaction are not visibile in other connections',
          () async {
        final entity = {
          "id": 1,
          "name": "first!",
        };
        await connection.setAutocommit(false);
        await cursor.execute(
          Insert(userSchema, [entity]),
        );

        final otherCursor = await otherConnection.cursor();

        try {
          await otherCursor.execute(Query(from: userSchema));
          final result = await otherCursor.fetchall();
          expect(result, isEmpty);
        } on OperationalError {
          // execute/fetchall could fail. If it does so raising OperationalError, it's ok.
          // e.g. SQLite in memory takes this branch, while SQLite on file completes without
          // exceptions.
          // TODO: consider adding non-generic tests for specific behaviour in package:dbapi_sqlite
          assert(true);
        }
      });
    });

    group('on multiple collections', () {
      test('can read from multiple collections', () async {
        final user = {
          "id": 1,
          "name": "first!",
        };
        final article = {
          "id": 1,
          "title": "A great article",
        };
        await cursor.execute(Insert(userSchema, [user]));
        await cursor.execute(Insert(articleSchema, [article]));

        await connection.setAutocommit(false);
        await cursor.execute(Query(from: userSchema));
        var dbUser = await cursor.fetchone();
        await cursor.execute(Query(from: articleSchema));
        var dbArticle = await cursor.fetchone();
        await connection.commit();

        expect(dbUser, user);
        expect(dbArticle, article);
      });

      test('can write to multiple collections', () async {
        final user = {
          "id": 1,
          "name": "first!",
        };
        final article = {
          "id": 1,
          "title": "A great article",
        };
        await connection.setAutocommit(false);

        await cursor.execute(Insert(userSchema, [user]));
        await cursor.execute(Insert(articleSchema, [article]));
        await connection.commit();

        await cursor.execute(Query(from: userSchema));
        var dbUser = await cursor.fetchone();
        await cursor.execute(Query(from: articleSchema));
        var dbArticle = await cursor.fetchone();

        expect(dbUser, user);
        expect(dbArticle, article);
      });

      test('can rea and write to multiple collections', () async {
        final user = {
          "id": 1,
          "name": "first!",
        };
        final article = {
          "id": 1,
          "title": "A great article",
        };
        await connection.setAutocommit(false);

        await cursor.execute(Insert(userSchema, [user]));
        await cursor.execute(Insert(articleSchema, [article]));

        await cursor.execute(Query(from: userSchema));
        var dbUser = await cursor.fetchone();
        await cursor.execute(Query(from: articleSchema));
        var dbArticle = await cursor.fetchone();

        await connection.commit();

        expect(dbUser, user);
        expect(dbArticle, article);
      });
    });
  }, skip: requireFeature(DatabaseFeature.transactions));
}