Skip to content

Commit 73a4620

Browse files
committed
typescript tests + coverage
1 parent f977d0c commit 73a4620

9 files changed

Lines changed: 58 additions & 104 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ dist/
22
docs/
33
examples/
44
node_modules/
5+
coverage/
56
package-lock.json
67
premaster.txt

package.json

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"scripts": {
1717
"docs": "typedoc --entryPoints src/index.ts",
1818
"lint": "eslint src",
19-
"test": "ava",
19+
"test": "c8 ava",
2020
"prebuild": "sed -i'' \"s/VERSION = .*/VERSION = '$npm_package_version'/\" src/amqp-base-client.ts && git add src/amqp-base-client.ts",
2121
"build": "rm -rf dist && tsc && tsc -p tsconfig.cjs.json && rollup -c",
2222
"prepack": "npm run build",
@@ -44,10 +44,23 @@
4444
"@typescript-eslint/eslint-plugin": "^5.7.0",
4545
"@typescript-eslint/parser": "^5.7.0",
4646
"ava": "^3.15.0",
47+
"c8": "^7.10.0",
4748
"eslint": "^7.32.0",
4849
"rollup": "^2.39.1",
4950
"rollup-plugin-cleanup": "^3.2.1",
51+
"ts-node": "^10.4.0",
5052
"typedoc": "^0.22.10",
5153
"typescript": "^4.5.4"
54+
},
55+
"ava": {
56+
"extensions": {
57+
"ts": "module"
58+
},
59+
"nonSemVerExperiments": {
60+
"configurableModuleFormat": true
61+
},
62+
"nodeArguments": [
63+
"--loader=ts-node/esm"
64+
]
5265
}
5366
}

