UNPKG

@mintlify/previewing

Version:

Preview Mintlify docs locally

221 lines (220 loc) • 9.58 kB
import fse from 'fs-extra'; import { pipeline } from 'node:stream/promises'; import tar from 'tar'; import { mockProcessExit } from 'vitest-mock-process'; import * as constants from '../constants.js'; import { downloadTargetMint } from '../local-preview/client.js'; import * as utils from '../util.js'; vi.mock('fs-extra', () => { const mocks = { existsSync: vi.fn().mockReturnValue(true), moveSync: vi.fn().mockReturnValue(undefined), ensureDirSync: vi.fn().mockReturnValue(undefined), removeSync: vi.fn().mockReturnValue(undefined), writeFileSync: vi.fn().mockReturnValue(undefined), createWriteStream: vi.fn().mockReturnValue({ write: vi.fn(), end: vi.fn() }), }; return { ...mocks, default: mocks, }; }); vi.mock('../util.js', () => ({ buildLogger: vi.fn().mockReturnValue({ text: '', succeed: vi.fn(), fail: vi.fn(), warn: vi.fn(), start: vi.fn(), stop: vi.fn(), stopAndPersist: vi.fn(), }), restoreMintlifyLast: vi.fn().mockReturnValue(undefined), getTarUrl: vi.fn().mockReturnValue('https://asdfghjkl.cloudfront.net/mint-1.0.1.tar.gz'), })); vi.mock('node:stream/promises', () => ({ pipeline: vi.fn(), })); vi.mock('got', () => { const mocks = { stream: vi.fn().mockReturnValue({ pipe: vi.fn(), on: vi.fn() }), }; return { ...mocks, default: mocks, }; }); vi.mock('tar', () => { const mocks = { x: vi.fn(), }; return { ...mocks, default: mocks, }; }); const buildLoggerMock = vi.mocked(utils.buildLogger); const restoreMintlifyLastMock = vi.mocked(utils.restoreMintlifyLast); const pipelineMock = vi.mocked(pipeline); const getTarUrlMock = vi.mocked(utils.getTarUrl); const writeFileSyncMock = vi.mocked(fse.writeFileSync); const tarMock = vi.mocked(tar); const existsSyncMock = vi.mocked(fse.existsSync); const moveSyncMock = vi.mocked(fse.moveSync); const removeSyncMock = vi.mocked(fse.removeSync); const processExitMock = mockProcessExit(); describe('downloadTargetMint', () => { beforeEach(() => { vi.clearAllMocks(); }); it('downloads and extracts a new version happy path', async () => { const logger = buildLoggerMock(); const targetMintVersion = '1.0.1'; const versionString = '1.0.0'; pipelineMock.mockResolvedValue(undefined); await downloadTargetMint({ logger, targetVersion: targetMintVersion, existingVersion: versionString, }); // Verify backup was created expect(existsSyncMock).toHaveBeenCalledWith(constants.DOT_MINTLIFY); expect(moveSyncMock).toHaveBeenCalledWith(constants.DOT_MINTLIFY, constants.DOT_MINTLIFY_LAST, { overwrite: true, }); expect(fse.ensureDirSync).toHaveBeenCalledWith(constants.DOT_MINTLIFY); // Verify download and extraction expect(getTarUrlMock).toHaveBeenCalledWith(targetMintVersion); expect(pipelineMock).toHaveBeenCalled(); expect(tarMock.x).toHaveBeenCalled(); expect(logger.text).toBe('Extracting Mintlify framework...'); // Verify cleanup expect(removeSyncMock).toHaveBeenCalledWith(constants.TAR_PATH); expect(removeSyncMock).toHaveBeenCalledWith(constants.DOT_MINTLIFY_LAST); expect(writeFileSyncMock).toHaveBeenCalledWith(constants.VERSION_PATH, targetMintVersion); // Verify no restore was needed expect(restoreMintlifyLastMock).not.toHaveBeenCalled(); }); it('downloads and extracts a specific client version happy path', async () => { const logger = buildLoggerMock(); const versionString = '1.0.0'; const clientVersion = '2.0.0'; pipelineMock.mockResolvedValue(undefined); await downloadTargetMint({ logger, targetVersion: clientVersion, existingVersion: versionString, }); // Verify backup was created expect(existsSyncMock).toHaveBeenCalledWith(constants.DOT_MINTLIFY); expect(moveSyncMock).toHaveBeenCalledWith(constants.DOT_MINTLIFY, constants.DOT_MINTLIFY_LAST, { overwrite: true, }); expect(fse.ensureDirSync).toHaveBeenCalledWith(constants.DOT_MINTLIFY); // Verify download and extraction expect(getTarUrlMock).toHaveBeenCalledWith(clientVersion); expect(pipelineMock).toHaveBeenCalled(); expect(tarMock.x).toHaveBeenCalled(); expect(logger.text).toBe('Extracting Mintlify framework...'); // Verify cleanup expect(removeSyncMock).toHaveBeenCalledWith(constants.TAR_PATH); expect(removeSyncMock).toHaveBeenCalledWith(constants.DOT_MINTLIFY_LAST); expect(writeFileSyncMock).toHaveBeenCalledWith(constants.VERSION_PATH, clientVersion); // Verify no restore was needed expect(restoreMintlifyLastMock).not.toHaveBeenCalled(); }); describe('downloadTargetMint with backup version', () => { beforeEach(() => { vi.clearAllMocks(); }); it('fails to download new version', async () => { const logger = buildLoggerMock(); const targetMintVersion = '1.0.1'; const versionString = '1.0.0'; pipelineMock.mockRejectedValue(new Error('connection timed out')); await downloadTargetMint({ logger, targetVersion: targetMintVersion, existingVersion: versionString, }); // Verify backup was created expect(existsSyncMock).toHaveBeenCalledWith(constants.DOT_MINTLIFY); expect(moveSyncMock).toHaveBeenCalledWith(constants.DOT_MINTLIFY, constants.DOT_MINTLIFY_LAST, { overwrite: true, }); expect(fse.ensureDirSync).toHaveBeenCalledWith(constants.DOT_MINTLIFY); // Verify download fail expect(logger.warn).toHaveBeenCalledWith('Failed to download Mintlify framework version 1.0.1, Error: connection timed out, falling back to existing version: 1.0.0'); // Verify use backup version expect(restoreMintlifyLastMock).toHaveBeenCalled(); // Verify no extraction expect(tarMock.x).not.toHaveBeenCalled(); // Verify no cleanup expect(removeSyncMock).not.toHaveBeenCalled(); expect(writeFileSyncMock).not.toHaveBeenCalled(); }); it('fails to extract new version', async () => { const logger = buildLoggerMock(); const targetMintVersion = '1.0.1'; const versionString = '1.0.0'; pipelineMock.mockResolvedValue(undefined); tarMock.x.mockImplementation(() => { throw new Error('Zlib error'); }); await downloadTargetMint({ logger, targetVersion: targetMintVersion, existingVersion: versionString, }); // Verify backup was created expect(existsSyncMock).toHaveBeenCalledWith(constants.DOT_MINTLIFY); expect(moveSyncMock).toHaveBeenCalledWith(constants.DOT_MINTLIFY, constants.DOT_MINTLIFY_LAST, { overwrite: true, }); expect(fse.ensureDirSync).toHaveBeenCalledWith(constants.DOT_MINTLIFY); // Verify download success expect(pipelineMock).toHaveBeenCalled(); // Verify extraction fail expect(logger.warn).toHaveBeenCalledWith('Failed to extract Mintlify framework version 1.0.1, Error: Zlib error, using existing version: 1.0.0'); // Verify use backup version expect(restoreMintlifyLastMock).toHaveBeenCalled(); // Verify no cleanup expect(removeSyncMock).not.toHaveBeenCalled(); expect(writeFileSyncMock).not.toHaveBeenCalled(); }); }); describe('downloadTargetMint without backup version', () => { beforeEach(() => { vi.clearAllMocks(); }); it('fails to download new version with no fallback', async () => { const logger = buildLoggerMock(); const targetMintVersion = '1.0.1'; const versionString = null; pipelineMock.mockRejectedValue(new Error('connection timed out')); await downloadTargetMint({ logger, targetVersion: targetMintVersion, existingVersion: versionString, }); expect(logger.fail).toHaveBeenCalledWith('Failed to download Mintlify framework version 1.0.1, Error: connection timed out'); expect(processExitMock).toHaveBeenCalledWith(1); }); it('fails to extract new version with no fallback', async () => { const logger = buildLoggerMock(); const targetMintVersion = '1.0.1'; const versionString = null; pipelineMock.mockResolvedValue(undefined); tarMock.x.mockImplementation(() => { throw new Error('Zlib error'); }); await downloadTargetMint({ logger, targetVersion: targetMintVersion, existingVersion: versionString, }); expect(logger.fail).toHaveBeenCalledWith('Failed to extract Mintlify framework version 1.0.1, Error: Zlib error'); expect(processExitMock).toHaveBeenCalledWith(1); }); }); });