diff --git a/.dockerignore b/.dockerignore index ea90c5605..30151a930 100644 --- a/.dockerignore +++ b/.dockerignore @@ -11,3 +11,4 @@ Dockerfile docs node_modules storybook_static +.tanstack diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 5970636c8..8042da8bc 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -47,7 +47,6 @@ jobs: env: VITE_VERSION: ${{ inputs.version || github.sha }} VITE_GRAASP_API_HOST: ${{ vars.VITE_GRAASP_API_HOST }} - VITE_GRAASP_WS_HOST: ${{ vars.VITE_GRAASP_WS_HOST }} VITE_GRAASP_LIBRARY_HOST: ${{ vars.VITE_GRAASP_LIBRARY_HOST }} VITE_SENTRY_ENV: ${{ vars.VITE_SENTRY_ENV }} VITE_SENTRY_DSN: ${{ secrets.VITE_SENTRY_DSN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ec670a8ec..01f183971 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,7 +21,7 @@ jobs: unit: name: Unit runs-on: ubuntu-latest - timeout-minutes: 10 + timeout-minutes: 20 steps: - name: Checkout uses: actions/checkout@v4 diff --git a/cypress/e2e/account/settings/preferences.cy.ts b/cypress/e2e/account/settings/preferences.cy.ts index 03e480894..c20b712a2 100644 --- a/cypress/e2e/account/settings/preferences.cy.ts +++ b/cypress/e2e/account/settings/preferences.cy.ts @@ -83,7 +83,7 @@ describe('Display preferences', () => { pathname: /\/api\/members\/current\/marketing\/unsubscribe$/, }, ({ reply }) => { - reply(); + reply({}); }, ).as('unsubscribe'); diff --git a/cypress/e2e/builder/item/bookmarks/bookmarks.cy.ts b/cypress/e2e/builder/item/bookmarks/bookmarks.cy.ts index 99ea860ab..86c6dd849 100644 --- a/cypress/e2e/builder/item/bookmarks/bookmarks.cy.ts +++ b/cypress/e2e/builder/item/bookmarks/bookmarks.cy.ts @@ -26,7 +26,7 @@ const removefromItemCard = (itemId: string) => { cy.get(`#${buildItemCard(itemId)} ${UNBOOKMARK_ICON_SELECTOR}`).click(); }; const removefromBookmarkCard = (itemId: string) => { - cy.get(`#${BOOKMARK_MANAGE_BUTTON_ID} `).click(); + cy.get(`#${BOOKMARK_MANAGE_BUTTON_ID}`).click(); cy.get(buildBookmarkCardRemoveButton(itemId)).click(); }; @@ -85,7 +85,7 @@ describe('Bookmarked Item', () => { }); }); - it('remove item from item card', () => { + it('remove item from bookmark card', () => { const itemId = ITEMS[1].id; removefromBookmarkCard(itemId); diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 99c6443cd..367ac81f0 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -142,6 +142,7 @@ import { mockPostAvatar, mockPostInvitations, mockPostItem, + mockPostItemActions, mockPostItemChatMessage, mockPostItemFlag, mockPostItemLogin, @@ -541,6 +542,8 @@ Cypress.Commands.add( mockEnroll(); mockGetCurrentSettings(currentMember, currentSettings); + + mockPostItemActions(); }, ); diff --git a/cypress/support/server.ts b/cypress/support/server.ts index d42e4f8b6..5cb2ca849 100644 --- a/cypress/support/server.ts +++ b/cypress/support/server.ts @@ -998,6 +998,22 @@ export const mockGetItemChat = ( { items }: { items: ItemForTest[] }, shouldThrowError: boolean, ): void => { + cy.intercept( + { + method: HttpMethod.Get, + pathname: /\/api\/items\/[0-9a-fA-F-]{36}\/chat$/, + }, + ({ reply, url }) => { + if (shouldThrowError) { + return reply({ statusCode: StatusCodes.BAD_REQUEST }); + } + + const itemId = url.split('/')[-2]; + const item = items.find(({ id }) => itemId === id); + + return reply(item?.chat ?? []); + }, + ).as('getItemChatAPI'); cy.intercept( { method: HttpMethod.Get, @@ -2424,3 +2440,15 @@ export const mockGetCurrentSettings = ( }, ).as('getCurrentSettings'); }; + +export const mockPostItemActions = (): void => { + cy.intercept( + { + method: HttpMethod.Post, + pathname: /\/api\/items\/[0-9a-fA-F-]{36}\/actions$/, + }, + ({ reply }) => { + reply([]); + }, + ).as('postItemActions'); +}; diff --git a/src/config/env.ts b/src/config/env.ts index c52021917..573186f8a 100644 --- a/src/config/env.ts +++ b/src/config/env.ts @@ -1,8 +1,7 @@ export const API_HOST = import.meta.env.VITE_GRAASP_API_HOST ?? 'http://localhost:3000'; -export const WS_HOST = - import.meta.env.VITE_GRAASP_WS_HOST ?? 'ws://localhost:3000'; +export const WS_HOST = API_HOST.replace('http', 'ws'); export const SHOW_NOTIFICATIONS = (import.meta.env.VITE_SHOW_NOTIFICATIONS ?? 'true') === 'true'; diff --git a/src/config/i18n.ts b/src/config/i18n.ts index c1c2a4581..ff8511eb9 100644 --- a/src/config/i18n.ts +++ b/src/config/i18n.ts @@ -14,7 +14,9 @@ i18n // namespaces that will be loaded by default ns: ['common'], backend: { - loadPath: '/locales/{{lng}}/{{ns}}.json', + loadPath: `${ + import.meta.env.VITE_BASE_URL ? '/client' : '' + }/locales/{{lng}}/{{ns}}.json`, }, // specify which languages are supported // 1. prefers exact match across all supported langs diff --git a/src/config/queryClient.ts b/src/config/queryClient.ts index c029c0e0a..1f5b228b3 100644 --- a/src/config/queryClient.ts +++ b/src/config/queryClient.ts @@ -2,12 +2,10 @@ import { configureWebsocketClient } from '@graasp/sdk'; import { configureQueryClient } from '@/query'; -import { API_HOST, SHOW_NOTIFICATIONS } from './env'; +import { API_HOST, SHOW_NOTIFICATIONS, WS_HOST } from './env'; import notifier from './notifier'; -export const WS_CLIENT = configureWebsocketClient( - `${API_HOST.replace('http', 'ws')}/ws`, -); +export const WS_CLIENT = configureWebsocketClient(WS_HOST); const { queryClient, @@ -29,13 +27,13 @@ const { wsClient: WS_CLIENT, }); export { - useQueryClient, + axios, + hooks, mutations, queryClient, QueryClientProvider, - hooks, - useMutation, ReactQueryDevtools, - axios, + useMutation, useQuery, + useQueryClient, }; diff --git a/vite.config.ts b/vite.config.ts index 30e41077f..68b5a3076 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -33,7 +33,7 @@ const config = ({ mode }: { mode: string }): UserConfig => { const shouldOpen = BROWSER && BROWSER !== 'none'; return defineConfig({ - base: '/', + base: process.env.VITE_BASE_URL ? '/client' : '/', server: { port: PORT, // whether we should open the url on start