Missing Commits from previous merge (#321)
* fix: Maintain this binding for pagination * chore: fix tests to match core sdk * fix: Upgrade Dockerfile and uv
This commit is contained in:
parent
ee12164835
commit
5978c670de
|
|
@ -3,6 +3,9 @@ name: Unified Tests (Fly Runner)
|
|||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'src/**'
|
||||
- 'tests/**'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
@ -58,7 +61,7 @@ jobs:
|
|||
which python3.12
|
||||
|
||||
- name: Install the project
|
||||
run: uv sync --all-extras --dev
|
||||
run: uv sync --all-extras
|
||||
|
||||
- name: Run unified tests
|
||||
run: uv run python -m tests.unified.run
|
||||
|
|
|
|||
26
Dockerfile
26
Dockerfile
|
|
@ -1,38 +1,41 @@
|
|||
# https://pythonspeed.com/articles/base-image-python-docker-images/
|
||||
# https://testdriven.io/blog/docker-best-practices/
|
||||
FROM python:3.11-slim-bullseye
|
||||
FROM python:3.13-slim-bookworm
|
||||
|
||||
COPY --from=ghcr.io/astral-sh/uv:0.4.9 /uv /bin/uv
|
||||
COPY --from=ghcr.io/astral-sh/uv:0.9.24 /uv /bin/uv
|
||||
|
||||
# Set Working directory
|
||||
WORKDIR /app
|
||||
|
||||
RUN addgroup --system app && adduser --system --group app
|
||||
RUN chown -R app:app /app
|
||||
USER app
|
||||
|
||||
# Enable bytecode compilation
|
||||
ENV UV_COMPILE_BYTECODE=1
|
||||
|
||||
# Copy from the cache instead of linking since it's a mounted volume
|
||||
ENV UV_LINK_MODE=copy
|
||||
|
||||
# Python optimizations
|
||||
ENV PYTHONDONTWRITEBYTECODE=1
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
|
||||
# Install the project's dependencies using the lockfile and settings
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
--mount=type=bind,source=uv.lock,target=uv.lock \
|
||||
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
|
||||
uv sync --frozen --no-install-project --no-dev
|
||||
uv sync --frozen --no-install-project --no-group dev
|
||||
|
||||
# Copy only requirements to cache them in docker layer
|
||||
COPY uv.lock pyproject.toml /app/
|
||||
|
||||
# Sync the project
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv sync --frozen --no-dev
|
||||
uv sync --frozen --no-group dev
|
||||
|
||||
# Place executables in the environment at the front of the path
|
||||
ENV PATH="/app/.venv/bin:$PATH"
|
||||
|
||||
# Create non-root user and set ownership
|
||||
RUN addgroup --system app && adduser --system --group app && chown -R app:app /app
|
||||
|
||||
COPY --chown=app:app src/ /app/src/
|
||||
COPY --chown=app:app migrations/ /app/migrations/
|
||||
COPY --chown=app:app scripts/ /app/scripts/
|
||||
|
|
@ -40,7 +43,12 @@ COPY --chown=app:app alembic.ini /app/alembic.ini
|
|||
# Copy config files - this will copy config.toml if it exists, and config.toml.example
|
||||
COPY --chown=app:app config.toml* /app/
|
||||
|
||||
# Switch to non-root user
|
||||
USER app
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
# https://stackoverflow.com/questions/29663459/python-app-does-not-print-anything-when-running-detached-in-docker
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/openapi.json')" || exit 1
|
||||
|
||||
CMD ["fastapi", "run", "--host", "0.0.0.0", "src/main.py"]
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ dependencies = [
|
|||
"cashews[redis]==7.4.4",
|
||||
"scikit-learn>=1.6.0",
|
||||
]
|
||||
[tool.uv]
|
||||
dev-dependencies = [
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"pytest>=8.2.2",
|
||||
"sqlalchemy-utils>=0.41.2",
|
||||
"pytest-asyncio>=0.23.7",
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ describe('Honcho Client', () => {
|
|||
],
|
||||
total: 2,
|
||||
size: 2,
|
||||
hasNextPage: false,
|
||||
hasNextPage: () => false,
|
||||
};
|
||||
mockClient.workspaces.peers.list.mockResolvedValue(mockPeersData);
|
||||
|
||||
|
|
@ -155,7 +155,7 @@ describe('Honcho Client', () => {
|
|||
items: [],
|
||||
total: 0,
|
||||
size: 0,
|
||||
hasNextPage: false,
|
||||
hasNextPage: () => false,
|
||||
};
|
||||
mockClient.workspaces.peers.list.mockResolvedValue(mockPeersData);
|
||||
|
||||
|
|
@ -218,7 +218,7 @@ describe('Honcho Client', () => {
|
|||
],
|
||||
total: 2,
|
||||
size: 2,
|
||||
hasNextPage: false,
|
||||
hasNextPage: () => false,
|
||||
};
|
||||
mockClient.workspaces.sessions.list.mockResolvedValue(mockSessionsData);
|
||||
|
||||
|
|
@ -233,7 +233,7 @@ describe('Honcho Client', () => {
|
|||
items: [],
|
||||
total: 0,
|
||||
size: 0,
|
||||
hasNextPage: false,
|
||||
hasNextPage: () => false,
|
||||
};
|
||||
mockClient.workspaces.sessions.list.mockResolvedValue(mockSessionsData);
|
||||
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ describe('Honcho SDK Integration Tests', () => {
|
|||
],
|
||||
total: 2,
|
||||
size: 2,
|
||||
hasNextPage: false,
|
||||
hasNextPage: () => false,
|
||||
[Symbol.asyncIterator]: async function*() {
|
||||
for (const item of this.items) {
|
||||
yield item
|
||||
|
|
@ -422,7 +422,7 @@ describe('Honcho SDK Integration Tests', () => {
|
|||
mockWorkspacesApi.workspaces.peers.list.mockResolvedValue({
|
||||
items: [],
|
||||
total: 0,
|
||||
hasNextPage: false,
|
||||
hasNextPage: () => false,
|
||||
})
|
||||
mockWorkspacesApi.workspaces.sessions.context.mockResolvedValue({
|
||||
messages: [],
|
||||
|
|
|
|||
|
|
@ -273,7 +273,7 @@ describe('Metadata and Configuration Caching', () => {
|
|||
],
|
||||
total: 2,
|
||||
size: 2,
|
||||
hasNextPage: false,
|
||||
hasNextPage: () => false,
|
||||
};
|
||||
mockClient.workspaces.peers.list.mockResolvedValue(mockPeersData);
|
||||
|
||||
|
|
@ -297,7 +297,7 @@ describe('Metadata and Configuration Caching', () => {
|
|||
],
|
||||
total: 1,
|
||||
size: 1,
|
||||
hasNextPage: false,
|
||||
hasNextPage: () => false,
|
||||
};
|
||||
mockClient.workspaces.peers.list.mockResolvedValue(mockPeersData);
|
||||
|
||||
|
|
@ -444,7 +444,7 @@ describe('Metadata and Configuration Caching', () => {
|
|||
],
|
||||
total: 2,
|
||||
size: 2,
|
||||
hasNextPage: false,
|
||||
hasNextPage: () => false,
|
||||
};
|
||||
mockClient.workspaces.sessions.list.mockResolvedValue(mockSessionsData);
|
||||
|
||||
|
|
@ -468,7 +468,7 @@ describe('Metadata and Configuration Caching', () => {
|
|||
],
|
||||
total: 1,
|
||||
size: 1,
|
||||
hasNextPage: false,
|
||||
hasNextPage: () => false,
|
||||
};
|
||||
mockClient.workspaces.sessions.list.mockResolvedValue(mockSessionsData);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
import { Page } from "../src/pagination";
|
||||
import { Page } from '../src/pagination'
|
||||
|
||||
describe("Page", () => {
|
||||
let mockOriginalPage: any;
|
||||
let mockItems: any[];
|
||||
describe('Page', () => {
|
||||
let mockOriginalPage: any
|
||||
let mockItems: any[]
|
||||
|
||||
beforeEach(() => {
|
||||
mockItems = [
|
||||
{ id: "item1", name: "Item 1" },
|
||||
{ id: "item2", name: "Item 2" },
|
||||
{ id: "item3", name: "Item 3" },
|
||||
];
|
||||
{ id: 'item1', name: 'Item 1' },
|
||||
{ id: 'item2', name: 'Item 2' },
|
||||
{ id: 'item3', name: 'Item 3' },
|
||||
]
|
||||
|
||||
mockOriginalPage = {
|
||||
items: mockItems,
|
||||
|
|
@ -20,311 +20,312 @@ describe("Page", () => {
|
|||
hasNextPage: () => true,
|
||||
[Symbol.asyncIterator]: async function*() {
|
||||
for (const item of mockItems) {
|
||||
yield item;
|
||||
yield item
|
||||
}
|
||||
},
|
||||
} as any;
|
||||
});
|
||||
} as any
|
||||
})
|
||||
|
||||
describe("constructor", () => {
|
||||
it("should initialize with original page", () => {
|
||||
const page = new Page(mockOriginalPage);
|
||||
describe('constructor', () => {
|
||||
it('should initialize with original page', () => {
|
||||
const page = new Page(mockOriginalPage)
|
||||
|
||||
expect(page["_originalPage"]).toBe(mockOriginalPage);
|
||||
expect(page["_transformFunc"]).toBeUndefined();
|
||||
});
|
||||
expect(page['_originalPage']).toBe(mockOriginalPage)
|
||||
expect(page['_transformFunc']).toBeUndefined()
|
||||
})
|
||||
|
||||
it("should initialize with transform function", () => {
|
||||
const transformFunc = (item: any) => ({ ...item, transformed: true });
|
||||
const page = new Page(mockOriginalPage, transformFunc);
|
||||
it('should initialize with transform function', () => {
|
||||
const transformFunc = (item: any) => ({ ...item, transformed: true })
|
||||
const page = new Page(mockOriginalPage, transformFunc)
|
||||
|
||||
expect(page["_originalPage"]).toBe(mockOriginalPage);
|
||||
expect(page["_transformFunc"]).toBe(transformFunc);
|
||||
});
|
||||
});
|
||||
expect(page['_originalPage']).toBe(mockOriginalPage)
|
||||
expect(page['_transformFunc']).toBe(transformFunc)
|
||||
})
|
||||
})
|
||||
|
||||
describe("Symbol.asyncIterator", () => {
|
||||
it("should iterate through items without transform", async () => {
|
||||
const page = new Page(mockOriginalPage);
|
||||
const items: any[] = [];
|
||||
describe('Symbol.asyncIterator', () => {
|
||||
it('should iterate through items without transform', async () => {
|
||||
const page = new Page(mockOriginalPage)
|
||||
const items: any[] = []
|
||||
|
||||
for await (const item of page) {
|
||||
items.push(item);
|
||||
items.push(item)
|
||||
}
|
||||
|
||||
expect(items).toEqual(mockItems);
|
||||
});
|
||||
expect(items).toEqual(mockItems)
|
||||
})
|
||||
|
||||
it("should iterate through items with transform", async () => {
|
||||
const transformFunc = (item: any) => ({ ...item, transformed: true });
|
||||
const page = new Page(mockOriginalPage, transformFunc);
|
||||
const items: any[] = [];
|
||||
it('should iterate through items with transform', async () => {
|
||||
const transformFunc = (item: any) => ({ ...item, transformed: true })
|
||||
const page = new Page(mockOriginalPage, transformFunc)
|
||||
const items: any[] = []
|
||||
|
||||
for await (const item of page) {
|
||||
items.push(item);
|
||||
items.push(item)
|
||||
}
|
||||
|
||||
expect(items).toEqual([
|
||||
{ id: "item1", name: "Item 1", transformed: true },
|
||||
{ id: "item2", name: "Item 2", transformed: true },
|
||||
{ id: "item3", name: "Item 3", transformed: true },
|
||||
]);
|
||||
});
|
||||
{ id: 'item1', name: 'Item 1', transformed: true },
|
||||
{ id: 'item2', name: 'Item 2', transformed: true },
|
||||
{ id: 'item3', name: 'Item 3', transformed: true },
|
||||
])
|
||||
})
|
||||
|
||||
it("should handle transform function that throws error", async () => {
|
||||
it('should handle transform function that throws error', async () => {
|
||||
const errorTransform = () => {
|
||||
throw new Error("Transform error");
|
||||
};
|
||||
const page = new Page(mockOriginalPage, errorTransform);
|
||||
throw new Error('Transform error')
|
||||
}
|
||||
const page = new Page(mockOriginalPage, errorTransform)
|
||||
|
||||
const iterate = async () => {
|
||||
for await (const item of page) {
|
||||
// This should throw
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
await expect(iterate()).rejects.toThrow("Transform error");
|
||||
});
|
||||
});
|
||||
await expect(iterate()).rejects.toThrow('Transform error')
|
||||
})
|
||||
})
|
||||
|
||||
describe("get", () => {
|
||||
it("should get item by index without transform", () => {
|
||||
const page = new Page(mockOriginalPage);
|
||||
describe('get', () => {
|
||||
it('should get item by index without transform', () => {
|
||||
const page = new Page(mockOriginalPage)
|
||||
|
||||
const item = page.get(1);
|
||||
const item = page.get(1)
|
||||
|
||||
expect(item).toEqual(mockItems[1]);
|
||||
});
|
||||
expect(item).toEqual(mockItems[1])
|
||||
})
|
||||
|
||||
it("should get item by index with transform", () => {
|
||||
const transformFunc = (item: any) => ({ ...item, transformed: true });
|
||||
const page = new Page(mockOriginalPage, transformFunc);
|
||||
it('should get item by index with transform', () => {
|
||||
const transformFunc = (item: any) => ({ ...item, transformed: true })
|
||||
const page = new Page(mockOriginalPage, transformFunc)
|
||||
|
||||
const item = page.get(1);
|
||||
const item = page.get(1)
|
||||
|
||||
expect(item).toEqual({ ...mockItems[1], transformed: true });
|
||||
});
|
||||
expect(item).toEqual({ ...mockItems[1], transformed: true })
|
||||
})
|
||||
|
||||
it("should handle out of bounds index", () => {
|
||||
const page = new Page(mockOriginalPage);
|
||||
it('should handle out of bounds index', () => {
|
||||
const page = new Page(mockOriginalPage)
|
||||
|
||||
expect(() => page.get(999)).toThrow(
|
||||
"Index 999 is out of bounds for page with 3 items",
|
||||
);
|
||||
});
|
||||
});
|
||||
'Index 999 is out of bounds for page with 3 items'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("length getter", () => {
|
||||
it("should return length of items array", () => {
|
||||
const page = new Page(mockOriginalPage);
|
||||
describe('length getter', () => {
|
||||
it('should return length of items array', () => {
|
||||
const page = new Page(mockOriginalPage)
|
||||
|
||||
expect(page.length).toBe(3);
|
||||
});
|
||||
expect(page.length).toBe(3)
|
||||
})
|
||||
|
||||
it("should handle empty items array", () => {
|
||||
const emptyPage = { ...mockOriginalPage, items: [] };
|
||||
const page = new Page(emptyPage);
|
||||
it('should handle empty items array', () => {
|
||||
const emptyPage = { ...mockOriginalPage, items: [] }
|
||||
const page = new Page(emptyPage)
|
||||
|
||||
expect(page.length).toBe(0);
|
||||
});
|
||||
expect(page.length).toBe(0)
|
||||
})
|
||||
|
||||
it("should handle undefined items", () => {
|
||||
const noItemsPage = { ...mockOriginalPage, items: undefined };
|
||||
const page = new Page(noItemsPage);
|
||||
it('should handle undefined items', () => {
|
||||
const noItemsPage = { ...mockOriginalPage, items: undefined }
|
||||
const page = new Page(noItemsPage)
|
||||
|
||||
expect(page.length).toBe(0);
|
||||
});
|
||||
});
|
||||
expect(page.length).toBe(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe("items getter", () => {
|
||||
it("should return items array without transform", () => {
|
||||
const page = new Page(mockOriginalPage);
|
||||
describe('items getter', () => {
|
||||
it('should return items array without transform', () => {
|
||||
const page = new Page(mockOriginalPage)
|
||||
|
||||
const data = page.items;
|
||||
const data = page.items
|
||||
|
||||
expect(data).toEqual(mockItems);
|
||||
});
|
||||
expect(data).toEqual(mockItems)
|
||||
})
|
||||
|
||||
it("should return items array with transform", () => {
|
||||
const transformFunc = (item: any) => ({ ...item, transformed: true });
|
||||
const page = new Page(mockOriginalPage, transformFunc);
|
||||
it('should return items array with transform', () => {
|
||||
const transformFunc = (item: any) => ({ ...item, transformed: true })
|
||||
const page = new Page(mockOriginalPage, transformFunc)
|
||||
|
||||
const data = page.items;
|
||||
const data = page.items
|
||||
|
||||
expect(data).toEqual([
|
||||
{ id: "item1", name: "Item 1", transformed: true },
|
||||
{ id: "item2", name: "Item 2", transformed: true },
|
||||
{ id: "item3", name: "Item 3", transformed: true },
|
||||
]);
|
||||
});
|
||||
{ id: 'item1', name: 'Item 1', transformed: true },
|
||||
{ id: 'item2', name: 'Item 2', transformed: true },
|
||||
{ id: 'item3', name: 'Item 3', transformed: true },
|
||||
])
|
||||
})
|
||||
|
||||
it("should handle transform function returning null", () => {
|
||||
const nullTransform = () => null;
|
||||
const page = new Page(mockOriginalPage, nullTransform);
|
||||
it('should handle transform function returning null', () => {
|
||||
const nullTransform = () => null
|
||||
const page = new Page(mockOriginalPage, nullTransform)
|
||||
|
||||
const data = page.items;
|
||||
const data = page.items
|
||||
|
||||
expect(data).toEqual([null, null, null]);
|
||||
});
|
||||
});
|
||||
expect(data).toEqual([null, null, null])
|
||||
})
|
||||
})
|
||||
|
||||
describe("pagination metadata getters", () => {
|
||||
it("should return total from original page", () => {
|
||||
const page = new Page(mockOriginalPage);
|
||||
describe('pagination metadata getters', () => {
|
||||
it('should return total from original page', () => {
|
||||
const page = new Page(mockOriginalPage)
|
||||
|
||||
expect(page.total).toBe(10);
|
||||
});
|
||||
expect(page.total).toBe(10)
|
||||
})
|
||||
|
||||
it("should return page number from original page", () => {
|
||||
const page = new Page(mockOriginalPage);
|
||||
it('should return page number from original page', () => {
|
||||
const page = new Page(mockOriginalPage)
|
||||
|
||||
expect(page.page).toBe(1);
|
||||
});
|
||||
expect(page.page).toBe(1)
|
||||
})
|
||||
|
||||
it("should return size from original page", () => {
|
||||
const page = new Page(mockOriginalPage);
|
||||
it('should return size from original page', () => {
|
||||
const page = new Page(mockOriginalPage)
|
||||
|
||||
expect(page.size).toBe(3);
|
||||
});
|
||||
expect(page.size).toBe(3)
|
||||
})
|
||||
|
||||
it("should return pages from original page", () => {
|
||||
const page = new Page(mockOriginalPage);
|
||||
it('should return pages from original page', () => {
|
||||
const page = new Page(mockOriginalPage)
|
||||
|
||||
expect(page.pages).toBe(4);
|
||||
});
|
||||
expect(page.pages).toBe(4)
|
||||
})
|
||||
|
||||
it("should handle undefined metadata", () => {
|
||||
const minimalPage = { items: mockItems };
|
||||
const page = new Page(minimalPage as any);
|
||||
it('should handle undefined metadata', () => {
|
||||
const minimalPage = { items: mockItems }
|
||||
const page = new Page(minimalPage as any)
|
||||
|
||||
expect(page.total).toBeUndefined();
|
||||
expect(page.page).toBeUndefined();
|
||||
expect(page.size).toBeUndefined();
|
||||
expect(page.pages).toBeUndefined();
|
||||
});
|
||||
});
|
||||
expect(page.total).toBeUndefined()
|
||||
expect(page.page).toBeUndefined()
|
||||
expect(page.size).toBeUndefined()
|
||||
expect(page.pages).toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
describe("hasNextPage getter", () => {
|
||||
it("should return true when hasNextPage is true", () => {
|
||||
const page = new Page(mockOriginalPage);
|
||||
describe('hasNextPage getter', () => {
|
||||
it('should return true when hasNextPage is true', () => {
|
||||
const page = new Page(mockOriginalPage)
|
||||
|
||||
expect(page.hasNextPage).toBe(true);
|
||||
});
|
||||
expect(page.hasNextPage).toBe(true)
|
||||
})
|
||||
|
||||
it("should return false when hasNextPage is false", () => {
|
||||
const lastPage = { ...mockOriginalPage, hasNextPage: false };
|
||||
const page = new Page(lastPage);
|
||||
it('should return false when hasNextPage function returns false', () => {
|
||||
const lastPage = { ...mockOriginalPage, hasNextPage: () => false }
|
||||
|
||||
expect(page.hasNextPage).toBe(false);
|
||||
});
|
||||
const page = new Page(lastPage)
|
||||
|
||||
it("should call hasNextPage function if it is a function", () => {
|
||||
const hasNextPageFn = jest.fn(() => true);
|
||||
const pageWithFn = { ...mockOriginalPage, hasNextPage: hasNextPageFn };
|
||||
const page = new Page(pageWithFn);
|
||||
expect(page.hasNextPage).toBe(false)
|
||||
})
|
||||
|
||||
const result = page.hasNextPage;
|
||||
it('should call hasNextPage function if it is a function', () => {
|
||||
const hasNextPageFn = jest.fn(() => true)
|
||||
const pageWithFn = { ...mockOriginalPage, hasNextPage: hasNextPageFn }
|
||||
const page = new Page(pageWithFn)
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect(hasNextPageFn).toHaveBeenCalled();
|
||||
});
|
||||
const result = page.hasNextPage
|
||||
|
||||
it("should return false when hasNextPage is undefined", () => {
|
||||
const noNextPage = { ...mockOriginalPage };
|
||||
delete noNextPage.hasNextPage;
|
||||
const page = new Page(noNextPage);
|
||||
expect(result).toBe(true)
|
||||
expect(hasNextPageFn).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
expect(page.hasNextPage).toBe(false);
|
||||
});
|
||||
});
|
||||
it('should return false when hasNextPage is undefined', () => {
|
||||
const noNextPage = { ...mockOriginalPage }
|
||||
delete noNextPage.hasNextPage
|
||||
const page = new Page(noNextPage)
|
||||
|
||||
describe("getNextPage", () => {
|
||||
it("should return next page with same transform function", async () => {
|
||||
expect(page.hasNextPage).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('getNextPage', () => {
|
||||
it('should return next page with same transform function', async () => {
|
||||
const nextPageData = {
|
||||
items: [{ id: "item4", name: "Item 4" }],
|
||||
items: [{ id: 'item4', name: 'Item 4' }],
|
||||
size: 1,
|
||||
total: 10,
|
||||
page: 2,
|
||||
pages: 4,
|
||||
hasNextPage: false,
|
||||
hasNextPage: () => false,
|
||||
[Symbol.asyncIterator]: async function*() {
|
||||
for (const item of this.items) {
|
||||
yield item;
|
||||
yield item
|
||||
}
|
||||
},
|
||||
};
|
||||
const transformFunc = (item: any) => ({ ...item, transformed: true });
|
||||
mockOriginalPage.getNextPage = jest.fn().mockResolvedValue(nextPageData);
|
||||
const page = new Page(mockOriginalPage, transformFunc);
|
||||
}
|
||||
const transformFunc = (item: any) => ({ ...item, transformed: true })
|
||||
mockOriginalPage.getNextPage = jest.fn().mockResolvedValue(nextPageData)
|
||||
const page = new Page(mockOriginalPage, transformFunc)
|
||||
|
||||
const nextPage = await page.getNextPage();
|
||||
const nextPage = await page.getNextPage()
|
||||
|
||||
expect(nextPage).toBeInstanceOf(Page);
|
||||
expect(nextPage!["_transformFunc"]).toBe(transformFunc);
|
||||
expect(mockOriginalPage.getNextPage).toHaveBeenCalled();
|
||||
});
|
||||
expect(nextPage).toBeInstanceOf(Page)
|
||||
expect(nextPage!['_transformFunc']).toBe(transformFunc)
|
||||
expect(mockOriginalPage.getNextPage).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("should return null when no next page", async () => {
|
||||
mockOriginalPage.getNextPage = jest.fn().mockResolvedValue(null);
|
||||
const page = new Page(mockOriginalPage);
|
||||
it('should return null when no next page', async () => {
|
||||
mockOriginalPage.getNextPage = jest.fn().mockResolvedValue(null)
|
||||
const page = new Page(mockOriginalPage)
|
||||
|
||||
const nextPage = await page.getNextPage();
|
||||
const nextPage = await page.getNextPage()
|
||||
|
||||
expect(nextPage).toBeNull();
|
||||
});
|
||||
expect(nextPage).toBeNull()
|
||||
})
|
||||
|
||||
it("should return null when getNextPage returns undefined", async () => {
|
||||
mockOriginalPage.getNextPage = jest.fn().mockResolvedValue(undefined);
|
||||
const page = new Page(mockOriginalPage);
|
||||
it('should return null when getNextPage returns undefined', async () => {
|
||||
mockOriginalPage.getNextPage = jest.fn().mockResolvedValue(undefined)
|
||||
const page = new Page(mockOriginalPage)
|
||||
|
||||
const nextPage = await page.getNextPage();
|
||||
const nextPage = await page.getNextPage()
|
||||
|
||||
expect(nextPage).toBeNull();
|
||||
});
|
||||
expect(nextPage).toBeNull()
|
||||
})
|
||||
|
||||
it("should return null when getNextPage method does not exist", async () => {
|
||||
const pageWithoutNext = { ...mockOriginalPage };
|
||||
delete pageWithoutNext.getNextPage;
|
||||
const page = new Page(pageWithoutNext);
|
||||
it('should return null when getNextPage method does not exist', async () => {
|
||||
const pageWithoutNext = { ...mockOriginalPage }
|
||||
delete pageWithoutNext.getNextPage
|
||||
const page = new Page(pageWithoutNext)
|
||||
|
||||
const nextPage = await page.getNextPage();
|
||||
const nextPage = await page.getNextPage()
|
||||
|
||||
expect(nextPage).toBeNull();
|
||||
});
|
||||
expect(nextPage).toBeNull()
|
||||
})
|
||||
|
||||
it("should propagate transform function to next page", async () => {
|
||||
it('should propagate transform function to next page', async () => {
|
||||
const nextPageData = {
|
||||
items: [{ id: "item4", name: "Item 4" }],
|
||||
items: [{ id: 'item4', name: 'Item 4' }],
|
||||
[Symbol.asyncIterator]: async function*() {
|
||||
for (const item of this.items) {
|
||||
yield item;
|
||||
yield item
|
||||
}
|
||||
},
|
||||
};
|
||||
const transformFunc = (item: any) => ({ ...item, count: 999 });
|
||||
mockOriginalPage.getNextPage = jest.fn().mockResolvedValue(nextPageData);
|
||||
const page = new Page(mockOriginalPage, transformFunc);
|
||||
}
|
||||
const transformFunc = (item: any) => ({ ...item, count: 999 })
|
||||
mockOriginalPage.getNextPage = jest.fn().mockResolvedValue(nextPageData)
|
||||
const page = new Page(mockOriginalPage, transformFunc)
|
||||
|
||||
const nextPage = await page.getNextPage();
|
||||
const nextPage = await page.getNextPage()
|
||||
|
||||
expect(nextPage).not.toBeNull();
|
||||
const transformedItem = nextPage!.get(0);
|
||||
expect(nextPage).not.toBeNull()
|
||||
const transformedItem = nextPage!.get(0)
|
||||
expect(transformedItem).toEqual({
|
||||
id: "item4",
|
||||
name: "Item 4",
|
||||
id: 'item4',
|
||||
name: 'Item 4',
|
||||
count: 999,
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
|
||||
it("should handle error from getNextPage", async () => {
|
||||
it('should handle error from getNextPage', async () => {
|
||||
mockOriginalPage.getNextPage = jest
|
||||
.fn()
|
||||
.mockRejectedValue(new Error("Failed to get next page"));
|
||||
const page = new Page(mockOriginalPage);
|
||||
.mockRejectedValue(new Error('Failed to get next page'))
|
||||
const page = new Page(mockOriginalPage)
|
||||
|
||||
await expect(page.getNextPage()).rejects.toThrow(
|
||||
"Failed to get next page",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
'Failed to get next page'
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ describe('Peer', () => {
|
|||
],
|
||||
total: 2,
|
||||
size: 2,
|
||||
hasNextPage: false,
|
||||
hasNextPage: () => false,
|
||||
};
|
||||
mockClient.workspaces.peers.sessions.list.mockResolvedValue(mockSessionsData);
|
||||
|
||||
|
|
@ -184,7 +184,7 @@ describe('Peer', () => {
|
|||
items: [],
|
||||
total: 0,
|
||||
size: 0,
|
||||
hasNextPage: false,
|
||||
hasNextPage: () => false,
|
||||
};
|
||||
mockClient.workspaces.peers.sessions.list.mockResolvedValue(mockSessionsData);
|
||||
|
||||
|
|
|
|||
|
|
@ -290,7 +290,7 @@ describe('Session', () => {
|
|||
],
|
||||
total: 2,
|
||||
size: 2,
|
||||
hasNextPage: false,
|
||||
hasNextPage: () => false,
|
||||
}
|
||||
mockClient.workspaces.sessions.peers.list.mockResolvedValue(mockPeersData)
|
||||
|
||||
|
|
@ -311,7 +311,7 @@ describe('Session', () => {
|
|||
items: [],
|
||||
total: 0,
|
||||
size: 0,
|
||||
hasNextPage: false,
|
||||
hasNextPage: () => false,
|
||||
}
|
||||
mockClient.workspaces.sessions.peers.list.mockResolvedValue(mockPeersData)
|
||||
|
||||
|
|
@ -638,7 +638,7 @@ describe('Session', () => {
|
|||
],
|
||||
total: 2,
|
||||
size: 2,
|
||||
hasNextPage: false,
|
||||
hasNextPage: () => false,
|
||||
}
|
||||
mockClient.workspaces.sessions.messages.list.mockResolvedValue(
|
||||
mockMessagesData
|
||||
|
|
@ -659,7 +659,7 @@ describe('Session', () => {
|
|||
items: [],
|
||||
total: 0,
|
||||
size: 0,
|
||||
hasNextPage: false,
|
||||
hasNextPage: () => false,
|
||||
}
|
||||
mockClient.workspaces.sessions.messages.list.mockResolvedValue(
|
||||
mockMessagesData
|
||||
|
|
|
|||
Loading…
Reference in New Issue