@jgardner04/ghost-mcp-server 1.1.5 → 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jgardner04/ghost-mcp-server",
3
- "version": "1.1.5",
3
+ "version": "1.1.6",
4
4
  "description": "A Model Context Protocol (MCP) server for interacting with Ghost CMS via the Admin API",
5
5
  "author": "Jonathan Gardner",
6
6
  "type": "module",
@@ -0,0 +1,92 @@
1
+ import { vi } from 'vitest';
2
+
3
+ /**
4
+ * Creates a mock Ghost Admin API instance with configurable behavior.
5
+ *
6
+ * @param {Object} options - Configuration options for the mock
7
+ * @param {Object} options.posts - Mock implementations for posts methods
8
+ * @param {Object} options.tags - Mock implementations for tags methods
9
+ * @param {Object} options.site - Mock implementations for site methods
10
+ * @param {Object} options.images - Mock implementations for images methods
11
+ * @returns {Object} Mock Ghost Admin API instance
12
+ *
13
+ * @example
14
+ * import { createMockGhostApi } from '../helpers/mockGhostApi.js';
15
+ *
16
+ * const api = createMockGhostApi({
17
+ * posts: {
18
+ * add: vi.fn().mockResolvedValue({ id: '1', title: 'Test Post' }),
19
+ * },
20
+ * tags: {
21
+ * browse: vi.fn().mockResolvedValue([{ id: '1', name: 'Test Tag' }]),
22
+ * },
23
+ * });
24
+ */
25
+ export function createMockGhostApi(options = {}) {
26
+ return {
27
+ posts: {
28
+ add: vi.fn(),
29
+ browse: vi.fn(),
30
+ read: vi.fn(),
31
+ edit: vi.fn(),
32
+ delete: vi.fn(),
33
+ ...options.posts,
34
+ },
35
+ tags: {
36
+ add: vi.fn(),
37
+ browse: vi.fn(),
38
+ read: vi.fn(),
39
+ edit: vi.fn(),
40
+ delete: vi.fn(),
41
+ ...options.tags,
42
+ },
43
+ site: {
44
+ read: vi.fn(),
45
+ ...options.site,
46
+ },
47
+ images: {
48
+ upload: vi.fn(),
49
+ ...options.images,
50
+ },
51
+ };
52
+ }
53
+
54
+ /**
55
+ * Creates a mock Ghost Admin API constructor for use with vi.mock().
56
+ *
57
+ * @param {Object} defaultOptions - Default configuration for all instances
58
+ * @returns {Function} Mock constructor function
59
+ *
60
+ * @example
61
+ * import { createMockGhostApiConstructor } from '../helpers/mockGhostApi.js';
62
+ *
63
+ * vi.mock('@tryghost/admin-api', () => ({
64
+ * default: createMockGhostApiConstructor({
65
+ * posts: {
66
+ * add: vi.fn().mockResolvedValue({ id: '1', title: 'Test Post' }),
67
+ * },
68
+ * }),
69
+ * }));
70
+ */
71
+ export function createMockGhostApiConstructor(defaultOptions = {}) {
72
+ return vi.fn(function () {
73
+ return createMockGhostApi(defaultOptions);
74
+ });
75
+ }
76
+
77
+ /**
78
+ * Creates a default mock Ghost Admin API module for vi.mock().
79
+ *
80
+ * @param {Object} options - Configuration options for the mock API
81
+ * @returns {Object} Mock module with default export
82
+ *
83
+ * @example
84
+ * import { mockGhostApiModule } from '../helpers/mockGhostApi.js';
85
+ *
86
+ * vi.mock('@tryghost/admin-api', () => mockGhostApiModule());
87
+ */
88
+ export function mockGhostApiModule(options = {}) {
89
+ return {
90
+ default: createMockGhostApiConstructor(options),
91
+ };
92
+ }
@@ -0,0 +1,41 @@
1
+ import { vi } from 'vitest';
2
+
3
+ /**
4
+ * Creates a mock logger instance with spy functions for testing.
5
+ *
6
+ * @returns {Object} Mock logger with common logging methods
7
+ *
8
+ * @example
9
+ * import { createMockLogger } from '../helpers/mockLogger.js';
10
+ *
11
+ * const logger = createMockLogger();
12
+ * logger.info('test message');
13
+ * expect(logger.info).toHaveBeenCalledWith('test message');
14
+ */
15
+ export function createMockLogger() {
16
+ return {
17
+ apiRequest: vi.fn(),
18
+ apiResponse: vi.fn(),
19
+ apiError: vi.fn(),
20
+ warn: vi.fn(),
21
+ error: vi.fn(),
22
+ info: vi.fn(),
23
+ debug: vi.fn(),
24
+ };
25
+ }
26
+
27
+ /**
28
+ * Creates a mock context logger factory that returns a mock logger.
29
+ *
30
+ * @returns {Function} Mock createContextLogger function
31
+ *
32
+ * @example
33
+ * import { createMockContextLogger } from '../helpers/mockLogger.js';
34
+ *
35
+ * vi.mock('../../utils/logger.js', () => ({
36
+ * createContextLogger: createMockContextLogger(),
37
+ * }));
38
+ */
39
+ export function createMockContextLogger() {
40
+ return vi.fn(() => createMockLogger());
41
+ }
@@ -0,0 +1,105 @@
1
+ import { vi } from 'vitest';
2
+
3
+ /**
4
+ * Creates a mock environment variable configuration.
5
+ *
6
+ * @param {Object} env - Environment variables to set
7
+ * @returns {Object} Mock dotenv module
8
+ *
9
+ * @example
10
+ * import { mockEnv } from '../helpers/testUtils.js';
11
+ *
12
+ * vi.mock('dotenv', () => mockEnv({
13
+ * GHOST_ADMIN_API_URL: 'https://test.ghost.io',
14
+ * GHOST_ADMIN_API_KEY: 'test-key',
15
+ * }));
16
+ */
17
+ export function mockEnv(env = {}) {
18
+ // Set environment variables
19
+ Object.entries(env).forEach(([key, value]) => {
20
+ process.env[key] = value;
21
+ });
22
+
23
+ return {
24
+ default: {
25
+ config: vi.fn(),
26
+ },
27
+ };
28
+ }
29
+
30
+ /**
31
+ * Cleans up environment variables after tests.
32
+ *
33
+ * @param {string[]} keys - Array of environment variable keys to remove
34
+ *
35
+ * @example
36
+ * import { cleanupEnv } from '../helpers/testUtils.js';
37
+ *
38
+ * afterEach(() => {
39
+ * cleanupEnv(['GHOST_ADMIN_API_URL', 'GHOST_ADMIN_API_KEY']);
40
+ * });
41
+ */
42
+ export function cleanupEnv(keys) {
43
+ keys.forEach((key) => {
44
+ delete process.env[key];
45
+ });
46
+ }
47
+
48
+ /**
49
+ * Creates a mock dotenv module for use with vi.mock().
50
+ *
51
+ * @returns {Object} Mock dotenv module
52
+ *
53
+ * @example
54
+ * import { mockDotenv } from '../helpers/testUtils.js';
55
+ *
56
+ * vi.mock('dotenv', () => mockDotenv());
57
+ */
58
+ export function mockDotenv() {
59
+ return {
60
+ default: {
61
+ config: vi.fn(),
62
+ },
63
+ };
64
+ }
65
+
66
+ /**
67
+ * Waits for a condition to be true or times out.
68
+ *
69
+ * @param {Function} condition - Function that returns true when condition is met
70
+ * @param {number} timeout - Maximum time to wait in milliseconds
71
+ * @param {number} interval - Check interval in milliseconds
72
+ * @returns {Promise<boolean>} True if condition met, false if timeout
73
+ *
74
+ * @example
75
+ * import { waitFor } from '../helpers/testUtils.js';
76
+ *
77
+ * await waitFor(() => mockFn.mock.calls.length > 0, 1000, 100);
78
+ */
79
+ export async function waitFor(condition, timeout = 5000, interval = 100) {
80
+ const startTime = Date.now();
81
+
82
+ while (Date.now() - startTime < timeout) {
83
+ if (condition()) {
84
+ return true;
85
+ }
86
+ await new Promise((resolve) => setTimeout(resolve, interval));
87
+ }
88
+
89
+ return false;
90
+ }
91
+
92
+ /**
93
+ * Creates a promise that resolves after a specified delay.
94
+ *
95
+ * @param {number} ms - Milliseconds to delay
96
+ * @returns {Promise<void>}
97
+ *
98
+ * @example
99
+ * import { delay } from '../helpers/testUtils.js';
100
+ *
101
+ * await delay(1000); // Wait 1 second
102
+ */
103
+ export function delay(ms) {
104
+ return new Promise((resolve) => setTimeout(resolve, ms));
105
+ }
@@ -1,46 +1,17 @@
1
1
  import { describe, it, expect, vi } from 'vitest';
