Skip to content

Commit

Permalink
eslint, chubbyts-function-mock, node 16
Browse files Browse the repository at this point in the history
  • Loading branch information
dominikzogg committed May 13, 2023
1 parent 3e9f6a7 commit b112c86
Show file tree
Hide file tree
Showing 9 changed files with 173 additions and 184 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('@chubbyts/chubbyts-eslint/dist/eslintrc').default;
19 changes: 5 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,15 @@ name: CI
on:
push:
pull_request:
branches:
- master
schedule:
- cron: '0 0 * * *'

jobs:
node14:
name: Node 14
runs-on: ubuntu-20.04
steps:
- name: checkout
uses: actions/checkout@v3
- name: checkout node
uses: actions/setup-node@v3
with:
node-version: '14'
- run: npm install
- run: npm test
node16:
name: Node 16
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- name: checkout
uses: actions/checkout@v3
Expand All @@ -33,7 +23,7 @@ jobs:
- run: npm test
node18:
name: Node 18
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- name: checkout
uses: actions/checkout@v3
Expand All @@ -42,6 +32,7 @@ jobs:
with:
node-version: '18'
- run: npm install
- run: npm run lint
- run: npm run cs
- run: npm test -- --coverage --no-cache
- run: npm run infection
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ A minimal static file handler for chubbyts-http-types.

## Requirements

* node: 14
* [@chubbyts/chubbyts-http-error][2]: ^2.0.2
* [@chubbyts/chubbyts-http-types][3]: ^1.0.1
* node: 16
* [@chubbyts/chubbyts-http-error][2]: ^2.2.0
* [@chubbyts/chubbyts-http-types][3]: ^1.1.0

## Installation

