$count, 'fetch' => function ($offset, $limit) use (&$calls, $prefix, $count) { $calls[] = [$prefix, $offset, $limit]; return array_map(fn ($i) => ['title' => $prefix.$i, 'url' => '/'.$prefix.$i], array_slice(range(1, $count), $offset, $limit)); }]; }; }; $sources = ['Páginas' => $factory('p', 3), 'Oportunidades' => $factory('o', 7), 'Documentos' => $factory('d', 2)]; $service = new FederatedSearch; $first = $service->page($sources, 1); $this->assertSame(['p1', 'p2', 'p3', 'o1', 'o2'], array_column($first['data'], 'title')); $this->assertSame(['Páginas', 'Páginas', 'Páginas', 'Oportunidades', 'Oportunidades'], array_column($first['data'], 'category')); $this->assertSame(12, $first['total']); $this->assertSame(3, $first['last_page']); $calls = []; $second = $service->page($sources, 2); $this->assertSame(['o3', 'o4', 'o5', 'o6', 'o7'], array_column($second['data'], 'title')); $this->assertSame([['p', 0, 5], ['o', 0, 5], ['d', 0, 5], ['o', 5, 5]], $calls); $third = $service->page($sources, 99); $this->assertSame(3, $third['current_page']); $this->assertSame(['d1', 'd2'], array_column($third['data'], 'title')); } public function test_more_relevant_titles_appear_first_across_sources(): void { $factories = [ 'Serviços' => fn () => ['count' => 1, 'fetch' => fn ($offset, $limit) => array_slice([['title' => 'Informação', 'url' => '/info', 'score' => 10]], $offset, $limit)], 'Sectores' => fn () => ['count' => 1, 'fetch' => fn ($offset, $limit) => array_slice([['title' => 'Sectores', 'url' => '/sectores', 'score' => 100]], $offset, $limit)], ]; $result = (new FederatedSearch)->page($factories, 1, 5, fn ($item) => $item['score']); $this->assertSame(['Sectores', 'Informação'], array_column($result['data'], 'title')); } public function test_direct_matches_precede_associations_across_sources_and_pages(): void { $search = new SearchTerms; $term = 'corredor da beira'; $tokens = $search->tokens($term); $sources = [ 'Oportunidades' => fn () => ['count' => 2, 'fetch' => fn ($offset, $limit) => array_slice([ ['title' => 'Açúcar no Corredor da Beira'], ['title' => 'Produção de açúcar'], ], $offset, $limit)], 'Carteira' => fn () => ['count' => 1, 'fetch' => fn ($offset, $limit) => array_slice([ ['title' => 'Corredor da Beira'], ], $offset, $limit)], ]; $score = fn ($item) => $search->score($item['title'], $term, $tokens); $service = new FederatedSearch; $this->assertSame(['Corredor da Beira', 'Açúcar no Corredor da Beira'], array_column($service->page($sources, 1, 2, $score)['data'], 'title')); $this->assertSame(['Produção de açúcar'], array_column($service->page($sources, 2, 2, $score)['data'], 'title')); } }