Skip to main content
Glama

Prisma MCP Server

Official
by prisma
Apache 2.0
4
44,192
  • Linux
  • Apple
nps.test.ts13.2 kB
import fs from 'fs' import readline from 'readline' import { PassThrough } from 'stream' import { CommandState } from '../utils/commandState' import { createSafeReadlineProxy, handleNpsSurveyImpl } from '../utils/nps/survey' const currentDate = new Date('2022-01-01T00:00:00.000Z') const laterDate = new Date('2023-01-01T00:00:00.000Z') const earlierDate = new Date('2021-01-01T00:00:00.000Z') const evenEarlierDate = new Date('2020-01-01T00:00:00.000Z') const longTimeUserCommandState: CommandState = { firstCommandTimestamp: '2019-01-01T00:00:00.000Z' } describe('nps survey', () => { const originalEnv = { ...process.env } const restoreEnv = () => { for (const key of Object.keys(process.env)) { if (!(key in originalEnv)) { delete process.env[key] } } for (const [key, value] of Object.entries(originalEnv)) { if (value === undefined) { delete process.env[key] } else { process.env[key] = value } } } let mockRead: jest.SpyInstance let mockWrite: jest.SpyInstance let mockExists: jest.SpyInstance beforeEach(() => { restoreEnv() for (const key of Object.keys(process.env)) { delete process.env[key] } }) afterEach(() => { mockRead?.mockRestore() mockWrite?.mockRestore() mockExists?.mockRestore() }) afterAll(() => { restoreEnv() }) it('should exit immediately if running in CI', async () => { mockRead = jest.spyOn(fs.promises, 'readFile').mockImplementation() mockWrite = jest.spyOn(fs.promises, 'writeFile').mockImplementation() const status = jest.fn() const readline = { question: jest.fn(), write: jest.fn(), } const capture = jest.fn() process.env.CI = 'true' await handleNpsSurveyImpl(currentDate, { status }, readline, { capture }, longTimeUserCommandState) expect(mockRead).toHaveBeenCalledTimes(0) expect(mockWrite).toHaveBeenCalledTimes(0) expect(status).toHaveBeenCalledTimes(0) expect(readline.question).toHaveBeenCalledTimes(0) expect(capture).toHaveBeenCalledTimes(0) }) it('should exit immediately if running in a Podman container', async () => { mockExists = jest.spyOn(fs, 'existsSync').mockImplementation((path) => { return path === '/run/.containerenv' }) mockRead = jest.spyOn(fs.promises, 'readFile').mockImplementation() mockWrite = jest.spyOn(fs.promises, 'writeFile').mockImplementation() const status = jest.fn() const readline = { question: jest.fn(), write: jest.fn(), } const capture = jest.fn() await handleNpsSurveyImpl(currentDate, { status }, readline, { capture }, longTimeUserCommandState) expect(mockRead).toHaveBeenCalledTimes(0) expect(mockWrite).toHaveBeenCalledTimes(0) expect(status).toHaveBeenCalledTimes(0) expect(readline.question).toHaveBeenCalledTimes(0) expect(capture).toHaveBeenCalledTimes(0) }) it('should exit immediately if running in a Docker container', async () => { mockExists = jest.spyOn(fs, 'existsSync').mockImplementation((path) => { return path === '/.dockerenv' }) mockRead = jest.spyOn(fs.promises, 'readFile').mockImplementation() mockWrite = jest.spyOn(fs.promises, 'writeFile').mockImplementation() const status = jest.fn() const readline = { question: jest.fn(), write: jest.fn(), } const capture = jest.fn() await handleNpsSurveyImpl(currentDate, { status }, readline, { capture }, longTimeUserCommandState) expect(mockRead).toHaveBeenCalledTimes(0) expect(mockWrite).toHaveBeenCalledTimes(0) expect(status).toHaveBeenCalledTimes(0) expect(readline.question).toHaveBeenCalledTimes(0) expect(capture).toHaveBeenCalledTimes(0) }) it('should exit immediately if running in a Kubernetes pod', async () => { mockRead = jest.spyOn(fs.promises, 'readFile').mockImplementation() mockWrite = jest.spyOn(fs.promises, 'writeFile').mockImplementation() const status = jest.fn() const readline = { question: jest.fn(), write: jest.fn(), } const capture = jest.fn() process.env.KUBERNETES_SERVICE_HOST = '10.96.0.1' await handleNpsSurveyImpl(currentDate, { status }, readline, { capture }, longTimeUserCommandState) expect(mockRead).toHaveBeenCalledTimes(0) expect(mockWrite).toHaveBeenCalledTimes(0) expect(status).toHaveBeenCalledTimes(0) expect(readline.question).toHaveBeenCalledTimes(0) expect(capture).toHaveBeenCalledTimes(0) }) it('should exit immediately if running in a pre-commit git hook', async () => { mockRead = jest.spyOn(fs.promises, 'readFile').mockImplementation() mockWrite = jest.spyOn(fs.promises, 'writeFile').mockImplementation() const status = jest.fn() const readline = { question: jest.fn(), write: jest.fn(), } const capture = jest.fn() process.env.GIT_EXEC_PATH = '/nix/store/9z3jhc0rlj3zaw8nd1zka9vli6w0q11g-git-2.47.2/libexec/git-core' await handleNpsSurveyImpl(currentDate, { status }, readline, { capture }, longTimeUserCommandState) expect(mockRead).toHaveBeenCalledTimes(0) expect(mockWrite).toHaveBeenCalledTimes(0) expect(status).toHaveBeenCalledTimes(0) expect(readline.question).toHaveBeenCalledTimes(0) expect(capture).toHaveBeenCalledTimes(0) }) it('should exit immediately if running in a post-install npm hook or similar', async () => { mockRead = jest.spyOn(fs.promises, 'readFile').mockImplementation() mockWrite = jest.spyOn(fs.promises, 'writeFile').mockImplementation() const status = jest.fn() const readline = { question: jest.fn(), write: jest.fn(), } const capture = jest.fn() process.env.npm_command = 'install' process.env.npm_lifecycle_event = 'prepare' await handleNpsSurveyImpl(currentDate, { status }, readline, { capture }, longTimeUserCommandState) expect(mockRead).toHaveBeenCalledTimes(0) expect(mockWrite).toHaveBeenCalledTimes(0) expect(status).toHaveBeenCalledTimes(0) expect(readline.question).toHaveBeenCalledTimes(0) expect(capture).toHaveBeenCalledTimes(0) }) it('should read the config and exit when the current survey has been acknowledged', async () => { mockRead = jest .spyOn(fs.promises, 'readFile') .mockResolvedValue( JSON.stringify({ acknowledgedTimeframe: { start: earlierDate.toISOString(), end: laterDate.toISOString() } }), ) mockWrite = jest.spyOn(fs.promises, 'writeFile').mockImplementation() const status = jest.fn() const readline = { question: jest.fn(), write: jest.fn(), } const capture = jest.fn() await handleNpsSurveyImpl(currentDate, { status }, readline, { capture }, longTimeUserCommandState) expect(mockRead).toHaveBeenCalledTimes(1) expect(mockWrite).toHaveBeenCalledTimes(0) expect(status).toHaveBeenCalledTimes(0) expect(readline.question).toHaveBeenCalledTimes(0) expect(capture).toHaveBeenCalledTimes(0) }) it('should check the status if there is no config and exit if there is no survey', async () => { mockRead = jest.spyOn(fs.promises, 'readFile').mockRejectedValue({ code: 'ENOENT' }) mockWrite = jest.spyOn(fs.promises, 'writeFile').mockImplementation() const status = jest .fn() .mockResolvedValue({ currentTimeframe: { start: evenEarlierDate.toISOString(), end: earlierDate.toISOString() } }) const readline = { question: jest.fn(), write: jest.fn(), } const capture = jest.fn() await handleNpsSurveyImpl(currentDate, { status }, readline, { capture }, longTimeUserCommandState) expect(mockRead).toHaveBeenCalledTimes(1) expect(mockWrite).toHaveBeenCalledTimes(0) expect(status).toHaveBeenCalledTimes(1) expect(readline.question).toHaveBeenCalledTimes(0) expect(capture).toHaveBeenCalledTimes(0) }) it('should check the status if the acknowledged survey has expired', async () => { mockRead = jest.spyOn(fs.promises, 'readFile').mockResolvedValue( JSON.stringify({ acknowledgedTimeframe: { start: evenEarlierDate.toISOString(), end: earlierDate.toISOString() }, }), ) mockWrite = jest.spyOn(fs.promises, 'writeFile').mockImplementation() const status = jest.fn().mockResolvedValue({}) const readline = { question: jest.fn(), write: jest.fn(), } const capture = jest.fn() await handleNpsSurveyImpl(currentDate, { status }, readline, { capture }, longTimeUserCommandState) expect(mockRead).toHaveBeenCalledTimes(1) expect(mockWrite).toHaveBeenCalledTimes(0) expect(status).toHaveBeenCalledTimes(1) expect(readline.question).toHaveBeenCalledTimes(0) expect(capture).toHaveBeenCalledTimes(0) }) it('should exit if the status is undefined', async () => { mockRead = jest.spyOn(fs.promises, 'readFile').mockRejectedValue({ code: 'ENOENT' }) mockWrite = jest.spyOn(fs.promises, 'writeFile').mockImplementation() const status = jest.fn().mockResolvedValue({}) const readline = { question: jest.fn(), write: jest.fn(), } const capture = jest.fn().mockReturnValue(Promise.resolve()) await handleNpsSurveyImpl(currentDate, { status }, readline, { capture }, longTimeUserCommandState) expect(mockRead).toHaveBeenCalledTimes(1) expect(mockWrite).toHaveBeenCalledTimes(0) expect(status).toHaveBeenCalledTimes(1) expect(readline.question).toHaveBeenCalledTimes(0) expect(capture).toHaveBeenCalledTimes(0) }) it('should exit if this command is within 24 hours of the first command issued', async () => { const status = jest.fn().mockResolvedValue({}) const readline = { question: jest.fn(), write: jest.fn(), } const capture = jest.fn().mockReturnValue(Promise.resolve()) const commandState = { firstCommandTimestamp: new Date( Date.now() - ((Math.random() * Number.MAX_SAFE_INTEGER) % (23 * 60 * 60 * 1000)), ).toISOString(), } await handleNpsSurveyImpl(currentDate, { status }, readline, { capture }, commandState) expect(status).toHaveBeenCalledTimes(0) expect(readline.question).toHaveBeenCalledTimes(0) expect(capture).toHaveBeenCalledTimes(0) }) it('should prompt the user if the survey is active and update the config', async () => { mockRead = jest.spyOn(fs.promises, 'readFile').mockRejectedValue({ code: 'ENOENT' }) mockWrite = jest.spyOn(fs.promises, 'writeFile').mockImplementation() const currentTimeframe = { start: earlierDate.toISOString(), end: laterDate.toISOString() } const status = jest.fn().mockResolvedValue({ currentTimeframe }) const readline = { question: jest.fn().mockResolvedValueOnce('5').mockResolvedValueOnce('Great!'), write: jest.fn(), } const capture = jest.fn().mockReturnValue(Promise.resolve()) await handleNpsSurveyImpl(currentDate, { status }, readline, { capture }, longTimeUserCommandState) expect(mockRead).toHaveBeenCalled() expect(mockWrite).toHaveBeenLastCalledWith( expect.anything(), JSON.stringify({ acknowledgedTimeframe: currentTimeframe }), ) expect(status).toHaveBeenCalledTimes(1) expect(readline.question).toHaveBeenCalledTimes(2) expect(readline.write).toHaveBeenCalledWith('Thanks for your feedback!\n') expect(capture).toHaveBeenCalledWith(expect.anything(), 'NPS feedback', { rating: 5, feedback: 'Great!' }) }) it('should allow the user to skip the survey and still update the config', async () => { mockRead = jest.spyOn(fs.promises, 'readFile').mockRejectedValue({ code: 'ENOENT' }) mockWrite = jest.spyOn(fs.promises, 'writeFile').mockImplementation() const currentTimeframe = { start: earlierDate.toISOString(), end: laterDate.toISOString() } const status = jest.fn().mockResolvedValue({ currentTimeframe }) const readline = { question: jest.fn().mockResolvedValueOnce('no'), write: jest.fn(), } const capture = jest.fn().mockReturnValue(Promise.resolve()) await handleNpsSurveyImpl(currentDate, { status }, readline, { capture }, longTimeUserCommandState) expect(mockRead).toHaveBeenCalledTimes(1) expect(mockWrite).toHaveBeenCalledWith( expect.anything(), JSON.stringify({ acknowledgedTimeframe: currentTimeframe }), ) expect(status).toHaveBeenCalledTimes(1) expect(readline.question).toHaveBeenCalledTimes(1) expect(readline.write).toHaveBeenCalledWith('Not received a valid rating. Exiting the survey.\n') expect(capture).toHaveBeenCalledTimes(0) }) }) describe('createSafeReadlineProxy', () => { it('should handle an input stream that closes', async () => { const input = new PassThrough() const output = new PassThrough() const rl = readline.promises.createInterface({ input, output, }) const proxy = createSafeReadlineProxy(rl) process.nextTick(() => proxy.write('answer\n')) await expect(proxy.question('question')).resolves.toBe('answer') rl.close() expect(() => proxy.question('question')).toThrow('This operation was aborted') }) })

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/prisma/prisma'

If you have feedback or need assistance with the MCP directory API, please join our Discord server