mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-16 16:30:15 +01:00
* fix: add basePath pattern to support login/register and image paths * Fix linter errors * refactor: Update import statements for getBasePath and isEnabled, and add path utility functions with tests - Refactored imports in addImages.js and StableDiffusion.js to use getBasePath from '@librechat/api'. - Consolidated isEnabled and getBasePath imports in validateImageRequest.js. - Introduced new path utility functions in path.ts and corresponding unit tests in path.spec.ts to validate base path extraction logic. * fix: Update domain server base URL in MarkdownComponents and refactor authentication redirection logic - Changed the domain server base URL in MarkdownComponents.tsx to use the API base URL. - Refactored the useAuthRedirect hook to utilize React Router's navigate for redirection instead of window.location, ensuring a smoother SPA experience. - Added unit tests for the useAuthRedirect hook to verify authentication redirection behavior. * test: Mock isEnabled in validateImages.spec.js for improved test isolation - Updated validateImages.spec.js to mock the isEnabled function from @librechat/api, ensuring that tests can run independently of the actual implementation. - Cleared the DOMAIN_CLIENT environment variable before tests to avoid interference with basePath resolution. --------- Co-authored-by: Danny Avila <danny@librechat.ai>
246 lines
10 KiB
JavaScript
246 lines
10 KiB
JavaScript
let addImages = require('./addImages');
|
|
|
|
describe('addImages', () => {
|
|
let intermediateSteps;
|
|
let responseMessage;
|
|
let options;
|
|
|
|
beforeEach(() => {
|
|
intermediateSteps = [];
|
|
responseMessage = { text: '' };
|
|
options = { debug: false };
|
|
this.options = options;
|
|
addImages = addImages.bind(this);
|
|
});
|
|
|
|
it('should handle null or undefined parameters', () => {
|
|
addImages(null, responseMessage);
|
|
expect(responseMessage.text).toBe('');
|
|
|
|
addImages(intermediateSteps, null);
|
|
expect(responseMessage.text).toBe('');
|
|
|
|
addImages(null, null);
|
|
expect(responseMessage.text).toBe('');
|
|
});
|
|
|
|
it('should append correct image markdown if not present in responseMessage', () => {
|
|
intermediateSteps.push({ observation: '' });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe('\n');
|
|
});
|
|
|
|
it('should not append image markdown if already present in responseMessage', () => {
|
|
responseMessage.text = '';
|
|
intermediateSteps.push({ observation: '' });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe('');
|
|
});
|
|
|
|
it('should correct and append image markdown with erroneous URL', () => {
|
|
responseMessage.text = '';
|
|
intermediateSteps.push({ observation: '' });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe('');
|
|
});
|
|
|
|
it('should correct multiple erroneous URLs in responseMessage', () => {
|
|
responseMessage.text =
|
|
' ';
|
|
intermediateSteps.push({ observation: '' });
|
|
intermediateSteps.push({ observation: '' });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe(' ');
|
|
});
|
|
|
|
it('should not append non-image markdown observations', () => {
|
|
intermediateSteps.push({ observation: '[desc](/images/test.png)' });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe('');
|
|
});
|
|
|
|
it('should handle multiple observations', () => {
|
|
intermediateSteps.push({ observation: '' });
|
|
intermediateSteps.push({ observation: '' });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe('\n\n');
|
|
});
|
|
|
|
it('should not append if observation does not contain image markdown', () => {
|
|
intermediateSteps.push({ observation: 'This is a test observation without image markdown.' });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe('');
|
|
});
|
|
|
|
it('should append correctly from a real scenario', () => {
|
|
responseMessage.text =
|
|
"Here is the generated image based on your request. It depicts a surreal landscape filled with floating musical notes. The style is impressionistic, with vibrant sunset hues dominating the scene. At the center, there's a silhouette of a grand piano, adding a dreamy emotion to the overall image. This could serve as a unique and creative music album cover. Would you like to make any changes or generate another image?";
|
|
const originalText = responseMessage.text;
|
|
const imageMarkdown = '';
|
|
intermediateSteps.push({ observation: imageMarkdown });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe(`${originalText}\n${imageMarkdown}`);
|
|
});
|
|
|
|
it('should extract only image markdowns when there is text between them', () => {
|
|
const markdownWithTextBetweenImages = `
|
|

|
|
Some text between images that should not be included.
|
|

|
|
More text that should be ignored.
|
|

|
|
`;
|
|
intermediateSteps.push({ observation: markdownWithTextBetweenImages });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe('\n');
|
|
});
|
|
|
|
it('should only return the first image when multiple images are present', () => {
|
|
const markdownWithMultipleImages = `
|
|

|
|

|
|

|
|
`;
|
|
intermediateSteps.push({ observation: markdownWithMultipleImages });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe('\n');
|
|
});
|
|
|
|
it('should not include any text or metadata surrounding the image markdown', () => {
|
|
const markdownWithMetadata = `
|
|
Title: Test Document
|
|
Author: John Doe
|
|

|
|
Some content after the image.
|
|
Vector values: [0.1, 0.2, 0.3]
|
|
`;
|
|
intermediateSteps.push({ observation: markdownWithMetadata });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe('\n');
|
|
});
|
|
|
|
it('should handle complex markdown with multiple images and only return the first one', () => {
|
|
const complexMarkdown = `
|
|
# Document Title
|
|
|
|
## Section 1
|
|
Here's some text with an embedded image:
|
|

|
|
|
|
## Section 2
|
|
More text here...
|
|

|
|
|
|
### Subsection
|
|
Even more content
|
|

|
|
`;
|
|
intermediateSteps.push({ observation: complexMarkdown });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe('\n');
|
|
});
|
|
|
|
describe('basePath functionality', () => {
|
|
let originalDomainClient;
|
|
|
|
beforeEach(() => {
|
|
originalDomainClient = process.env.DOMAIN_CLIENT;
|
|
});
|
|
|
|
afterEach(() => {
|
|
process.env.DOMAIN_CLIENT = originalDomainClient;
|
|
});
|
|
|
|
it('should prepend base path to image URLs when DOMAIN_CLIENT is set', () => {
|
|
process.env.DOMAIN_CLIENT = 'http://localhost:3080/librechat';
|
|
intermediateSteps.push({ observation: '' });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe('\n');
|
|
});
|
|
|
|
it('should not prepend base path when image URL already has base path', () => {
|
|
process.env.DOMAIN_CLIENT = 'http://localhost:3080/librechat';
|
|
intermediateSteps.push({ observation: '' });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe('\n');
|
|
});
|
|
|
|
it('should correct erroneous URLs with base path', () => {
|
|
process.env.DOMAIN_CLIENT = 'http://localhost:3080/librechat';
|
|
responseMessage.text = '';
|
|
intermediateSteps.push({ observation: '' });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe('');
|
|
});
|
|
|
|
it('should handle empty base path (root deployment)', () => {
|
|
process.env.DOMAIN_CLIENT = 'http://localhost:3080/';
|
|
intermediateSteps.push({ observation: '' });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe('\n');
|
|
});
|
|
|
|
it('should handle missing DOMAIN_CLIENT', () => {
|
|
delete process.env.DOMAIN_CLIENT;
|
|
intermediateSteps.push({ observation: '' });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe('\n');
|
|
});
|
|
|
|
it('should handle observation without image path match', () => {
|
|
process.env.DOMAIN_CLIENT = 'http://localhost:3080/librechat';
|
|
intermediateSteps.push({ observation: '' });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe('\n');
|
|
});
|
|
|
|
it('should handle nested subdirectories in base path', () => {
|
|
process.env.DOMAIN_CLIENT = 'http://localhost:3080/apps/librechat';
|
|
intermediateSteps.push({ observation: '' });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe('\n');
|
|
});
|
|
|
|
it('should handle multiple observations with mixed base path scenarios', () => {
|
|
process.env.DOMAIN_CLIENT = 'http://localhost:3080/librechat';
|
|
intermediateSteps.push({ observation: '' });
|
|
intermediateSteps.push({ observation: '' });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe(
|
|
'\n\n',
|
|
);
|
|
});
|
|
|
|
it('should handle complex markdown with base path', () => {
|
|
process.env.DOMAIN_CLIENT = 'http://localhost:3080/librechat';
|
|
const complexMarkdown = `
|
|
# Document Title
|
|

|
|
Some text between images
|
|

|
|
`;
|
|
intermediateSteps.push({ observation: complexMarkdown });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe('\n');
|
|
});
|
|
|
|
it('should handle URLs that are already absolute', () => {
|
|
process.env.DOMAIN_CLIENT = 'http://localhost:3080/librechat';
|
|
intermediateSteps.push({ observation: '' });
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe('\n');
|
|
});
|
|
|
|
it('should handle data URLs', () => {
|
|
process.env.DOMAIN_CLIENT = 'http://localhost:3080/librechat';
|
|
intermediateSteps.push({
|
|
observation:
|
|
'',
|
|
});
|
|
addImages(intermediateSteps, responseMessage);
|
|
expect(responseMessage.text).toBe(
|
|
'\n',
|
|
);
|
|
});
|
|
});
|
|
});
|