Skip to content

Commit

Permalink
Merge pull request #475 from ottofeller/michaelpopov1/pla-256-add-bac…
Browse files Browse the repository at this point in the history
…kend-test-framework-template

Add backend test framework template
  • Loading branch information
quesabe authored Feb 1, 2024
2 parents 99b1155 + 837a42b commit 4c1d48d
Show file tree
Hide file tree
Showing 17 changed files with 1,748 additions and 0 deletions.
1,140 changes: 1,140 additions & 0 deletions src/backend-test/__tests__/__snapshots__/index.ts.snap

Large diffs are not rendered by default.

54 changes: 54 additions & 0 deletions src/backend-test/__tests__/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {synthSnapshot} from 'projen/lib/util/synth'
import {OttofellerBackendTestProject, OttofellerBackendTestProjectOptions} from '..'

describe('Backend-test template', () => {
test('sets defaults', () => {
const project = new TestBackendTestProject({hasGitHooks: true})
const snapshot = synthSnapshot(project)
expect(snapshot).toMatchSnapshot()
})

describe('has GraphQL', () => {
test('enabled by default', () => {
const project = new TestBackendTestProject()
const snapshot = synthSnapshot(project)
expect(snapshot['package.json'].dependencies).toHaveProperty('graphql')
expect(snapshot['package.json'].scripts).toHaveProperty('gql-to-ts')
expect(snapshot['codegen.ts']).toBeDefined()
})

test('disabled with an option', () => {
const project = new TestBackendTestProject({isGraphqlEnabled: false})
const snapshot = synthSnapshot(project)
expect(snapshot['package.json'].dependencies).not.toHaveProperty('graphql')
expect(snapshot['package.json'].scripts).not.toHaveProperty('gql-to-ts')
expect(snapshot['codegen.ts']).not.toBeDefined()
})
})

describe('has AwsDynamoDb', () => {
test('enabled by default', () => {
const project = new TestBackendTestProject()
const snapshot = synthSnapshot(project)
expect(snapshot['package.json'].devDependencies).toHaveProperty('@aws-sdk/client-dynamodb')
expect(snapshot['package.json'].devDependencies).toHaveProperty('@aws-sdk/lib-dynamodb')
})

test('disabled with an option', () => {
const project = new TestBackendTestProject({isAWSDynamoDBEnabled: false})
const snapshot = synthSnapshot(project)
expect(snapshot['package.json'].devDependencies).not.toHaveProperty('@aws-sdk/client-dynamodb')
expect(snapshot['package.json'].devDependencies).not.toHaveProperty('@aws-sdk/lib-dynamodb')
})
})
})

class TestBackendTestProject extends OttofellerBackendTestProject {
constructor(options: Partial<OttofellerBackendTestProjectOptions> = {}) {
super({
...options,
name: 'test-backend-test-project',
defaultReleaseBranch: 'main',
})
}
}
6 changes: 6 additions & 0 deletions src/backend-test/assets/.env.development
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
HASURA_GRAPHQL_URL=http://localhost:8080/v1/graphql
HASURA_GRAPHQL_ADMIN_SECRET=111
UPLOAD_AVATAR_URL=https://api.worldcoin-distributors.com/user/upload-avatar
BASE_URL=https://paysis.cyclic.app/
USERNAME=adminius
PASSWORD=supers3cret
5 changes: 5 additions & 0 deletions src/backend-test/assets/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
test-results/**/*
generated/index.ts
schema.graphql
*.generated.ts
*.generated.tsx
5 changes: 5 additions & 0 deletions src/backend-test/assets/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
generated/index.ts
*.generated.ts
tsconfig.json
.eslintrc.json
tsconfig.dev.json
2 changes: 2 additions & 0 deletions src/backend-test/assets/api/auth/index.ts.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './request'
export * from './response'
4 changes: 4 additions & 0 deletions src/backend-test/assets/api/auth/request.ts.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export type AuthRequestBody = {
login: string | undefined
password: string | undefined
}
4 changes: 4 additions & 0 deletions src/backend-test/assets/api/auth/response.ts.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export type AuthResponseBody = {
token?: string
message?: string
}
114 changes: 114 additions & 0 deletions src/backend-test/assets/codegen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import {CodegenConfig} from '@graphql-codegen/cli'
import * as dotenv from 'dotenv'

