Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

28 add testing setup #38

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
20 changes: 20 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Run Tests

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
- name: Install modules
run: yarn
- name: Run tests
run: yarn test
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
node_modules
.env
!prisma/.env
.DS_Store
build
data
Expand Down
24 changes: 12 additions & 12 deletions config/build-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,26 @@ const { build } = require("esbuild");

// See: https://github.com/evanw/esbuild/issues/1051
const nativeNodeModulesPlugin = {
name: 'native-node-modules',
name: "native-node-modules",
setup(build) {
build.onResolve({ filter: /\.node$/, namespace: 'file' }, args => ({
build.onResolve({ filter: /\.node$/, namespace: "file" }, (args) => ({
path: require.resolve(args.path, { paths: [args.resolveDir] }),
namespace: 'node-file',
}))
build.onLoad({ filter: /.*/, namespace: 'node-file' }, args => ({
namespace: "node-file",
}));
build.onLoad({ filter: /.*/, namespace: "node-file" }, (args) => ({
contents: `
import path from ${JSON.stringify(args.path)}
try { module.exports = require(path) }
catch {}
`,
}))
build.onResolve({ filter: /\.node$/, namespace: 'node-file' }, args => ({
}));
build.onResolve({ filter: /\.node$/, namespace: "node-file" }, (args) => ({
path: args.path,
namespace: 'file',
}))
let opts = build.initialOptions
opts.loader = opts.loader || {}
opts.loader['.node'] = 'file'
namespace: "file",
}));
let opts = build.initialOptions;
opts.loader = opts.loader || {};
opts.loader[".node"] = "file";
},
};

Expand Down
10 changes: 10 additions & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { JestConfigWithTsJest } from "ts-jest";

const config: JestConfigWithTsJest = {
preset: "ts-jest",
testEnvironment: "node",
setupFiles: ["./test/setEnv.js"],
reporters: ["default", "github-actions"],
};

export default config;
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"dev": "ts-node-dev --respawn --exit-child --transpile-only server/index.ts",
"build": "node ./config/build-config.js",
"start": "node ./build/index.js",
"test": "jest",
"prisma:generate": "prisma generate",
"prisma:db:push": "prisma db push",
"prisma:db:deploy": "prisma migrate deploy",
Expand All @@ -24,12 +25,16 @@
},
"devDependencies": {
"@types/bcryptjs": "^2.4.2",
"@types/express": "4.17.17",
"@types/express": "^4.17.17",
"@types/jest": "^29.4.0",
"@types/jsonwebtoken": "^9.0.1",
"@types/node": "^18.6.1",
"@types/ssh2": "^1.11.5",
"esbuild": "^0.16.17",
"jest": "^29.4.3",
"prisma": "^4.11.0",
"supertest": "^6.3.3",
"ts-jest": "^29.0.5",
"ts-node-dev": "^2.0.0",
"typescript": "^4.9.5"
},
Expand Down
8 changes: 6 additions & 2 deletions server/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
{
"extends": "../config/shared-tsconfig.json",
"include": ["./**/*"],
"include": [
"./**/*"
],
"compilerOptions": {
"paths": {
"~/*": ["./*"]
"~/*": [
"./*"
]
}
}
}
6 changes: 6 additions & 0 deletions test/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
parserOptions: {
tsconfigRootDir: __dirname,
project: "./tsconfig.json",
},
};
14 changes: 14 additions & 0 deletions test/setEnv.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
process.env.PORT = "8000";
process.env.HOST = "localhost";
process.env.PROTOCOL = "http";

process.env.DATA_FOLDER = "data_folder";

process.env.API_KEY = "api_key";

process.env.JWT_SECRET = "jwt_secret";
process.env.JWT_EXPIRES_IN = "900";

process.env.SSH_ENABLED = "true";
process.env.SSH_PRIVATE_KEY_PATH = "private_key_path";
process.env.SSH_PORT = "22";
10 changes: 10 additions & 0 deletions test/stores/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { LocalStore } from "../../server/stores/local-store";
import { getStore } from "../../server/stores";