Through [NPM](https://www.npmjs.com) as [@chubbyts/chubbyts-static-file][1].

```ts
npm i @chubbyts/chubbyts-static-file@^1.1.1
npm i @chubbyts/chubbyts-static-file@^1.2.0
```

## Usage
Expand Down
26 changes: 15 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@chubbyts/chubbyts-static-file",
"version": "1.1.1",
"version": "1.2.0",
"description": "A minimal static file handler for chubbyts-http-types.",
"keywords": [
"chubbyts",
Expand All @@ -13,6 +13,8 @@
"scripts": {
"cs-fix": "prettier --write src tests",
"cs": "prettier --check src tests",
"lint-fix": "eslint src tests --fix",
"lint": "eslint src tests",
"test": "jest",
"infection": "stryker run",
"build": "rm -Rf dist && tsc",
Expand Down Expand Up @@ -40,21 +42,23 @@
"dist"
],
"engines": {
"node": ">=14"
"node": ">=16"
},
"dependencies": {
"@chubbyts/chubbyts-http-error": "^2.0.2",
"@chubbyts/chubbyts-http-types": "^1.0.1"
"@chubbyts/chubbyts-http-error": "^2.2.0",
"@chubbyts/chubbyts-http-types": "^1.1.0"
},
"devDependencies": {
"@stryker-mutator/core": "^6.4.1",
"@stryker-mutator/jest-runner": "^6.4.1",
"@types/jest": "^29.5.0",
"@types/node": "^18.15.3",
"@chubbyts/chubbyts-eslint": "^1.1.1",
"@chubbyts/chubbyts-function-mock": "^1.3.2",
"@stryker-mutator/core": "^6.4.2",
"@stryker-mutator/jest-runner": "^6.4.2",
"@types/jest": "^29.5.1",
"@types/node": "^20.1.3",
"jest": "^29.5.0",
"prettier": "^2.8.4",
"ts-jest": "^29.0.5",
"typescript": "^4.9.5"
"prettier": "^2.8.8",
"ts-jest": "^29.1.0",
"typescript": "^5.0.4"
},
"publishConfig": {
"access": "public"
Expand Down
11 changes: 6 additions & 5 deletions src/handler.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Handler } from '@chubbyts/chubbyts-http-types/dist/handler';
import { Response, ServerRequest } from '@chubbyts/chubbyts-http-types/dist/message';
import { ResponseFactory, StreamFromFileFactory } from '@chubbyts/chubbyts-http-types/dist/message-factory';
import { createNotFound } from '@chubbyts/chubbyts-http-error/dist/http-error';
import { createHash, getHashes } from 'crypto';
import { accessSync, constants, createReadStream, statSync } from 'fs';
import { extname } from 'path';
import type { Handler } from '@chubbyts/chubbyts-http-types/dist/handler';
import type { Response, ServerRequest } from '@chubbyts/chubbyts-http-types/dist/message';
import type { ResponseFactory, StreamFromFileFactory } from '@chubbyts/chubbyts-http-types/dist/message-factory';
import { createNotFound } from '@chubbyts/chubbyts-http-error/dist/http-error';

export type MimeTypes = Map<string, string>;

Expand Down Expand Up @@ -47,7 +47,8 @@ export const createStaticFileHandler = (
responseFactory: ResponseFactory,
streamFromFileFactory: StreamFromFileFactory,
publicDirectory: string,
hashAlgorithm: string = 'md5',
hashAlgorithm = 'md5',
// eslint-disable-next-line @typescript-eslint/no-var-requires
mimeTypes: MimeTypes = require('./mimetypes').default,
): Handler => {
assertHashAlgorithm(hashAlgorithm);
Expand Down
6 changes: 4 additions & 2 deletions src/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import type { Handler } from '@chubbyts/chubbyts-http-types/dist/handler';
import type { Middleware } from '@chubbyts/chubbyts-http-types/dist/middleware';
import type { Response, ServerRequest } from '@chubbyts/chubbyts-http-types/dist/message';
import type { ResponseFactory, StreamFromFileFactory } from '@chubbyts/chubbyts-http-types/dist/message-factory';
import { MimeTypes, createStaticFileHandler } from './handler';
import { isHttpError } from '@chubbyts/chubbyts-http-error/dist/http-error';
import type { MimeTypes } from './handler';
import { createStaticFileHandler } from './handler';

/**
* @deprecated
Expand All @@ -12,7 +13,8 @@ export const createStaticFileMiddleware = (
responseFactory: ResponseFactory,
streamFromFileFactory: StreamFromFileFactory,
publicDirectory: string,
hashAlgorithm: string = 'md5',
hashAlgorithm = 'md5',
// eslint-disable-next-line @typescript-eslint/no-var-requires
mimeTypes: MimeTypes = require('./mimetypes').default,
): Middleware => {
const staticFileHandler = createStaticFileHandler(
Expand Down
113 changes: 60 additions & 53 deletions tests/handler.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { describe, expect, test } from '@jest/globals';
import { Response, ServerRequest } from '@chubbyts/chubbyts-http-types/dist/message';
import { createStaticFileHandler } from '../src/handler';
import { tmpdir } from 'os';
import { randomBytes } from 'crypto';
import { createReadStream, mkdirSync, rmSync, writeFileSync } from 'fs';
import { Duplex, PassThrough, Stream } from 'stream';
import type { Stream } from 'stream';
import { Duplex, PassThrough } from 'stream';
import type { Response, ServerRequest } from '@chubbyts/chubbyts-http-types/dist/message';
import { describe, expect, test } from '@jest/globals';
import { HttpError } from '@chubbyts/chubbyts-http-error/dist/http-error';
import { useFunctionMock } from '@chubbyts/chubbyts-function-mock/dist/function-mock';
import type { ResponseFactory, StreamFromFileFactory } from '@chubbyts/chubbyts-http-types/dist/message-factory';
import { createStaticFileHandler } from '../src/handler';

const jpegHex = `
ffd8ffe000104a46494600010101012c012c0000fffe0013437265617465
Expand Down Expand Up @@ -53,6 +56,7 @@ ffc40014100100000000000000000000000000000000ffda000801010001

const readStream = async (stream: Stream) => {
return new Promise((resolve, reject) => {
// eslint-disable-next-line functional/no-let
let data = '';

stream.on('data', (chunk) => (data += chunk));
Expand All @@ -63,9 +67,8 @@ const readStream = async (stream: Stream) => {

describe('handler', () => {
test('with not supported algorithm', async () => {
const responseFactory = jest.fn();
const streamFromFileFactory = jest.fn();
const publicDirectory = `${tmpdir()}/${randomBytes(16).toString('hex')}`;
const [responseFactory, responseFactoryMocks] = useFunctionMock<ResponseFactory>([]);
const [streamFromFileFactory, streamFromFileFactoryMocks] = useFunctionMock<StreamFromFileFactory>([]);

try {
createStaticFileHandler(responseFactory, streamFromFileFactory, '/unknown', 'some-algo');
Expand All @@ -75,15 +78,16 @@ describe('handler', () => {
expect((e as Error).message).toMatch(/Not supported hash algorithm: "some-algo", supported are: "([^"]+)", ".*"/);
}

expect(responseFactory).toHaveBeenCalledTimes(0);
expect(streamFromFileFactory).toHaveBeenCalledTimes(0);
expect(responseFactoryMocks.length).toBe(0);
expect(streamFromFileFactoryMocks.length).toBe(0);
});

test('with missing file', async () => {
const request = { uri: { path: '/test.jpg' } } as ServerRequest;

const responseFactory = jest.fn();
const streamFromFileFactory = jest.fn();
const [responseFactory, responseFactoryMocks] = useFunctionMock<ResponseFactory>([]);
const [streamFromFileFactory, streamFromFileFactoryMocks] = useFunctionMock<StreamFromFileFactory>([]);

const publicDirectory = `${tmpdir()}/${randomBytes(16).toString('hex')}`;

mkdirSync(publicDirectory, { recursive: true });
Expand All @@ -95,13 +99,13 @@ describe('handler', () => {
throw new Error('Missing error');
} catch (e) {
expect(e).toBeInstanceOf(HttpError);
expect(e).toMatchInlineSnapshot(`[Error: Not Found]`);
expect(e).toMatchInlineSnapshot('[Error: Not Found]');
}

rmSync(publicDirectory, { recursive: true });

expect(responseFactory).toHaveBeenCalledTimes(0);
expect(streamFromFileFactory).toHaveBeenCalledTimes(0);
expect(responseFactoryMocks.length).toBe(0);
expect(streamFromFileFactoryMocks.length).toBe(0);
});

test('with directory', async () => {
Expand All @@ -114,8 +118,8 @@ describe('handler', () => {

const request = { uri: { path } } as ServerRequest;

const responseFactory = jest.fn();
const streamFromFileFactory = jest.fn();
const [responseFactory, responseFactoryMocks] = useFunctionMock<ResponseFactory>([]);
const [streamFromFileFactory, streamFromFileFactoryMocks] = useFunctionMock<StreamFromFileFactory>([]);

const handler = createStaticFileHandler(responseFactory, streamFromFileFactory, publicDirectory);

Expand All @@ -124,13 +128,13 @@ describe('handler', () => {
throw new Error('Missing error');
} catch (e) {
expect(e).toBeInstanceOf(HttpError);
expect(e).toMatchInlineSnapshot(`[Error: Not Found]`);
expect(e).toMatchInlineSnapshot('[Error: Not Found]');
}

rmSync(publicDirectory, { recursive: true });

expect(responseFactory).toHaveBeenCalledTimes(0);
expect(streamFromFileFactory).toHaveBeenCalledTimes(0);
expect(responseFactoryMocks.length).toBe(0);
expect(streamFromFileFactoryMocks.length).toBe(0);
});

test('with image', async () => {
Expand All @@ -147,17 +151,19 @@ describe('handler', () => {
const request = { headers: {}, uri: { path } } as ServerRequest;
const response = { headers: {} } as Response;

const responseFactory = jest.fn((givenStatus) => {
expect(givenStatus).toBe(200);

return response;
});

const streamFromFileFactory = jest.fn((filepath) => {
const newStream = new PassThrough();
createReadStream(filepath).pipe(newStream);
return newStream;
});
const [responseFactory, responseFactoryMocks] = useFunctionMock<ResponseFactory>([
{ parameters: [200], return: response },
]);

const [streamFromFileFactory, streamFromFileFactoryMocks] = useFunctionMock<StreamFromFileFactory>([
{
callback: (filepath) => {
const newStream = new PassThrough();
createReadStream(filepath).pipe(newStream);
return newStream;
},
},
]);

const handler = createStaticFileHandler(responseFactory, streamFromFileFactory, publicDirectory);

Expand All @@ -177,8 +183,8 @@ describe('handler', () => {

rmSync(publicDirectory, { recursive: true });

expect(responseFactory).toHaveBeenCalledTimes(1);
expect(streamFromFileFactory).toHaveBeenCalledTimes(1);
expect(responseFactoryMocks.length).toBe(0);
expect(streamFromFileFactoryMocks.length).toBe(0);
});

test('with image and matching etag', async () => {
Expand All @@ -201,13 +207,11 @@ describe('handler', () => {

const response = { headers: {}, body: { end } } as unknown as Response;

const responseFactory = jest.fn((givenStatus) => {
expect(givenStatus).toBe(304);

return response;
});
const [responseFactory, responseFactoryMocks] = useFunctionMock<ResponseFactory>([
{ parameters: [304], return: response },
]);

const streamFromFileFactory = jest.fn();
const [streamFromFileFactory, streamFromFileFactoryMocks] = useFunctionMock<StreamFromFileFactory>([]);

const handler = createStaticFileHandler(responseFactory, streamFromFileFactory, publicDirectory);

Expand All @@ -225,8 +229,9 @@ describe('handler', () => {
rmSync(publicDirectory, { recursive: true });

expect(end).toHaveBeenCalledTimes(1);
expect(responseFactory).toHaveBeenCalledTimes(1);
expect(streamFromFileFactory).toHaveBeenCalledTimes(0);

expect(responseFactoryMocks.length).toBe(0);
expect(streamFromFileFactoryMocks.length).toBe(0);
});

test('with unknown file', async () => {
Expand All @@ -241,17 +246,19 @@ describe('handler', () => {
const request = { headers: {}, uri: { path } } as ServerRequest;
const response = { headers: {} } as Response;

const responseFactory = jest.fn((givenStatus) => {
expect(givenStatus).toBe(200);

return response;
});

const streamFromFileFactory = jest.fn((filepath) => {
const newStream = new PassThrough();
createReadStream(filepath).pipe(newStream);
return newStream;
});
const [responseFactory, responseFactoryMocks] = useFunctionMock<ResponseFactory>([
{ parameters: [200], return: response },
]);

const [streamFromFileFactory, streamFromFileFactoryMocks] = useFunctionMock<StreamFromFileFactory>([
{
callback: (filepath) => {
const newStream = new PassThrough();
createReadStream(filepath).pipe(newStream);
return newStream;
},
},
]);

const handler = createStaticFileHandler(responseFactory, streamFromFileFactory, publicDirectory);

Expand All @@ -270,7 +277,7 @@ describe('handler', () => {

rmSync(publicDirectory, { recursive: true });

expect(responseFactory).toHaveBeenCalledTimes(1);
expect(streamFromFileFactory).toHaveBeenCalledTimes(1);
expect(responseFactoryMocks.length).toBe(0);
expect(streamFromFileFactoryMocks.length).toBe(0);
});
});
Loading

0 comments on commit b112c86

Please sign in to comment.