Skip to main content
Glama
attachments.test.ts6.1 kB
import { describe, it, expect, beforeAll } from 'vitest' import { ShortcutClient } from '../../src/shortcutClient' describe('Attachment functionality', () => { let client: ShortcutClient beforeAll(() => { const apiToken = process.env.SHORTCUT_TOKEN if (!apiToken) { throw new Error('SHORTCUT_TOKEN not found in environment') } client = new ShortcutClient({ apiToken, baseUrl: 'https://api.app.shortcut.com/api/v3', }) }) describe('getStoryFiles', () => { it('should retrieve files from a story', async () => { // Find a story with attachments const results = await client.searchStories('has:attachment') if (results.stories.data.length > 0) { const storyWithFiles = results.stories.data.find(s => s.files && s.files.length > 0) if (storyWithFiles) { const files = await client.getStoryFiles(storyWithFiles.id) expect(files).toBeDefined() expect(Array.isArray(files)).toBe(true) if (files.length > 0) { const file = files[0] expect(file).toHaveProperty('id') expect(file).toHaveProperty('name') expect(file).toHaveProperty('url') expect(file).toHaveProperty('content_type') expect(file).toHaveProperty('size') } } } }) }) describe('downloadFile', () => { it('should download file content', async () => { // Find a story with a small text file const results = await client.searchStories('has:attachment') if (results.stories.data.length > 0) { const storyWithFiles = results.stories.data.find(s => s.files && s.files.some(f => f.content_type?.includes('text') || f.name?.endsWith('.txt') || f.name?.endsWith('.csv') ) ) if (storyWithFiles && storyWithFiles.files) { const textFile = storyWithFiles.files.find(f => f.content_type?.includes('text') || f.name?.endsWith('.txt') || f.name?.endsWith('.csv') ) if (textFile && textFile.url && textFile.size < 1000000) { // Less than 1MB const { content, contentType } = await client.downloadFile(textFile.url) expect(content).toBeDefined() expect(content).toBeInstanceOf(Buffer) expect(content.length).toBeGreaterThan(0) expect(contentType).toBeDefined() } } } }) }) describe('downloadFileAsText', () => { it('should download and decode text files correctly', async () => { // Find a story with a CSV or text file const results = await client.searchStories('has:attachment') if (results.stories.data.length > 0) { const storyWithTextFile = results.stories.data.find(s => s.files && s.files.some(f => f.content_type === 'text/csv' || f.content_type === 'text/plain' || f.name?.endsWith('.csv') || f.name?.endsWith('.txt') ) ) if (storyWithTextFile && storyWithTextFile.files) { const textFile = storyWithTextFile.files.find(f => f.content_type === 'text/csv' || f.content_type === 'text/plain' || f.name?.endsWith('.csv') || f.name?.endsWith('.txt') ) if (textFile && textFile.url && textFile.size < 1000000) { // Less than 1MB const content = await client.downloadFileAsText(textFile.url) expect(content).toBeDefined() expect(typeof content).toBe('string') expect(content.length).toBeGreaterThan(0) // Should not be base64 for text files expect(content).not.toMatch(/^[A-Za-z0-9+/]+=*$/) } } } }) it('should return base64 for binary files', async () => { // Find a story with an image const results = await client.searchStories('has:attachment') if (results.stories.data.length > 0) { const storyWithImage = results.stories.data.find(s => s.files && s.files.some(f => f.content_type?.startsWith('image/')) ) if (storyWithImage && storyWithImage.files) { const imageFile = storyWithImage.files.find(f => f.content_type?.startsWith('image/') ) if (imageFile && imageFile.url && imageFile.size < 100000) { // Less than 100KB const content = await client.downloadFileAsText(imageFile.url) expect(content).toBeDefined() expect(typeof content).toBe('string') // Should be valid base64 expect(() => Buffer.from(content, 'base64')).not.toThrow() } } } }) }) })

Latest Blog Posts

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/currentspace/shortcut_mcp'

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