79a73aad00adacd6f0164dcbac4e547ef17ddb23
1 /* eslint-disable capitalized-comments */
5 const assert
= require('assert');
6 const ContentNegotiation
= require('../../lib/content-negotiation');
7 const Enum
= require('../../lib/enum');
12 ImagePng: 'image/png',
14 TextHtml: 'text/html',
15 TextPlain: 'text/plain',
16 AppJson: 'application/json',
19 describe('ContentNegotiation', function () {
20 describe('_unpackAcceptClause', function () {
21 it('handles bare type', function () {
22 const clause
= TYPES
.TextPlain
;
24 type: TYPES
.TextPlain
,
28 const result
= ContentNegotiation
._unpackAcceptClause(clause
);
29 assert
.deepStrictEqual(result
, expected
);
31 it('handles weighted type', function () {
32 const clause
= ` ${TYPES.TextPlain}; q=0.2`;
34 type: TYPES
.TextPlain
,
38 const result
= ContentNegotiation
._unpackAcceptClause(clause
);
39 assert
.deepStrictEqual(result
, expected
);
41 it('handles type with extension parameters', function () {
42 const clause
= `${TYPES.TextPlain}; format=flowed;charset=UTF-8`;
44 type: TYPES
.TextPlain
,
51 const result
= ContentNegotiation
._unpackAcceptClause(clause
);
52 assert
.deepStrictEqual(result
, expected
);
54 it('handles type with params and weight', function () {
55 const clause
= `${TYPES.AppJson};charset=UTF-8;q=0.123;ext=local`;
64 const result
= ContentNegotiation
._unpackAcceptClause(clause
);
65 assert
.deepStrictEqual(result
, expected
);
67 it('ignores empty type', function () {
69 const expected
= undefined;
70 const result
= ContentNegotiation
._unpackAcceptClause(clause
);
71 assert
.deepStrictEqual(result
, expected
);
73 it('ignores weird param', function () {
74 const clause
= `${TYPES.AppJson};blah`;
80 const result
= ContentNegotiation
._unpackAcceptClause(clause
);
81 assert
.deepStrictEqual(result
, expected
);
83 }); // _unpackAcceptClause
85 describe('_acceptClauses', function () {
86 it('orders multiple types properly', function () {
87 const acceptHeader
= 'text/*;q=0.3, text/html;q=0.7, text/html;level=1,text/html;level=2;q=0.4, */*;q=0.5';
89 { type: TYPES
.TextHtml
, weight: 1.0, params: { 'level': '1' } },
90 { type: TYPES
.TextHtml
, weight: 0.7, params: {} },
91 { type: TYPES
.Any
, weight: 0.4998, params: {} }, // N.B. Implementation detail
92 { type: TYPES
.TextHtml
, weight: 0.4, params: { 'level': '2' } },
93 { type: TYPES
.TextAny
, weight: 0.2999, params: {} }, // N.B. Implementation detail
95 const result
= ContentNegotiation
._acceptClauses(acceptHeader
);
96 assert
.deepStrictEqual(result
, expected
);
98 it('does the expected', function () {
99 const acceptHeader
= 'text/*;q=0.5, text/plain;q=0.7, */*;q=0.2';
101 { type: TYPES
.TextPlain
, weight: 0.7, params: {} },
102 { type: TYPES
.TextAny
, weight: 0.4999, params: {} }, // N.B. Implementation detail
103 { type: TYPES
.Any
, weight: 0.1998, params: {} }, // N.B. Implementation detail
105 const result
= ContentNegotiation
._acceptClauses(acceptHeader
);
106 assert
.deepStrictEqual(result
, expected
);
108 it('covers missing data', function () {
109 const result
= ContentNegotiation
._acceptClauses(undefined);
110 assert
.deepStrictEqual(result
, []);
112 }); // _acceptClauses
114 describe('_matchType', function () {
115 it('matches simmple', function () {
116 const result
= ContentNegotiation
._matchType(TYPES
.TextPlain
, TYPES
.TextPlain
);
117 assert
.strictEqual(result
, true);
119 it('does not match simmple', function () {
120 const result
= ContentNegotiation
._matchType(TYPES
.TextPlain
, TYPES
.TextHtml
);
121 assert
.strictEqual(result
, false);
123 it('matches subtype wildcard', function () {
124 const result
= ContentNegotiation
._matchType(TYPES
.ImageAny
, TYPES
.ImagePng
);
125 assert
.strictEqual(result
, true);
127 it('does not match subtype wildcard', function () {
128 const result
= ContentNegotiation
._matchType(TYPES
.ImageAny
, TYPES
.TextPlain
);
129 assert
.strictEqual(result
, false);
131 it('matches any wildcard', function () {
132 const result
= ContentNegotiation
._matchType(TYPES
.Any
, TYPES
.AppJson
);
133 assert
.strictEqual(result
, true);
135 it('matches main type', function () {
136 const result
= ContentNegotiation
._matchType('image', TYPES
.ImagePng
);
137 assert
.strictEqual(result
, true);
139 it('does not match main type', function () {
140 const result
= ContentNegotiation
._matchType('image', TYPES
.AppJson
);
141 assert
.strictEqual(result
, false);
145 describe('accept', function () {
146 it('accepts anything', function () {
147 const types
= [ TYPES
.AppJson
, TYPES
.TextPlain
];
148 const acceptHeader
= undefined;
149 const result
= ContentNegotiation
.accept(types
, acceptHeader
);
150 assert
.strictEqual(result
, TYPES
.AppJson
);
153 it('picks the most acceptible type', function () {
154 const types
= [ TYPES
.AppJson
, TYPES
.TextPlain
];
155 const acceptHeader
= 'text/*;q=0.5, text/html;q=0.6, text/plain;q=0.7, */*;q=0.2, image/png;q=0.0, image/gif;q=0.0';
156 const result
= ContentNegotiation
.accept(types
, acceptHeader
);
157 assert
.strictEqual(result
, TYPES
.TextPlain
);
159 it('picks the most acceptible type', function () {
160 const types
= [ TYPES
.AppJson
, TYPES
.TextPlain
];
161 const acceptHeader
= 'image/png;q=0.0, image/gif;q=0.0, text/html;q=0.6, text/*;q=0.5, text/plain;q=0.7, */*;q=0.7';
162 const result
= ContentNegotiation
.accept(types
, acceptHeader
);
163 assert
.strictEqual(result
, TYPES
.TextPlain
);
165 it('refuses to pick a zero-weight type', function () {
166 const types
= [ TYPES
.AppJson
, TYPES
.TextPlain
];
167 const acceptHeader
= 'application/*;q=0.0, unhandled/type;q=0.7, none/none;q=0.2';
168 const result
= ContentNegotiation
.accept(types
, acceptHeader
);
169 assert
.strictEqual(result
, undefined);
171 it('picks least-wild match', function () {
172 const types
= [ TYPES
.TextHtml
, TYPES
.TextPlain
];
173 const acceptHeader
= '*/*;q=0.5, text/plain;q=0.5, text/*;q=0.5';
174 const result
= ContentNegotiation
.accept(types
, acceptHeader
);
175 assert
.strictEqual(result
, TYPES
.TextPlain
);
179 describe('preferred', function () {
180 it('falls back to identity', function () {
181 const encodings
= [];
182 const header
= 'br, gzip';
183 const result
= ContentNegotiation
.preferred(encodings
, header
);
184 assert
.deepStrictEqual(result
, [Enum
.EncodingType
.Identity
]);
186 it('picks appropriate', function () {
187 const encodings
= ['br', 'identity'];
188 const header
= 'lz4, br, gzip;q=.5';
189 const result
= ContentNegotiation
.preferred(encodings
, header
);
190 assert
.deepStrictEqual(result
, [Enum
.EncodingType
.Brotli
, Enum
.EncodingType
.Identity
]);
192 it('respects forbidding', function () {
193 const encodings
= ['br'];
194 const header
= 'gzip, *;q=0';
195 const result
= ContentNegotiation
.preferred(encodings
, header
);
196 assert
.deepStrictEqual(result
, []);
198 it('respects identity', function () {
199 const encodings
= ['br'];
200 const header
= 'gzip, identity;q=0.1, *;q=0';
201 const result
= ContentNegotiation
.preferred(encodings
, header
);
202 assert
.deepStrictEqual(result
, [Enum
.EncodingType
.Identity
]);
206 }); // ContentNegotiation