|
|
@@ -40,294 +40,132 @@ describe('pageListingApiModule', () => {
|
|
|
it('should anonymize path parameter when present', () => {
|
|
|
const originalUrl = '/_api/v3/page-listing/ancestors-children?path=/sensitive/path&limit=10';
|
|
|
|
|
|
- const result = pageListingApiModule.handle(mockRequest, originalUrl);
|
|
|
-
|
|
|
- expect(result).toEqual({
|
|
|
- 'http.target': '/_api/v3/page-listing/ancestors-children?path=%5BANONYMIZED%5D&limit=10',
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- it('should handle encoded path parameters', () => {
|
|
|
- const originalUrl = '/_api/v3/page-listing/ancestors-children?path=%2Fuser%2Fdocs&includeEmpty=true';
|
|
|
-
|
|
|
- const result = pageListingApiModule.handle(mockRequest, originalUrl);
|
|
|
-
|
|
|
- expect(result).toEqual({
|
|
|
- 'http.target': '/_api/v3/page-listing/ancestors-children?path=%5BANONYMIZED%5D&includeEmpty=true',
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- it('should return null when no path parameter is present', () => {
|
|
|
- const url = '/_api/v3/page-listing/ancestors-children?limit=10&sort=name';
|
|
|
-
|
|
|
- const result = pageListingApiModule.handle(mockRequest, url);
|
|
|
-
|
|
|
- expect(result).toBeNull();
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- describe('children endpoint', () => {
|
|
|
- it('should anonymize path parameter', () => {
|
|
|
- const originalUrl = '/_api/v3/page-listing/children?path=/project/docs&offset=0';
|
|
|
-
|
|
|
- const result = pageListingApiModule.handle(mockRequest, originalUrl);
|
|
|
-
|
|
|
- expect(result).toEqual({
|
|
|
- 'http.target': '/_api/v3/page-listing/children?path=%5BANONYMIZED%5D&offset=0',
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- it('should handle root path parameter', () => {
|
|
|
- const originalUrl = '/_api/v3/page-listing/children?path=/&includePrivate=false';
|
|
|
+ // Ensure canHandle returns true for this URL
|
|
|
+ expect(pageListingApiModule.canHandle(originalUrl)).toBe(true);
|
|
|
|
|
|
const result = pageListingApiModule.handle(mockRequest, originalUrl);
|
|
|
|
|
|
expect(result).toEqual({
|
|
|
- 'http.target': '/_api/v3/page-listing/children?path=%5BANONYMIZED%5D&includePrivate=false',
|
|
|
+ 'http.target': '/_api/v3/page-listing/ancestors-children?path=%5BANONYMIZED%5D&limit=10',
|
|
|
});
|
|
|
});
|
|
|
|
|
|
- it('should return null when no path parameter is present', () => {
|
|
|
- const url = '/_api/v3/page-listing/children?sort=updated&limit=20';
|
|
|
-
|
|
|
- const result = pageListingApiModule.handle(mockRequest, url);
|
|
|
+ it('should anonymize empty path parameter', () => {
|
|
|
+ const originalUrl = '/_api/v3/page-listing/ancestors-children?path=&limit=5';
|
|
|
|
|
|
- expect(result).toBeNull();
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- describe('info endpoint', () => {
|
|
|
- it('should anonymize path parameter', () => {
|
|
|
- const originalUrl = '/_api/v3/page-listing/info?path=/wiki/documentation';
|
|
|
+ // Ensure canHandle returns true for this URL
|
|
|
+ expect(pageListingApiModule.canHandle(originalUrl)).toBe(true);
|
|
|
|
|
|
const result = pageListingApiModule.handle(mockRequest, originalUrl);
|
|
|
|
|
|
+ // Empty path parameter should now be anonymized
|
|
|
expect(result).toEqual({
|
|
|
- 'http.target': '/_api/v3/page-listing/info?path=%5BANONYMIZED%5D',
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- it('should handle multiple parameters including path', () => {
|
|
|
- const originalUrl = '/_api/v3/page-listing/info?path=/admin&includeMetadata=true&format=json';
|
|
|
-
|
|
|
- const result = pageListingApiModule.handle(mockRequest, originalUrl);
|
|
|
-
|
|
|
- expect(result).toEqual({
|
|
|
- 'http.target': '/_api/v3/page-listing/info?path=%5BANONYMIZED%5D&includeMetadata=true&format=json',
|
|
|
+ 'http.target': '/_api/v3/page-listing/ancestors-children?path=%5BANONYMIZED%5D&limit=5',
|
|
|
});
|
|
|
});
|
|
|
|
|
|
it('should return null when no path parameter is present', () => {
|
|
|
- const url = '/_api/v3/page-listing/info?includeMetadata=true';
|
|
|
-
|
|
|
- const result = pageListingApiModule.handle(mockRequest, url);
|
|
|
-
|
|
|
- expect(result).toBeNull();
|
|
|
- });
|
|
|
- });
|
|
|
+ const originalUrl = '/_api/v3/page-listing/ancestors-children?limit=10';
|
|
|
|
|
|
- describe('edge cases', () => {
|
|
|
- it('should handle empty path parameter', () => {
|
|
|
- const originalUrl = '/_api/v3/page-listing/children?path=&limit=5';
|
|
|
+ // Ensure canHandle returns true for this URL
|
|
|
+ expect(pageListingApiModule.canHandle(originalUrl)).toBe(true);
|
|
|
|
|
|
const result = pageListingApiModule.handle(mockRequest, originalUrl);
|
|
|
|
|
|
- expect(result).toEqual({
|
|
|
- 'http.target': '/_api/v3/page-listing/children?path=%5BANONYMIZED%5D&limit=5',
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- it('should handle URLs without any parameters', () => {
|
|
|
- const url = '/_api/v3/page-listing/ancestors-children';
|
|
|
-
|
|
|
- const result = pageListingApiModule.handle(mockRequest, url);
|
|
|
-
|
|
|
expect(result).toBeNull();
|
|
|
});
|
|
|
-
|
|
|
- it('should preserve parameter order while anonymizing path', () => {
|
|
|
- const originalUrl = '/_api/v3/page-listing/info?format=json&path=/secret&includeMetadata=true';
|
|
|
-
|
|
|
- const result = pageListingApiModule.handle(mockRequest, originalUrl);
|
|
|
-
|
|
|
- expect(result).toEqual({
|
|
|
- 'http.target': '/_api/v3/page-listing/info?format=json&path=%5BANONYMIZED%5D&includeMetadata=true',
|
|
|
- });
|
|
|
- });
|
|
|
});
|
|
|
- });
|
|
|
-});
|
|
|
-
|
|
|
-const mockAnonymizeQueryParams = vi.fn();
|
|
|
-vi.mock('../utils/anonymize-query-params', () => ({
|
|
|
- anonymizeQueryParams: mockAnonymizeQueryParams,
|
|
|
-}));
|
|
|
|
|
|
-describe('pageListingApiModule', () => {
|
|
|
- const mockRequest = {} as IncomingMessage;
|
|
|
-
|
|
|
- beforeEach(() => {
|
|
|
- vi.clearAllMocks();
|
|
|
- });
|
|
|
-
|
|
|
- describe('canHandle', () => {
|
|
|
- it.each`
|
|
|
- description | url | expected
|
|
|
- ${'ancestors-children endpoint'} | ${'/_api/v3/page-listing/ancestors-children?path=/home'} | ${true}
|
|
|
- ${'children endpoint'} | ${'/_api/v3/page-listing/children?path=/docs'} | ${true}
|
|
|
- ${'info endpoint'} | ${'/_api/v3/page-listing/info?path=/wiki'} | ${true}
|
|
|
- ${'ancestors-children without query'} | ${'/_api/v3/page-listing/ancestors-children'} | ${true}
|
|
|
- ${'children without query'} | ${'/_api/v3/page-listing/children'} | ${true}
|
|
|
- ${'info without query'} | ${'/_api/v3/page-listing/info'} | ${true}
|
|
|
- ${'other page-listing endpoint'} | ${'/_api/v3/page-listing/other'} | ${false}
|
|
|
- ${'different API version'} | ${'/_api/v2/page-listing/children'} | ${false}
|
|
|
- ${'non-page-listing API'} | ${'/_api/v3/pages/list'} | ${false}
|
|
|
- ${'regular page path'} | ${'/page/path'} | ${false}
|
|
|
- ${'root path'} | ${'/'} | ${false}
|
|
|
- ${'empty URL'} | ${''} | ${false}
|
|
|
- ${'partial match but different endpoint'} | ${'/_api/v3/page-listing-other/children'} | ${false}
|
|
|
- `('should return $expected for $description: $url', ({ url, expected }) => {
|
|
|
- const result = pageListingApiModule.canHandle(url);
|
|
|
- expect(result).toBe(expected);
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- describe('handle', () => {
|
|
|
- describe('ancestors-children endpoint', () => {
|
|
|
- it('should anonymize path parameter', () => {
|
|
|
- const originalUrl = '/_api/v3/page-listing/ancestors-children?path=/sensitive/path&limit=10';
|
|
|
- const anonymizedUrl = '/_api/v3/page-listing/ancestors-children?path=<ANONYMIZED>&limit=10';
|
|
|
+ describe('children endpoint', () => {
|
|
|
+ it('should anonymize path parameter when present', () => {
|
|
|
+ const originalUrl = '/_api/v3/page-listing/children?path=/docs/api&offset=0&limit=20';
|
|
|
|
|
|
- mockAnonymizeQueryParams.mockReturnValue(anonymizedUrl);
|
|
|
+ // Ensure canHandle returns true for this URL
|
|
|
+ expect(pageListingApiModule.canHandle(originalUrl)).toBe(true);
|
|
|
|
|
|
const result = pageListingApiModule.handle(mockRequest, originalUrl);
|
|
|
|
|
|
- expect(mockAnonymizeQueryParams).toHaveBeenCalledWith(originalUrl, ['path']);
|
|
|
expect(result).toEqual({
|
|
|
- 'http.target': anonymizedUrl,
|
|
|
+ 'http.target': '/_api/v3/page-listing/children?path=%5BANONYMIZED%5D&offset=0&limit=20',
|
|
|
});
|
|
|
});
|
|
|
|
|
|
- it('should return anonymized URL when no path parameter is present', () => {
|
|
|
- const url = '/_api/v3/page-listing/ancestors-children?limit=10';
|
|
|
+ it('should handle encoded path parameter', () => {
|
|
|
+ const originalUrl = '/_api/v3/page-listing/children?path=%2Fencoded%2Fpath&limit=10';
|
|
|
|
|
|
- mockAnonymizeQueryParams.mockReturnValue(url);
|
|
|
-
|
|
|
- const result = pageListingApiModule.handle(mockRequest, url);
|
|
|
-
|
|
|
- expect(mockAnonymizeQueryParams).toHaveBeenCalledWith(url, ['path']);
|
|
|
- expect(result).toEqual({
|
|
|
- 'http.target': url,
|
|
|
- });
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- describe('children endpoint', () => {
|
|
|
- it('should anonymize path parameter', () => {
|
|
|
- const originalUrl = '/_api/v3/page-listing/children?path=/user/documents&offset=0';
|
|
|
- const anonymizedUrl = '/_api/v3/page-listing/children?path=<ANONYMIZED>&offset=0';
|
|
|
-
|
|
|
- mockAnonymizeQueryParams.mockReturnValue(anonymizedUrl);
|
|
|
+ // Ensure canHandle returns true for this URL
|
|
|
+ expect(pageListingApiModule.canHandle(originalUrl)).toBe(true);
|
|
|
|
|
|
const result = pageListingApiModule.handle(mockRequest, originalUrl);
|
|
|
|
|
|
- expect(mockAnonymizeQueryParams).toHaveBeenCalledWith(originalUrl, ['path']);
|
|
|
expect(result).toEqual({
|
|
|
- 'http.target': anonymizedUrl,
|
|
|
+ 'http.target': '/_api/v3/page-listing/children?path=%5BANONYMIZED%5D&limit=10',
|
|
|
});
|
|
|
});
|
|
|
|
|
|
- it('should handle encoded path parameters', () => {
|
|
|
- const originalUrl = '/_api/v3/page-listing/children?path=%2Fuser%2Fdocs&sort=name';
|
|
|
- const anonymizedUrl = '/_api/v3/page-listing/children?path=<ANONYMIZED>&sort=name';
|
|
|
+ it('should return null when no path parameter is present', () => {
|
|
|
+ const originalUrl = '/_api/v3/page-listing/children?limit=10';
|
|
|
|
|
|
- mockAnonymizeQueryParams.mockReturnValue(anonymizedUrl);
|
|
|
+ // Ensure canHandle returns true for this URL
|
|
|
+ expect(pageListingApiModule.canHandle(originalUrl)).toBe(true);
|
|
|
|
|
|
const result = pageListingApiModule.handle(mockRequest, originalUrl);
|
|
|
|
|
|
- expect(mockAnonymizeQueryParams).toHaveBeenCalledWith(originalUrl, ['path']);
|
|
|
- expect(result).toEqual({
|
|
|
- 'http.target': anonymizedUrl,
|
|
|
- });
|
|
|
+ expect(result).toBeNull();
|
|
|
});
|
|
|
});
|
|
|
|
|
|
describe('info endpoint', () => {
|
|
|
- it('should anonymize path parameter', () => {
|
|
|
- const originalUrl = '/_api/v3/page-listing/info?path=/project/wiki';
|
|
|
- const anonymizedUrl = '/_api/v3/page-listing/info?path=<ANONYMIZED>';
|
|
|
+ it('should anonymize path parameter when present', () => {
|
|
|
+ const originalUrl = '/_api/v3/page-listing/info?path=/wiki/documentation';
|
|
|
|
|
|
- mockAnonymizeQueryParams.mockReturnValue(anonymizedUrl);
|
|
|
+ // Ensure canHandle returns true for this URL
|
|
|
+ expect(pageListingApiModule.canHandle(originalUrl)).toBe(true);
|
|
|
|
|
|
const result = pageListingApiModule.handle(mockRequest, originalUrl);
|
|
|
|
|
|
- expect(mockAnonymizeQueryParams).toHaveBeenCalledWith(originalUrl, ['path']);
|
|
|
expect(result).toEqual({
|
|
|
- 'http.target': anonymizedUrl,
|
|
|
+ 'http.target': '/_api/v3/page-listing/info?path=%5BANONYMIZED%5D',
|
|
|
});
|
|
|
});
|
|
|
|
|
|
- it('should handle multiple parameters including path', () => {
|
|
|
- const originalUrl = '/_api/v3/page-listing/info?path=/docs/api&includeEmpty=true&format=json';
|
|
|
- const anonymizedUrl = '/_api/v3/page-listing/info?path=<ANONYMIZED>&includeEmpty=true&format=json';
|
|
|
+ it('should return null when no path parameter is present', () => {
|
|
|
+ const originalUrl = '/_api/v3/page-listing/info';
|
|
|
|
|
|
- mockAnonymizeQueryParams.mockReturnValue(anonymizedUrl);
|
|
|
+ // Ensure canHandle returns true for this URL
|
|
|
+ expect(pageListingApiModule.canHandle(originalUrl)).toBe(true);
|
|
|
|
|
|
const result = pageListingApiModule.handle(mockRequest, originalUrl);
|
|
|
|
|
|
- expect(mockAnonymizeQueryParams).toHaveBeenCalledWith(originalUrl, ['path']);
|
|
|
- expect(result).toEqual({
|
|
|
- 'http.target': anonymizedUrl,
|
|
|
- });
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- describe('non-matching URLs', () => {
|
|
|
- it('should return null for URLs that do not match any endpoint', () => {
|
|
|
- const url = '/_api/v3/pages/list?path=/some/path';
|
|
|
-
|
|
|
- const result = pageListingApiModule.handle(mockRequest, url);
|
|
|
-
|
|
|
- expect(mockAnonymizeQueryParams).not.toHaveBeenCalled();
|
|
|
- expect(result).toBeNull();
|
|
|
- });
|
|
|
-
|
|
|
- it('should return null for URLs without page-listing endpoints', () => {
|
|
|
- const url = '/_api/v3/search?q=test';
|
|
|
-
|
|
|
- const result = pageListingApiModule.handle(mockRequest, url);
|
|
|
-
|
|
|
- expect(mockAnonymizeQueryParams).not.toHaveBeenCalled();
|
|
|
expect(result).toBeNull();
|
|
|
});
|
|
|
});
|
|
|
|
|
|
describe('edge cases', () => {
|
|
|
- it('should handle empty path parameter', () => {
|
|
|
- const originalUrl = '/_api/v3/page-listing/children?path=&limit=5';
|
|
|
- const anonymizedUrl = '/_api/v3/page-listing/children?path=<ANONYMIZED>&limit=5';
|
|
|
+ it('should handle URL with complex query parameters', () => {
|
|
|
+ const originalUrl = '/_api/v3/page-listing/ancestors-children?path=/complex/path&sort=name&direction=asc&filter=active';
|
|
|
|
|
|
- mockAnonymizeQueryParams.mockReturnValue(anonymizedUrl);
|
|
|
+ // Ensure canHandle returns true for this URL
|
|
|
+ expect(pageListingApiModule.canHandle(originalUrl)).toBe(true);
|
|
|
|
|
|
const result = pageListingApiModule.handle(mockRequest, originalUrl);
|
|
|
|
|
|
- expect(mockAnonymizeQueryParams).toHaveBeenCalledWith(originalUrl, ['path']);
|
|
|
expect(result).toEqual({
|
|
|
- 'http.target': anonymizedUrl,
|
|
|
+ 'http.target': '/_api/v3/page-listing/ancestors-children?path=%5BANONYMIZED%5D&sort=name&direction=asc&filter=active',
|
|
|
});
|
|
|
});
|
|
|
|
|
|
- it('should handle root path parameter', () => {
|
|
|
- const originalUrl = '/_api/v3/page-listing/ancestors-children?path=/';
|
|
|
- const anonymizedUrl = '/_api/v3/page-listing/ancestors-children?path=<ANONYMIZED>';
|
|
|
+ it('should handle URL with fragment', () => {
|
|
|
+ const originalUrl = '/_api/v3/page-listing/children?path=/docs#section';
|
|
|
|
|
|
- mockAnonymizeQueryParams.mockReturnValue(anonymizedUrl);
|
|
|
+ // Ensure canHandle returns true for this URL
|
|
|
+ expect(pageListingApiModule.canHandle(originalUrl)).toBe(true);
|
|
|
|
|
|
const result = pageListingApiModule.handle(mockRequest, originalUrl);
|
|
|
|
|
|
- expect(mockAnonymizeQueryParams).toHaveBeenCalledWith(originalUrl, ['path']);
|
|
|
+ // Fragment should be preserved by anonymizeQueryParams
|
|
|
expect(result).toEqual({
|
|
|
- 'http.target': anonymizedUrl,
|
|
|
+ 'http.target': '/_api/v3/page-listing/children?path=%5BANONYMIZED%5D#section',
|
|
|
});
|
|
|
});
|
|
|
});
|