Files
RSSHub/test/middleware/cache.js
T
Tony 6d901cb7dc style(eslint): add eslint-unicorn (#14257)
* style: add eslint-unicorn

* style: fix unicorn/no-useless-spread

* style: fix unicorn/no-useless-promise-resolve-reject

* style: fix unicorn/no-for-loop

* fix: codeql bad HTML filtering regexp

* fix: codeql incomplete replace

* fix: unicorn/no-abusive-eslint-disable

* style: fix unicorn/no-new-array

* style: fix unicorn/no-typeof-undefined

* style: fix unicorn/no-zero-fractions

* style: fix unicorn/no-empty-file

* style: fix unicorn/prefer-date-now

* revert: auto fix unicorn/prefer-switch on lib/v2/kuaidi100/utils.js

* style: fix unicorn/prefer-array-find

* style: fix unicorn/prefer-array-flat

* style: fix unicorn/prefer-array-flat-map

* style: fix unicorn/prefer-at

* style: fix unicorn/prefer-string-starts-ends-with

* style: fix unicorn/prefer-includes

* fix: codeql URL substring sanitization

* style: fix unicorn/prefer-optional-catch-binding

* style: fix unicorn/catch-error-name

* style: fix unicorn/escape-case

* style: fix unicorn/prefer-native-coercion-functions

* style: fix unicorn/prefer-regexp-test

* style: fix unicorn/require-array-join-separator

* style: fix unicorn/prefer-math-trunc

* style: fix unicorn/prefer-negative-index

* style: fix unicorn/prefer-dom-node-dataset

* style: fix unicorn/prefer-dom-node-text-content

* style: fix unicorn/prefer-query-selector

* style: fix unicorn/no-array-for-each

* style: fix unicorn/no-negated-condition

* style: fix unicorn/prefer-add-event-listener

* style: fix unicorn/import-style

* style: fix prefer-regex-literals

* style: disable unicorn/no-useless-switch-case

* style: disable unicorn/text-encoding-identifier-case

* style: fix unicorn/prefer-set-has

* style: fix unicorn/prefer-spread

* revert: auto fix on lib/routes/universities/ynnu/edu/base64.js

* style: fix unicorn/no-useless-undefined

* style: fix unicorn/no-array-push-push

* style: fix unicorn/no-useless-undefined again

* style: fix unicorn/no-lonely-if

* style: fix unicorn/prefer-reflect-apply

* style: fix unicorn/switch-case-braces

* style: fix unicorn/prefer-switch

* style: fix unicorn/prefer-array-some

* fix: deepscan UNUSED_VAR_ASSIGN

* style: fix unicorn/prefer-ternary

* fix: follow-up of unicorn/prefer-ternary

* revert: auto fix of unicorn/prefer-string-slice for substring()

* style: disable unicorn/prefer-string-slice

fix: auto fix slice over deprecated substr

* style: fix unicorn/throw-new-error

* style: fix unicorn/filename-case

* test: fix dateParser renaming

* style: fix unicorn/better-regex

* style: fix unicorn/prefer-string-replace-all

* fix(deps): add sanitize-html

* style: fix no-prototype-builtins

* style: fix unicorn/consistent-destructuring

* style: fix unicorn/consistent-function-scoping

* style: fix unicorn/prefer-regexp-test

* style: fix unicorn/prefer-logical-operator-over-ternary

* style: fix unicorn/no-array-callback-reference

* style: add prefer-object-has-own

* style: warn unicorn/no-empty-file

* style: fix unicorn/prefer-number-properties

* style: fix no-useless-undefined again

* style: fix unicorn/numeric-separators-style

* style: disable unicorn/no-array-callback-reference

false postive with cheerio
2024-01-18 20:43:40 +08:00

220 lines
8.2 KiB
JavaScript

const supertest = require('supertest');
const Parser = require('rss-parser');
const parser = new Parser();
const wait = require('../../lib/utils/wait');
let server;
jest.mock('request-promise-native');
beforeAll(() => {
process.env.CACHE_EXPIRE = 1;
process.env.CACHE_CONTENT_EXPIRE = 3;
});
afterEach(() => {
delete process.env.CACHE_TYPE;
jest.resetModules();
server?.close();
});
afterAll(() => {
delete process.env.CACHE_EXPIRE;
});
describe('cache', () => {
it('memory', async () => {
process.env.CACHE_TYPE = 'memory';
server = require('../../lib/index');
const request = supertest(server);
const response1 = await request.get('/test/cache');
const response2 = await request.get('/test/cache');
const parsed1 = await parser.parseString(response1.text);
const parsed2 = await parser.parseString(response2.text);
delete parsed1.lastBuildDate;
delete parsed2.lastBuildDate;
expect(parsed2).toMatchObject(parsed1);
expect(response2.status).toBe(200);
expect(response2.headers['x-koa-memory-cache']).toBe('true');
expect(response2.headers).not.toHaveProperty('x-koa-redis-cache');
await wait(1 * 1000 + 100);
const response3 = await request.get('/test/cache');
expect(response3.headers).not.toHaveProperty('x-koa-redis-cache');
expect(response3.headers).not.toHaveProperty('x-koa-memory-cache');
const parsed3 = await parser.parseString(response3.text);
await wait(3 * 1000 + 100);
const response4 = await request.get('/test/cache');
const parsed4 = await parser.parseString(response4.text);
expect(parsed1.items[0].content).toBe('Cache1');
expect(parsed2.items[0].content).toBe('Cache1');
expect(parsed3.items[0].content).toBe('Cache1');
expect(parsed4.items[0].content).toBe('Cache2');
const app = require('../../lib/app');
await app.context.cache.set('mock', undefined);
expect(await app.context.cache.get('mock')).toBe('');
await app.context.cache.globalCache.set('mock', undefined);
expect(await app.context.cache.globalCache.get('mock')).toBe('');
await app.context.cache.globalCache.set('mock', {
mock: 1,
});
expect(await app.context.cache.globalCache.get('mock')).toBe('{"mock":1}');
await request.get('/test/refreshCache');
await wait(1 * 1000 + 100);
const response5 = await request.get('/test/refreshCache');
const parsed5 = await parser.parseString(response5.text);
await wait(2 * 1000 + 100);
const response6 = await request.get('/test/refreshCache');
const parsed6 = await parser.parseString(response6.text);
expect(parsed5.items[0].content).toBe('1 1');
expect(parsed6.items[0].content).toBe('1 0');
}, 10000);
it('redis', async () => {
process.env.CACHE_TYPE = 'redis';
server = require('../../lib/index');
const request = supertest(server);
const response1 = await request.get('/test/cache');
const response2 = await request.get('/test/cache');
const parsed1 = await parser.parseString(response1.text);
const parsed2 = await parser.parseString(response2.text);
delete parsed1.lastBuildDate;
delete parsed2.lastBuildDate;
expect(parsed2).toMatchObject(parsed1);
expect(response2.status).toBe(200);
expect(response2.headers['x-koa-redis-cache']).toBe('true');
expect(response2.headers).not.toHaveProperty('x-koa-memory-cache');
await wait(1 * 1000 + 100);
const response3 = await request.get('/test/cache');
expect(response3.headers).not.toHaveProperty('x-koa-redis-cache');
expect(response3.headers).not.toHaveProperty('x-koa-memory-cache');
const parsed3 = await parser.parseString(response3.text);
await wait(3 * 1000 + 100);
const response4 = await request.get('/test/cache');
const parsed4 = await parser.parseString(response4.text);
expect(parsed1.items[0].content).toBe('Cache1');
expect(parsed2.items[0].content).toBe('Cache1');
expect(parsed3.items[0].content).toBe('Cache1');
expect(parsed4.items[0].content).toBe('Cache2');
const app = require('../../lib/app');
await app.context.cache.set('mock1', undefined);
expect(await app.context.cache.get('mock1')).toBe('');
await app.context.cache.set('mock2', '2');
await app.context.cache.set('mock2', '2');
expect(await app.context.cache.get('mock2')).toBe('2');
await request.get('/test/refreshCache');
await wait(1 * 1000 + 100);
const response5 = await request.get('/test/refreshCache');
const parsed5 = await parser.parseString(response5.text);
await wait(2 * 1000 + 100);
const response6 = await request.get('/test/refreshCache');
const parsed6 = await parser.parseString(response6.text);
expect(parsed5.items[0].content).toBe('1 1');
expect(parsed6.items[0].content).toBe('1 0');
}, 10000);
it('redis with quit', async () => {
process.env.CACHE_TYPE = 'redis';
server = require('../../lib/index');
const { redisClient } = require('../../lib/app').context.cache.clients;
await redisClient.quit();
const request = supertest(server);
const response1 = await request.get('/test/cache');
const response2 = await request.get('/test/cache');
const parsed1 = await parser.parseString(response1.text);
const parsed2 = await parser.parseString(response2.text);
expect(response2.status).toBe(200);
expect(response2.headers).not.toHaveProperty('x-koa-redis-cache');
expect(response2.headers).not.toHaveProperty('x-koa-memory-cache');
expect(parsed1.items[0].content).toBe('Cache1');
expect(parsed2.items[0].content).toBe('Cache2');
});
it('redis with error', async () => {
process.env.CACHE_TYPE = 'redis';
process.env.REDIS_URL = 'redis://wrongpath:6379';
server = require('../../lib/index');
const request = supertest(server);
const response1 = await request.get('/test/cache');
const response2 = await request.get('/test/cache');
const parsed1 = await parser.parseString(response1.text);
const parsed2 = await parser.parseString(response2.text);
expect(response2.status).toBe(200);
expect(response2.headers).not.toHaveProperty('x-koa-redis-cache');
expect(response2.headers).not.toHaveProperty('x-koa-memory-cache');
expect(parsed1.items[0].content).toBe('Cache1');
expect(parsed2.items[0].content).toBe('Cache2');
});
it('no cache', async () => {
process.env.CACHE_TYPE = '';
server = require('../../lib/index');
const request = supertest(server);
const response1 = await request.get('/test/cache');
const response2 = await request.get('/test/cache');
const parsed1 = await parser.parseString(response1.text);
const parsed2 = await parser.parseString(response2.text);
expect(response2.status).toBe(200);
expect(response2.headers).not.toHaveProperty('x-koa-redis-cache');
expect(response2.headers).not.toHaveProperty('x-koa-memory-cache');
expect(parsed1.items[0].content).toBe('Cache1');
expect(parsed2.items[0].content).toBe('Cache2');
});
it('throws URL key', async () => {
process.env.CACHE_TYPE = 'memory';
server = require('../../lib/index');
const request = supertest(server);
try {
const response = await request.get('/test/cacheUrlKey');
expect(response).toThrow(Error);
} catch (error) {
expect(error.message).toContain('Cache key must be a string');
}
});
it('throws TTL key', async () => {
process.env.CACHE_TYPE = 'redis';
const app = require('../../lib/app');
try {
await app.context.cache.get('rsshub:cacheTtl:mock');
} catch (error) {
expect(error.message).toContain('reserved for the internal usage');
} finally {
await app.context.cache.clients.redisClient.quit();
}
});
});