@amqp-contract/testing 0.7.0 โ†’ 0.8.0

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/README.md CHANGED
@@ -102,7 +102,8 @@ The extension provides:
102
102
 
103
103
  ## Container Details
104
104
 
105
- - **Image**: `rabbitmq:3-management-alpine`
105
+ - **Image**: `rabbitmq:4.2.1-management-alpine` (default)
106
+ - Can be configured via `RABBITMQ_IMAGE` environment variable
106
107
  - **Ports**:
107
108
  - 5672 (AMQP)
108
109
  - 15672 (Management console)
@@ -112,6 +113,14 @@ The extension provides:
112
113
 
113
114
  ## Environment Variables
114
115
 
116
+ ### Configuration
117
+
118
+ - `RABBITMQ_IMAGE` - Docker image to use for the RabbitMQ container
119
+ - Default: `rabbitmq:4.2.1-management-alpine`
120
+ - Can be set to any compatible RabbitMQ image with management plugin
121
+
122
+ ### Test Context
123
+
115
124
  The following variables are provided to tests:
116
125
 
117
126
  - `__TESTCONTAINERS_RABBITMQ_IP__` - Container host IP
@@ -1 +1 @@
1
- {"version":3,"file":"extension.mjs","names":["vitestIt","consumerTags: string[]","messages: amqpLib.ConsumeMessage[]"],"sources":["../src/extension.ts"],"sourcesContent":["/**\n * Vitest extension module for AMQP testing utilities\n *\n * This module provides a Vitest test extension that adds AMQP-specific fixtures\n * to your tests. Each test gets an isolated virtual host (vhost) with pre-configured\n * connections, channels, and helper functions for publishing and consuming messages.\n *\n * @module extension\n * @packageDocumentation\n */\n\nimport amqpLib, { type Channel, type ChannelModel } from \"amqplib\";\nimport { inject, vi, it as vitestIt } from \"vitest\";\nimport { randomUUID } from \"node:crypto\";\n\nexport const it = vitestIt.extend<{\n vhost: string;\n amqpConnectionUrl: string;\n amqpConnection: ChannelModel;\n amqpChannel: Channel;\n publishMessage: (exchange: string, routingKey: string, content: unknown) => void;\n initConsumer: (\n exchange: string,\n routingKey: string,\n ) => Promise<\n (options?: { nbEvents?: number; timeout?: number }) => Promise<amqpLib.ConsumeMessage[]>\n >;\n}>({\n /**\n * Test fixture that provides an isolated RabbitMQ virtual host (vhost) for the test.\n *\n * Creates a new vhost with a random UUID name for test isolation. The vhost is automatically\n * created before the test runs using the RabbitMQ Management API.\n *\n * @example\n * ```typescript\n * it('should use isolated vhost', async ({ vhost }) => {\n * console.log(`Test running in vhost: ${vhost}`);\n * });\n * ```\n */\n // oxlint-disable-next-line no-empty-pattern\n vhost: async ({}, use) => {\n const vhost = await createVhost();\n try {\n await use(vhost);\n } finally {\n await deleteVhost(vhost);\n }\n },\n /**\n * Test fixture that provides the AMQP connection URL for the test container.\n *\n * Constructs a connection URL using the test container's IP and port, along with\n * the isolated vhost. The URL follows the format: `amqp://guest:guest@host:port/vhost`.\n *\n * @example\n * ```typescript\n * it('should connect with URL', async ({ amqpConnectionUrl }) => {\n * console.log(`Connecting to: ${amqpConnectionUrl}`);\n * });\n * ```\n */\n amqpConnectionUrl: async ({ vhost }, use) => {\n const url = `amqp://guest:guest@${inject(\"__TESTCONTAINERS_RABBITMQ_IP__\")}:${inject(\"__TESTCONTAINERS_RABBITMQ_PORT_5672__\")}/${vhost}`;\n await use(url);\n },\n /**\n * Test fixture that provides an active AMQP connection to RabbitMQ.\n *\n * Establishes a connection using the provided connection URL and automatically closes\n * it after the test completes. This fixture is useful for tests that need direct\n * access to the connection object (e.g., to create multiple channels).\n *\n * @example\n * ```typescript\n * it('should use connection', async ({ amqpConnection }) => {\n * const channel = await amqpConnection.createChannel();\n * // ... use channel\n * });\n * ```\n */\n amqpConnection: async ({ amqpConnectionUrl }, use) => {\n const connection = await amqpLib.connect(amqpConnectionUrl);\n await use(connection);\n await connection.close();\n },\n /**\n * Test fixture that provides an AMQP channel for interacting with RabbitMQ.\n *\n * Creates a channel from the active connection and automatically closes it after\n * the test completes. The channel is used for declaring exchanges, queues, bindings,\n * and publishing/consuming messages.\n *\n * @example\n * ```typescript\n * it('should use channel', async ({ amqpChannel }) => {\n * await amqpChannel.assertExchange('test-exchange', 'topic');\n * await amqpChannel.assertQueue('test-queue');\n * });\n * ```\n */\n amqpChannel: async ({ amqpConnection }, use) => {\n const channel = await amqpConnection.createChannel();\n await use(channel);\n await channel.close();\n },\n /**\n * Test fixture for publishing messages to an AMQP exchange.\n *\n * Provides a helper function to publish messages directly to an exchange during tests.\n * The message content is automatically serialized to JSON and converted to a Buffer.\n *\n * @param exchange - The name of the exchange to publish to\n * @param routingKey - The routing key for message routing\n * @param content - The message payload (will be JSON serialized)\n * @throws Error if the message cannot be published (e.g., write buffer is full)\n *\n * @example\n * ```typescript\n * it('should publish message', async ({ publishMessage }) => {\n * publishMessage('my-exchange', 'routing.key', { data: 'test' });\n * });\n * ```\n */\n publishMessage: async ({ amqpChannel }, use) => {\n function publishMessage(exchange: string, routingKey: string, content: unknown): void {\n const success = amqpChannel.publish(\n exchange,\n routingKey,\n Buffer.from(JSON.stringify(content)),\n );\n if (!success) {\n throw new Error(\n `Failed to publish message to exchange \"${exchange}\" with routing key \"${routingKey}\"`,\n );\n }\n }\n await use(publishMessage);\n },\n /**\n * Test fixture for initializing a message consumer on an AMQP queue.\n *\n * Creates a temporary queue, binds it to the specified exchange with the given routing key,\n * and returns a function to collect messages from that queue. The queue is automatically\n * created with a random UUID name to avoid conflicts between tests.\n *\n * The returned function uses `vi.waitFor()` with a configurable timeout to wait for messages.\n * If the expected number of messages is not received within the timeout period, the Promise\n * will reject with a timeout error, preventing tests from hanging indefinitely.\n *\n * @param exchange - The name of the exchange to bind the queue to\n * @param routingKey - The routing key pattern for message filtering\n * @returns A function that accepts optional configuration ({ nbEvents?, timeout? }) and returns a Promise that resolves to an array of ConsumeMessage objects\n *\n * @example\n * ```typescript\n * it('should consume messages', async ({ initConsumer, publishMessage }) => {\n * const waitForMessages = await initConsumer('my-exchange', 'routing.key');\n * publishMessage('my-exchange', 'routing.key', { data: 'test' });\n * // With defaults (1 message, 5000ms timeout)\n * const messages = await waitForMessages();\n * expect(messages).toHaveLength(1);\n *\n * // With custom options\n * publishMessage('my-exchange', 'routing.key', { data: 'test2' });\n * publishMessage('my-exchange', 'routing.key', { data: 'test3' });\n * const messages2 = await waitForMessages({ nbEvents: 2, timeout: 10000 });\n * expect(messages2).toHaveLength(2);\n * });\n * ```\n */\n initConsumer: async ({ amqpChannel }, use) => {\n const consumerTags: string[] = [];\n\n async function initConsumer(\n exchange: string,\n routingKey: string,\n ): Promise<\n (options?: { nbEvents?: number; timeout?: number }) => Promise<amqpLib.ConsumeMessage[]>\n > {\n const queue = randomUUID();\n\n await amqpChannel.assertQueue(queue);\n await amqpChannel.bindQueue(queue, exchange, routingKey);\n\n const messages: amqpLib.ConsumeMessage[] = [];\n const consumer = await amqpChannel.consume(\n queue,\n (msg) => {\n if (msg) {\n messages.push(msg);\n }\n },\n { noAck: true },\n );\n\n consumerTags.push(consumer.consumerTag);\n\n return async (options = {}) => {\n const { nbEvents = 1, timeout = 5000 } = options;\n await vi.waitFor(\n () => {\n if (messages.length < nbEvents) {\n throw new Error(\n `Expected ${nbEvents} message(s) but only received ${messages.length}`,\n );\n }\n },\n { timeout },\n );\n return messages.splice(0, nbEvents);\n };\n }\n\n try {\n await use(initConsumer);\n } finally {\n // Cancel all consumers before fixture cleanup (which deletes the vhost)\n await Promise.all(\n consumerTags.map(async (consumerTag) => {\n try {\n await amqpChannel.cancel(consumerTag);\n } catch (error) {\n // Swallow cancellation errors during cleanup\n // eslint-disable-next-line no-console\n console.error(\"Failed to cancel AMQP consumer during fixture cleanup:\", error);\n }\n }),\n );\n }\n },\n});\n\nasync function createVhost() {\n const namespace = randomUUID();\n\n const username = inject(\"__TESTCONTAINERS_RABBITMQ_USERNAME__\");\n const password = inject(\"__TESTCONTAINERS_RABBITMQ_PASSWORD__\");\n\n const vhostResponse = await fetch(\n `http://${inject(\"__TESTCONTAINERS_RABBITMQ_IP__\")}:${inject(\"__TESTCONTAINERS_RABBITMQ_PORT_15672__\")}/api/vhosts/${encodeURIComponent(namespace)}`,\n {\n method: \"PUT\",\n headers: {\n Authorization: `Basic ${btoa(`${username}:${password}`)}`,\n },\n },\n );\n\n if (vhostResponse.status !== 201) {\n const responseBody = await vhostResponse.text().catch(() => \"\");\n const errorMessage = responseBody\n ? `Failed to create vhost '${namespace}': ${vhostResponse.status} - ${responseBody}`\n : `Failed to create vhost '${namespace}': ${vhostResponse.status}`;\n throw new Error(errorMessage, {\n cause: vhostResponse,\n });\n }\n\n return namespace;\n}\n\nasync function deleteVhost(vhost: string) {\n const username = inject(\"__TESTCONTAINERS_RABBITMQ_USERNAME__\");\n const password = inject(\"__TESTCONTAINERS_RABBITMQ_PASSWORD__\");\n\n const vhostResponse = await fetch(\n `http://${inject(\"__TESTCONTAINERS_RABBITMQ_IP__\")}:${inject(\"__TESTCONTAINERS_RABBITMQ_PORT_15672__\")}/api/vhosts/${encodeURIComponent(vhost)}`,\n {\n method: \"DELETE\",\n headers: {\n Authorization: `Basic ${btoa(`${username}:${password}`)}`,\n },\n },\n );\n\n // 204 = successfully deleted, 404 = already deleted or doesn't exist\n if (vhostResponse.status !== 204 && vhostResponse.status !== 404) {\n const responseBody = await vhostResponse.text().catch(() => \"\");\n const errorMessage = responseBody\n ? `Failed to delete vhost '${vhost}': ${vhostResponse.status} - ${responseBody}`\n : `Failed to delete vhost '${vhost}': ${vhostResponse.status}`;\n throw new Error(errorMessage, {\n cause: vhostResponse,\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"extension.mjs","names":["vitestIt"],"sources":["../src/extension.ts"],"sourcesContent":["/**\n * Vitest extension module for AMQP testing utilities\n *\n * This module provides a Vitest test extension that adds AMQP-specific fixtures\n * to your tests. Each test gets an isolated virtual host (vhost) with pre-configured\n * connections, channels, and helper functions for publishing and consuming messages.\n *\n * @module extension\n * @packageDocumentation\n */\n\nimport amqpLib, { type Channel, type ChannelModel } from \"amqplib\";\nimport { inject, vi, it as vitestIt } from \"vitest\";\nimport { randomUUID } from \"node:crypto\";\n\nexport const it = vitestIt.extend<{\n vhost: string;\n amqpConnectionUrl: string;\n amqpConnection: ChannelModel;\n amqpChannel: Channel;\n publishMessage: (exchange: string, routingKey: string, content: unknown) => void;\n initConsumer: (\n exchange: string,\n routingKey: string,\n ) => Promise<\n (options?: { nbEvents?: number; timeout?: number }) => Promise<amqpLib.ConsumeMessage[]>\n >;\n}>({\n /**\n * Test fixture that provides an isolated RabbitMQ virtual host (vhost) for the test.\n *\n * Creates a new vhost with a random UUID name for test isolation. The vhost is automatically\n * created before the test runs using the RabbitMQ Management API.\n *\n * @example\n * ```typescript\n * it('should use isolated vhost', async ({ vhost }) => {\n * console.log(`Test running in vhost: ${vhost}`);\n * });\n * ```\n */\n // oxlint-disable-next-line no-empty-pattern\n vhost: async ({}, use) => {\n const vhost = await createVhost();\n try {\n await use(vhost);\n } finally {\n await deleteVhost(vhost);\n }\n },\n /**\n * Test fixture that provides the AMQP connection URL for the test container.\n *\n * Constructs a connection URL using the test container's IP and port, along with\n * the isolated vhost. The URL follows the format: `amqp://guest:guest@host:port/vhost`.\n *\n * @example\n * ```typescript\n * it('should connect with URL', async ({ amqpConnectionUrl }) => {\n * console.log(`Connecting to: ${amqpConnectionUrl}`);\n * });\n * ```\n */\n amqpConnectionUrl: async ({ vhost }, use) => {\n const url = `amqp://guest:guest@${inject(\"__TESTCONTAINERS_RABBITMQ_IP__\")}:${inject(\"__TESTCONTAINERS_RABBITMQ_PORT_5672__\")}/${vhost}`;\n await use(url);\n },\n /**\n * Test fixture that provides an active AMQP connection to RabbitMQ.\n *\n * Establishes a connection using the provided connection URL and automatically closes\n * it after the test completes. This fixture is useful for tests that need direct\n * access to the connection object (e.g., to create multiple channels).\n *\n * @example\n * ```typescript\n * it('should use connection', async ({ amqpConnection }) => {\n * const channel = await amqpConnection.createChannel();\n * // ... use channel\n * });\n * ```\n */\n amqpConnection: async ({ amqpConnectionUrl }, use) => {\n const connection = await amqpLib.connect(amqpConnectionUrl);\n await use(connection);\n await connection.close();\n },\n /**\n * Test fixture that provides an AMQP channel for interacting with RabbitMQ.\n *\n * Creates a channel from the active connection and automatically closes it after\n * the test completes. The channel is used for declaring exchanges, queues, bindings,\n * and publishing/consuming messages.\n *\n * @example\n * ```typescript\n * it('should use channel', async ({ amqpChannel }) => {\n * await amqpChannel.assertExchange('test-exchange', 'topic');\n * await amqpChannel.assertQueue('test-queue');\n * });\n * ```\n */\n amqpChannel: async ({ amqpConnection }, use) => {\n const channel = await amqpConnection.createChannel();\n await use(channel);\n await channel.close();\n },\n /**\n * Test fixture for publishing messages to an AMQP exchange.\n *\n * Provides a helper function to publish messages directly to an exchange during tests.\n * The message content is automatically serialized to JSON and converted to a Buffer.\n *\n * @param exchange - The name of the exchange to publish to\n * @param routingKey - The routing key for message routing\n * @param content - The message payload (will be JSON serialized)\n * @throws Error if the message cannot be published (e.g., write buffer is full)\n *\n * @example\n * ```typescript\n * it('should publish message', async ({ publishMessage }) => {\n * publishMessage('my-exchange', 'routing.key', { data: 'test' });\n * });\n * ```\n */\n publishMessage: async ({ amqpChannel }, use) => {\n function publishMessage(exchange: string, routingKey: string, content: unknown): void {\n const success = amqpChannel.publish(\n exchange,\n routingKey,\n Buffer.from(JSON.stringify(content)),\n );\n if (!success) {\n throw new Error(\n `Failed to publish message to exchange \"${exchange}\" with routing key \"${routingKey}\"`,\n );\n }\n }\n await use(publishMessage);\n },\n /**\n * Test fixture for initializing a message consumer on an AMQP queue.\n *\n * Creates a temporary queue, binds it to the specified exchange with the given routing key,\n * and returns a function to collect messages from that queue. The queue is automatically\n * created with a random UUID name to avoid conflicts between tests.\n *\n * The returned function uses `vi.waitFor()` with a configurable timeout to wait for messages.\n * If the expected number of messages is not received within the timeout period, the Promise\n * will reject with a timeout error, preventing tests from hanging indefinitely.\n *\n * @param exchange - The name of the exchange to bind the queue to\n * @param routingKey - The routing key pattern for message filtering\n * @returns A function that accepts optional configuration ({ nbEvents?, timeout? }) and returns a Promise that resolves to an array of ConsumeMessage objects\n *\n * @example\n * ```typescript\n * it('should consume messages', async ({ initConsumer, publishMessage }) => {\n * const waitForMessages = await initConsumer('my-exchange', 'routing.key');\n * publishMessage('my-exchange', 'routing.key', { data: 'test' });\n * // With defaults (1 message, 5000ms timeout)\n * const messages = await waitForMessages();\n * expect(messages).toHaveLength(1);\n *\n * // With custom options\n * publishMessage('my-exchange', 'routing.key', { data: 'test2' });\n * publishMessage('my-exchange', 'routing.key', { data: 'test3' });\n * const messages2 = await waitForMessages({ nbEvents: 2, timeout: 10000 });\n * expect(messages2).toHaveLength(2);\n * });\n * ```\n */\n initConsumer: async ({ amqpChannel }, use) => {\n const consumerTags: string[] = [];\n\n async function initConsumer(\n exchange: string,\n routingKey: string,\n ): Promise<\n (options?: { nbEvents?: number; timeout?: number }) => Promise<amqpLib.ConsumeMessage[]>\n > {\n const queue = randomUUID();\n\n await amqpChannel.assertQueue(queue);\n await amqpChannel.bindQueue(queue, exchange, routingKey);\n\n const messages: amqpLib.ConsumeMessage[] = [];\n const consumer = await amqpChannel.consume(\n queue,\n (msg) => {\n if (msg) {\n messages.push(msg);\n }\n },\n { noAck: true },\n );\n\n consumerTags.push(consumer.consumerTag);\n\n return async (options = {}) => {\n const { nbEvents = 1, timeout = 5000 } = options;\n await vi.waitFor(\n () => {\n if (messages.length < nbEvents) {\n throw new Error(\n `Expected ${nbEvents} message(s) but only received ${messages.length}`,\n );\n }\n },\n { timeout },\n );\n return messages.splice(0, nbEvents);\n };\n }\n\n try {\n await use(initConsumer);\n } finally {\n // Cancel all consumers before fixture cleanup (which deletes the vhost)\n await Promise.all(\n consumerTags.map(async (consumerTag) => {\n try {\n await amqpChannel.cancel(consumerTag);\n } catch (error) {\n // Swallow cancellation errors during cleanup\n // eslint-disable-next-line no-console\n console.error(\"Failed to cancel AMQP consumer during fixture cleanup:\", error);\n }\n }),\n );\n }\n },\n});\n\nasync function createVhost() {\n const namespace = randomUUID();\n\n const username = inject(\"__TESTCONTAINERS_RABBITMQ_USERNAME__\");\n const password = inject(\"__TESTCONTAINERS_RABBITMQ_PASSWORD__\");\n\n const vhostResponse = await fetch(\n `http://${inject(\"__TESTCONTAINERS_RABBITMQ_IP__\")}:${inject(\"__TESTCONTAINERS_RABBITMQ_PORT_15672__\")}/api/vhosts/${encodeURIComponent(namespace)}`,\n {\n method: \"PUT\",\n headers: {\n Authorization: `Basic ${btoa(`${username}:${password}`)}`,\n },\n },\n );\n\n if (vhostResponse.status !== 201) {\n const responseBody = await vhostResponse.text().catch(() => \"\");\n const errorMessage = responseBody\n ? `Failed to create vhost '${namespace}': ${vhostResponse.status} - ${responseBody}`\n : `Failed to create vhost '${namespace}': ${vhostResponse.status}`;\n throw new Error(errorMessage, {\n cause: vhostResponse,\n });\n }\n\n return namespace;\n}\n\nasync function deleteVhost(vhost: string) {\n const username = inject(\"__TESTCONTAINERS_RABBITMQ_USERNAME__\");\n const password = inject(\"__TESTCONTAINERS_RABBITMQ_PASSWORD__\");\n\n const vhostResponse = await fetch(\n `http://${inject(\"__TESTCONTAINERS_RABBITMQ_IP__\")}:${inject(\"__TESTCONTAINERS_RABBITMQ_PORT_15672__\")}/api/vhosts/${encodeURIComponent(vhost)}`,\n {\n method: \"DELETE\",\n headers: {\n Authorization: `Basic ${btoa(`${username}:${password}`)}`,\n },\n },\n );\n\n // 204 = successfully deleted, 404 = already deleted or doesn't exist\n if (vhostResponse.status !== 204 && vhostResponse.status !== 404) {\n const responseBody = await vhostResponse.text().catch(() => \"\");\n const errorMessage = responseBody\n ? `Failed to delete vhost '${vhost}': ${vhostResponse.status} - ${responseBody}`\n : `Failed to delete vhost '${vhost}': ${vhostResponse.status}`;\n throw new Error(errorMessage, {\n cause: vhostResponse,\n });\n }\n}\n"],"mappings":"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"}
@@ -36,7 +36,7 @@ declare module "vitest" {
36
36
  */
37
37
  declare function setup({
38
38
  provide
39
- }: TestProject): Promise<() => Promise<void>>;
39
+ }: TestProject): Promise<void>;
40
40
  //#endregion