describe("Store", () => {
test("Calling getStore should return LocalStore", () => {
const store = getStore();

expect(store).toBe(LocalStore);
});
});
6 changes: 6 additions & 0 deletions test/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": "../config/shared-tsconfig.json",
"include": [
"./**/*"
],
}
101 changes: 101 additions & 0 deletions test/utils/action.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import type { JwtPayload } from "jsonwebtoken";
import {
getUploadAction,
getDownloadAction,
getVerifyAction,
} from "../../server/utils/actions";
import { verifyJWT } from "../../server/utils/jwt";

describe("Actions Utils", () => {
beforeAll(() => {
Date.now = jest.fn(() => 1677970800);
});

test("Generate upload action", async () => {
const gitUser = "user";
const repo = "repo";
const oid = "15";

const uploadAction = getUploadAction(gitUser, repo, oid);

const authorizationHeader = uploadAction.header.Authorization.split(" ");
const token = verifyJWT<JwtPayload>(authorizationHeader[1]!);

expect(uploadAction).toStrictEqual({
href: "http://localhost:8000/user/repo/objects/15",
expires_in: 900,
header: {
Authorization:
"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJnaXRVc2VyIjoidXNlciIsInJlcG8iOiJyZXBvIiwiYWN0aW9uIjoidXBsb2FkIiwib2lkIjoiMTUiLCJpYXQiOjE2Nzc5NzAsImV4cCI6MTY3ODg3MH0.q3sqZbuQQ1PrUdVseO8h4nGxuBYmasqwItX_0tYVo44",
},
});
expect(authorizationHeader.length).toBe(2);
expect(token.isVerified).toBe(true);
expect(token.payload).toStrictEqual({
gitUser,
repo,
oid,
action: "upload",
iat: 1677970,
exp: 1678870,
});
});

test("Generate download action", async () => {
const gitUser = "user";
const repo = "repo";
const oid = "15";

const downloadAction = getDownloadAction(gitUser, repo, oid);

const authorizationHeader = downloadAction.header.Authorization.split(" ");
const token = verifyJWT<JwtPayload>(authorizationHeader[1]!);

expect(downloadAction).toStrictEqual({
href: "http://localhost:8000/user/repo/objects/15",
expires_in: 900,
header: {
Authorization:
"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJnaXRVc2VyIjoidXNlciIsInJlcG8iOiJyZXBvIiwiYWN0aW9uIjoiZG93bmxvYWQiLCJvaWQiOiIxNSIsImlhdCI6MTY3Nzk3MCwiZXhwIjoxNjc4ODcwfQ.cbzUv0FTYH3mcz2nl1Y_9Kf_zb4_qZs8kuTGivMyDVg",
},
});
expect(authorizationHeader.length).toBe(2);
expect(token.isVerified).toBe(true);
expect(token.payload).toStrictEqual({
gitUser,
repo,
oid,
action: "download",
iat: 1677970,
exp: 1678870,
});
});

test("Generate verify action", async () => {
const gitUser = "user";
const repo = "repo";

const verifyAction = getVerifyAction(gitUser, repo);

const authorizationHeader = verifyAction.header.Authorization.split(" ");
const token = verifyJWT<JwtPayload>(authorizationHeader[1]!);

expect(verifyAction).toStrictEqual({
href: "http://localhost:8000/user/repo/verify",
expires_in: 900,
header: {
Authorization:
"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJnaXRVc2VyIjoidXNlciIsInJlcG8iOiJyZXBvIiwiYWN0aW9uIjoidmVyaWZ5IiwiaWF0IjoxNjc3OTcwLCJleHAiOjE2Nzg4NzB9.PRLusomJ2I9BcBrI-d5YPeOeW8RsI-iHg7Usbc5btKM",
},
});
expect(authorizationHeader.length).toBe(2);
expect(token.isVerified).toBe(true);
expect(token.payload).toStrictEqual({
gitUser,
repo,
action: "verify",
iat: 1677970,
exp: 1678870,
});
});
});
Loading