newsie
Version:
An NNTP Client Library targeting NodeJS. It supports the authentication, TLS encryption, base NNTP commands, and more.
421 lines (392 loc) • 13.2 kB
text/typescript
import { c, client, integrationSetup, s, server } from './IntegrationCommon'
integrationSetup()
describe('2.2. Advertising the STREAMING Extension', () => {
test(
'Example of a client using CAPABILITIES and MODE STREAM on a mode-\n' + ' switching server:',
async () => {
c('CAPABILITIES')
s('101 Capability list:')
s('VERSION 2')
s('MODE-READER')
s('IHAVE')
s('LIST ACTIVE')
s('STREAMING')
s('.')
let response = await client.capabilities()
expect(response).toEqual({
code: 101,
comment: 'Capability list:',
description: 'Capability list follows (multi-line)',
capabilities: {
VERSION: ['2'],
'MODE-READER': [],
IHAVE: [],
LIST: ['ACTIVE'],
STREAMING: []
}
})
c('MODE STREAM')
s('203 Streaming permitted')
response = await client.modeStream()
expect(response).toEqual({
code: 203,
comment: 'Streaming permitted',
description: 'Streaming permitted'
})
c('CAPABILITIES')
s('101 Capability list:')
s('VERSION 2')
s('MODE-READER')
s('IHAVE')
s('LIST ACTIVE')
s('STREAMING')
s('.')
response = await client.capabilities()
expect(response).toEqual({
code: 101,
comment: 'Capability list:',
description: 'Capability list follows (multi-line)',
capabilities: {
VERSION: ['2'],
'MODE-READER': [],
IHAVE: [],
LIST: ['ACTIVE'],
STREAMING: []
}
})
c('MODE READER')
s('200 Posting allowed')
response = await client.modeReader()
expect(response).toEqual({
code: 200,
comment: 'Posting allowed',
description: 'Posting allowed'
})
c('CAPABILITIES')
s('101 Capability list:')
s('VERSION 2')
s('READER')
s('POST')
s('LIST ACTIVE NEWSGROUPS HEADERS')
s('HDR')
s('.')
response = await client.capabilities()
expect(response).toEqual({
code: 101,
comment: 'Capability list:',
description: 'Capability list follows (multi-line)',
capabilities: {
VERSION: ['2'],
READER: [],
POST: [],
LIST: ['ACTIVE', 'NEWSGROUPS', 'HEADERS'],
HDR: []
}
})
}
)
})
describe('2.3. MODE STREAM Command', () => {
test(
'Example of a client checking the ability to stream articles on a\n' +
' server which does not support this extension:',
async () => {
c('MODE STREAM')
s('501 Unknown MODE variant')
let caught = false
return client
.modeStream()
.catch(response => {
caught = true
expect(response).toEqual({
code: 501,
comment: 'Unknown MODE variant',
description: 'syntax error in command'
})
})
.then(() => expect(caught).toBe(true))
}
)
test(
'Example of a client checking the ability to stream articles on a' +
' server which supports this extension:',
async () => {
c('MODE STREAM')
s('203 Streaming permitted')
const response = await client.modeStream()
expect(response).toEqual({
code: 203,
comment: 'Streaming permitted',
description: 'Streaming permitted'
})
}
)
})
describe('2.4. CHECK Command', () => {
test(
'Example of a client checking whether the server would like a set of' +
'articles and getting a mixture of responses:',
async () => {
c('CHECK <i.am.an.article.you.will.want@example.com>')
s('238 <i.am.an.article.you.will.want@example.com>')
const response = await client.check('<i.am.an.article.you.will.want@example.com>')
expect(response).toEqual({
code: 238,
comment: '',
description: 'Send article to be transferred',
article: {
messageId: '<i.am.an.article.you.will.want@example.com>'
}
})
c('CHECK <i.am.an.article.you.have@example.com>')
s('438 <i.am.an.article.you.have@example.com>')
let caught = false
try {
await client.check('<i.am.an.article.you.have@example.com>')
} catch (response) {
caught = true
expect(response).toEqual({
code: 438,
comment: '',
description: 'Article not wanted',
article: {
messageId: '<i.am.an.article.you.have@example.com>'
}
})
}
expect(caught).toBe(true)
c('CHECK <i.am.an.article.you.defer@example.com>')
s('431 <i.am.an.article.you.defer@example.com>')
caught = false
try {
await client.check('<i.am.an.article.you.defer@example.com>')
} catch (response) {
caught = true
expect(response).toEqual({
code: 431,
comment: '',
description: 'Transfer not possible; try again later',
article: {
messageId: '<i.am.an.article.you.defer@example.com>'
}
})
}
expect(caught).toBe(true)
}
)
test('Example of pipelining the CHECK commands in the previous example:', async () => {
c('CHECK <i.am.an.article.you.will.want@example.com>')
c('CHECK <i.am.an.article.you.have@example.com>')
c('CHECK <i.am.an.article.you.defer@example.com>')
s('238 <i.am.an.article.you.will.want@example.com>')
s('438 <i.am.an.article.you.have@example.com>')
s('431 <i.am.an.article.you.defer@example.com>')
// Setup pipelined response (awkward with MockServer)
server.resetHandlers()
server.addSimpleHandler((command, args) => {
expect(command).toEqual('CHECK')
const line = args.join(' ')
expect(line).toBe(
'<i.am.an.article.you.will.want@example.com>\r\nCHECK <i.am.an.article.you.have@example.com>\r\nCHECK <i.am.an.article.you.defer@example.com>'
)
return (
'238 <i.am.an.article.you.will.want@example.com>\r\n' +
'438 <i.am.an.article.you.have@example.com>\r\n' +
'431 <i.am.an.article.you.defer@example.com>\r\n'
)
})
const responses = await Promise.all([
client.check('<i.am.an.article.you.will.want@example.com>').catch(r => r),
client.check('<i.am.an.article.you.have@example.com>').catch(r => r),
client.check('<i.am.an.article.you.defer@example.com>').catch(r => r)
])
expect(responses).toEqual([
{
code: 238,
comment: '',
description: 'Send article to be transferred',
article: {
messageId: '<i.am.an.article.you.will.want@example.com>'
}
},
{
code: 438,
comment: '',
description: 'Article not wanted',
article: {
messageId: '<i.am.an.article.you.have@example.com>'
}
},
{
code: 431,
comment: '',
description: 'Transfer not possible; try again later',
article: {
messageId: '<i.am.an.article.you.defer@example.com>'
}
}
])
})
})
describe('2.5. TAKETHIS Command', () => {
test(
'Example of streaming two articles to another site (the first article' +
'is accepted and the second is rejected):',
async () => {
c(
'TAKETHIS <i.am.an.article.you.will.want@example.com>',
'Path: pathost!demo!somewhere!not-for-mail',
'From: "Demo User" <nobody@example.com>',
'Newsgroups: misc.test',
'Subject: I am just a test article',
'Date: 6 Oct 1998 04:38:40 -0500',
'Organization: An Example Com, San Jose, CA',
'Message-ID: <i.am.an.article.you.will.want@example.com>',
'',
'This is just a test article.',
'.'
)
c(
'TAKETHIS <i.am.an.article.you.have@example.com>',
'Path: pathost!demo!somewhere!not-for-mail',
'From: "Demo User" <nobody@example.com>',
'Newsgroups: misc.test',
'Subject: I am just a test article',
'Date: 6 Oct 1998 04:38:40 -0500',
'Organization: An Example Com, San Jose, CA',
'Message-ID: <i.am.an.article.you.have@example.com>',
'',
'This is just a test article.',
'.'
)
s('239 <i.am.an.article.you.will.want@example.com>')
s('439 <i.am.an.article.you.have@example.com>')
// Setup pipelined response (awkward with MockServer)
server.resetHandlers()
server.addSimpleHandler((command, args) => {
expect(command).toEqual('TAKETHIS')
expect(args).toEqual(expect.any(Array))
const data = args.join(' ').split('\r\n')
data[0] = command + ' ' + data[0]
expect(data).toEqual([
'TAKETHIS <i.am.an.article.you.will.want@example.com>',
'PATH: pathost!demo!somewhere!not-for-mail',
'FROM: "Demo User" <nobody@example.com>',
'NEWSGROUPS: misc.test',
'SUBJECT: I am just a test article',
'DATE: 6 Oct 1998 04:38:40 -0500',
'ORGANIZATION: An Example Com, San Jose, CA',
'MESSAGE-ID: <i.am.an.article.you.will.want@example.com>',
'',
'This is just a test article.',
'.',
'TAKETHIS <i.am.an.article.you.have@example.com>',
'PATH: pathost!demo!somewhere!not-for-mail',
'FROM: "Demo User" <nobody@example.com>',
'NEWSGROUPS: misc.test',
'SUBJECT: I am just a test article',
'DATE: 6 Oct 1998 04:38:40 -0500',
'ORGANIZATION: An Example Com, San Jose, CA',
'MESSAGE-ID: <i.am.an.article.you.have@example.com>',
'',
'This is just a test article.',
'.'
])
return (
'239 <i.am.an.article.you.will.want@example.com>\r\n' +
'439 <i.am.an.article.you.have@example.com>\r\n'
)
})
const responses = await Promise.all([
client
.takeThis({
messageId: '<i.am.an.article.you.will.want@example.com>',
headers: {
PATH: 'pathost!demo!somewhere!not-for-mail',
FROM: '"Demo User" <nobody@example.com>',
NEWSGROUPS: 'misc.test',
SUBJECT: 'I am just a test article',
DATE: '6 Oct 1998 04:38:40 -0500',
ORGANIZATION: 'An Example Com, San Jose, CA',
'MESSAGE-ID': '<i.am.an.article.you.will.want@example.com>'
},
body: ['This is just a test article.']
})
.catch(r => r),
client
.takeThis({
messageId: '<i.am.an.article.you.have@example.com>',
headers: {
PATH: 'pathost!demo!somewhere!not-for-mail',
FROM: '"Demo User" <nobody@example.com>',
NEWSGROUPS: 'misc.test',
SUBJECT: 'I am just a test article',
DATE: '6 Oct 1998 04:38:40 -0500',
ORGANIZATION: 'An Example Com, San Jose, CA',
'MESSAGE-ID': '<i.am.an.article.you.have@example.com>'
},
body: ['This is just a test article.']
})
.catch(r => r)
])
expect(responses).toEqual([
{
code: 239,
comment: '',
description: 'Article transferred OK',
article: {
messageId: '<i.am.an.article.you.will.want@example.com>'
}
},
{
code: 439,
comment: '',
description: 'Transfer rejected; do not retry',
article: {
messageId: '<i.am.an.article.you.have@example.com>'
}
}
])
}
)
test('Example of sending an article to a site where the transfer fails:', async () => {
c(
'TAKETHIS <i.am.an.article.you.will.want@example.com>',
'PATH: pathost!demo!somewhere!not-for-mail',
'FROM: "Demo User" <nobody@example.com>',
'NEWSGROUPS: misc.test',
'SUBJECT: I am just a test article',
'DATE: 6 Oct 1998 04:38:40 -0500',
'ORGANIZATION: An Example Com, San Jose, CA',
'MESSAGE-ID: <i.am.an.article.you.will.want@example.com>',
'',
'This is just a test article.',
'.'
)
s('400 Service temporarily unavailable')
let caught = false
try {
await client.takeThis({
messageId: '<i.am.an.article.you.will.want@example.com>',
headers: {
PATH: 'pathost!demo!somewhere!not-for-mail',
FROM: '"Demo User" <nobody@example.com>',
NEWSGROUPS: 'misc.test',
SUBJECT: 'I am just a test article',
DATE: '6 Oct 1998 04:38:40 -0500',
ORGANIZATION: 'An Example Com, San Jose, CA',
'MESSAGE-ID': '<i.am.an.article.you.will.want@example.com>'
},
body: ['This is just a test article.']
})
} catch (response) {
caught = true
expect(response).toEqual({
code: 400,
comment: 'Service temporarily unavailable',
description: 'service not available or no longer available'
})
}
expect(caught).toBe(true)
})
})