Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • tddd96-grupp11/teknikattan-scoring-system
1 result
Select Git revision
Show changes
Showing
with 586 additions and 38 deletions
import { render } from '@testing-library/react'
import React from 'react'
import { Provider } from 'react-redux'
import { BrowserRouter } from 'react-router-dom'
import store from '../../../store'
import AddRegion from './AddRegion'
it('renders add region', () => {
render(
<BrowserRouter>
<Provider store={store}>
<AddRegion />
</Provider>
</BrowserRouter>
)
})
import { render } from '@testing-library/react'
import mockedAxios from 'axios'
import React from 'react'
import { Provider } from 'react-redux'
import { BrowserRouter } from 'react-router-dom'
import store from '../../../store'
import RegionManager from './Regions'
it('renders region manager', () => {
const cityRes: any = {
data: {
items: [
{
id: 1,
name: 'Link\u00f6ping',
},
{
id: 2,
name: 'Stockholm',
},
],
count: 2,
total_count: 3,
},
}
;(mockedAxios.get as jest.Mock).mockImplementation((path: string, params?: any) => {
return Promise.resolve(cityRes)
})
render(
<BrowserRouter>
<Provider store={store}>
<RegionManager />
</Provider>
</BrowserRouter>
)
})
import { render } from '@testing-library/react'
import React from 'react'
import { Provider } from 'react-redux'
import { BrowserRouter } from 'react-router-dom'
import store from '../../../store'
import EditUser from './EditUser'
it('renders edit user', () => {
render(
<BrowserRouter>
<Provider store={store}>
<EditUser user={{ id: 0, name: '', email: '', role_id: 0, city_id: 0 }} />
</Provider>
</BrowserRouter>
)
})
import { render } from '@testing-library/react'
import React from 'react'
import { Provider } from 'react-redux'
import { BrowserRouter } from 'react-router-dom'
import store from '../../../store'
import AddUser from './AddUser'
it('renders edit user', () => {
render(
<BrowserRouter>
<Provider store={store}>
<AddUser />
</Provider>
</BrowserRouter>
)
})
import { render } from '@testing-library/react'
import mockedAxios from 'axios'
import React from 'react'
import { Provider } from 'react-redux'
import { BrowserRouter } from 'react-router-dom'
import store from '../../../store'
import UserManager from './UserManager'
it('renders user manager', () => {
const userRes: any = {
data: {
items: [
{
id: 1,
name: 'user1',
email: 'user1@email.com',
role_id: 0,
city_id: 0,
},
{
id: 2,
name: 'Stockholm',
email: 'user2@email.com',
role_id: 0,
city_id: 0,
},
],
count: 2,
total_count: 3,
},
}
;(mockedAxios.get as jest.Mock).mockImplementation((path: string, params?: any) => {
return Promise.resolve(userRes)
})
render(
<BrowserRouter>
<Provider store={store}>
<UserManager />
</Provider>
</BrowserRouter>
)
})
...@@ -70,7 +70,6 @@ const UserManager: React.FC = (props: any) => { ...@@ -70,7 +70,6 @@ const UserManager: React.FC = (props: any) => {
}, []) }, [])
useEffect(() => { useEffect(() => {
console.log('asd')
setEditAnchorEl(null) setEditAnchorEl(null)
setAnchorEl(null) setAnchorEl(null)
}, [users]) }, [users])
......
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import React from 'react' import React from 'react'
import CompetitionSettings from './CompetitionSettings' import ImageComponentDisplay from './ImageComponentDisplay'
it('renders competition settings', () => { it('renders image component display', () => {
render(<CompetitionSettings />) render(<ImageComponentDisplay component={{ id: 0, x: 0, y: 0, w: 0, h: 0, type: 0, media_id: 0 }} />)
}) })
import { render } from '@testing-library/react'
import React from 'react'
import ImageComponentDisplay from './ImageComponentDisplay'
it('renders competition settings', () => {
render(<ImageComponentDisplay component={{ id: 0, x: 0, y: 0, w: 0, h: 0, media_id: 0, type: 2 }} />)
})
import { Editor } from '@tinymce/tinymce-react'
import { mount } from 'enzyme'
import React from 'react'
import TextComponentDisplay from './TextComponentDisplay'
it('renders text component display', () => {
const testText = 'TEST'
const container = mount(
<TextComponentDisplay component={{ id: 0, x: 0, y: 0, w: 0, h: 0, text: testText, type: 2, font: '123123' }} />
)
expect(container.find(Editor).prop('initialValue')).toBe(testText)
})
import Types from '../actions/types'
import citiesReducer from './citiesReducer'
const initialState = {
cities: [],
total: 0,
count: 0,
}
it('should return the initial state', () => {
expect(citiesReducer(undefined, {} as any)).toEqual(initialState)
})
it('should handle SET_CITIES', () => {
const testCities = [{ name: 'testName', id: 0 }]
expect(
citiesReducer(initialState, {
type: Types.SET_CITIES,
payload: testCities,
})
).toEqual({
cities: testCities,
total: 0,
count: 0,
})
})
it('should handle SET_CITIES_TOTAL', () => {
const testTotal = 123123
expect(
citiesReducer(initialState, {
type: Types.SET_CITIES_TOTAL,
payload: testTotal,
})
).toEqual({
cities: [],
total: testTotal,
count: 0,
})
})
it('should handle SET_CITIES_COUNT', () => {
const testCount = 456456
expect(
citiesReducer(initialState, {
type: Types.SET_CITIES_COUNT,
payload: testCount,
})
).toEqual({
cities: [],
total: 0,
count: testCount,
})
})
import Types from '../actions/types'
import { RichSlide } from '../interfaces/ApiRichModels'
import { Slide } from '../interfaces/Slide'
import presentationReducer from './presentationReducer'
const initialState = {
competition: {
name: '',
id: 0,
city: {
id: 0,
name: '',
},
slides: [],
year: 0,
teams: [],
},
slide: {
competition_id: 0,
id: 0,
order: 0,
timer: 0,
title: '',
},
teams: [],
}
it('should return the initial state', () => {
expect(presentationReducer(undefined, {} as any)).toEqual(initialState)
})
it('should handle SET_PRESENTATION_COMPETITION', () => {
const testCompetition = {
name: 'testCompName',
id: 4,
city: {
id: 3,
name: 'testCityName',
},
slides: [{ id: 20 }],
year: 1999,
teams: [],
}
expect(
presentationReducer(initialState, {
type: Types.SET_PRESENTATION_COMPETITION,
payload: testCompetition,
})
).toEqual({
competition: testCompetition,
slide: testCompetition.slides[0],
teams: [],
})
})
it('should handle SET_PRESENTATION_TEAMS', () => {
const testTeams = [
{
name: 'testTeamName1',
id: 3,
},
{
name: 'testTeamName2',
id: 5,
},
]
expect(
presentationReducer(initialState, {
type: Types.SET_PRESENTATION_TEAMS,
payload: testTeams,
})
).toEqual({
competition: initialState.competition,
slide: initialState.slide,
teams: testTeams,
})
})
it('should handle SET_PRESENTATION_SLIDE', () => {
const testSlide = [
{
competition_id: 20,
id: 4,
order: 3,
timer: 123,
title: 'testSlideTitle',
},
]
expect(
presentationReducer(initialState, {
type: Types.SET_PRESENTATION_SLIDE,
payload: testSlide,
})
).toEqual({
competition: initialState.competition,
slide: testSlide,
teams: initialState.teams,
})
})
describe('should handle SET_PRESENTATION_SLIDE_PREVIOUS', () => {
it('by changing slide to the previous if there is one', () => {
const testPresentationState = {
competition: {
...initialState.competition,
slides: [
{ competition_id: 0, order: 0 },
{ competition_id: 0, order: 1 },
] as RichSlide[],
},
teams: initialState.teams,
slide: { competition_id: 0, order: 1 } as Slide,
}
expect(
presentationReducer(testPresentationState, {
type: Types.SET_PRESENTATION_SLIDE_PREVIOUS,
})
).toEqual({
competition: testPresentationState.competition,
slide: testPresentationState.competition.slides[0],
teams: testPresentationState.teams,
})
})
it('by not changing slide if there is no previous one', () => {
const testPresentationState = {
competition: {
...initialState.competition,
slides: [
{ competition_id: 0, order: 0 },
{ competition_id: 0, order: 1 },
] as RichSlide[],
},
teams: initialState.teams,
slide: { competition_id: 0, order: 0 } as Slide,
}
expect(
presentationReducer(testPresentationState, {
type: Types.SET_PRESENTATION_SLIDE_PREVIOUS,
})
).toEqual({
competition: testPresentationState.competition,
slide: testPresentationState.competition.slides[0],
teams: testPresentationState.teams,
})
})
})
describe('should handle SET_PRESENTATION_SLIDE_NEXT', () => {
it('by changing slide to the next if there is one', () => {
const testPresentationState = {
competition: {
...initialState.competition,
slides: [
{ competition_id: 0, order: 0 },
{ competition_id: 0, order: 1 },
] as RichSlide[],
},
teams: initialState.teams,
slide: { competition_id: 0, order: 0 } as Slide,
}
expect(
presentationReducer(testPresentationState, {
type: Types.SET_PRESENTATION_SLIDE_NEXT,
})
).toEqual({
competition: testPresentationState.competition,
slide: testPresentationState.competition.slides[1],
teams: testPresentationState.teams,
})
})
it('by not changing slide if there is no next one', () => {
const testPresentationState = {
competition: {
...initialState.competition,
slides: [
{ competition_id: 0, order: 0 },
{ competition_id: 0, order: 1 },
] as RichSlide[],
},
teams: initialState.teams,
slide: { competition_id: 0, order: 1 } as Slide,
}
expect(
presentationReducer(testPresentationState, {
type: Types.SET_PRESENTATION_SLIDE_NEXT,
})
).toEqual({
competition: testPresentationState.competition,
slide: testPresentationState.competition.slides[1],
teams: testPresentationState.teams,
})
})
})
import Types from '../actions/types'
import userReducer from './userReducer'
const initialState = {
authenticated: false,
loading: false,
userInfo: null,
}
it('should return the initial state', () => {
expect(userReducer(undefined, {} as any)).toEqual(initialState)
})
it('should handle SET_AUTHENTICATED', () => {
expect(
userReducer(initialState, {
type: Types.SET_AUTHENTICATED,
})
).toEqual({
authenticated: true,
loading: initialState.loading,
userInfo: initialState.userInfo,
})
})
it('should handle SET_UNAUTHENTICATED', () => {
expect(
userReducer(initialState, {
type: Types.SET_UNAUTHENTICATED,
})
).toEqual(initialState)
})
it('should handle SET_USER', () => {
const testUserInfo = {
name: 'testName',
email: 'test@email.com',
role: { id: 0, name: 'roleName' },
city: { id: 0, name: 'cityName' },
id: 0,
}
expect(
userReducer(initialState, {
type: Types.SET_USER,
payload: testUserInfo,
})
).toEqual({
authenticated: true,
loading: false,
userInfo: testUserInfo,
})
})
it('should handle LOADING_USER', () => {
expect(
userReducer(initialState, {
type: Types.LOADING_USER,
})
).toEqual({
loading: true,
authenticated: initialState.authenticated,
userInfo: initialState.userInfo,
})
})
import Types from '../actions/types'
import uiReducer from './uiReducer'
const initialState = {
loading: false,
errors: null,
}
it('should return the initial state', () => {
expect(uiReducer(undefined, {} as any)).toEqual(initialState)
})
it('should handle SET_ERRORS', () => {
const testError = { message: 'errorMessage' }
expect(
uiReducer(initialState, {
type: Types.SET_ERRORS,
payload: testError,
})
).toEqual({
loading: false,
errors: testError,
})
})
it('should handle CLEAR_ERRORS', () => {
expect(
uiReducer(initialState, {
type: Types.CLEAR_ERRORS,
})
).toEqual({
loading: false,
errors: null,
})
})
it('should handle LOADING_UI', () => {
expect(
uiReducer(initialState, {
type: Types.LOADING_UI,
})
).toEqual({
loading: true,
errors: initialState.errors,
})
})
import mockedAxios from 'axios'
import Types from '../actions/types'
import store from '../store'
import { CheckAuthentication } from './checkAuthentication'
it('dispatches correct actions when auth token is ok', async () => {
const userRes: any = {
data: {
name: 'username',
},
}
;(mockedAxios.get as jest.Mock).mockImplementation((path: string, params?: any) => {
return Promise.resolve(userRes)
})
const spy = jest.spyOn(store, 'dispatch')
const testToken =
'Bearer eyJ0eXAiOiJeyJ0eXAiOiJKV1QeyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2MTgzMDQ5MzksImV4cCI6MzI1MTI1MjU3NTcsImF1ZCI6Ind3dy5leGFtcGxlLmNvbSIsInN1YiI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJHaXZlbk5hbWUiOiJKb2hubnkiLCJTdXJuYW1lIjoiUm9ja2V0IiwiRW1haWwiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiUm9sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19.DrOOcCo5jMR-SNERE0uRp_kolQ2HjX8-hHXYEMnIxSceyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2MTgzMDQ5MzksImV4cCI6MzI1MTI1MjU3NTcsImF1ZCI6Ind3dy5leGFtcGxlLmNvbSIsInN1YiI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJHaXZlbk5hbWUiOiJKb2hubnkiLCJTdXJuYW1lIjoiUm9ja2V0IiwiRW1haWwiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiUm9sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19.DrOOcCo5jMR-SNERE0uRp_kolQ2HjX8-hHXYEMnIxSceyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2MTgzMDQ5MzksImV4cCI6MzI1MTI1MjU3NTcsImF1ZCI6Ind3dy5leGFtcGxlLmNvbSIsInN1YiI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJHaXZlbk5hbWUiOiJKb2hubnkiLCJTdXJuYW1lIjoiUm9ja2V0IiwiRW1haWwiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiUm9sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19.DrOOcCo5jMR-SNERE0uRp_kolQ2HjX8-hHXYEMnIxSceyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2MTgzMDQ5MzksImV4cCI6MzI1MTI1MjU3NTcsImF1ZCI6Ind3dy5leGFtcGxlLmNvbSIsInN1YiI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJHaXZlbk5hbWUiOiJKb2hubnkiLCJTdXJuYW1lIjoiUm9ja2V0IiwiRW1haWwiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiUm9sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19.DrOOcCo5jMR-SNERE0uRp_kolQ2HjX8-hHXYEMnIxSciLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2MTgzMDQ5MzksImV4cCI6MzI1MTI1MjU3NTcsImF1ZCI6Ind3dy5leGFtcGxlLmNvbSIsInN1YiI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJHaXZlbk5hbWUiOiJKb2hubnkiLCJTdXJuYW1lIjoiUm9ja2V0IiwiRW1haWwiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiUm9sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19.DrOOcCo5jMR-SNERE0uRp_kolQ2HjX8-hHXYEMnIxScKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2MTgzMDQ5MzksImV4cCI6MzI1MTI1MjU3NTcsImF1ZCI6Ind3dy5leGFtcGxlLmNvbSIsInN1YiI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJHaXZlbk5hbWUiOiJKb2hubnkiLCJTdXJuYW1lIjoiUm9ja2V0IiwiRW1haWwiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiUm9sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19.DrOOcCo5jMR-SNERE0uRp_kolQ2HjX8-hHXYEMnIxSc'
localStorage.setItem('token', testToken)
await CheckAuthentication()
expect(spy).toBeCalledWith({ type: Types.LOADING_USER })
expect(spy).toBeCalledWith({ type: Types.SET_AUTHENTICATED })
expect(spy).toBeCalledWith({ type: Types.SET_USER, payload: userRes.data })
expect(spy).toBeCalledTimes(3)
})
it('dispatches correct actions when getting user data fails', async () => {
console.log = jest.fn()
;(mockedAxios.get as jest.Mock).mockImplementation((path: string, params?: any) => {
return Promise.reject(new Error('failed getting user data'))
})
const spy = jest.spyOn(store, 'dispatch')
const testToken =
'Bearer eyJ0eXAiOiJeyJ0eXAiOiJKV1QeyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2MTgzMDQ5MzksImV4cCI6MzI1MTI1MjU3NTcsImF1ZCI6Ind3dy5leGFtcGxlLmNvbSIsInN1YiI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJHaXZlbk5hbWUiOiJKb2hubnkiLCJTdXJuYW1lIjoiUm9ja2V0IiwiRW1haWwiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiUm9sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19.DrOOcCo5jMR-SNERE0uRp_kolQ2HjX8-hHXYEMnIxSceyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2MTgzMDQ5MzksImV4cCI6MzI1MTI1MjU3NTcsImF1ZCI6Ind3dy5leGFtcGxlLmNvbSIsInN1YiI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJHaXZlbk5hbWUiOiJKb2hubnkiLCJTdXJuYW1lIjoiUm9ja2V0IiwiRW1haWwiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiUm9sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19.DrOOcCo5jMR-SNERE0uRp_kolQ2HjX8-hHXYEMnIxSceyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2MTgzMDQ5MzksImV4cCI6MzI1MTI1MjU3NTcsImF1ZCI6Ind3dy5leGFtcGxlLmNvbSIsInN1YiI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJHaXZlbk5hbWUiOiJKb2hubnkiLCJTdXJuYW1lIjoiUm9ja2V0IiwiRW1haWwiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiUm9sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19.DrOOcCo5jMR-SNERE0uRp_kolQ2HjX8-hHXYEMnIxSceyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2MTgzMDQ5MzksImV4cCI6MzI1MTI1MjU3NTcsImF1ZCI6Ind3dy5leGFtcGxlLmNvbSIsInN1YiI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJHaXZlbk5hbWUiOiJKb2hubnkiLCJTdXJuYW1lIjoiUm9ja2V0IiwiRW1haWwiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiUm9sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19.DrOOcCo5jMR-SNERE0uRp_kolQ2HjX8-hHXYEMnIxSciLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2MTgzMDQ5MzksImV4cCI6MzI1MTI1MjU3NTcsImF1ZCI6Ind3dy5leGFtcGxlLmNvbSIsInN1YiI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJHaXZlbk5hbWUiOiJKb2hubnkiLCJTdXJuYW1lIjoiUm9ja2V0IiwiRW1haWwiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiUm9sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19.DrOOcCo5jMR-SNERE0uRp_kolQ2HjX8-hHXYEMnIxScKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2MTgzMDQ5MzksImV4cCI6MzI1MTI1MjU3NTcsImF1ZCI6Ind3dy5leGFtcGxlLmNvbSIsInN1YiI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJHaXZlbk5hbWUiOiJKb2hubnkiLCJTdXJuYW1lIjoiUm9ja2V0IiwiRW1haWwiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiUm9sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19.DrOOcCo5jMR-SNERE0uRp_kolQ2HjX8-hHXYEMnIxSc'
localStorage.setItem('token', testToken)
await CheckAuthentication()
expect(spy).toBeCalledWith({ type: Types.LOADING_USER })
expect(spy).toBeCalledWith({ type: Types.SET_UNAUTHENTICATED })
expect(spy).toBeCalledTimes(2)
expect(console.log).toHaveBeenCalled()
})
it('dispatches no actions when no token exists', async () => {
const spy = jest.spyOn(store, 'dispatch')
await CheckAuthentication()
expect(spy).not.toBeCalled()
})
it('dispatches correct actions when token is expired', async () => {
const testToken =
'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2MTgzMDY1MTUsImV4cCI6MTU4Njc3MDUxNSwiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoianJvY2tldEBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6IkpvaG5ueSIsIlN1cm5hbWUiOiJSb2NrZXQiLCJFbWFpbCI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJSb2xlIjpbIk1hbmFnZXIiLCJQcm9qZWN0IEFkbWluaXN0cmF0b3IiXX0.R5-oWGGumd-YWPoKyziJmVB8SdX6B9SsV6m7novIfgg'
localStorage.setItem('token', testToken)
const spy = jest.spyOn(store, 'dispatch')
await CheckAuthentication()
expect(spy).toBeCalledWith({ type: Types.SET_UNAUTHENTICATED })
expect(spy).toBeCalledTimes(1)
})
...@@ -15,7 +15,6 @@ export const CheckAuthentication = async () => { ...@@ -15,7 +15,6 @@ export const CheckAuthentication = async () => {
if (decodedToken.exp * 1000 >= Date.now()) { if (decodedToken.exp * 1000 >= Date.now()) {
axios.defaults.headers.common['Authorization'] = authToken axios.defaults.headers.common['Authorization'] = authToken
store.dispatch({ type: Types.LOADING_USER }) store.dispatch({ type: Types.LOADING_USER })
console.log('loading user')
await axios await axios
.get('/users') .get('/users')
.then((res) => { .then((res) => {
...@@ -26,7 +25,7 @@ export const CheckAuthentication = async () => { ...@@ -26,7 +25,7 @@ export const CheckAuthentication = async () => {
}) })
}) })
.catch((error) => { .catch((error) => {
console.error(error) console.log(error)
UnAuthorized() UnAuthorized()
}) })
} else { } else {
......
from flask import Flask, redirect, request from flask import Flask, redirect, request
from flask_uploads import IMAGES, UploadSet, configure_uploads
import app.core.models as models import app.database.models as models
from app.core import bcrypt, db, jwt, ma from app.core import bcrypt, db, jwt, ma
from app.core.dto import MediaDTO
def create_app(config_name="configmodule.DevelopmentConfig"): def create_app(config_name="configmodule.DevelopmentConfig"):
...@@ -14,6 +16,7 @@ def create_app(config_name="configmodule.DevelopmentConfig"): ...@@ -14,6 +16,7 @@ def create_app(config_name="configmodule.DevelopmentConfig"):
jwt.init_app(app) jwt.init_app(app)
db.init_app(app) db.init_app(app)
ma.init_app(app) ma.init_app(app)
configure_uploads(app, (MediaDTO.image_set,))
from app.apis import flask_api from app.apis import flask_api
......
...@@ -44,6 +44,7 @@ from flask_restx import Api ...@@ -44,6 +44,7 @@ from flask_restx import Api
from .auth import api as auth_ns from .auth import api as auth_ns
from .competitions import api as comp_ns from .competitions import api as comp_ns
from .media import api as media_ns
from .misc import api as misc_ns from .misc import api as misc_ns
from .questions import api as question_ns from .questions import api as question_ns
from .slides import api as slide_ns from .slides import api as slide_ns
...@@ -51,6 +52,7 @@ from .teams import api as team_ns ...@@ -51,6 +52,7 @@ from .teams import api as team_ns
from .users import api as user_ns from .users import api as user_ns
flask_api = Api() flask_api = Api()
flask_api.add_namespace(media_ns, path="/api/media")
flask_api.add_namespace(misc_ns, path="/api/misc") flask_api.add_namespace(misc_ns, path="/api/misc")
flask_api.add_namespace(user_ns, path="/api/users") flask_api.add_namespace(user_ns, path="/api/users")
flask_api.add_namespace(auth_ns, path="/api/auth") flask_api.add_namespace(auth_ns, path="/api/auth")
...@@ -58,3 +60,4 @@ flask_api.add_namespace(comp_ns, path="/api/competitions") ...@@ -58,3 +60,4 @@ flask_api.add_namespace(comp_ns, path="/api/competitions")
flask_api.add_namespace(slide_ns, path="/api/competitions/<CID>/slides") flask_api.add_namespace(slide_ns, path="/api/competitions/<CID>/slides")
flask_api.add_namespace(team_ns, path="/api/competitions/<CID>/teams") flask_api.add_namespace(team_ns, path="/api/competitions/<CID>/teams")
flask_api.add_namespace(question_ns, path="/api/competitions/<CID>/questions") flask_api.add_namespace(question_ns, path="/api/competitions/<CID>/questions")
# flask_api.add_namespace(question_ns, path="/api/competitions/<CID>/slides/<SID>/question")
###
# Admin stuff placed here for later use
# No need to implement this before the application is somewhat done
###
from flask import Blueprint
admin_blueprint = Blueprint("admin", __name__)
import app.core.controller as dbc
import app.core.http_codes as codes import app.core.http_codes as codes
import app.database.controller as dbc
from app.apis import admin_required, item_response, text_response from app.apis import admin_required, item_response, text_response
from app.core.dto import AuthDTO from app.core.dto import AuthDTO
from app.core.models import User
from app.core.parsers import create_user_parser, login_parser from app.core.parsers import create_user_parser, login_parser
from app.database.models import User
from flask_jwt_extended import ( from flask_jwt_extended import (
create_access_token, create_access_token,
create_refresh_token, create_refresh_token,
...@@ -30,14 +30,10 @@ class AuthSignup(Resource): ...@@ -30,14 +30,10 @@ class AuthSignup(Resource):
args = create_user_parser.parse_args(strict=True) args = create_user_parser.parse_args(strict=True)
email = args.get("email") email = args.get("email")
if User.query.filter(User.email == email).count() > 0: if dbc.get.user_exists(email):
api.abort(codes.BAD_REQUEST, "User already exists") api.abort(codes.BAD_REQUEST, "User already exists")
item_user = dbc.add.user(**args) item_user = dbc.add.user(**args)
# TODO: Clarify when this case is needed or add it to a test
if not item_user:
api.abort(codes.BAD_REQUEST, "User could not be created")
return item_response(schema.dump(item_user)) return item_response(schema.dump(item_user))
...@@ -46,10 +42,7 @@ class AuthSignup(Resource): ...@@ -46,10 +42,7 @@ class AuthSignup(Resource):
class AuthDelete(Resource): class AuthDelete(Resource):
@jwt_required @jwt_required
def delete(self, ID): def delete(self, ID):
item_user = User.query.filter(User.id == ID).first() item_user = dbc.get.user(ID)
if not item_user:
api.abort(codes.NOT_FOUND, f"Could not find user with id {ID}.")
dbc.delete.default(item_user) dbc.delete.default(item_user)
if int(ID) == get_jwt_identity(): if int(ID) == get_jwt_identity():
...@@ -64,7 +57,7 @@ class AuthLogin(Resource): ...@@ -64,7 +57,7 @@ class AuthLogin(Resource):
args = login_parser.parse_args(strict=True) args = login_parser.parse_args(strict=True)
email = args.get("email") email = args.get("email")
password = args.get("password") password = args.get("password")
item_user = User.query.filter_by(email=email).first() item_user = dbc.get.user_by_email(email, required=False)
if not item_user or not item_user.is_correct_password(password): if not item_user or not item_user.is_correct_password(password):
api.abort(codes.UNAUTHORIZED, "Invalid email or password") api.abort(codes.UNAUTHORIZED, "Invalid email or password")
...@@ -92,7 +85,7 @@ class AuthRefresh(Resource): ...@@ -92,7 +85,7 @@ class AuthRefresh(Resource):
def post(self): def post(self):
old_jti = get_raw_jwt()["jti"] old_jti = get_raw_jwt()["jti"]
item_user = User.query.filter_by(id=get_jwt_identity()).first() item_user = dbc.get.user(get_jwt_identity())
access_token = create_access_token(item_user.id, user_claims=get_user_claims(item_user)) access_token = create_access_token(item_user.id, user_claims=get_user_claims(item_user))
dbc.add.blacklist(old_jti) dbc.add.blacklist(old_jti)
response = {"access_token": access_token} response = {"access_token": access_token}
......
import app.core.controller as dbc import app.database.controller as dbc
from app.apis import admin_required, item_response, list_response from app.apis import admin_required, item_response, list_response
from app.core.dto import CompetitionDTO from app.core.dto import CompetitionDTO
from app.core.models import Competition
from app.core.parsers import competition_parser, competition_search_parser from app.core.parsers import competition_parser, competition_search_parser
from app.database.models import Competition
from flask_jwt_extended import jwt_required from flask_jwt_extended import jwt_required
from flask_restx import Resource from flask_restx import Resource
...@@ -11,10 +11,6 @@ schema = CompetitionDTO.schema ...@@ -11,10 +11,6 @@ schema = CompetitionDTO.schema
list_schema = CompetitionDTO.list_schema list_schema = CompetitionDTO.list_schema
def get_comp(CID):
return Competition.query.filter(Competition.id == CID).first()
@api.route("/") @api.route("/")
class CompetitionsList(Resource): class CompetitionsList(Resource):
@jwt_required @jwt_required
...@@ -34,20 +30,22 @@ class CompetitionsList(Resource): ...@@ -34,20 +30,22 @@ class CompetitionsList(Resource):
class Competitions(Resource): class Competitions(Resource):
@jwt_required @jwt_required
def get(self, CID): def get(self, CID):
item = get_comp(CID) item = dbc.get.competition(CID)
return item_response(schema.dump(item)) return item_response(schema.dump(item))
@jwt_required @jwt_required
def put(self, CID): def put(self, CID):
args = competition_parser.parse_args(strict=True) args = competition_parser.parse_args(strict=True)
item = get_comp(CID) item = dbc.get.competition(CID)
item = dbc.edit.competition(item, **args) item = dbc.edit.competition(item, **args)
return item_response(schema.dump(item)) return item_response(schema.dump(item))
@jwt_required @jwt_required
def delete(self, CID): def delete(self, CID):
item = get_comp(CID) item = dbc.get.competition(CID)
dbc.delete.competition(item) dbc.delete.competition(item)
return "deleted" return "deleted"
...@@ -56,5 +54,5 @@ class CompetitionSearch(Resource): ...@@ -56,5 +54,5 @@ class CompetitionSearch(Resource):
@jwt_required @jwt_required
def get(self): def get(self):
args = competition_search_parser.parse_args(strict=True) args = competition_search_parser.parse_args(strict=True)
items, total = dbc.get.search_competitions(**args) items, total = dbc.search.competition(**args)
return list_response(list_schema.dump(items), total) return list_response(list_schema.dump(items), total)