Skip to content

Commit 7646486

Browse files
committed
test: add etag function tests and export
1 parent 7812519 commit 7646486

File tree

4 files changed

+144
-0
lines changed

4 files changed

+144
-0
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@
5454
"husky": "^9.1.7",
5555
"mocha": "^11.7.5",
5656
"mockdate": "^3.0.5",
57+
"safe-buffer": "^5.2.1",
58+
"seedrandom": "^3.0.5",
5759
"tsdown": "^0.17.2",
5860
"typescript": "^5.9.3"
5961
}

pnpm-lock.yaml

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Hit, Miss, Data, Status, Type } from './common.js';
2+
import { etag } from './etag.js';
23
import { createFilesystemStore } from './store-filesystem.js';
34
import { createMemoryStore, type Store } from './store-memory.js';
45

@@ -107,6 +108,7 @@ export class Cacheism {
107108

108109
// Named exports for ESM users
109110
export { Hit, Miss, Data, Status, Type };
111+
export { etag };
110112
export { createFilesystemStore, createMemoryStore };
111113
export type { Store } from './store-memory.js';
112114
export type { FilesystemStoreConfig } from './store-filesystem.js';

test/etag.cjs

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
2+
const assert = require('assert')
3+
const Buffer = require('safe-buffer').Buffer
4+
const { etag } = require('../dist/index.cjs')
5+
const fs = require('fs')
6+
const seedrandom = require('seedrandom')
7+
8+
const buf5kb = getbuffer(5 * 1024)
9+
const str5kb = getbuffer(5 * 1024).toString()
10+
11+
describe('etag(entity)', function () {
12+
it('should require an entity', function () {
13+
assert.throws(etag.bind(), /argument entity is required/)
14+
})
15+
16+
it('should reject number entities', function () {
17+
assert.throws(etag.bind(null, 4), /argument entity must be/)
18+
})
19+
20+
describe('when "entity" is a string', function () {
21+
it('should generate a strong ETag', function () {
22+
assert.strictEqual(etag('beep boop'), '"9-fINXV39R1PCo05OqGqr7KIY9lCE"')
23+
})
24+
25+
it('should work containing Unicode', function () {
26+
assert.strictEqual(etag('论'), '"3-QkSKq8sXBjHL2tFAZknA2n6LYzM"')
27+
assert.strictEqual(etag('论', { weak: true }), 'W/"3-QkSKq8sXBjHL2tFAZknA2n6LYzM"')
28+
})
29+
30+
it('should work for empty string', function () {
31+
assert.strictEqual(etag(''), '"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"')
32+
})
33+
})
34+
35+
describe('when "entity" is a Buffer', function () {
36+
it('should generate a strong ETag', function () {
37+
assert.strictEqual(etag(Buffer.from([1, 2, 3])), '"3-cDeAcZjCKn0rCAc3HXY3eahP388"')
38+
})
39+
40+
it('should work for empty Buffer', function () {
41+
assert.strictEqual(etag(Buffer.alloc(0)), '"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"')
42+
})
43+
})
44+
45+
describe('when "entity" is a fs.Stats', function () {
46+
it('should generate a weak ETag', function () {
47+
assert.ok(isweak(etag(fs.statSync(__filename))))
48+
})
49+
50+
it('should generate consistently', function () {
51+
assert.strictEqual(etag(fs.statSync(__filename)), etag(fs.statSync(__filename)))
52+
})
53+
})
54+
55+
describe('when "entity" looks like a stats object', function () {
56+
it('should generate a weak ETag', function () {
57+
const fakeStat = {
58+
ctime: new Date('2014-09-01T14:52:07Z'),
59+
mtime: new Date('2014-09-01T14:52:07Z'),
60+
ino: 0,
61+
size: 3027
62+
}
63+
assert.strictEqual(etag(fakeStat), 'W/"bd3-14831b399d8"')
64+
})
65+
})
66+
67+
describe('with "weak" option', function () {
68+
describe('when "false"', function () {
69+
it('should generate a strong ETag for a string', function () {
70+
assert.strictEqual(etag('', { weak: false }), '"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"')
71+
assert.strictEqual(etag('beep boop', { weak: false }), '"9-fINXV39R1PCo05OqGqr7KIY9lCE"')
72+
assert.strictEqual(etag(str5kb, { weak: false }), '"1400-CH0oWYLQGHe/yDhUrMkMg3fIdVU"')
73+
})
74+
75+
it('should generate a strong ETag for a Buffer', function () {
76+
assert.strictEqual(etag(Buffer.alloc(0), { weak: false }), '"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"')
77+
assert.strictEqual(etag(Buffer.from([1, 2, 3]), { weak: false }), '"3-cDeAcZjCKn0rCAc3HXY3eahP388"')
78+
assert.strictEqual(etag(buf5kb, { weak: false }), '"1400-CH0oWYLQGHe/yDhUrMkMg3fIdVU"')
79+
})
80+
81+
it('should generate a strong ETag for fs.Stats', function () {
82+
assert.ok(!isweak(etag(fs.statSync(__filename), { weak: false })))
83+
})
84+
})
85+
86+
describe('when "true"', function () {
87+
it('should generate a weak ETag for a string', function () {
88+
assert.strictEqual(etag('', { weak: true }), 'W/"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"')
89+
assert.strictEqual(etag('beep boop', { weak: true }), 'W/"9-fINXV39R1PCo05OqGqr7KIY9lCE"')
90+
assert.strictEqual(etag(str5kb, { weak: true }), 'W/"1400-CH0oWYLQGHe/yDhUrMkMg3fIdVU"')
91+
})
92+
93+
it('should generate a weak ETag for a Buffer', function () {
94+
assert.strictEqual(etag(Buffer.alloc(0), { weak: true }), 'W/"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"')
95+
assert.strictEqual(etag(Buffer.from([1, 2, 3]), { weak: true }), 'W/"3-cDeAcZjCKn0rCAc3HXY3eahP388"')
96+
assert.strictEqual(etag(buf5kb, { weak: true }), 'W/"1400-CH0oWYLQGHe/yDhUrMkMg3fIdVU"')
97+
})
98+
99+
it('should generate a weak ETag for fs.Stats', function () {
100+
assert.ok(isweak(etag(fs.statSync(__filename), { weak: true })))
101+
})
102+
103+
it('should generate different ETags for different strings', function () {
104+
assert.notStrictEqual(etag('plumless', { weak: true }), etag('buckeroo', { weak: true }))
105+
})
106+
})
107+
})
108+
})
109+
110+
function getbuffer (size) {
111+
const buffer = Buffer.alloc(size)
112+
const rng = seedrandom('etag test')
113+
114+
for (let i = 0; i < buffer.length; i++) {
115+
buffer[i] = (rng() * 94 + 32) | 0
116+
}
117+
118+
return buffer
119+
}
120+
121+
function isweak (etag) {
122+
const weak = /^(W\/|)"([^"]+)"/.exec(etag)
123+
124+
if (weak === null) {
125+
throw new Error('invalid ETag: ' + etag)
126+
}
127+
128+
return weak[1] === 'W/'
129+
}

0 commit comments

Comments
 (0)