findTest function

List<dynamic Function(FoodbTestContext)> findTest()

Implementation

List<Function(FoodbTestContext)> findTest() {
  return [
    (FoodbTestContext ctx) {
      test('fetchDesignDoc()', () async {
        final db = await ctx.db('fetch-design-doc');
        await db.createIndex(
            index: QueryViewOptionsDef(fields: ['name']),
            ddoc: 'type_user_name',
            name: 'index_by_name');
        var designDoc = await db.fetchDesignDoc(ddocName: 'type_user_name');
        expect(designDoc, isNotNull);
        expect(designDoc.model.language, 'query');
        var view = designDoc.model.views['index_by_name'];
        expect(view, isNotNull);
        expect(view is QueryDesignDocView, true);
        view as QueryDesignDocView;
        expect(view.reduce, '_count');
        expect(view.map.fields.length, 1);
        expect(view.map.fields['name'], 'asc');
        expect(view.options.def.fields.length, 1);
        expect(view.options.def.fields[0], 'name');
      });
    },
    (FoodbTestContext ctx) {
      test('fetchDesignDocs()', () async {
        final db = await ctx.db('fetch-all-design-docs');
        await db.createIndex(
            index: QueryViewOptionsDef(fields: ['_id']), ddoc: 'type_user_id');
        await db.createIndex(
            index: QueryViewOptionsDef(fields: ['name']),
            ddoc: 'type_user_name');
        List<Doc<DesignDoc>?> designDoc = await db.fetchAllDesignDocs();
        expect(designDoc.length, equals(2));
      });
    },
    (FoodbTestContext ctx) {
      test('clear-design-doc-view', () async {
        try {
          final db = await ctx.db('clear-design-doc-view');
          await db.createIndex(
              index: QueryViewOptionsDef(fields: ['name']),
              ddoc: 'type_user_name',
              name: 'index_by_name');
          await db.put(doc: Doc(id: 'a', model: {'name': 'x'}));
          await db.put(doc: Doc(id: 'b', model: {'name': 'y'}));
          final response1 = await db.find(
              FindRequest(selector: EqualOperator(key: 'name', expected: 'x')),
              (p0) => p0);
          expect(response1.docs.length, 1);
          await db.clearView('_design/type_user_name', 'index_by_name');
          final response2 = await db.find(
              FindRequest(selector: EqualOperator(key: 'name', expected: 'x')),
              (p0) => p0);
          expect(response2.docs.length, 1);
        } on UnimplementedError catch (ex) {
          print(
              'clear-design-doc-view skipped: ${ctx.runtimeType} clearView() not implemented');
        }
      });
    },
    (FoodbTestContext ctx) {
      test('clear-all-docs-view', () async {
        try {
          final db = await ctx.db('clear-all-docs-view');
          await db.put(doc: Doc(id: 'a', model: {'name': 'x'}));
          await db.put(doc: Doc(id: 'b', model: {'name': 'y'}));
          final response1 = await db.allDocs(GetViewRequest(), (json) => null);
          expect(response1.rows.length, 2);
          await db.clearView('_design/all_docs', 'all_docs');
          final response2 = await db.allDocs(GetViewRequest(), (json) => null);
          expect(response2.rows.length, 2);
        } on UnimplementedError catch (ex) {
          print(
              'clear-all-docs-view skipped: ${ctx.runtimeType} clearView() not implemented');
        }
      });
    },
    (FoodbTestContext ctx) {
      test('correct-view-building-after-crud', () async {
        final db = await ctx.db('correct-view-building-after-crud');
        var a = await db.put(doc: Doc(id: 'a', model: {'name': 'a'}));
        var a2 = await db.put(doc: Doc(id: 'a-2', model: {'name': 'a'}));
        await db.delete(id: 'a-2', rev: a2.rev);
        await db.put(doc: Doc(id: 'b', model: {'name': 'b'}));

        //"-" is not allowed as index name
        var indexResponse = await db.createIndex(
            index: QueryViewOptionsDef(fields: ['name']),
            ddoc: 'name_view',
            name: 'name_index');
        expect(indexResponse, isNotNull);

        var result = await db.view(
            'name_view',
            'name_index',
            GetViewRequest(
                startkey: ['a'], endkey: ['a\ufff0'], includeDocs: true),
            (json) => json);
        expect(result.rows.length, equals(1));
        await db.put(doc: Doc(id: 'c', model: {'name': 'c'}));
        await db.put(doc: Doc(id: 'c-2', model: {}));
        await db.delete(id: 'a', rev: a.rev);
        var result2 = await db.view(
            'name_view',
            'name_index',
            GetViewRequest(
                startkey: ['a'], endkey: ['a\ufff0'], includeDocs: true),
            (json) => json);
        expect(result2.rows.length, equals(0));
        var result3 = await db.view(
            'name_view',
            'name_index',
            GetViewRequest(
                startkey: ['b'], endkey: ['c\ufff0'], includeDocs: true),
            (json) => json);
        expect(result3.rows.length, equals(2));
      });
    },
    (FoodbTestContext ctx) {
      test('view-by-startkey-and-endkey', () async {
        final db = await ctx.db('view-by-startkey-and-endkey');
        await db.put(doc: Doc(id: 'a', model: {'name': 'a', 'no': 99}));
        await db.put(doc: Doc(id: 'b', model: {'name': 'b', 'no': 88}));

        //"-" is not allowed as index name
        var indexResponse = await db.createIndex(
            index: QueryViewOptionsDef(fields: ['name', 'no']),
            ddoc: 'name_view',
            name: 'name_index');
        expect(indexResponse, isNotNull);
        var query = GetViewRequest(
            startkey: ['a', 100], endkey: ['b\ufff0', 77], includeDocs: true);
        var result =
            await db.view('name_view', 'name_index', query, (json) => json);
        expect(result.rows.length, equals(1));
        await db.put(doc: Doc(id: 'c', model: {'name': 'b', 'no': 77}));

        var result2 =
            await db.view('name_view', 'name_index', query, (json) => json);
        expect(result2.rows.length, equals(2));
      });
    },
    (FoodbTestContext ctx) {
      test('view-by-keys', () async {
        final db = await ctx.db('view-by-keys');
        await db.put(doc: Doc(id: 'a', model: {'name': 'a', 'no': 99}));
        await db.put(doc: Doc(id: 'b', model: {'name': 'b', 'no': 88}));

        //"-" is not allowed as index name
        var indexResponse = await db.createIndex(
            index: QueryViewOptionsDef(fields: ['name', 'no']),
            ddoc: 'name_view',
            name: 'name_index');
        expect(indexResponse, isNotNull);
        var query = GetViewRequest(keys: [
          ['b', 88],
        ], includeDocs: true);
        var result =
            await db.view('name_view', 'name_index', query, (json) => json);
        expect(result.rows.length, equals(1));
        await db.put(doc: Doc(id: 'c', model: {'name': 'b', 'no': 88}));

        var result2 =
            await db.view('name_view', 'name_index', query, (json) => json);
        expect(result2.rows.length, equals(2));
      });
    },
    (FoodbTestContext ctx) {
      test('create with indexFields only', () async {
        final db = await ctx.db('index');
        var indexResponse =
            await db.createIndex(index: QueryViewOptionsDef(fields: ['_id']));
        expect(indexResponse, isNotNull);

        var doc = await db.get(id: indexResponse.id, fromJsonT: (json) => json);
        expect(doc, isNotNull);
      });
    },
    (FoodbTestContext ctx) {
      test('multiple create will update existing with indexFields only',
          () async {
        final db = await ctx.db('index');
        var indexResponse = await db.createIndex(
            index: QueryViewOptionsDef(fields: ['_id']), ddoc: 'test');
        expect(indexResponse, isNotNull);
        var doc = await db.get(id: indexResponse.id, fromJsonT: (json) => json);
        expect(doc, isNotNull);
        var allDoc = await db.allDocs(GetViewRequest(), (json) => json);
        expect(allDoc.rows, hasLength(1));
        indexResponse = await db.createIndex(
            index: QueryViewOptionsDef(fields: ['_id']), ddoc: 'test');
        allDoc =
            await db.allDocs(GetViewRequest(includeDocs: true), (json) => json);
        expect(indexResponse.result, 'exists');
        expect(allDoc.rows, hasLength(1));
        expect(allDoc.rows[0].value['rev'], startsWith('1'));
      });
    },
    (FoodbTestContext ctx) {
      test('find-correct-rebuild', () async {
        final db = await ctx.db('view-by-keys');
        var doc1 = await db.put(
          doc: Doc(id: '1', model: {'type': true, 'status': 'D'}),
        );
        var doc2 = await db.put(
          doc: Doc(id: '2', model: {'type': true, 'status': 'D'}),
        );

        //"-" is not allowed as index name
        var indexResponse = await db.createIndex(
            index: QueryViewOptionsDef(fields: ['type', 'status']),
            ddoc: 'status_view',
            name: 'status_index');
        expect(indexResponse, isNotNull);
        var query = FindRequest(
            selector: AndOperator(operators: [
          EqualOperator(key: 'type', expected: true),
          EqualOperator(key: 'status', expected: 'D')
        ]));
        var result = await db.find(query, (p0) => p0);
        expect(result.docs.length, equals(2));
        await db.put(
            doc: Doc(
          id: '2',
          model: {'type': true, 'status': 'D'},
          rev: doc2.rev,
        ));

        result = await db.find(query, (p0) => p0);
        expect(result.docs.length, equals(2));
      });
    },
    (FoodbTestContext ctx) {
      group('find()', () {
        test(
            'flat selector without _id, docs with missing keys, fields of design_doc< fields of selector',
            () async {
          final db = await ctx.db('find');
          await db.createIndex(
              index: QueryViewOptionsDef(fields: ['no', 'name']));
          await db.put(
              doc: Doc(id: 'user_01', model: {
            'name': 'foo',
            'no': 3,
          }));
          await db.put(doc: Doc(id: 'admin_01', model: {'name': 'foo'}));
          await db.put(
              doc: Doc(id: 'user_02', model: {'name': 'foo', 'no': 2, 'k': 1}));

          final findResponse = await db.find<Map<String, dynamic>>(
              FindRequest(
                selector: AndOperator(operators: [
                  GreaterThanOperator(key: 'k', expected: 0),
                  EqualOperator(key: 'name', expected: 'foo'),
                  GreaterThanOperator(key: 'no', expected: 0),
                  RegexOperator(key: '_id', expected: '^user_')
                ]),
              ),
              (value) => value);

          expect(findResponse.docs.length, equals(1));
          expect(findResponse.docs.first.id, 'user_02');
        });
        test(
            'flat selector with _id, docs with missing keys, fields of designdoc < fields of selector',
            () async {
          final db = await ctx.db('find');
          await db.createIndex(
              index: QueryViewOptionsDef(fields: ['name', '_id']));
          await db.put(
              doc: Doc(id: 'user_01', model: {
            'name': 'foo',
            'no': 0,
          }));
          await db.put(doc: Doc(id: 'admin_01', model: {'name': 'foo'}));
          await db.put(
              doc: Doc(id: 'user_02', model: {'name': 'foo', 'no': 2}));
          final findResponse = await db.find<Map<String, dynamic>>(
              FindRequest(
                selector: AndOperator(operators: [
                  GreaterThanOperator(key: 'no', expected: 0),
                  EqualOperator(key: 'name', expected: 'foo'),
                  RegexOperator(key: '_id', expected: '^user')
                ]),
              ),
              (value) => value);
          expect(findResponse.docs.length, equals(1));
          expect(findResponse.docs.first.id, 'user_02');
        });

        test(
            'flat selector, nested fields, docs with missing keys, fields of designdoc < fields of selector',
            () async {
          final db = await ctx.db('find');
          await db.createIndex(
              index: QueryViewOptionsDef(fields: ['name', '_id']));
          await db.put(
              doc: Doc(id: 'user_01', model: {
            'name': {
              'first': {'name': 'foo'}
            },
            'no': 2,
          }));
          await db.put(doc: Doc(id: 'admin_01', model: {'name': 'foo'}));
          await db.put(
              doc: Doc(id: 'user_02', model: {'name': 'foo', 'no': 0}));
          final findResponse = await db.find<Map<String, dynamic>>(
              FindRequest(
                selector: AndOperator(operators: [
                  GreaterThanOperator(key: 'no', expected: 0),
                  EqualOperator(key: 'name.first.name', expected: 'foo'),
                  RegexOperator(key: '_id', expected: '^user')
                ]),
              ),
              (value) => value);
          expect(findResponse.docs.length, equals(1));
          expect(findResponse.docs.first.id, 'user_01');
        });

        test('nested selector with _id, docs with missing keys, call all_docs',
            () async {
          final db = await ctx.db('find');
          await db.createIndex(
              index: QueryViewOptionsDef(fields: ['name', 'no']));
          await db.put(
              doc: Doc(id: 'user_01', model: {
            'name': 'foo',
            'no': 1,
          }));
          await db.put(doc: Doc(id: 'admin_01', model: {'name': 'foo'}));
          await db.put(
              doc: Doc(id: 'user_02', model: {'name': 'foo', 'no': 2}));
          final findResponse = await db.find<Map<String, dynamic>>(
              FindRequest(
                selector: AndOperator(operators: [
                  AndOperator(operators: [
                    EqualOperator(key: 'name', expected: 'foo'),
                    GreaterThanOperator(key: 'no', expected: 0),
                    AndOperator(operators: [
                      RegexOperator(key: '_id', expected: '^user')
                    ])
                  ])
                ]),
              ),
              (value) => value);

          expect(findResponse.docs.length, equals(2));
          expect(findResponse.docs.first.id, 'user_01');
          expect(findResponse.docs[1].id, 'user_02');
        });
        test(
            'nested selector without _id, docs with missing keys, fields of designdoc = first layer of selector',
            () async {
          final db = await ctx.db('find');
          await db.createIndex(
              index: QueryViewOptionsDef(fields: ['name', 'k']));
          await db.put(
              doc: Doc(id: 'user_01', model: {'name': 'foo', 'no': 1, 'k': 1}));
          await db.put(
              doc: Doc(id: 'admin_01', model: {'name': 'food', 'k': 2}));
          await db.put(
              doc: Doc(id: 'user_02', model: {'name': 'foo', 'no': 2, 'k': 3}));
          final findResponse = await db.find<Map<String, dynamic>>(
              FindRequest(
                selector: AndOperator(operators: [
                  EqualOperator(key: 'name', expected: 'foo'),
                  GreaterThanOperator(key: 'k', expected: 0),
                  AndOperator(operators: [
                    GreaterThanOperator(key: 'no', expected: 0),
                    AndOperator(operators: [
                      RegexOperator(key: '_id', expected: '^user')
                    ])
                  ])
                ]),
              ),
              (value) => value);

          expect(findResponse.docs.length, equals(2));
          expect(findResponse.docs.first.id, 'user_01');
          expect(findResponse.docs[1].id, 'user_02');
        });

        test(
            'nested selector, nested field, docs with missing keys, call all_docs',
            () async {
          final db = await ctx.db('find');
          await db.createIndex(
              index: QueryViewOptionsDef(fields: ['name', 'no']));
          await db.put(
              doc: Doc(id: 'user_01', model: {
            'name': {
              'first': {'name': 'foo'}
            },
            'no': 1,
          }));
          await db.put(doc: Doc(id: 'admin_01', model: {'name': 'foo'}));
          await db.put(
              doc: Doc(id: 'user_02', model: {'name': 'foo', 'no': 2}));
          final findResponse = await db.find<Map<String, dynamic>>(
              FindRequest(
                selector: AndOperator(operators: [
                  AndOperator(operators: [
                    EqualOperator(key: 'name.first.name', expected: 'foo'),
                    GreaterThanOperator(key: 'no', expected: 0),
                    AndOperator(operators: [
                      RegexOperator(key: '_id', expected: '^user')
                    ])
                  ])
                ]),
              ),
              (value) => value);

          expect(findResponse.docs.length, equals(1));
          expect(findResponse.docs.first.id, 'user_01');
        });
      });
    },
    (FoodbTestContext ctx) {
      group('explain()', () {
        test('equal operator come before regex', () async {
          final db = await ctx.db('explain');
          await db.createIndex(
              name: 'id-name-index',
              index: QueryViewOptionsDef(fields: ['_id', 'name']));
          await db.createIndex(
              name: 'name-id-index',
              index: QueryViewOptionsDef(fields: ['name', '_id']));
          var explainResponse = await db.explain(FindRequest(
              selector: AndOperator(operators: [
                EqualOperator(key: 'name', expected: 'nasi'),
                RegexOperator(
                  key: '_id',
                  expected: '^user',
                )
              ]),
              sort: []));
          expect(explainResponse.index.name, 'name-id-index');
        });
        test('same operator will sort by id', () async {
          final db = await ctx.db('explain');
          await db.createIndex(
              name: 'id-name-index',
              index: QueryViewOptionsDef(fields: ['_id', 'name']));
          await db.createIndex(
              name: 'name-id-index',
              index: QueryViewOptionsDef(fields: ['name', '_id']));
          var explainResponse = await db.explain(FindRequest(
              selector: AndOperator(operators: [
                EqualOperator(
                  key: '_id',
                  expected: 'user',
                ),
                EqualOperator(key: 'name', expected: 'nasi'),
              ]),
              sort: []));
          expect(explainResponse.index.name, 'id-name-index');
          explainResponse = await db.explain(FindRequest(
              selector: AndOperator(operators: [
                EqualOperator(key: 'name', expected: 'nasi'),
                EqualOperator(
                  key: '_id',
                  expected: 'user',
                ),
              ]),
              sort: []));
          expect(explainResponse.index.name, 'id-name-index');
        });
        test(
            'selected design-doc fields should less or equal to selector and ignore _id',
            () async {
          final db = await ctx.db('explain');
          await db.createIndex(
              name: 'id-name-k-index',
              index: QueryViewOptionsDef(fields: ['no', 'name', 'k']));
          await db.createIndex(
              name: 'id-name-index',
              index: QueryViewOptionsDef(fields: ['name', '_id']));

          var explainResponse = await db.explain(FindRequest(
              selector: AndOperator(operators: [
                EqualOperator(key: 'no', expected: 100),
                RegexOperator(
                  key: 'name',
                  expected: '^user',
                )
              ]),
              sort: []));
          expect(explainResponse.index.name, 'id-name-index');
        });
        test('should return all_docs if no suitable design docs', () async {
          final db = await ctx.db('explain');
          await db.createIndex(
              name: 'id-name-index',
              index: QueryViewOptionsDef(fields: ['k', '_id']));
          await db.createIndex(
              name: 'id-name-k-index',
              index: QueryViewOptionsDef(fields: ['no', 'name', 'k']));

          var explainResponse = await db.explain(FindRequest(
              selector: AndOperator(operators: [
                EqualOperator(key: 'no', expected: 100),
                RegexOperator(
                  key: 'name',
                  expected: '^user',
                )
              ]),
              sort: []));
          expect(explainResponse.index.name.contains('all_docs'), true);
        });
        test('check when last generate view failed halfway', () async {
          final db = await ctx.db('generate-view-fail');
          await db.createIndex(
              name: 'id-name-index',
              index: QueryViewOptionsDef(fields: ['name']));
          var doc = await db.put(doc: Doc(id: '1', model: {'name': 'a'}));
          var find = await db.find(
              FindRequest(selector: EqualOperator(key: 'name', expected: 'a')),
              (p0) => p0);
          print(find);
        });
      });
    }
  ];
}