protected getPagedDictionary(pageNumber: number, pageSize: number, sortBy: string = this.state.sortBy) {
this.dictionaryServiceList.getPagedDictionary(pageNumber, pageSize, sortBy)
- .subscribe((pages: DictionaryPage) => {
+ .subscribe((pages: DictionaryPage[]) => {
console.log(pages);
this.setState({
...this.state,
- page: pages,
- filteredPackages: pages,
+ page: pages[0],
+ filteredPackages: pages[0],
command: '',
- totalPackages: pages.totalElements,
+ totalPackages: pages[0].totalElements,
currentPage: pageNumber,
// this param is set only in get all as it represents the total number of pacakges in the server
- totalDictionariesWithoutSearchorFilters: pages.totalElements,
+ totalDictionariesWithoutSearchorFilters: pages[0].totalElements,
tags: [],
sortBy
});
private searchPagedDictionary(keyWord: string, pageNumber: number, pageSize: number, sortBy: string = this.state.sortBy) {
this.dictionaryServiceList.getPagedDictionaryByKeyWord(keyWord, pageNumber, pageSize, sortBy)
- .subscribe((pages: DictionaryPage) => {
+ .subscribe((pages: DictionaryPage[]) => {
console.log(pages);
this.setState({
...this.state,
- page: pages,
- filteredPackages: pages,
+ page: pages[0],
+ filteredPackages: pages[0],
command: keyWord,
- totalPackages: pages.totalElements,
+ totalPackages: pages[0].totalElements,
currentPage: pageNumber,
tags: [],
sortBy
* 3. Search & filter UI – sub-components render.
* 4. API integration – requests are proxied through the LoopBack BFF to the
* mock-processor and return successful responses.
- *
- * Implementation note: the BFF does not expose a paged dictionary endpoint
- * (/resourcedictionary/paged), so the dictionary list on this page renders *
- * empty in the test environment. The tests that assert on card data are
- * therefore skipped; this serves as a documented gap in the BFF implementation
- * rather than a test environment problem.
+ * 5. Dictionary listing – the paged endpoint returns data and dictionary
+ * cards are rendered.
+ * 6. Create-then-list flow – creating a dictionary then navigating back
+ * shows the list.
*/
import { test, expect } from '@playwright/test';
await expect(page.locator('app-dictionary-header')).toBeAttached({ timeout: 10_000 });
});
});
+
+test.describe('Resource Dictionary – paged listing', () => {
+ test('GET /resourcedictionary/paged returns a Page object with content array', async ({ request }) => {
+ const resp = await request.get('http://localhost:3000/resourcedictionary/paged?offset=0&limit=5&sort=DATE&sortType=ASC');
+ expect(resp.status()).toBe(200);
+ const body = await resp.json();
+ // LoopBack REST connector wraps the response in a single-element array
+ expect(Array.isArray(body)).toBe(true);
+ expect(body.length).toBe(1);
+ const pageObj = body[0];
+ expect(pageObj).toHaveProperty('content');
+ expect(pageObj).toHaveProperty('totalElements');
+ expect(Array.isArray(pageObj.content)).toBe(true);
+ expect(pageObj.totalElements).toBeGreaterThan(0);
+ expect(pageObj.content.length).toBeGreaterThan(0);
+ });
+
+ test('dictionary cards are rendered on the page', async ({ page }) => {
+ // Register response listener BEFORE navigating to avoid race condition
+ await Promise.all([
+ page.waitForResponse(
+ r => r.url().includes('/resourcedictionary/paged') && r.status() === 200,
+ { timeout: 15_000 },
+ ),
+ page.goto('/#/resource-dictionary'),
+ ]);
+ // Wait for Angular to render the dictionary list items
+ const cards = page.locator('app-dictionary-list .card');
+ await expect(cards.first()).toBeVisible({ timeout: 10_000 });
+ // The fixture has 3 dictionaries + 1 static "Create/Import" card = 4
+ await expect(cards).toHaveCount(4);
+ });
+
+ test('dictionary header shows correct total count', async ({ page }) => {
+ await Promise.all([
+ page.waitForResponse(
+ r => r.url().includes('/resourcedictionary/paged') && r.status() === 200,
+ { timeout: 15_000 },
+ ),
+ page.goto('/#/resource-dictionary'),
+ ]);
+ // The header shows "Resource Dictionary (N Dictionary)"
+ const header = page.locator('app-dictionary-header h2');
+ await expect(header).toContainText('3', { timeout: 10_000 });
+ });
+});
+
+test.describe('Resource Dictionary – create then list', () => {
+ test('creating a dictionary and navigating back shows the list', async ({ page }) => {
+ // Navigate to the create dictionary page
+ await Promise.all([
+ page.waitForResponse(
+ r => r.url().includes('/resourcedictionary/paged') && r.status() === 200,
+ { timeout: 15_000 },
+ ),
+ page.goto('/#/resource-dictionary'),
+ ]);
+
+ // Click "Create Dictionary" link on the add-card
+ await page.locator('a', { hasText: 'Create Dictionary' }).click();
+ await expect(page).toHaveURL(/createDictionary/);
+
+ // Navigate back to the dictionary list – register listener before navigating
+ await Promise.all([
+ page.waitForResponse(
+ r => r.url().includes('/resourcedictionary/paged') && r.status() === 200,
+ { timeout: 15_000 },
+ ),
+ page.goto('/#/resource-dictionary'),
+ ]);
+
+ // Dictionary list should still render cards (3 dictionaries + 1 create card)
+ const cards = page.locator('app-dictionary-list .card');
+ await expect(cards.first()).toBeVisible({ timeout: 10_000 });
+ await expect(cards).toHaveCount(4);
+ });
+});
public rdservice: ResourceDictionaryService,
) { }
+ @get('/resourcedictionary/paged', {
+ responses: {
+ '200': {
+ description: 'Resource Dictionary with pagination',
+ content: { 'application/json': {} },
+ },
+ },
+ })
+ async getPagedDictionary(
+ @param.query.number('limit') limit: number,
+ @param.query.number('offset') offset: number,
+ @param.query.string('sort') sort: string,
+ @param.query.string('sortType') sortType: string) {
+ return await this.rdservice.getPagedDictionary(limit, offset, sort, sortType || 'ASC');
+ }
+
@get('/resourcedictionary/{name}', {
responses: {
'200': {