Skip to content

Commit

Permalink
Merge branch 'main' into fix-statistics-endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
Mnigos authored Dec 9, 2023
2 parents 548da54 + 33587ed commit 9aea61c
Show file tree
Hide file tree
Showing 33 changed files with 209 additions and 107 deletions.
2 changes: 0 additions & 2 deletions src/common/adapters/artists.adapter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { describe, test, expect } from 'vitest'

import {
spotifyArtistMock,
artistMock,
Expand Down
2 changes: 0 additions & 2 deletions src/common/adapters/audio-features.adapter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { expect, test, describe } from 'vitest'

import { spotifyAudioFeaturesMock, audioFeaturesMock } from '../mocks'

import { adaptAudioFeatures } from './audio-features.adapter'
Expand Down
2 changes: 0 additions & 2 deletions src/common/adapters/devices.adapter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { expect, test, describe } from 'vitest'

import { spotifyDevicesMock, devicesMock } from '../mocks'

import { adaptDevices } from './devices.adapter'
Expand Down
2 changes: 0 additions & 2 deletions src/common/adapters/genres.adapter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { test, describe, expect } from 'vitest'

import { spotifyArtistsMock, topGenresMock } from '../mocks'

import { adaptGenres } from './genres.adapter'
Expand Down
2 changes: 0 additions & 2 deletions src/common/adapters/paginated.adapter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { describe, test, expect } from 'vitest'

import {
artistsMock,
spotifyArtistsMock,
Expand Down
2 changes: 0 additions & 2 deletions src/common/adapters/playback-state.adapter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { test, describe, expect } from 'vitest'

import { spotifyPlaybackStateMock, playbackStateMock } from '../mocks'

import { adaptPlaybackState } from './playback-state.adapter'
Expand Down
2 changes: 0 additions & 2 deletions src/common/adapters/profile.adapter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { test, describe, expect } from 'vitest'

import { spotifyProfileMock, profileMock } from '../mocks'

import { adaptProfile } from './profile.adapter'
Expand Down
2 changes: 0 additions & 2 deletions src/common/adapters/secret-data.adapter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { test, describe, expect } from 'vitest'

import { SpotifyToken } from '../types/spotify'

import { adaptSecretData } from './secret-data.adapter'
Expand Down
2 changes: 0 additions & 2 deletions src/common/adapters/tracks.adapter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { test, describe, expect } from 'vitest'

import {
spotifyTracksMock,
tracksMock,
Expand Down
5 changes: 3 additions & 2 deletions src/common/mocks/axios-response.factory.mock.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { AxiosResponse, InternalAxiosRequestConfig } from 'axios'

export const axiosResponseMockFactory = <TData = unknown>(
data: TData
data: TData,
status = 200
): AxiosResponse<TData> => ({
data,
status: 200,
status,
statusText: 'OK',
headers: {},
config: {} as InternalAxiosRequestConfig,
Expand Down
2 changes: 0 additions & 2 deletions src/common/utils/apply-authorization-header.util.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { test, describe, expect } from 'vitest'

import { applyAuthorizationHeader } from './apply-authorization-header.util'

describe('applyAuthorizationHeader', () => {
Expand Down
87 changes: 56 additions & 31 deletions src/common/utils/catch-spotify-error.spec.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,77 @@
import { test, describe, expect } from 'vitest'
import { BadGatewayException, UnauthorizedException } from '@nestjs/common'

import {
InternalServerErrorException,
UnauthorizedException,
} from '@nestjs/common'
SPOTIFY_DEFAULT_ERROR_MESSAGE,
SpotifyAuthError,
catchSpotifyError,
} from './catch-spotify-error'

import { catchSpotifyError } from './catch-spotify-error'
import { axiosResponseMockFactory } from '@common/mocks'

describe('catchSpotifyError', () => {
test('should throw UnauthorizedException', () => {
const message = 'Unauthorized'

expect(() =>
catchSpotifyError({
response: {
data: {
catchSpotifyError(
axiosResponseMockFactory(
{
error: {
message: 'Unauthorized',
message,
status: 401,
},
},
status: 401,
},
})
).toThrowError(UnauthorizedException)
401
)
)
).toThrowError(new UnauthorizedException(message))
})

test('should throw UnauthorizedException as invalid grant', () => {
const message = 'Invalid token'

expect(() =>
catchSpotifyError({
response: {
data: {
catchSpotifyError(
axiosResponseMockFactory(
{
error: 'invalid_grant',
error_description: message,
},
status: 401,
},
})
).toThrowError(UnauthorizedException)
401
)
)
).toThrowError(new UnauthorizedException(message))
})

test('should throw InternalServerErrorException', () => {
test('should throw BadGatewayException', () => {
const message = 'Bad Gateway'

expect(() =>
catchSpotifyError({
response: {
data: {
error: {
message: 'Internal Server Error',
},
catchSpotifyError(
axiosResponseMockFactory({
error: {
message,
status: 502,
},
status: 500,
},
})
).toThrowError(InternalServerErrorException)
})
)
).toThrowError(
new BadGatewayException(SPOTIFY_DEFAULT_ERROR_MESSAGE + message)
)
})

test('should throw BadGatewayException', () => {
const message = 'Bad Gateway'

expect(() =>
catchSpotifyError(
axiosResponseMockFactory<SpotifyAuthError>({
error: message,
error_description: message,
})
)
).toThrowError(
new BadGatewayException(SPOTIFY_DEFAULT_ERROR_MESSAGE + message)
)
})
})
66 changes: 41 additions & 25 deletions src/common/utils/catch-spotify-error.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,45 @@
import {
ForbiddenException,
InternalServerErrorException,
UnauthorizedException,
} from '@nestjs/common'

export const catchSpotifyError = error => {
console.log(error)

const {
response: { data, status },
} = error

if (data?.error === 'invalid_grant')
throw new UnauthorizedException('Invalid token')
if (status === 401) throw new UnauthorizedException(data?.error?.message)
if (
status === 403 &&
data === 'User not registered in the Developer Dashboard'
)
throw new ForbiddenException(
'User not registered in the Developer Dashboard'
import { BadGatewayException, UnauthorizedException } from '@nestjs/common'
import { AxiosResponse } from 'axios'

export interface SpotifyAuthError {
error: string
error_description: string
}

export interface SpotifyError {
error: {
status: number
message: string
}
}

export type SpotifyResponseError = AxiosResponse<
SpotifyError | SpotifyAuthError
>

export const SPOTIFY_DEFAULT_ERROR_MESSAGE =
'Something went wrong with fetching data from spotify API:'

export const catchSpotifyError = (response: SpotifyResponseError) => {
console.log(response.data.error)

const { data, status } = response

if ('error_description' in data) {
console.log('ee')
if (data.error === 'invalid_grant')
throw new UnauthorizedException('Invalid token')

throw new BadGatewayException(
SPOTIFY_DEFAULT_ERROR_MESSAGE + data.error_description
)
}

console.log(status)

if (status === 401) throw new UnauthorizedException(data.error.message)

throw new InternalServerErrorException(
'Something went wrong with fetching data from spotify API',
data?.error
throw new BadGatewayException(
SPOTIFY_DEFAULT_ERROR_MESSAGE + data.error.message
)
}
2 changes: 0 additions & 2 deletions src/common/utils/get-most-frequent-items.util.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { test, describe, expect } from 'vitest'

import { getMostFrequentItems } from '.'

describe('GetMostFrequentItems', () => {
Expand Down
1 change: 0 additions & 1 deletion src/modules/auth/auth.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { test, describe, expect, beforeEach, vi } from 'vitest'
import { HttpStatus } from '@nestjs/common'
import { ConfigService } from '@nestjs/config'
import { Test, TestingModule } from '@nestjs/testing'
Expand Down
13 changes: 12 additions & 1 deletion src/modules/auth/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ import {
} from '@nestjs/common'
import { ConfigService } from '@nestjs/config'
import { firstValueFrom } from 'rxjs'
import { ApiExcludeEndpoint, ApiOkResponse, ApiTags } from '@nestjs/swagger'
import {
ApiExcludeEndpoint,
ApiOkResponse,
ApiOperation,
ApiTags,
} from '@nestjs/swagger'

import { AuthService } from './auth.service'
import { spotifyAuthorizationScopes } from './config'
Expand Down Expand Up @@ -94,6 +99,9 @@ export class AuthController {
}

@Get('refresh')
@ApiOperation({
summary: 'Refreshing access token.',
})
@ApiAuth(AuthenticationType.REFRESH_TOKEN)
@ApiOkResponse({
description: 'Access token has been succesfully refreshed',
Expand All @@ -104,6 +112,9 @@ export class AuthController {
}

@Get('profile')
@ApiOperation({
summary: "Getting current user's profile.",
})
@ApiAuth(AuthenticationType.ACCESS_TOKEN)
@ApiOkResponse({
description: "User's profile has been succesfully found",
Expand Down
1 change: 0 additions & 1 deletion src/modules/auth/auth.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { URLSearchParams } from 'node:url'

import { test, describe, expect, beforeEach, vi } from 'vitest'
import { HttpService } from '@nestjs/axios'
import { ConfigService } from '@nestjs/config'
import { JwtService } from '@nestjs/jwt'
Expand Down
1 change: 0 additions & 1 deletion src/modules/auth/decorators/token.decorator.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { test, describe, expect, vi } from 'vitest'
import { ExecutionContext, UnauthorizedException } from '@nestjs/common'
import { mock } from 'vitest-mock-extended'

Expand Down
1 change: 0 additions & 1 deletion src/modules/images/images.repository.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { beforeEach, describe, expect, test, vi } from 'vitest'
import { Test } from '@nestjs/testing'
import { DataSource } from 'typeorm'

Expand Down
1 change: 0 additions & 1 deletion src/modules/player/player.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { test, describe, expect, beforeEach, vi } from 'vitest'
import { Test, TestingModule } from '@nestjs/testing'
import { firstValueFrom, of } from 'rxjs'

Expand Down
17 changes: 15 additions & 2 deletions src/modules/player/player.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Controller, Get, Put, Query } from '@nestjs/common'
import {
ApiForbiddenResponse,
ApiOkResponse,
ApiOperation,
ApiQuery,
ApiTags,
} from '@nestjs/swagger'
Expand All @@ -19,6 +20,9 @@ export class PlayerController {
constructor(private readonly playerService: PlayerService) {}

@Get('/devices')
@ApiOperation({
summary: "Getting current user's available devices.",
})
@ApiOkResponse({
description: 'Available devices has been succesfully found',
})
Expand All @@ -27,6 +31,9 @@ export class PlayerController {
}

@Get('/state')
@ApiOperation({
summary: "Getting current user's playback state.",
})
@ApiOkResponse({
description: 'Current playback state has been succesfully found',
})
Expand All @@ -35,13 +42,16 @@ export class PlayerController {
}

@Put('/pause')
@ApiOperation({
summary: "Pausing current user's player.",
})
@ApiQuery({ name: 'afterTime', type: Number, required: false })
@ApiQuery({ name: 'deviceId', type: String, required: false })
@ApiForbiddenResponse({
description: 'No device is currently playing',
})
@ApiOkResponse({
description: 'Player state has been succesfully paused',
description: 'Player has been succesfully paused',
type: Success,
})
pausePlayer(
Expand All @@ -53,12 +63,15 @@ export class PlayerController {
}

@Put('/resume')
@ApiOperation({
summary: "Resuming current user's player.",
})
@ApiQuery({ name: 'deviceId', type: String, required: false })
@ApiForbiddenResponse({
description: 'Device is already playing',
})
@ApiOkResponse({
description: 'Player state has been succesfully resumed',
description: 'Player has been succesfully resumed',
type: Success,
})
resumePlayer(
Expand Down
1 change: 0 additions & 1 deletion src/modules/player/player.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { test, describe, expect, beforeEach, vi } from 'vitest'
import { HttpService } from '@nestjs/axios'
import { TestingModule, Test } from '@nestjs/testing'
import { of, firstValueFrom, throwError, catchError } from 'rxjs'
Expand Down
1 change: 0 additions & 1 deletion src/modules/profiles/profiles.repository.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { beforeEach, describe, expect, test, vi } from 'vitest'
import { DataSource } from 'typeorm'
import { Test, TestingModule } from '@nestjs/testing'

Expand Down
1 change: 0 additions & 1 deletion src/modules/profiles/profiles.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { beforeEach, describe, expect, test, vi } from 'vitest'
import { Test } from '@nestjs/testing'
import { mock } from 'vitest-mock-extended'

Expand Down
Loading

0 comments on commit 9aea61c

Please sign in to comment.