Skip to content

Commit

Permalink
Merge pull request #133 from codeforjapan/yash/e2e-part2
Browse files Browse the repository at this point in the history
  • Loading branch information
shogo-mitomo authored May 14, 2020
2 parents f8f0dc6 + bcd5e4c commit f43e8fc
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 29 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"@types/supertest": "^2.0.8",
"@typescript-eslint/eslint-plugin": "^2.23.0",
"@typescript-eslint/parser": "^2.23.0",
"axios": "^0.19.2",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.0",
"eslint-plugin-import": "^2.20.1",
Expand Down
6 changes: 4 additions & 2 deletions src/auth/dto/login-normal-user.dto.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { ApiProperty } from '@nestjs/swagger'
import { IsNumber } from 'class-validator'
import { IsInt, Min, Max } from 'class-validator'

export class LoginNormalUserRequestDto {
@ApiProperty()
@IsNumber()
@IsInt()
@Min(0)
@Max(47)
prefecture: number
}
10 changes: 7 additions & 3 deletions src/users/dto/create-user.dto.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'
import { IsString, IsNumber, IsOptional, IsNotEmpty } from 'class-validator'
import { IsString, IsOptional, IsNotEmpty, IsInt, Max, Min } from 'class-validator'

export class CreateUserDto {
@ApiProperty()
Expand All @@ -10,14 +10,18 @@ export class CreateUserDto {

export class CreateUserProfileDto {
@ApiProperty()
@IsNumber()
@IsInt()
@Min(0)
@Max(47)
prefecture: number
}

export class UpdateUserProfileDto {
@ApiPropertyOptional({ example: 14 })
@IsOptional()
@IsNumber()
@IsInt()
@Min(0)
@Max(47)
prefecture: number

// Keys without any decorators are non-Whitelisted. Validator will throw error if it's passed in payload.
Expand Down
14 changes: 12 additions & 2 deletions test/app.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,33 @@ import { Test, TestingModule } from '@nestjs/testing'
import { INestApplication } from '@nestjs/common'
import * as request from 'supertest'
import { AppModule } from './../src/app.module'
import * as firebaseAdmin from 'firebase-admin'

describe('AppController (e2e)', () => {
let app: INestApplication

beforeEach(async () => {
beforeAll(async (done) => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile()

app = moduleFixture.createNestApplication()
await app.init()

done()
})

it('/ (GET)', () => {
it('/ (GET)', (done) => {
return request(app.getHttpServer())
.get('/')
.expect(200)
.expect('Hello World!')
.end(() => done())
})

afterAll(async (done) => {
await firebaseAdmin.app().delete()
await app.close()
done()
})
})
97 changes: 87 additions & 10 deletions test/auth.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,46 @@ import * as request from 'supertest'
import { AppModule } from './../src/app.module'
import { ConfigService } from '@nestjs/config'
import * as firebaseAdmin from 'firebase-admin'
import { generateFirebaseDefaultToken } from './util'
import { generateFirebaseDefaultToken, deleteFirebaseTestUser } from './util'

describe('AppController (e2e)', () => {
describe('AuthController (e2e)', () => {
let app: INestApplication
let customToken: string
let firebaseDefaultToken: string
const testUIDNormalUser = 'E2E_TEST_UID_NORMAL_USER'

beforeAll(async () => {
beforeAll(async (done) => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile()

app = moduleFixture.createNestApplication()
await app.init()

// TODO @yashmurty : Add API Key to env file.
const configService = app.get(ConfigService)
const firebaseWebAPIKey = configService.get('FIREBASE_WEB_API_KEY')
console.log('firebaseWebAPIKey : ', firebaseWebAPIKey)
customToken = await firebaseAdmin.auth().createCustomToken('uid')
customToken = await firebaseAdmin.auth().createCustomToken(testUIDNormalUser, {
// eslint-disable-next-line @typescript-eslint/camelcase
provider_id: 'anonymous',
})

await generateFirebaseDefaultToken(customToken, firebaseWebAPIKey)
firebaseDefaultToken = await generateFirebaseDefaultToken(customToken, firebaseWebAPIKey)

done()
})

it('/auth/login (POST) - No Auth bearer', () => {
it('/auth/login (POST) - No Auth bearer', (done) => {
return request(app.getHttpServer())
.post('/auth/login')
.expect(401)
.expect((response) => {
expect(response.body.error).toEqual('Unauthorized')
expect(response.body.message).toEqual('No bearer token found in the header')
})
.end(() => done())
})

it('/auth/login (POST) - Invalid Auth bearer', () => {
it('/auth/login (POST) - Invalid Auth bearer', (done) => {
return request(app.getHttpServer())
.post('/auth/login')
.set('Authorization', 'Bearer RANDOM_STRING')
Expand All @@ -46,9 +52,10 @@ describe('AppController (e2e)', () => {
expect(response.body.error).toEqual('Unauthorized')
expect(response.body.message).toContain('Decoding Firebase ID token failed')
})
.end(() => done())
})

it('/auth/login (POST) - CustomToken Auth bearer', () => {
it('/auth/login (POST) - CustomToken Auth bearer', (done) => {
return request(app.getHttpServer())
.post('/auth/login')
.set('Authorization', `Bearer ${customToken}`)
Expand All @@ -57,5 +64,75 @@ describe('AppController (e2e)', () => {
expect(response.body.error).toEqual('Unauthorized')
expect(response.body.message).toContain('expects an ID token, but was given a custom token')
})
.end(() => done())
})

it('/auth/login (POST) - FDT Auth bearer without prefecture', (done) => {
return request(app.getHttpServer())
.post('/auth/login')
.set('Authorization', `Bearer ${firebaseDefaultToken}`)
.expect(400)
.expect((response) => {
expect(response.body.error).toEqual('Bad Request')
expect(response.body.message).toBeInstanceOf(Array)
expect(response.body.message).toContain('prefecture must be an integer number')
})
.end(() => done())
})

it('/auth/login (POST) - FDT Auth bearer with invalid prefecture', (done) => {
return request(app.getHttpServer())
.post('/auth/login')
.set('Authorization', `Bearer ${firebaseDefaultToken}`)
.send({
prefecture: 'random_value',
})
.expect(400)
.expect((response) => {
expect(response.body.error).toEqual('Bad Request')
expect(response.body.message).toBeInstanceOf(Array)
expect(response.body.message).toContain('prefecture must be an integer number')
})
.end(() => done())
})

it('/auth/login (POST) - FDT Auth bearer with invalid prefecture', (done) => {
return request(app.getHttpServer())
.post('/auth/login')
.set('Authorization', `Bearer ${firebaseDefaultToken}`)
.send({
prefecture: 100,
})
.expect(400)
.expect((response) => {
expect(response.body.error).toEqual('Bad Request')
expect(response.body.message).toBeInstanceOf(Array)
expect(response.body.message).toContain('prefecture must not be greater than 47')
})
.end(() => done())
})

it('/auth/login (POST) - FDT Auth bearer with valid prefecture', (done) => {
return request(app.getHttpServer())
.post('/auth/login')
.set('Authorization', `Bearer ${firebaseDefaultToken}`)
.send({
prefecture: 1,
})
.expect(200)
.expect((response) => {
expect(response.body).toEqual({})
expect(response.body).toBeInstanceOf(Object)
expect(response.body).toMatchObject({})
})
.end(() => done())
})

afterAll(async (done) => {
await deleteFirebaseTestUser(testUIDNormalUser)

await firebaseAdmin.app().delete()
await app.close()
done()
})
})
63 changes: 51 additions & 12 deletions test/util.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,54 @@
import * as request from 'supertest'

// TODO @yashmurty : WIP.
export async function generateFirebaseDefaultToken(customToken: string, firebaseWebAPIKey: string) {
await request(`https://identitytoolkit.googleapis.com/`)
.post(`/v1/accounts:signInWithCustomToken?key=${firebaseWebAPIKey}`)
.send({
token: customToken,
returnSecureToken: true,
import axios from 'axios'
import * as firebaseAdmin from 'firebase-admin'

/**
* Generate firebase default token. Uses the custom token generated via
* Firebase Admin SDK and returns firebase idToken.
* @param customToken
* @param firebaseWebAPIKey
*/
export async function generateFirebaseDefaultToken(
customToken: string,
firebaseWebAPIKey: string
): Promise<string> {
let firebaseDefaultToken: string

await axios
.post(
`https://identitytoolkit.googleapis.com/v1/accounts:signInWithCustomToken?key=
${firebaseWebAPIKey}`,
{
token: customToken,
returnSecureToken: true,
}
)
.then(function(response) {
firebaseDefaultToken = response.data.idToken
})
.set('Content-Type', 'application/json')
.expect((response) => {
console.log(response.body)
.catch(function(error) {
console.log(error.response.data.error)
throw error
})

return firebaseDefaultToken
}

/**
* Delete the test user from firebase auth and firestore.
* @param testUIDNormalUser
*/
export async function deleteFirebaseTestUser(testUIDNormalUser: string): Promise<void> {
await firebaseAdmin.auth().deleteUser(testUIDNormalUser)
await firebaseAdmin
.firestore()
.collection('users')
.doc(testUIDNormalUser)
.collection('profile')
.doc(testUIDNormalUser)
.delete()
await firebaseAdmin
.firestore()
.collection('users')
.doc(testUIDNormalUser)
.delete()
}

0 comments on commit f43e8fc

Please sign in to comment.