2
+ import { mockGhostApiModule } from '../../__tests__/helpers/mockGhostApi.js';
3
+ import { createMockContextLogger } from '../../__tests__/helpers/mockLogger.js';
4
+ import { mockDotenv } from '../../__tests__/helpers/testUtils.js';
2
5
 
3
6
  // Mock the Ghost Admin API
4
- vi.mock('@tryghost/admin-api', () => {
5
- const GhostAdminAPI = vi.fn(function () {
6
- return {
7
- posts: {
8
- add: vi.fn(),
9
- },
10
- tags: {
11
- add: vi.fn(),
12
- browse: vi.fn(),
13
- },
14
- site: {
15
- read: vi.fn(),
16
- },
17
- images: {
18
- upload: vi.fn(),
19
- },
20
- };
21
- });
22
-
23
- return {
24
- default: GhostAdminAPI,
25
- };
26
- });
7
+ vi.mock('@tryghost/admin-api', () => mockGhostApiModule());
27
8
 
28
9
  // Mock dotenv
29
- vi.mock('dotenv', () => ({
30
- default: {
31
- config: vi.fn(),
32
- },
33
- }));
10
+ vi.mock('dotenv', () => mockDotenv());
34
11
 
35
12
  // Mock logger
36
13
  vi.mock('../../utils/logger.js', () => ({
37
- createContextLogger: vi.fn(() => ({
38
- apiRequest: vi.fn(),
39
- apiResponse: vi.fn(),
40
- apiError: vi.fn(),
41
- warn: vi.fn(),
42
- error: vi.fn(),
43
- })),
14
+ createContextLogger: createMockContextLogger(),
44
15
  }));
45
16
 
46
17
  // Import after setting up mocks and environment