src/amqp-base-client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export default abstract class AMQPBaseClient {
4848
* Open a channel
4949
* @param [id] - An existing or non existing specific channel
5050
*/
51-
channel(id: number): Promise<AMQPChannel> {
51+
channel(id?: number): Promise<AMQPChannel> {
5252
if (this.closed) return this.rejectClosed()
5353
if (id && id > 0 && this.channels[id]) return Promise.resolve(this.channels[id])
5454
// Store channels in an array, set position to null when channel is closed

src/amqp-channel.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ export default class AMQPChannel {
119119
* @param [param.args={}] - custom arguments
120120
* @param {function(AMQPMessage) : void} callback - will be called for each message delivered to this consumer
121121
*/
122-
basicConsume(queue: string, {tag = "", noAck = true, exclusive = false, args = {}} = {}, callback: (msg: AMQPMessage) => void) {
122+
basicConsume(queue: string, {tag = "", noAck = true, exclusive = false, args = {}} = {}, callback: (msg: AMQPMessage) => void): Promise<AMQPConsumer> {
123123
if (this.closed) return this.rejectClosed()
124124
let j = 0
125125
const noWait = false
@@ -156,7 +156,7 @@ export default class AMQPChannel {
156156
* Cancel/stop a consumer
157157
* @param tag - consumer tag
158158
*/
159-
basicCancel(tag: string) {
159+
basicCancel(tag: string): Promise<AMQPChannel> {
160160
if (this.closed) return this.rejectClosed()
161161
const noWait = false
162162
let j = 0
@@ -188,7 +188,7 @@ export default class AMQPChannel {
188188
* @param deliveryTag - tag of the message
189189
* @param [multiple=false] - batch confirm all messages up to this delivery tag
190190
*/
191-
basicAck(deliveryTag: number, multiple = false) {
191+
basicAck(deliveryTag: number, multiple = false): Promise<void> {
192192
if (this.closed) return this.rejectClosed()
193193
let j = 0
194194
const frame = new AMQPView(new ArrayBuffer(21))
@@ -209,7 +209,7 @@ export default class AMQPChannel {
209209
* @param [requeue=false] - if the message should be requeued or removed
210210
* @param [multiple=false] - batch confirm all messages up to this delivery tag
211211
*/
212-
basicNack(deliveryTag: number, requeue = false, multiple = false) {
212+
basicNack(deliveryTag: number, requeue = false, multiple = false): Promise<void> {
213213
if (this.closed) return this.rejectClosed()
214214
let j = 0
215215
const frame = new AMQPView(new ArrayBuffer(21))

src/amqp-consumer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export default class AMQPConsumer {
3030
* @param [timeout] wait for this many milliseconds and then return regardless
3131
* @return Fulfilled when the consumer/channel/connection is closed by the client. Rejected if the timeout is hit.
3232
*/
33-
wait(timeout: number) {
33+
wait(timeout?: number) {
3434
if (this.closedError) return Promise.reject(this.closedError)
3535
if (this.closed) return Promise.resolve()
3636
return new Promise((resolve, reject) => {

src/amqp-queue.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ export default class AMQPQueue {
2424
* @param args - arguments
2525
* @return
2626
*/
27-
bind(exchange: string, routingkey: string, args = {}) {
27+
bind(exchange: string, routingKey = "", args = {}) {
2828
const self = this
2929
return new Promise((resolve, reject) => {
30-
this.channel.queueBind(this.name, exchange, routingkey, args)
30+
this.channel.queueBind(this.name, exchange, routingKey, args)
3131
.then(() => resolve(self))
3232
.catch(reject)
3333
})
@@ -40,10 +40,10 @@ export default class AMQPQueue {
4040
* @param args - arguments
4141
* @return
4242
*/
43-
unbind(exchange: string, routingkey: string, args = {}) {
43+
unbind(exchange: string, routingKey = "", args = {}) {
4444
const self = this
4545
return new Promise((resolve, reject) => {
46-
this.channel.queueUnbind(this.name, exchange, routingkey, args)
46+
this.channel.queueUnbind(this.name, exchange, routingKey, args)
4747
.then(() => resolve(self))
4848
.catch(reject)
4949
})
@@ -55,7 +55,7 @@ export default class AMQPQueue {
5555
* @param properties - publish properties
5656
* @return - fulfilled when the message is enqueue on the socket, or if publish confirm is enabled when the message is confirmed by the server
5757
*/
58-
publish(body: string|Uint8Array|ArrayBuffer, properties: AMQPProperties = {}) {
58+
publish(body: string|Uint8Array|ArrayBuffer, properties: AMQPProperties = {}): Promise<AMQPQueue> {
5959
const self = this
6060
return new Promise((resolve, reject) => {
6161
this.channel.basicPublish("", this.name, body, properties)

test/test.ts

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import test from 'ava';
2-
import { AMQPClient } from '../dist/index.js';
2+
import { AMQPClient, AMQPMessage } from '../src/index.js';
33

44
test('can parse the url correctly', t => {
55
const username = 'user_name'
@@ -26,7 +26,7 @@ test('can open a connection and a channel', t => {
2626

2727
test('can publish and consume', t => {
2828
const amqp = new AMQPClient("amqp://localhost")
29-
return new Promise((resolve, reject) => {
29+
return new Promise<AMQPMessage>((resolve, reject) => {
3030
amqp.connect()
3131
.then(conn => conn.channel())
3232
.then(ch => ch.queue(""))
@@ -36,15 +36,15 @@ test('can publish and consume', t => {
3636
resolve(msg)
3737
}))
3838
.catch(reject)
39-
}).then((result) => t.is(result.bodyString(), "hello world"))
39+
}).then((result: AMQPMessage) => t.is(result.bodyString(), "hello world"))
4040
})
4141

42-
test('will throw an error', t => {
42+
test('will throw an error', async t => {
4343
const amqp = new AMQPClient("amqp://localhost")
44-
return amqp.connect()
45-
.then((conn) => conn.channel())
46-
.then((ch) => ch.queue("amq.foobar"))
47-
.catch((e) => t.regex(e.message, /ACCESS_REFUSED/))
44+
const conn = await amqp.connect()
45+
const ch = await conn.channel()
46+
await t.throwsAsync(async () => { await ch.queue("amq.foobar") },
47+
{ message: /ACCESS_REFUSED/ })
4848
})
4949

5050
test('can cancel a consumer', t => {
@@ -71,19 +71,16 @@ test('connection error raises everywhere', async t => {
7171
const conn = await amqp.connect()
7272
const ch = await conn.channel()
7373
await conn.close()
74-
try {
75-
await ch.close()
76-
} catch (err) {
77-
t.is(err.message, 'Channel is closed');
78-
}
74+
await t.throwsAsync(async () => { await ch.close() },
75+
{ message: /Channel is closed/ })
7976
})
8077

8178
test('consumer stops wait on cancel', async t => {
8279
const amqp = new AMQPClient("amqp://localhost")
8380
const conn = await amqp.connect()
8481
const ch = await conn.channel()
8582
const q = await ch.queue()
86-
const consumer = await q.subscribe({}, () => { })
83+
const consumer = await q.subscribe({}, () => ({}))
8784
await q.publish("foobar")
8885
await consumer.cancel()
8986
const ok = await consumer.wait()
@@ -95,7 +92,7 @@ test('consumer stops wait on channel error', async t => {
9592
const conn = await amqp.connect()
9693
const ch = await conn.channel()
9794
const q = await ch.queue()
98-
const consumer = await q.subscribe({}, () => { })
95+
const consumer = await q.subscribe({}, () => ({}))
9996
// acking invalid delivery tag should close channel
10097
setTimeout(() => ch.basicAck(99999), 1)
10198
await t.throwsAsync(consumer.wait())
@@ -144,7 +141,7 @@ test('can handle rejects', async t => {
144141

145142
const returned = new Promise((resolve) => ch.onReturn = resolve)
146143
await ch.basicPublish("", "not-a-queue", "body", {}, true)
147-
const msg = await returned
144+
const msg = await returned as AMQPMessage
148145
t.is(msg.replyCode, 312)
149146
t.is(msg.routingKey, "not-a-queue")
150147
})
@@ -163,9 +160,9 @@ test('can handle nacks on confirm channel', async t => {
163160
test('throws on invalid exchange type', async t => {
164161
const amqp = new AMQPClient("amqp://localhost")
165162
const conn = await amqp.connect()
166-
let ch = await conn.channel()
163+
const ch = await conn.channel()
167164
const name = "test" + Math.random()
168-
let err = await t.throwsAsync(ch.exchangeDeclare(name, "none"))
165+
const err = await t.throwsAsync(ch.exchangeDeclare(name, "none"))
169166
t.regex(err.message, /invalid exchange type/)
170167
})
171168

@@ -194,14 +191,16 @@ test('exchange to exchange bind/unbind', async t => {
194191
const q = await ch.queue()
195192
await q.bind(name2)
196193
await ch.confirmSelect()
197-
await ch.basicPublish(name1)
194+
await ch.basicPublish(name1, "", "")
198195
const msg1 = await ch.basicGet(q.name)
199-
t.is(msg1.exchange, name1)
196+
t.assert(msg1)
197+
if (msg1)
198+
t.is(msg1.exchange, name1)
200199
await ch.exchangeUnbind(name2, name1)
201-
await ch.basicPublish(name1)
200+
await ch.basicPublish(name1, "", "")
202201
const msg2 = await ch.basicGet(q.name)
203202
t.is(msg2, null)
204-
await ch.exchangeDelete(name1, "fanout")
203+
await ch.exchangeDelete(name1)
205204
})
206205

207206
test.skip('can change flow state of channel', async t => {
@@ -224,7 +223,9 @@ test('basic get', async t => {
224223
t.is(msg, null)
225224
await q.publish("foobar")
226225
msg = await ch.basicGet(q.name)
227-
t.is(msg.bodyToString(), "foobar")
226+
t.assert(msg)
227+
if (msg)
228+
t.is(msg.bodyToString(), "foobar")
228229
})
229230

230231
test('transactions', async t => {
@@ -238,7 +239,9 @@ test('transactions', async t => {
238239
t.is(msg1, null)
239240
await ch.txCommit()
240241
const msg2 = await ch.basicGet(q.name)
241-
t.is(msg2.bodyToString(), "foobar")
242+
t.assert(msg2, "missing message")
243+
if (msg2)
244+
t.is(msg2.bodyToString(), "foobar")
242245

243246
await q.publish("foobar")
244247
await ch.txRollback()

test/tls.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import test from 'ava';
2-
import process from 'process';
3-
import { AMQPClient } from '../dist/index.js';
2+
import { AMQPClient } from '../src/index.js';
43

54
test('can connect with TLS', t => {
65
const amqp = new AMQPClient(process.env["AMQPS_URL"] || "amqps://localhost?insecure=true")

tsconfig.json

Lines changed: 4 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,18 @@
11
{
22
"include": ["./src"],
33
"compilerOptions": {
4-
/* Visit https://aka.ms/tsconfig.json to read more about this file */
5-
6-
/* Projects */
7-
// "incremental": true, /* Enable incremental compilation */
8-
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
9-
// "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
10-
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
11-
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
12-
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
13-
14-
/* Language and Environment */
154
"target": "es2020", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
16-
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
17-
// "jsx": "preserve", /* Specify what JSX code is generated. */
18-
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
19-
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
20-
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
21-
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
22-
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
23-
// "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
24-
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
25-
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
26-
27-
/* Modules */
285
"module": "es2020", /* Specify what module code is generated. */
29-
// "rootDir": "./", /* Specify the root folder within your source files. */
30-
//"moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
31-
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
32-
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
33-
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
34-
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
35-
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
36-
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
37-
// "resolveJsonModule": true, /* Enable importing .json files */
38-
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
39-
40-
/* JavaScript Support */
41-
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
42-
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
43-
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
44-
45-
/* Emit */
6+
"moduleResolution": "node",
467
"declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
478
"declarationMap": true, /* Create sourcemaps for d.ts files. */
48-
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
499
"sourceMap": true, /* Create source map files for emitted JavaScript files. */
50-
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
5110
"outDir": "dist/esm", /* Specify an output folder for all emitted files. */
5211
"removeComments": true, /* Disable emitting comments. */
53-
// "noEmit": true, /* Disable emitting files from a compilation. */
54-
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
55-
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
56-
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
57-
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
58-
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
59-
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
60-
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
61-
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
62-
// "newLine": "crlf", /* Set the newline character for emitting files. */
63-
// "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
64-
// "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
65-
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
66-
// "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
12+
"noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
6713
"declarationDir": "dist/types", /* Specify the output directory for generated declaration files. */
68-
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
69-
70-
/* Interop Constraints */
71-
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
72-
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
7314
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
74-
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
7515
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
76-
77-
/* Type Checking */
7816
"strict": true, /* Enable all strict type-checking options. */
7917
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
8018
"strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
@@ -92,8 +30,8 @@
9230
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
9331
"noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
9432
"noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
95-
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
96-
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
33+
"allowUnusedLabels": false, /* Disable error reporting for unused labels. */
34+
"allowUnreachableCode": false, /* Disable error reporting for unreachable code. */
9735

9836
/* Completeness */
9937
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */

0 commit comments

Comments
 (0)