41
41
  export { setup as default };
42
42
  //# sourceMappingURL=global-setup.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"global-setup.d.mts","names":[],"sources":["../src/global-setup.ts"],"sourcesContent":[],"mappings":";;;;eAgD4D,QAAA,CAAA;EAAA,UAAA,eAAA,CAAA;IAAA,8BAAA,EAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA9B,KAAA;;GAAmB,cAAW,cAAA"}
1
+ {"version":3,"file":"global-setup.d.mts","names":[],"sources":["../src/global-setup.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyD8B,KAAA;;GAAmB,cAAW"}
@@ -8,10 +8,18 @@ import { GenericContainer, Wait } from "testcontainers";
8
8
  * a RabbitMQ container with the management plugin before tests run, and stops
9
9
  * it after all tests complete.
10
10
  *
11
+ * The RabbitMQ image can be configured via the `RABBITMQ_IMAGE` environment variable.
12
+ * By default, it uses the public Docker Hub image (`rabbitmq:4.2.1-management-alpine`).
13
+ *
11
14
  * @module global-setup
12
15
  * @packageDocumentation
13
16
  */
14
17
  /**
18
+ * Default RabbitMQ Docker image to use for testing.
19
+ * Can be overridden via RABBITMQ_IMAGE environment variable.
20
+ */
21
+ const DEFAULT_RABBITMQ_IMAGE = "rabbitmq:4.2.1-management-alpine";
22
+ /**
15
23
  * Setup function for Vitest globalSetup
16
24
  *
17
25
  * Starts a RabbitMQ container before all tests and provides connection details
@@ -35,8 +43,10 @@ import { GenericContainer, Wait } from "testcontainers";
35
43
  * @returns Cleanup function that stops the RabbitMQ container
36
44
  */
37
45
  async function setup({ provide }) {
46
+ const rabbitmqImage = process.env["RABBITMQ_IMAGE"] ?? DEFAULT_RABBITMQ_IMAGE;
38
47
  console.log("๐Ÿณ Starting RabbitMQ test environment...");
39
- const rabbitmqContainer = await new GenericContainer("rabbitmq:4.2.1-management-alpine").withExposedPorts(5672, 15672).withEnvironment({
48
+ console.log(`๐Ÿ“ฆ Using RabbitMQ image: ${rabbitmqImage}`);
49
+ const rabbitmqContainer = await new GenericContainer(rabbitmqImage).withExposedPorts(5672, 15672).withEnvironment({
40
50
  RABBITMQ_DEFAULT_USER: "guest",
41
51
  RABBITMQ_DEFAULT_PASS: "guest"
42
52
  }).withHealthCheck({
@@ -50,7 +60,7 @@ async function setup({ provide }) {
50
60
  retries: 30,
51
61
  startPeriod: 3e3,
52
62
  timeout: 5e3
53
- }).withWaitStrategy(Wait.forHealthCheck()).start();
63
+ }).withWaitStrategy(Wait.forHealthCheck()).withReuse().withAutoRemove(true).start();
54
64
  console.log("โœ… RabbitMQ container started");
55
65
  const __TESTCONTAINERS_RABBITMQ_IP__ = rabbitmqContainer.getHost();
56
66
  const __TESTCONTAINERS_RABBITMQ_PORT_5672__ = rabbitmqContainer.getMappedPort(5672);
@@ -64,11 +74,6 @@ async function setup({ provide }) {
64
74
  provide("__TESTCONTAINERS_RABBITMQ_PASSWORD__", __TESTCONTAINERS_RABBITMQ_PASSWORD__);
65
75
  console.log(`๐Ÿš€ RabbitMQ test environment is ready at ${__TESTCONTAINERS_RABBITMQ_IP__}:${__TESTCONTAINERS_RABBITMQ_PORT_5672__}`);
66
76
  console.log(`๐Ÿ“Š RabbitMQ management console available at http://${__TESTCONTAINERS_RABBITMQ_IP__}:${__TESTCONTAINERS_RABBITMQ_PORT_15672__}`);
67
- return async () => {
68
- console.log("๐Ÿงน Stopping RabbitMQ test environment...");
69
- await rabbitmqContainer.stop();
70
- console.log("โœ… RabbitMQ test environment stopped");
71
- };
72
77
  }
73
78
 
74
79
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"global-setup.mjs","names":[],"sources":["../src/global-setup.ts"],"sourcesContent":["/**\n * Global setup module for starting RabbitMQ test containers\n *\n * This module provides a Vitest globalSetup function that automatically starts\n * a RabbitMQ container with the management plugin before tests run, and stops\n * it after all tests complete.\n *\n * @module global-setup\n * @packageDocumentation\n */\n\nimport { GenericContainer, Wait } from \"testcontainers\";\nimport type { TestProject } from \"vitest/node\";\n\ndeclare module \"vitest\" {\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions -- Module augmentation requires interface for declaration merging\n export interface ProvidedContext {\n __TESTCONTAINERS_RABBITMQ_IP__: string;\n __TESTCONTAINERS_RABBITMQ_PORT_5672__: number;\n __TESTCONTAINERS_RABBITMQ_PORT_15672__: number;\n __TESTCONTAINERS_RABBITMQ_USERNAME__: string;\n __TESTCONTAINERS_RABBITMQ_PASSWORD__: string;\n }\n}\n\n/**\n * Setup function for Vitest globalSetup\n *\n * Starts a RabbitMQ container before all tests and provides connection details\n * to tests via Vitest's provide API. The container is automatically stopped\n * and cleaned up after all tests complete.\n *\n * This function should be configured in your `vitest.config.ts`:\n *\n * @example\n * ```typescript\n * import { defineConfig } from \"vitest/config\";\n *\n * export default defineConfig({\n * test: {\n * globalSetup: [\"@amqp-contract/testing/global-setup\"],\n * },\n * });\n * ```\n *\n * @param provide - Function to provide context values to tests\n * @returns Cleanup function that stops the RabbitMQ container\n */\nexport default async function setup({ provide }: TestProject) {\n console.log(\"๐Ÿณ Starting RabbitMQ test environment...\");\n\n // Start RabbitMQ container with management plugin\n const rabbitmqContainer = await new GenericContainer(\"rabbitmq:4.2.1-management-alpine\")\n .withExposedPorts(5672, 15672)\n .withEnvironment({\n RABBITMQ_DEFAULT_USER: \"guest\",\n RABBITMQ_DEFAULT_PASS: \"guest\",\n })\n .withHealthCheck({\n test: [\"CMD\", \"rabbitmq-diagnostics\", \"-q\", \"check_running\"],\n interval: 1_000,\n retries: 30,\n startPeriod: 3_000,\n timeout: 5_000,\n })\n .withWaitStrategy(Wait.forHealthCheck())\n .start();\n\n console.log(\"โœ… RabbitMQ container started\");\n\n const __TESTCONTAINERS_RABBITMQ_IP__ = rabbitmqContainer.getHost();\n const __TESTCONTAINERS_RABBITMQ_PORT_5672__ = rabbitmqContainer.getMappedPort(5672);\n const __TESTCONTAINERS_RABBITMQ_PORT_15672__ = rabbitmqContainer.getMappedPort(15672);\n const __TESTCONTAINERS_RABBITMQ_USERNAME__ = \"guest\";\n const __TESTCONTAINERS_RABBITMQ_PASSWORD__ = \"guest\";\n\n // Provide context values with type assertions to work around TypeScript limitations\n provide(\"__TESTCONTAINERS_RABBITMQ_IP__\", __TESTCONTAINERS_RABBITMQ_IP__);\n provide(\"__TESTCONTAINERS_RABBITMQ_PORT_5672__\", __TESTCONTAINERS_RABBITMQ_PORT_5672__);\n provide(\"__TESTCONTAINERS_RABBITMQ_PORT_15672__\", __TESTCONTAINERS_RABBITMQ_PORT_15672__);\n provide(\"__TESTCONTAINERS_RABBITMQ_USERNAME__\", __TESTCONTAINERS_RABBITMQ_USERNAME__);\n provide(\"__TESTCONTAINERS_RABBITMQ_PASSWORD__\", __TESTCONTAINERS_RABBITMQ_PASSWORD__);\n\n console.log(\n `๐Ÿš€ RabbitMQ test environment is ready at ${__TESTCONTAINERS_RABBITMQ_IP__}:${__TESTCONTAINERS_RABBITMQ_PORT_5672__}`,\n );\n console.log(\n `๐Ÿ“Š RabbitMQ management console available at http://${__TESTCONTAINERS_RABBITMQ_IP__}:${__TESTCONTAINERS_RABBITMQ_PORT_15672__}`,\n );\n\n // Return cleanup function\n return async () => {\n console.log(\"๐Ÿงน Stopping RabbitMQ test environment...\");\n await rabbitmqContainer.stop();\n console.log(\"โœ… RabbitMQ test environment stopped\");\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDA,eAA8B,MAAM,EAAE,WAAwB;AAC5D,SAAQ,IAAI,2CAA2C;CAGvD,MAAM,oBAAoB,MAAM,IAAI,iBAAiB,mCAAmC,CACrF,iBAAiB,MAAM,MAAM,CAC7B,gBAAgB;EACf,uBAAuB;EACvB,uBAAuB;EACxB,CAAC,CACD,gBAAgB;EACf,MAAM;GAAC;GAAO;GAAwB;GAAM;GAAgB;EAC5D,UAAU;EACV,SAAS;EACT,aAAa;EACb,SAAS;EACV,CAAC,CACD,iBAAiB,KAAK,gBAAgB,CAAC,CACvC,OAAO;AAEV,SAAQ,IAAI,+BAA+B;CAE3C,MAAM,iCAAiC,kBAAkB,SAAS;CAClE,MAAM,wCAAwC,kBAAkB,cAAc,KAAK;CACnF,MAAM,yCAAyC,kBAAkB,cAAc,MAAM;CACrF,MAAM,uCAAuC;CAC7C,MAAM,uCAAuC;AAG7C,SAAQ,kCAAkC,+BAA+B;AACzE,SAAQ,yCAAyC,sCAAsC;AACvF,SAAQ,0CAA0C,uCAAuC;AACzF,SAAQ,wCAAwC,qCAAqC;AACrF,SAAQ,wCAAwC,qCAAqC;AAErF,SAAQ,IACN,4CAA4C,+BAA+B,GAAG,wCAC/E;AACD,SAAQ,IACN,sDAAsD,+BAA+B,GAAG,yCACzF;AAGD,QAAO,YAAY;AACjB,UAAQ,IAAI,2CAA2C;AACvD,QAAM,kBAAkB,MAAM;AAC9B,UAAQ,IAAI,sCAAsC"}
1
+ {"version":3,"file":"global-setup.mjs","names":[],"sources":["../src/global-setup.ts"],"sourcesContent":["/**\n * Global setup module for starting RabbitMQ test containers\n *\n * This module provides a Vitest globalSetup function that automatically starts\n * a RabbitMQ container with the management plugin before tests run, and stops\n * it after all tests complete.\n *\n * The RabbitMQ image can be configured via the `RABBITMQ_IMAGE` environment variable.\n * By default, it uses the public Docker Hub image (`rabbitmq:4.2.1-management-alpine`).\n *\n * @module global-setup\n * @packageDocumentation\n */\n\nimport { GenericContainer, Wait } from \"testcontainers\";\nimport type { TestProject } from \"vitest/node\";\n\n/**\n * Default RabbitMQ Docker image to use for testing.\n * Can be overridden via RABBITMQ_IMAGE environment variable.\n */\nconst DEFAULT_RABBITMQ_IMAGE = \"rabbitmq:4.2.1-management-alpine\";\n\ndeclare module \"vitest\" {\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions -- Module augmentation requires interface for declaration merging\n export interface ProvidedContext {\n __TESTCONTAINERS_RABBITMQ_IP__: string;\n __TESTCONTAINERS_RABBITMQ_PORT_5672__: number;\n __TESTCONTAINERS_RABBITMQ_PORT_15672__: number;\n __TESTCONTAINERS_RABBITMQ_USERNAME__: string;\n __TESTCONTAINERS_RABBITMQ_PASSWORD__: string;\n }\n}\n\n/**\n * Setup function for Vitest globalSetup\n *\n * Starts a RabbitMQ container before all tests and provides connection details\n * to tests via Vitest's provide API. The container is automatically stopped\n * and cleaned up after all tests complete.\n *\n * This function should be configured in your `vitest.config.ts`:\n *\n * @example\n * ```typescript\n * import { defineConfig } from \"vitest/config\";\n *\n * export default defineConfig({\n * test: {\n * globalSetup: [\"@amqp-contract/testing/global-setup\"],\n * },\n * });\n * ```\n *\n * @param provide - Function to provide context values to tests\n * @returns Cleanup function that stops the RabbitMQ container\n */\nexport default async function setup({ provide }: TestProject) {\n const rabbitmqImage = process.env[\"RABBITMQ_IMAGE\"] ?? DEFAULT_RABBITMQ_IMAGE;\n\n console.log(\"๐Ÿณ Starting RabbitMQ test environment...\");\n console.log(`๐Ÿ“ฆ Using RabbitMQ image: ${rabbitmqImage}`);\n\n // Start RabbitMQ container with management plugin\n const rabbitmqContainer = await new GenericContainer(rabbitmqImage)\n .withExposedPorts(5672, 15672)\n .withEnvironment({\n RABBITMQ_DEFAULT_USER: \"guest\",\n RABBITMQ_DEFAULT_PASS: \"guest\",\n })\n .withHealthCheck({\n test: [\"CMD\", \"rabbitmq-diagnostics\", \"-q\", \"check_running\"],\n interval: 1_000,\n retries: 30,\n startPeriod: 3_000,\n timeout: 5_000,\n })\n .withWaitStrategy(Wait.forHealthCheck())\n .withReuse()\n .withAutoRemove(true)\n .start();\n\n console.log(\"โœ… RabbitMQ container started\");\n\n const __TESTCONTAINERS_RABBITMQ_IP__ = rabbitmqContainer.getHost();\n const __TESTCONTAINERS_RABBITMQ_PORT_5672__ = rabbitmqContainer.getMappedPort(5672);\n const __TESTCONTAINERS_RABBITMQ_PORT_15672__ = rabbitmqContainer.getMappedPort(15672);\n const __TESTCONTAINERS_RABBITMQ_USERNAME__ = \"guest\";\n const __TESTCONTAINERS_RABBITMQ_PASSWORD__ = \"guest\";\n\n // Provide context values with type assertions to work around TypeScript limitations\n provide(\"__TESTCONTAINERS_RABBITMQ_IP__\", __TESTCONTAINERS_RABBITMQ_IP__);\n provide(\"__TESTCONTAINERS_RABBITMQ_PORT_5672__\", __TESTCONTAINERS_RABBITMQ_PORT_5672__);\n provide(\"__TESTCONTAINERS_RABBITMQ_PORT_15672__\", __TESTCONTAINERS_RABBITMQ_PORT_15672__);\n provide(\"__TESTCONTAINERS_RABBITMQ_USERNAME__\", __TESTCONTAINERS_RABBITMQ_USERNAME__);\n provide(\"__TESTCONTAINERS_RABBITMQ_PASSWORD__\", __TESTCONTAINERS_RABBITMQ_PASSWORD__);\n\n console.log(\n `๐Ÿš€ RabbitMQ test environment is ready at ${__TESTCONTAINERS_RABBITMQ_IP__}:${__TESTCONTAINERS_RABBITMQ_PORT_5672__}`,\n );\n console.log(\n `๐Ÿ“Š RabbitMQ management console available at http://${__TESTCONTAINERS_RABBITMQ_IP__}:${__TESTCONTAINERS_RABBITMQ_PORT_15672__}`,\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAqBA,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;AAoC/B,eAA8B,MAAM,EAAE,WAAwB;CAC5D,MAAM,gBAAgB,QAAQ,IAAI,qBAAqB;AAEvD,SAAQ,IAAI,2CAA2C;AACvD,SAAQ,IAAI,4BAA4B,gBAAgB;CAGxD,MAAM,oBAAoB,MAAM,IAAI,iBAAiB,cAAc,CAChE,iBAAiB,MAAM,MAAM,CAC7B,gBAAgB;EACf,uBAAuB;EACvB,uBAAuB;EACxB,CAAC,CACD,gBAAgB;EACf,MAAM;GAAC;GAAO;GAAwB;GAAM;GAAgB;EAC5D,UAAU;EACV,SAAS;EACT,aAAa;EACb,SAAS;EACV,CAAC,CACD,iBAAiB,KAAK,gBAAgB,CAAC,CACvC,WAAW,CACX,eAAe,KAAK,CACpB,OAAO;AAEV,SAAQ,IAAI,+BAA+B;CAE3C,MAAM,iCAAiC,kBAAkB,SAAS;CAClE,MAAM,wCAAwC,kBAAkB,cAAc,KAAK;CACnF,MAAM,yCAAyC,kBAAkB,cAAc,MAAM;CACrF,MAAM,uCAAuC;CAC7C,MAAM,uCAAuC;AAG7C,SAAQ,kCAAkC,+BAA+B;AACzE,SAAQ,yCAAyC,sCAAsC;AACvF,SAAQ,0CAA0C,uCAAuC;AACzF,SAAQ,wCAAwC,qCAAqC;AACrF,SAAQ,wCAAwC,qCAAqC;AAErF,SAAQ,IACN,4CAA4C,+BAA+B,GAAG,wCAC/E;AACD,SAAQ,IACN,sDAAsD,+BAA+B,GAAG,yCACzF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amqp-contract/testing",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Testing utilities for AMQP contracts with testcontainers",
5
5
  "keywords": [
6
6
  "amqp",
@@ -34,13 +34,13 @@
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/amqplib": "0.10.8",
37
- "tsdown": "0.18.4",
37
+ "tsdown": "0.19.0",
38
38
  "typedoc": "0.28.15",
39
39
  "typedoc-plugin-markdown": "4.9.0",
40
40
  "typescript": "5.9.3",
41
41
  "vitest": "4.0.16",
42
- "@amqp-contract/tsconfig": "0.0.0",
43
- "@amqp-contract/typedoc": "0.0.1"
42
+ "@amqp-contract/tsconfig": "0.1.0",
43
+ "@amqp-contract/typedoc": "0.1.0"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "vitest": "^4"