dotenv.config({path: '.env.local'})
dotenv.config({path: '.env.development'})

if (!process.env.HASURA_GRAPHQL_URL || !process.env.HASURA_GRAPHQL_ADMIN_SECRET) {
throw new Error('HASURA_GRAPHQL_URL or HASURA_GRAPHQL_ADMIN_SECRET does not exist. Check your .env files')
}

const config: CodegenConfig = {
overwrite: true,

config: {
defaultScalarType: 'unknown',
scalars: {
uuid: 'string',
_uuid: 'Array<string>',
timestamp: 'string',
timestamptz: 'string',
numeric: 'string',
jsonb: 'any',
json: 'any',
bigint: 'string',
AWSDate: 'string',
AWSTime: 'string',
AWSDateTime: 'string',
AWSTimestamp: 'string',
AWSEmail: 'string',
AWSJSON: 'string',
AWSURL: 'string',
AWSPhone: 'string',
AWSIPAddress: 'string',
interval: 'string',
date: 'string',
float8: 'string',
},
},

generates: {
// Generate common types
'generated/index.ts': {
schema: [
{
[process.env.HASURA_GRAPHQL_URL]: {
headers: {
'x-hasura-admin-secret': process.env.HASURA_GRAPHQL_ADMIN_SECRET,
'x-hasura-user-id': 'service',
'x-hasura-user-role': 'service',
},
},
},
],
plugins: [
'typescript',
{
add: {
placement: 'prepend',
content: '/* eslint-disable -- Generated */ // @ts-nocheck',

Check warning on line 59 in src/backend-test/assets/codegen.ts

View workflow job for this annotation

GitHub Actions / lint

Unknown word: "nocheck"
},
},
],
config: {
strictScalars: true,
skipDocumentsValidation: {
OverlappingFieldsCanBeMergedRule: true,
},
},
},

// Generate types for graphql requests
src: {
schema: [
{
[process.env.HASURA_GRAPHQL_URL]: {
headers: {
'x-hasura-admin-secret': process.env.HASURA_GRAPHQL_ADMIN_SECRET,
'x-hasura-user-id': 'service',
'x-hasura-user-role': 'service',
},
},
},
],
documents: ['common/graphql/**/*.ts', '!common/graphql/**/*.generated.ts'],
preset: 'near-operation-file',
presetConfig: {
extension: '.generated.ts',
baseTypesPath: '~generated',
},
plugins: ['typescript-operations', 'typescript-graphql-request'],
config: {
skipTypename: true,
useTypeImports: true,
directiveArgumentAndInputFieldMappings: 'Model',
},
},

// Generate schema file for e2e
'schema.graphql': {
schema: [
{
[process.env.HASURA_GRAPHQL_URL]: {
headers: {
'x-hasura-admin-secret': process.env.HASURA_GRAPHQL_ADMIN_SECRET,
},
},
},
],
plugins: ['schema-ast'],
},
},
}

export default config
7 changes: 7 additions & 0 deletions src/backend-test/assets/common/client.ts.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import axios from 'axios'

export const client = axios.create({
baseURL: process.env.BASE_URL,
timeout: 15000,
validateStatus: () => true,
})
1 change: 1 addition & 0 deletions src/backend-test/assets/common/index.ts.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './client'
113 changes: 113 additions & 0 deletions src/backend-test/assets/eslint-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import {Linter} from 'eslint'

