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

feat(social): commente un bouquet #180

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 36 additions & 1 deletion src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,39 @@ interface Subtheme {
name: string
}

export type { Theme, Subtheme }
interface Request {
method: string
url: string
data?: Record<string, any>
}

interface Response {
status: number
data?: Record<string, any>
error?: { message: string }
}

interface DiscussionParams {
title: string
comment: string
subject: DiscussionSubject
}

interface DiscussionSubject {
class: 'Topic'
id: string
}

interface DiscussionResponse extends Response {
status: 200 | number
data?: Partial<DiscussionParams>
}

export type {
Theme,
Subtheme,
Request,
Response,
DiscussionParams,
DiscussionResponse
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { toast } from 'vue3-toastify'
import { useLoading } from 'vue-loading-overlay'

import config from '@/config'
import type { Response } from '@/model'

// FIXME: the client should not depend be aware of the store.
import { useUserStore } from '../../store/UserStore'

const $loading = useLoading()
Expand All @@ -21,7 +23,7 @@ instance.interceptors.request.use(

return config
},
(error) => Promise.reject(error)
async (error) => await Promise.reject(error)
)

/**
Expand Down Expand Up @@ -73,14 +75,16 @@ export default class DatagouvfrAPI {
*/
async makeRequestAndHandleResponse(url, method = 'get', params = {}) {
const loader = $loading.show()
return this.request(url, method, params)
return await this.request(url, method, params)
.catch((error) => {
if (error && error.message) {
if (error?.message) {
toast(error.message, { type: 'error', autoClose: false }) // TODO: Refacto to handle the error
return error.response
}
})
.finally(() => loader.hide())
.finally(() => {
loader.hide()
})
}

/**
Expand Down Expand Up @@ -141,6 +145,23 @@ export default class DatagouvfrAPI {
)
}

/**
* Base function for HTTP calls (without error handling)
*
* @todo Remove this function once all API calls are all handled this way:
* leaving the error handling to the caller (store).
*
* @param {string} url
* @param {object} data
* @returns {Promise<Response>}
*/
async _create(url: string, data = {}): Promise<Response> {
return await this.httpClient.post(url, data).then(
(response) => response,
(error) => this.#handleError(error)
)
}

/**
* Update an entity (PUT)
*
Expand All @@ -160,17 +181,19 @@ export default class DatagouvfrAPI {
* Delete an entity (DELETE)
*
* @param {string} entityId - A UUID entity id
* @returns {Promise}
* @returns {Promise<Response>}
*/
async delete(entityId) {
return this.httpClient.delete(`${this.url()}/${entityId}/`).then(
async delete(entityId: string): Promise<Response> {
return await this.httpClient.delete(`${this.url()}/${entityId}/`).then(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Le await est nécessaire ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@edelagnier ? (Il me semble que c'est le npm run format qui rajoute ça automatiquement).

(response) => response,
(error) => this.#handleError(error)
)
}

#handleError({ response, message }) {
if (response) return { status: response.status }
return { message }
#handleError({ response, message }): Response {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@edelagnier vu que c'est du TypeScript maintenant, ne pourrait-on utiliser private plutôt ?

Suggested change
#handleError({ response, message }): Response {
private handleError({ response, message }): Response {

return {
...(response && { status: response.status }),
...(message && { error: { message } })
}
}
}
4 changes: 2 additions & 2 deletions src/services/api/__tests__/DatagouvfrAPI.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ test('delete when 404', async ({ client }) => {
})

test('delete something else', async ({ client }) => {
const { message } = await client.delete(networkError)
expect(message).toMatch(/network error/i)
const { error } = await client.delete(networkError)
expect(error.message).toMatch(/network error/i)
})

test('raw list', async ({ client }) => {
Expand Down
61 changes: 61 additions & 0 deletions src/services/api/__tests__/DiscussionsAPI.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import axios from 'axios'
import { HttpResponse, http } from 'msw'
import { setupServer } from 'msw/node'
import { createPinia, setActivePinia } from 'pinia'
import {
afterAll,
afterEach,
beforeAll,
beforeEach,
expect,
test
} from 'vitest'

import DiscussionsAPI from '@/services/api/resources/DiscussionsAPI'

const baseUrl = 'https://example.lol'
const version = '1234'
const endpoint = 'discussions'

const discussionRequest = {
title: 'Title of the discussion',
comment: 'This is a discussion.',
subject: {
class: 'Topic',
id: 'id123'
}
}

const server = setupServer(
http.post(`${baseUrl}/${version}/${endpoint}/`, () => {
return HttpResponse.json(discussionRequest, { status: 200 })
})
)

beforeAll(() => {
server.listen()
})

beforeEach(async (context) => {
const httpClient = axios.create()
httpClient.defaults.proxy = false
setActivePinia(createPinia())
context.client = new DiscussionsAPI({
baseUrl,
version,
httpClient
})
})

afterEach(() => {
server.resetHandlers()
})

afterAll(() => {
server.close()
})

test('create a discussion', async ({ client }) => {
const { data } = await client.create(discussionRequest)
expect(data.title).toEqual(discussionRequest.title)
})
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { DiscussionParams, DiscussionResponse } from '@/model'

import DatagouvfrAPI from '../DatagouvfrAPI'

export default class DiscussionsAPI extends DatagouvfrAPI {
Expand All @@ -14,4 +16,14 @@ export default class DiscussionsAPI extends DatagouvfrAPI {
const url = `${this.url()}/?for=${dataset_id}&page=${page}`
return await this.makeRequestAndHandleResponse(url)
}

/**
* Create a discussion (POST)
*
* @param {DiscussionParams} data
* @returns {Promise<DiscussionResponse>}
*/
async create(data: DiscussionParams): Promise<DiscussionResponse> {
return await this._create(`${this.url()}/`, data)
}
}