export const eslintConfig: Linter.Config = {
root: true,
env: {
jest: true,
node: true,
},
ignorePatterns: ['generated/index.ts', '**/*.generated.ts'],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 'latest',
sourceType: 'module',
},
rules: {
'padding-line-between-statements': [
'error',
{
blankLine: 'any',
prev: '*',
next: '*',
},
{
blankLine: 'always',
prev: '*',
next: 'multiline-block-like',
},
{
blankLine: 'always',
prev: 'multiline-block-like',
next: '*',
},
{
blankLine: 'always',
prev: '*',
next: 'multiline-const',
},
{
blankLine: 'always',
prev: 'multiline-const',
next: '*',
},
{
blankLine: 'always',
prev: '*',
next: 'multiline-expression',
},
{
blankLine: 'always',
prev: 'multiline-expression',
next: '*',
},
{
blankLine: 'always',
prev: '*',
next: 'multiline-let',
},
{
blankLine: 'always',
prev: 'multiline-let',
next: '*',
},
{
blankLine: 'never',
prev: ['singleline-const', 'singleline-let'],
next: ['singleline-const', 'singleline-let'],
},
],
'@typescript-eslint/ban-ts-comment': ['off'],
'@typescript-eslint/consistent-type-assertions': ['off'],
'@typescript-eslint/consistent-type-definitions': ['error', 'type'],
'@typescript-eslint/no-shadow': ['error'],
'@typescript-eslint/no-unused-expressions': ['error'],
'@typescript-eslint/no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
},
],
curly: ['error'],
'import/no-relative-parent-imports': ['error'],
'no-negated-condition': ['error'],
'no-nested-ternary': ['error'],
'eslint-comments/disable-enable-pair': [
'error',
{
allowWholeFile: true,
},
],
'eslint-comments/no-aggregating-enable': ['error'],
'eslint-comments/no-duplicate-disable': ['error'],
'eslint-comments/no-unlimited-disable': ['error'],
'eslint-comments/no-unused-disable': ['error'],
'eslint-comments/no-unused-enable': ['error'],
'eslint-comments/no-use': [
'error',
{
allow: ['eslint-disable', 'eslint-disable-next-line', 'eslint-enable'],
},
],
'eslint-comments/require-description': [
'error',
{
ignore: ['eslint-enable'],
},
],
},
extends: ['plugin:import/typescript', 'plugin:prettier/recommended'],
plugins: ['@typescript-eslint', 'eslint-comments', 'import', '@ottofeller/ottofeller'],
}
14 changes: 14 additions & 0 deletions src/backend-test/assets/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as dotenv from 'dotenv'
import type {Config} from 'jest'

dotenv.config({path: './.env.local'})
dotenv.config({path: './.env.development'})

const config: Config = {
testTimeout: 60000,
preset: 'ts-jest',
moduleDirectories: ['node_modules', '<rootDir>'],
setupFilesAfterEnv: ['jest-extended/all'],
}

export default config
43 changes: 43 additions & 0 deletions src/backend-test/assets/tests/auth.spec.ts.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import {AuthRequestBody, AuthResponseBody} from 'api/auth'
import {AxiosRequestConfig, AxiosResponse} from 'axios'
import {client} from 'common/client'

describe('Authorization & Authentication', () => {
test('Sign in with existing credentials', async () => {
const payload: AxiosRequestConfig<AuthRequestBody> = {
method: 'post',
url: '/auth',
data: {
login: process.env.USERNAME,
password: process.env.PASSWORD,
},
}

const response: AxiosResponse<AuthResponseBody> = await client.request(payload)

expect(response.status).toEqual(200)

expect(response.data).toEqual({
token: expect.any(String),
})
})

test('Sign in with not existing credentials', async () => {
const payload: AxiosRequestConfig<AuthRequestBody> = {
method: 'post',
url: '/auth',
data: {
login: 'invalid',
password: 'invalid',
},
}

const response: AxiosResponse<AuthResponseBody> = await client.request(payload)

expect(response.status).toEqual(404)

expect(response.data).toEqual({
message: expect.any(String),
})
})
})
Loading

0 comments on commit 4c1d48d

Please sign in to comment.