From 1ed419675e0038e6af40bae55b96cd1ad96a42e8 Mon Sep 17 00:00:00 2001 From: Marc Itzenthaler Date: Thu, 22 Feb 2024 16:35:20 +0100 Subject: [PATCH 1/8] fix: registration consulting types, added registration tests --- .env.sample | 2 +- cypress/e2e/appointments.cy.ts | 737 +++++---- cypress/e2e/login.cy.ts | 3 +- cypress/e2e/messages.cy.ts | 15 +- cypress/e2e/profile.cy.ts | 24 +- .../base.cy.ts} | 5 +- cypress/e2e/registration/consultingType.cy.ts | 910 +++++++++++ cypress/e2e/registration/topic.cy.ts | 1358 +++++++++++++++++ cypress/e2e/release-notes.cy.ts | 13 +- cypress/e2e/sessions.cy.ts | 17 +- cypress/e2e/tokens.cy.ts | 41 +- cypress/e2e/video-calls.cy.ts | 7 +- cypress/e2e/videoconference.cy.ts | 9 +- cypress/fixtures/registration/agency.json | 11 + .../fixtures/registration/consultingType.json | 70 + cypress/fixtures/registration/topic.json | 7 + cypress/fixtures/service.settings.json | 59 + cypress/fixtures/service.tenant.public.json | 32 + .../fixtures/service.users.data.askers.json | 32 - ...nsultants.json => service.users.data.json} | 32 + cypress/support/commands.ts | 34 - cypress/support/commands/api/agencies.ts | 37 + cypress/support/commands/api/appointments.ts | 2 +- cypress/support/commands/api/consultTypes.ts | 54 + cypress/support/commands/api/messages.ts | 30 + cypress/support/commands/api/rc.ts | 109 ++ cypress/support/commands/api/topic.ts | 9 + cypress/support/commands/api/uploads.ts | 12 + cypress/support/commands/api/users/chat.ts | 12 + .../support/commands/api/users/consultants.ts | 32 + cypress/support/commands/api/users/data.ts | 22 + .../support/commands/api/users/sessions.ts | 62 + cypress/support/commands/api/videocalls.ts | 6 + .../commands/{ => helper}/appointments.ts | 6 +- .../commands/{ => helper}/askerSessions.ts | 24 +- .../{ => helper}/consultantSessions.ts | 23 +- cypress/support/commands/helper/fastLogin.ts | 58 + cypress/support/commands/helper/login.ts | 43 + .../support/commands/{ => helper}/messages.ts | 23 +- cypress/support/commands/login.ts | 41 - cypress/support/commands/mockApi.ts | 455 ++---- cypress/support/e2e.ts | 8 + cypress/support/helpers.ts | 11 + cypress/support/index.d.ts | 50 + cypress/support/sessions.ts | 2 +- cypress/support/websocket.ts | 39 +- cypress/tsconfig.json | 6 +- proxy/config.js | 12 +- src/api/apiAgencySelection.ts | 49 +- src/api/apiGetAgencyId.ts | 14 +- src/api/apiGetConsultant.ts | 56 +- src/api/apiRegistrationNewConsultingTypes.ts | 6 +- src/api/fetchData.ts | 1 + src/components/app/app.tsx | 20 +- .../ConsultingTypeAgencySelection.tsx | 119 +- .../formAccordion/FormAccordion.tsx | 4 +- src/components/login/Login.tsx | 55 +- .../mainTopicSelection/MainTopicSelection.tsx | 37 +- src/components/registration/Registration.tsx | 52 +- .../registration/RegistrationForm.tsx | 26 +- .../serviceExplanation/ServiceExplanation.tsx | 6 +- .../waitingRoom/WaitingRoomLoader.tsx | 17 +- .../ProposedAgencies/ProposedAgencies.tsx | 37 +- .../hooks/useAgenciesForRegistration.ts | 70 +- ...useConsultantAgenciesAndConsultingTypes.ts | 79 - .../hooks/useConsultantRegistrationData.ts | 118 ++ .../AppConfig/AppConfigInterface.ts | 6 +- .../interfaces/UserDataInterface.ts | 6 +- .../provider/AgencySpecificProvider.tsx | 2 +- .../provider/UrlParamsProvider.tsx | 41 +- src/i18n.ts | 4 + src/utils/getUrlParameter.ts | 15 +- src/utils/loadConsultingTypeForAgency.ts | 11 + src/utils/useTenantTheming.ts | 11 +- src/utils/useUrlParamsLoader.tsx | 254 +-- 75 files changed, 4412 insertions(+), 1310 deletions(-) rename cypress/e2e/{registration.cy.ts => registration/base.cy.ts} (98%) create mode 100644 cypress/e2e/registration/consultingType.cy.ts create mode 100644 cypress/e2e/registration/topic.cy.ts create mode 100644 cypress/fixtures/registration/agency.json create mode 100644 cypress/fixtures/registration/consultingType.json create mode 100644 cypress/fixtures/registration/topic.json create mode 100644 cypress/fixtures/service.settings.json create mode 100644 cypress/fixtures/service.tenant.public.json delete mode 100644 cypress/fixtures/service.users.data.askers.json rename cypress/fixtures/{service.users.data.consultants.json => service.users.data.json} (65%) create mode 100644 cypress/support/commands/api/agencies.ts create mode 100644 cypress/support/commands/api/consultTypes.ts create mode 100644 cypress/support/commands/api/messages.ts create mode 100644 cypress/support/commands/api/rc.ts create mode 100644 cypress/support/commands/api/topic.ts create mode 100644 cypress/support/commands/api/uploads.ts create mode 100644 cypress/support/commands/api/users/chat.ts create mode 100644 cypress/support/commands/api/users/consultants.ts create mode 100644 cypress/support/commands/api/users/data.ts create mode 100644 cypress/support/commands/api/users/sessions.ts rename cypress/support/commands/{ => helper}/appointments.ts (85%) rename cypress/support/commands/{ => helper}/askerSessions.ts (52%) rename cypress/support/commands/{ => helper}/consultantSessions.ts (54%) create mode 100644 cypress/support/commands/helper/fastLogin.ts create mode 100644 cypress/support/commands/helper/login.ts rename cypress/support/commands/{ => helper}/messages.ts (60%) delete mode 100644 cypress/support/commands/login.ts create mode 100644 cypress/support/index.d.ts delete mode 100644 src/containers/registration/hooks/useConsultantAgenciesAndConsultingTypes.ts create mode 100644 src/containers/registration/hooks/useConsultantRegistrationData.ts create mode 100644 src/utils/loadConsultingTypeForAgency.ts diff --git a/.env.sample b/.env.sample index 1c26ee184..8c4d581c1 100644 --- a/.env.sample +++ b/.env.sample @@ -25,7 +25,7 @@ REACT_APP_DISABLE_2FA_DUTY=0 ### Registration # Enable fallback loader for direct link registration where slug could not be matched (0/1) -FRONTEND_REGISTRATION_DIRECTLINK_FALLBACKLOADER_ENABLED= +FRONTEND_REGISTRATION_USE_CONSULTINGTYPE_SLUG= ### Weblate # Weblate host diff --git a/cypress/e2e/appointments.cy.ts b/cypress/e2e/appointments.cy.ts index 4e9cb4c6f..9b970678b 100644 --- a/cypress/e2e/appointments.cy.ts +++ b/cypress/e2e/appointments.cy.ts @@ -1,5 +1,5 @@ import { v4 as uuid } from 'uuid'; -import { USER_CONSULTANT, USER_VIDEO } from '../support/commands/login'; +import { USER_CONSULTANT, USER_VIDEO } from '../support/commands/mockApi'; import { closeWebSocketServer, mockWebSocket, @@ -7,7 +7,7 @@ import { } from '../support/websocket'; const handleUiEdit = (cy, index, text, proceed = false) => { - cy.get('.appointments .box') + cy.get('.appointments *[class^="box_"]') .eq(index) .find('.appointment__actions') .eq(1) @@ -26,7 +26,7 @@ const handleUiEdit = (cy, index, text, proceed = false) => { }; const handleUiDelete = (cy, index, proceed = false) => { - cy.get('.appointments .box') + cy.get('.appointments *[class^="box_"]') .eq(index) .find('.appointment__actions') .eq(1) @@ -52,408 +52,515 @@ describe('appointments', () => { }); beforeEach(() => { - cy.mockApi(); mockWebSocket(); }); - describe('Asker', () => { + describe('Video Appointments disabled', () => { beforeEach(() => { - cy.fastLogin(); + cy.willReturn('settings', { + disableVideoAppointments: { + value: true, + readOnly: false + } + }); }); - it('Appointments List not exists', () => { - cy.contains('Video - Termine').should('not.exist'); + describe('Asker', () => { + beforeEach(() => { + cy.fastLogin(); + }); + + it('Appointments List not exists', () => { + cy.contains('Video - Termine').should('not.exist'); + }); }); - }); - describe('Consultant', () => { - beforeEach(() => { - cy.fastLogin({ - username: USER_CONSULTANT + describe('Consultant', () => { + beforeEach(() => { + cy.fastLogin({ + userId: USER_CONSULTANT + }); + }); + + it('Appointments List not exists', () => { + cy.contains('Video - Termine').should('not.exist'); }); }); - it('Appointments List not exists', () => { - cy.contains('Video - Termine').should('not.exist'); + describe('Video Consultant', () => { + beforeEach(() => { + cy.fastLogin({ + userId: USER_VIDEO + }); + }); + + it('Appointments List not exists', () => { + cy.contains('Video - Termine').should('not.exist'); + }); }); }); - describe('Video Consultant', () => { + describe('Video Appointments enabled', () => { beforeEach(() => { - cy.fastLogin({ - username: USER_VIDEO + cy.willReturn('settings', { + disableVideoAppointments: { + value: false, + readOnly: false + } }); }); - it('Appointments List without appointments', () => { - cy.contains('Video - Termine').should('exist').click(); - cy.wait('@appointments_get'); - cy.get('.appointments').contains('Aktuell gibt es keine Termine'); - }); - - it('Add appointment', () => { - // Default Meeting Time - const dMT = new Date(); - dMT.setHours(8); - dMT.setMinutes(0); - - cy.contains('Video - Termine').click(); - cy.wait('@appointments_get'); - - cy.get('.appointments .box').should('not.exist'); - cy.get('.appointments__actions .button__wrapper button').click(); + describe('Asker', () => { + beforeEach(() => { + cy.fastLogin(); + }); - cy.get('#overlay .onlineMeetingForm .react-datepicker--date') - .click() - .get( - '#overlay .onlineMeetingForm .react-datepicker--date .react-datepicker .react-datepicker__day--today' - ) - .get( - '#overlay .onlineMeetingForm .react-datepicker--date .react-datepicker .react-datepicker__day--today' - ) - .should('not.have.class', 'react-datepicker__day--disabled') - .click() - .get( - '#overlay .onlineMeetingForm .react-datepicker--time input' - ) - .should( - 'have.value', - `${(dMT.getHours() + 100).toString().substring(1)}:${( - dMT.getMinutes() + 100 - ) - .toString() - .substring(1)}` - ) - .get('#overlay .onlineMeetingForm textarea') - .type('Meine Beschreibung') - .get('#overlay .overlay__buttons button') - .contains('Speichern') - .click(); - cy.wait('@appointments_post'); - - cy.get('.appointments .box').should('have.length', 1); - cy.get('.appointments .box .appointment__description').should( - 'contain.text', - 'Meine Beschreibung' - ); - - cy.appointments(); + it('Appointments List not exists', () => { + cy.contains('Video - Termine').should('not.exist'); + }); }); - describe('Appointment actions', () => { + describe('Consultant', () => { beforeEach(() => { - const today = new Date(); - cy.appointments({ - id: uuid(), - description: 'Mein Termin 1', - datetime: today.toISOString() - }); - today.setDate(today.getDate() + 1); - cy.appointments({ - id: uuid(), - description: 'Mein Termin 2', - datetime: today.toISOString() + cy.fastLogin({ + userId: USER_CONSULTANT }); - today.setDate(today.getDate() + 1); - cy.appointments({ - id: uuid(), - description: 'Mein Termin 3', - datetime: today.toISOString() - }); - - cy.contains('Video - Termine').click(); - cy.wait('@appointments_get'); }); - afterEach(() => { - cy.appointments(); + it('Appointments List not exists', () => { + cy.contains('Video - Termine').should('not.exist'); }); + }); - it('Edit appointment', () => { - cy.get('.appointments .box').should('have.length', 3); - cy.get('.appointments .box') - .eq(0) - .find('.appointment__description') - .should('contain.text', 'Mein Termin 1'); - cy.get('.appointments .box') - .eq(1) - .find('.appointment__description') - .should('contain.text', 'Mein Termin 2'); - cy.get('.appointments .box') - .eq(2) - .find('.appointment__description') - .should('contain.text', 'Mein Termin 3'); - - // Edit appointment #1 - handleUiEdit(cy, 0, ' hat jetzt mehr Inhalt', true); - // Edit and cancel appointment #2 - handleUiEdit(cy, 1, ' wurde geändert aber abgebrochen', false); - // Edit appointment #3 - handleUiEdit(cy, 2, ' hat jetzt noch mehr Inhalt', true); - - // Check list - cy.get('.appointments .box') - .eq(0) - .find('.appointment__description') - .should( - 'contain.text', - 'Mein Termin 1 hat jetzt mehr Inhalt' - ); - cy.get('.appointments .box') - .eq(1) - .find('.appointment__description') - .should('contain.text', 'Mein Termin 2'); - cy.get('.appointments .box') - .eq(2) - .find('.appointment__description') - .should( - 'contain.text', - 'Mein Termin 3 hat jetzt noch mehr Inhalt' - ); + describe('Video Consultant', () => { + beforeEach(() => { + cy.fastLogin({ + userId: USER_VIDEO + }); }); - it('Delete appointment', () => { - cy.get('.appointments .box').should('have.length', 3); - cy.get('.appointments .box') - .eq(0) - .find('.appointment__description') - .should('contain.text', 'Mein Termin 1'); - cy.get('.appointments .box') - .eq(1) - .find('.appointment__description') - .should('contain.text', 'Mein Termin 2'); - cy.get('.appointments .box') - .eq(2) - .find('.appointment__description') - .should('contain.text', 'Mein Termin 3'); - - // Press delete and cancel - handleUiDelete(cy, 1, false); - cy.get('.appointments .box').should('have.length', 3); - - // Press delete and proceed - handleUiDelete(cy, 1, true); - cy.get('.appointments .box').should('have.length', 2); - - cy.get('.appointments .box') - .eq(0) - .find('.appointment__description') - .should('contain.text', 'Mein Termin 1'); - cy.get('.appointments .box') - .eq(1) - .find('.appointment__description') - .should('contain.text', 'Mein Termin 3'); - - handleUiDelete(cy, 0, true); - handleUiDelete(cy, 0, true); - cy.get('.appointments .box').should('have.length', 0); + it('Appointments List without appointments', () => { + cy.contains('Video - Termine').should('exist').click(); + cy.wait('@appointments_get'); cy.get('.appointments').contains( 'Aktuell gibt es keine Termine' ); }); - it('Copy appointment link', () => { - cy.get('.appointments .box').should('have.length', 3); + it('Add appointment', () => { + // Default Meeting Time + const dMT = new Date(); + dMT.setHours(8); + dMT.setMinutes(0); - cy.get('.appointments .box') - .eq(0) - .find('[data-cy=appointment_url]') - .then(($url) => { - const appointmentLink = $url.text(); - - cy.get('.appointments .box') - .eq(0) - .find('[data-cy=appointment_link] span') - .click(); - - cy.window().then((win) => { - if (win.navigator.clipboard) { - win.navigator.clipboard - .readText() - .then((text) => { - expect(text).to.eq(appointmentLink); - }); - } else { - win.clipboardData - .getData('text/plain') - .then((text) => { - expect(text).to.eq(appointmentLink); - }); - } - }); - }); - }); + cy.contains('Video - Termine').click(); + cy.wait('@appointments_get'); - it('Show appointment qr code', () => { - cy.get('.appointments .box').should('have.length', 3); + cy.get('.appointments *[class^="box_"]').should('not.exist'); + cy.get( + '.appointments__actions .button__wrapper button' + ).click(); - cy.get('.appointments .box') - .eq(0) - .find('[data-cy=appointment_qr_code] button') + cy.get( + '#overlay .onlineMeetingForm .react-datepicker--date' + ).click(); + cy.get( + '#overlay .onlineMeetingForm .react-datepicker--date .react-datepicker .react-datepicker__day--today' + ) + .should('not.have.class', 'react-datepicker__day--disabled') .click(); + cy.get( + '#overlay .onlineMeetingForm .react-datepicker--time input' + ).should( + 'have.value', + `${(dMT.getHours() + 100).toString().substring(1)}:${( + dMT.getMinutes() + 100 + ) + .toString() + .substring(1)}` + ); + cy.get('#overlay .onlineMeetingForm textarea').type( + 'Meine Beschreibung' + ); + cy.get('#overlay .overlay__buttons button') + .contains('Speichern') + .click(); + cy.wait('@appointments_post'); - cy.get('#overlay .generateQrCode__overlay').should('exist'); - }); - }); - - describe('Start video conference', () => { - beforeEach(() => { - const today = new Date(); - cy.appointments({ - id: uuid(), - description: 'Mein Termin 1', - datetime: today.toISOString() - }); - today.setDate(today.getDate() + 1); - cy.appointments({ - id: uuid(), - description: 'Mein Termin 2', - datetime: today.toISOString() - }); - today.setDate(today.getDate() + 1); - cy.appointments({ - id: uuid(), - description: 'Mein Termin 3', - datetime: today.toISOString() - }); - }); + cy.get('.appointments *[class^="box_"]').should( + 'have.length', + 1 + ); + cy.get( + '.appointments *[class^="box_"] .appointment__description' + ).should('contain.text', 'Meine Beschreibung'); - afterEach(() => { cy.appointments(); }); - describe('E2EE check enabled', () => { + describe('Appointment actions', () => { beforeEach(() => { - cy.willReturn('userData', { - e2eEncryptionEnabled: true + const today = new Date(); + cy.appointments({ + id: uuid(), + description: 'Mein Termin 1', + datetime: today.toISOString() }); - - cy.fastLogin({ - username: USER_VIDEO + today.setDate(today.getDate() + 1); + cy.appointments({ + id: uuid(), + description: 'Mein Termin 2', + datetime: today.toISOString() + }); + today.setDate(today.getDate() + 1); + cy.appointments({ + id: uuid(), + description: 'Mein Termin 3', + datetime: today.toISOString() }); cy.contains('Video - Termine').click(); cy.wait('@appointments_get'); }); - it('Enabled - E2EE not supported', () => { - cy.get('.appointments .box').should('have.length', 3); + afterEach(() => { + cy.appointments(); + }); - cy.window().then((window) => { - cy.stub(window, 'RTCRtpSender').returns(undefined); - }); + it('Edit appointment', () => { + cy.get('.appointments *[class^="box_"]').should( + 'have.length', + 3 + ); + cy.get('.appointments *[class^="box_"]') + .eq(0) + .find('.appointment__description') + .should('contain.text', 'Mein Termin 1'); + cy.get('.appointments *[class^="box_"]') + .eq(1) + .find('.appointment__description') + .should('contain.text', 'Mein Termin 2'); + cy.get('.appointments *[class^="box_"]') + .eq(2) + .find('.appointment__description') + .should('contain.text', 'Mein Termin 3'); + + // Edit appointment #1 + handleUiEdit(cy, 0, ' hat jetzt mehr Inhalt', true); + // Edit and cancel appointment #2 + handleUiEdit( + cy, + 1, + ' wurde geändert aber abgebrochen', + false + ); + // Edit appointment #3 + handleUiEdit(cy, 2, ' hat jetzt noch mehr Inhalt', true); - cy.get('.appointments .box') + // Check list + cy.get('.appointments *[class^="box_"]') .eq(0) - .find('[data-cy=appointment_start] button') - .click(); + .find('.appointment__description') + .should( + 'contain.text', + 'Mein Termin 1 hat jetzt mehr Inhalt' + ); + cy.get('.appointments *[class^="box_"]') + .eq(1) + .find('.appointment__description') + .should('contain.text', 'Mein Termin 2'); + cy.get('.appointments *[class^="box_"]') + .eq(2) + .find('.appointment__description') + .should( + 'contain.text', + 'Mein Termin 3 hat jetzt noch mehr Inhalt' + ); + }); - cy.get('#overlay .overlay__content .headline').contains( - 'Der Video-Call kann nicht gestartet werden' + it('Delete appointment', () => { + cy.get('.appointments *[class^="box_"]').should( + 'have.length', + 3 ); - - cy.get( - '#overlay .overlay__content .overlay__buttons .button__wrapper' - ) + cy.get('.appointments *[class^="box_"]') .eq(0) - .children('button') - .click(); + .find('.appointment__description') + .should('contain.text', 'Mein Termin 1'); + cy.get('.appointments *[class^="box_"]') + .eq(1) + .find('.appointment__description') + .should('contain.text', 'Mein Termin 2'); + cy.get('.appointments *[class^="box_"]') + .eq(2) + .find('.appointment__description') + .should('contain.text', 'Mein Termin 3'); + + // Press delete and cancel + handleUiDelete(cy, 1, false); + cy.get('.appointments *[class^="box_"]').should( + 'have.length', + 3 + ); - cy.get('#overlay .overlay__content').should('not.exist'); - }); + // Press delete and proceed + handleUiDelete(cy, 1, true); + cy.get('.appointments *[class^="box_"]').should( + 'have.length', + 2 + ); - it('Enabled - E2EE supported', () => { - cy.get('.appointments .box').should('have.length', 3); + cy.get('.appointments *[class^="box_"]') + .eq(0) + .find('.appointment__description') + .should('contain.text', 'Mein Termin 1'); + cy.get('.appointments *[class^="box_"]') + .eq(1) + .find('.appointment__description') + .should('contain.text', 'Mein Termin 3'); + + handleUiDelete(cy, 0, true); + handleUiDelete(cy, 0, true); + cy.get('.appointments *[class^="box_"]').should( + 'have.length', + 0 + ); + cy.get('.appointments').contains( + 'Aktuell gibt es keine Termine' + ); + }); - cy.window().then((window) => { - cy.stub(window, 'open').as('windowOpen'); - }); + it('Copy appointment link', () => { + cy.get('.appointments *[class^="box_"]').should( + 'have.length', + 3 + ); - cy.get('.appointments .box') + cy.get('.appointments *[class^="box_"]') .eq(0) - .find('[data-cy=appointment_start] button') - .click(); + .find('[data-cy=appointment_url]') + .then(($url) => { + const appointmentLink = $url.text(); + + cy.get('.appointments *[class^="box_"]') + .eq(0) + .find('[data-cy=appointment_link] span') + .click(); + + cy.window().then((win) => { + if (win.navigator.clipboard) { + win.navigator.clipboard + .readText() + .then((text) => { + expect(text).to.eq(appointmentLink); + }); + } else { + win.clipboardData + .getData('text/plain') + .then((text) => { + expect(text).to.eq(appointmentLink); + }); + } + }); + }); + }); - cy.get('#overlay .overlay__content .headline').contains( - 'Video-Call starten' + it('Show appointment qr code', () => { + cy.get('.appointments *[class^="box_"]').should( + 'have.length', + 3 ); - cy.get( - '#overlay .overlay__content .overlay__buttons .button__wrapper' - ) - .eq(1) - .children('button') + cy.get('.appointments *[class^="box_"]') + .eq(0) + .find('[data-cy=appointment_qr_code] button') .click(); - cy.get('@windowOpen').should('be.called'); + cy.get('#overlay .generateQrCode__overlay').should('exist'); }); }); - describe('E2EE check disabled', () => { + describe('Start video conference', () => { beforeEach(() => { - cy.willReturn('userData', { - e2eEncryptionEnabled: false + const today = new Date(); + cy.appointments({ + id: uuid(), + description: 'Mein Termin 1', + datetime: today.toISOString() }); - - cy.fastLogin({ - username: USER_VIDEO + today.setDate(today.getDate() + 1); + cy.appointments({ + id: uuid(), + description: 'Mein Termin 2', + datetime: today.toISOString() + }); + today.setDate(today.getDate() + 1); + cy.appointments({ + id: uuid(), + description: 'Mein Termin 3', + datetime: today.toISOString() }); + }); - cy.contains('Video - Termine').click(); - cy.wait('@appointments_get'); + afterEach(() => { + cy.appointments(); }); - it('Disabled - E2EE not supported', () => { - cy.get('.appointments .box').should('have.length', 3); + describe('E2EE check enabled', () => { + beforeEach(() => { + cy.willReturn( + 'userData', + { + e2eEncryptionEnabled: true + }, + true + ); + + cy.fastLogin({ + userId: USER_VIDEO + }); - cy.window().then((window) => { - cy.stub(window, 'open').as('windowOpen'); - cy.stub(window, 'RTCRtpSender').returns(undefined); + cy.contains('Video - Termine').click(); + cy.wait('@appointments_get'); }); - cy.get('.appointments .box') - .eq(0) - .find('[data-cy=appointment_start] button') - .click(); + it('Enabled - E2EE not supported', () => { + cy.get('.appointments *[class^="box_"]').should( + 'have.length', + 3 + ); - cy.get('#overlay .overlay__content .headline').contains( - 'Video-Call starten' - ); + cy.window().then((window) => { + cy.stub(window, 'RTCRtpSender').returns(undefined); + }); - cy.get( - '#overlay .overlay__content .overlay__buttons .button__wrapper' - ) - .eq(1) - .children('button') - .click(); + cy.get('.appointments *[class^="box_"]') + .eq(0) + .find('[data-cy=appointment_start] button') + .click(); - cy.get('@windowOpen').should('be.called'); + cy.get('#overlay .overlay__content .headline').contains( + 'Der Video-Call kann nicht gestartet werden' + ); + + cy.get( + '#overlay .overlay__content .overlay__buttons .button__wrapper' + ) + .eq(0) + .children('button') + .click(); + + cy.get('#overlay .overlay__content').should( + 'not.exist' + ); + }); + + it('Enabled - E2EE supported', () => { + cy.get('.appointments *[class^="box_"]').should( + 'have.length', + 3 + ); + + cy.window().then((window) => { + cy.stub(window, 'open').as('windowOpen'); + }); + + cy.get('.appointments *[class^="box_"]') + .eq(0) + .find('[data-cy=appointment_start] button') + .click(); + + cy.get('#overlay .overlay__content .headline').contains( + 'Video-Call starten' + ); + + cy.get( + '#overlay .overlay__content .overlay__buttons .button__wrapper' + ) + .eq(1) + .children('button') + .click(); + + cy.get('@windowOpen').should('be.called'); + }); }); - it('Disabled - E2EE supported', () => { - cy.get('.appointments .box').should('have.length', 3); + describe('E2EE check disabled', () => { + beforeEach(() => { + cy.willReturn( + 'userData', + { + e2eEncryptionEnabled: false + }, + true + ); + + cy.fastLogin({ + userId: USER_VIDEO + }); - cy.window().then((window) => { - cy.stub(window, 'open').as('windowOpen'); + cy.contains('Video - Termine').click(); + cy.wait('@appointments_get'); }); - cy.get('.appointments .box') - .eq(0) - .find('[data-cy=appointment_start] button') - .click(); + it('Disabled - E2EE not supported', () => { + cy.get('.appointments *[class^="box_"]').should( + 'have.length', + 3 + ); - cy.get('#overlay .overlay__content .headline').contains( - 'Video-Call starten' - ); + cy.window().then((window) => { + cy.stub(window, 'open').as('windowOpen'); + cy.stub(window, 'RTCRtpSender').returns(undefined); + }); - cy.get( - '#overlay .overlay__content .overlay__buttons .button__wrapper' - ) - .eq(1) - .children('button') - .click(); + cy.get('.appointments *[class^="box_"]') + .eq(0) + .find('[data-cy=appointment_start] button') + .click(); + + cy.get('#overlay .overlay__content .headline').contains( + 'Video-Call starten' + ); + + cy.get( + '#overlay .overlay__content .overlay__buttons .button__wrapper' + ) + .eq(1) + .children('button') + .click(); + + cy.get('@windowOpen').should('be.called'); + }); - cy.get('@windowOpen').should('be.called'); + it('Disabled - E2EE supported', () => { + cy.get('.appointments *[class^="box_"]').should( + 'have.length', + 3 + ); + + cy.window().then((window) => { + cy.stub(window, 'open').as('windowOpen'); + }); + + cy.get('.appointments *[class^="box_"]') + .eq(0) + .find('[data-cy=appointment_start] button') + .click(); + + cy.get('#overlay .overlay__content .headline').contains( + 'Video-Call starten' + ); + + cy.get( + '#overlay .overlay__content .overlay__buttons .button__wrapper' + ) + .eq(1) + .children('button') + .click(); + + cy.get('@windowOpen').should('be.called'); + }); }); }); }); diff --git a/cypress/e2e/login.cy.ts b/cypress/e2e/login.cy.ts index e15cc49cb..e96c8a5a1 100644 --- a/cypress/e2e/login.cy.ts +++ b/cypress/e2e/login.cy.ts @@ -14,7 +14,6 @@ describe('Login', () => { }); beforeEach(() => { - cy.mockApi(); mockWebSocket(); }); @@ -31,7 +30,7 @@ describe('Login', () => { cy.contains('Datenschutzerklärung'); }); - it('displays the login for resorts', () => { + it.only('displays the login for resorts', () => { cy.visit('/suchtberatung'); cy.contains('Login'); }); diff --git a/cypress/e2e/messages.cy.ts b/cypress/e2e/messages.cy.ts index f6d40d0e4..eb4f03480 100644 --- a/cypress/e2e/messages.cy.ts +++ b/cypress/e2e/messages.cy.ts @@ -15,7 +15,6 @@ describe('Messages', () => { }); beforeEach(() => { - cy.mockApi(); mockWebSocket(); }); @@ -53,7 +52,12 @@ describe('Messages', () => { cy.wait('@attachmentUpload'); - cy.contains('Sie haben das Limit zum Hochladen erreicht.'); + cy.window() + .its('i18n') + .then((i18n) => { + i18n.changeLanguage('cimode'); + cy.contains('attachments.error.quota.headline'); + }); }); }); @@ -81,7 +85,12 @@ describe('Messages', () => { cy.wait('@attachmentUpload'); - cy.contains('Du hast das Limit zum Hochladen erreicht.'); + cy.window() + .its('i18n') + .then((i18n) => { + i18n.changeLanguage('cimode'); + cy.contains('attachments.error.quota.headline'); + }); }); }); }); diff --git a/cypress/e2e/profile.cy.ts b/cypress/e2e/profile.cy.ts index 5ac9635e9..6f5c03aa1 100644 --- a/cypress/e2e/profile.cy.ts +++ b/cypress/e2e/profile.cy.ts @@ -4,7 +4,7 @@ import { mockWebSocket, startWebSocketServer } from '../support/websocket'; -import { USER_CONSULTANT } from '../support/commands/login'; +import { USER_CONSULTANT } from '../support/commands/mockApi'; describe('profile', () => { before(() => { @@ -16,7 +16,6 @@ describe('profile', () => { }); beforeEach(() => { - cy.mockApi(); mockWebSocket(); }); @@ -117,7 +116,7 @@ describe('profile', () => { describe('consultant absence', () => { beforeEach(() => { cy.fastLogin({ - username: USER_CONSULTANT + userId: USER_CONSULTANT }); }); @@ -127,9 +126,6 @@ describe('profile', () => { cy.contains('Meine Aktivitäten').click(); cy.contains('Hinterlegen Sie eine Abwesenheitsnachricht'); - cy.willReturn('userData', { - absent: true - }); cy.get('#absenceForm .mr--1').click(); cy.get('.button__autoClose').click(); cy.contains( @@ -139,10 +135,6 @@ describe('profile', () => { 'be.disabled' ); - cy.willReturn('userData', { - absent: false - }); - cy.get('#absenceForm .mr--1').click(); cy.get('.button__autoClose').click(); cy.contains('Hinterlegen Sie eine Abwesenheitsnachricht'); @@ -157,12 +149,10 @@ describe('profile', () => { cy.contains('Meine Aktivitäten').click(); cy.contains('Hinterlegen Sie eine Abwesenheitsnachricht'); - cy.get('#absenceForm .generalInformation textarea') - .type( - 'Liebe Ratsuchende, ich bin im Urlaub vom 23.05.2022 bis 05.06.2022.' - ) - .get('#absenceForm .mr--1') - .click(); + cy.get('#absenceForm .generalInformation textarea').type( + 'Liebe Ratsuchende, ich bin im Urlaub vom 23.05.2022 bis 05.06.2022.' + ); + cy.get('#absenceForm .mr--1').click(); cy.get('.button__autoClose').click(); cy.contains( 'Deaktivieren Sie Ihre Abwesenheit, um eine Nachricht zu hinterlegen oder sie zu bearbeiten.' @@ -183,7 +173,7 @@ describe('profile', () => { describe('consultant email notification', () => { beforeEach(() => { cy.fastLogin({ - username: USER_CONSULTANT + userId: USER_CONSULTANT }); }); diff --git a/cypress/e2e/registration.cy.ts b/cypress/e2e/registration/base.cy.ts similarity index 98% rename from cypress/e2e/registration.cy.ts rename to cypress/e2e/registration/base.cy.ts index 6ee145ca0..28fe26613 100644 --- a/cypress/e2e/registration.cy.ts +++ b/cypress/e2e/registration/base.cy.ts @@ -1,9 +1,9 @@ -import { endpoints } from '../../src/resources/scripts/endpoints'; +import { endpoints } from '../../../src/resources/scripts/endpoints'; import { closeWebSocketServer, mockWebSocket, startWebSocketServer -} from '../support/websocket'; +} from '../../support/websocket'; const checkForGenericRegistrationElements = () => { cy.get('#loginLogoWrapper').should('exist'); @@ -30,7 +30,6 @@ describe('registration', () => { }); beforeEach(() => { - cy.mockApi(); mockWebSocket(); cy.fixture('service.agencies.json').then((data) => { diff --git a/cypress/e2e/registration/consultingType.cy.ts b/cypress/e2e/registration/consultingType.cy.ts new file mode 100644 index 000000000..2fc5d93dc --- /dev/null +++ b/cypress/e2e/registration/consultingType.cy.ts @@ -0,0 +1,910 @@ +import merge from 'lodash.merge'; +import { + closeWebSocketServer, + mockWebSocket, + startWebSocketServer +} from '../../support/websocket'; +import { config } from '../../../src/resources/scripts/config'; + +const generateConsultingTypes = (base, variations) => + variations.map((variation, i) => merge({}, base, { id: i + 1 }, variation)); + +const generateTopics = (base, variations) => + variations.map((variation, i) => merge({}, base, { id: i + 1 }, variation)); + +const generateAgencies = (base, variations) => + variations.map((variation, i) => merge({}, base, { id: i + 1 }, variation)); + +let consultingTypes, agencies, topics; + +describe('Registration', () => { + before(() => { + startWebSocketServer(); + }); + + after(() => { + closeWebSocketServer(); + }); + + beforeEach(() => { + mockWebSocket(); + }); + + describe('ConsultingType', () => { + beforeEach(() => { + cy.fixture('registration/consultingType') + .then((consultingType) => { + consultingTypes = generateConsultingTypes(consultingType, [ + { + id: 1, + slug: 'consultingType1', + titles: { + welcome: 'Test Title Consulting Type 1' + } + }, + { + id: 2, + slug: 'consultingType2', + titles: { + welcome: 'Test Title Consulting Type 2' + } + }, + { + id: 3, + slug: 'consultingType3' + }, + { + id: 4, + slug: 'consultingType4', + registration: { + autoSelectPostcode: true + } + } + ]); + cy.willReturn('consultingTypes', consultingTypes); + }) + .as('consultingTypeFixture'); + cy.fixture('registration/agency') + .then((agency) => { + agencies = generateAgencies(agency, [ + { + id: 11, + name: 'Agency 11', + consultingType: 1 + }, + { + id: 12, + name: 'Agency 12', + consultingType: 1, + external: true + }, + { + id: 13, + name: 'Agency 13', + consultingType: 1 + }, + { + id: 21, + name: 'Agency 21', + consultingType: 2 + }, + { + id: 22, + name: 'Agency 22', + consultingType: 2 + }, + { + id: 31, + name: 'Agency 31', + consultingType: 3, + external: true + }, + { + id: 41, + name: 'Agency 41', + consultingType: 4, + external: true + } + ]); + cy.willReturn('agencies', agencies); + }) + .as('agencyFixture'); + }); + + describe('Without parameters', () => { + beforeEach(() => { + cy.visit('/consultingType1/registration'); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.get('.stage').should('have.class', 'stage--ready'); + }); + + it('should have consulting type loaded with title', () => { + cy.window() + .its('i18n') + .then((i18n) => { + i18n.changeLanguage('cimode'); + }); + cy.willReturn('consultingTypes').then((consultingTypes) => { + cy.get('.registrationWelcome .headline').should( + 'have.text', + consultingTypes[0].titles.welcome + ); + }); + }); + + it('should have registration steps', () => { + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').should('have.length', 4); + }); + + describe('agency search', () => { + beforeEach(() => { + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType without external', () => { + cy.get('input#postcode').type('12345', { force: true }); + cy.wait('@service.agencies'); + // Check if both agencies from consultingType2 are listed + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + // Check if one agency from consultingType1 is visible + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('exist'); + // Check if external agency from consultingType1 is hidden + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-12' + ).should('not.exist'); + // Check if one agency from other consultingType is hidden + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-21' + ).should('not.exist'); + }); + }); + }); + + describe('With valid aid parameters', () => { + beforeEach(() => { + cy.visit('/consultingType1/registration?aid=11'); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@service.agencies.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + }); + + describe('agency search', () => { + beforeEach(() => { + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show preselected agency', () => { + // Check if both agencies from consultingType2 are listed + cy.get('.preselectedAgency__item').should('have.length', 1); + // Check if one agency from consultingType1 is visible + cy.get( + '.preselectedAgency__item .radioButton__input#11' + ).should('exist'); + }); + }); + }); + + describe('With valid aid from other consultingType parameters', () => { + beforeEach(() => { + cy.visit('/consultingType1/registration?aid=21'); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@service.agencies.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + }); + + describe('agency search', () => { + beforeEach(() => { + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType', () => { + // Check if no agency are preselected + cy.get('.preselectedAgency__item').should('not.exist'); + // Check if search for agencies is working + cy.get('input#postcode').type('12345', { force: true }); + cy.wait('@service.agencies'); + // Check if both agencies from consultingType2 are listed + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + // Check if one agency from consultingType1 is visible + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('exist'); + // Check if external agency from consultingType1 is hidden + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-12' + ).should('not.exist'); + // Check if one agency from other consultingType is hidden + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-21' + ).should('not.exist'); + }); + }); + }); + + describe('With invalid aid parameter', () => { + beforeEach(() => { + cy.visit('/consultingType1/registration?aid=999'); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@service.agencies.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + }); + + describe('agency search', () => { + beforeEach(() => { + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType', () => { + // Check if no agency are preselected + cy.get('.preselectedAgency__item').should('not.exist'); + // Check if search for agencies is working + cy.get('input#postcode').type('12345', { force: true }); + cy.wait('@service.agencies'); + // Check if both agencies from consultingType2 are listed + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + // Check if one agency from consultingType1 is visible + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('exist'); + // Check if external agency from consultingType1 is hidden + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-12' + ).should('not.exist'); + // Check if one agency from other consultingType is hidden + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-21' + ).should('not.exist'); + }); + }); + }); + + describe('With all invalid parameter', () => { + it('should redirect to config.urls.landingpage if no conditions for registration', () => { + cy.visit( + '/unknown/registration?cid=xxxx-xxxx-xxxx-xxxx&aid=999' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.url().should('contain', config.urls.toRegistration); + }); + }); + + describe('Consultant [1 agency, 1 consultingType', () => { + beforeEach(() => { + cy.willReturn('agencies').then((agencies) => { + cy.fixture('service.agency.consultants.json').then( + (agencyConsultants) => { + cy.willReturn( + 'agencyConsultants', + agencyConsultants.map((c, k) => ({ + ...c, + agencies: [ + agencies.find( + (a) => a.consultingType === k + 1 + ) + ] + })) + ); + } + ); + }); + }); + describe('With valid cid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType1/registration?cid=8a81117b-d875-4ba4-8696-d62c3a2dae91' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show preselected agency', () => { + // Check if both agencies from consultingType2 are listed + cy.get('.preselectedAgency__item').should('have.length', 1); + // Check if one agency from consultingType1 is visible + cy.get( + '.preselectedAgency__item .radioButton__input#11' + ).should('exist'); + }); + }); + describe('With valid cid and aid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType1/registration?cid=8a81117b-d875-4ba4-8696-d62c3a2dae91&aid=11' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@service.agencies.id'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show preselected agency', () => { + // Check if both agencies from consultingType2 are listed + cy.get('.preselectedAgency__item').should('have.length', 1); + // Check if one agency from consultingType1 is visible + cy.get( + '.preselectedAgency__item .radioButton__input#11' + ).should('exist'); + }); + }); + describe('With valid cid and invalid aid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType1/registration?cid=8a81117b-d875-4ba4-8696-d62c3a2dae91&aid=21' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.wait('@service.agencies.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show all consultant agencies', () => { + // Check if both agencies from consultingType2 are listed + cy.get('.preselectedAgency__item').should('have.length', 1); + // Check if one agency from consultingType1 is visible + cy.get( + '.preselectedAgency__item .radioButton__input#11' + ).should('exist'); + }); + }); + describe('With valid cid from other consultingType parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType1/registration?cid=a5dc222c-94c0-4c1b-9654-0a5c34008de6' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType', () => { + // Check if both agencies from consultingType2 are listed + cy.get('.preselectedAgency__item').should('have.length', 1); + // Check if one agency from consultingType1 is visible + cy.get( + '.preselectedAgency__item .radioButton__input#21' + ).should('exist'); + }); + }); + describe('With valid cid from non existent consultingType parameters', () => { + beforeEach(() => { + cy.visit( + '/unknown/registration?cid=8a81117b-d875-4ba4-8696-d62c3a2dae91' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType', () => { + // Check if both agencies from consultingType2 are listed + cy.get('.preselectedAgency__item').should('have.length', 1); + // Check if one agency from consultingType1 is visible + cy.get( + '.preselectedAgency__item .radioButton__input#11' + ).should('exist'); + }); + }); + }); + describe('Consultant [2 agency, 1 consultingType', () => { + beforeEach(() => { + cy.willReturn('agencies').then((agencies) => { + cy.fixture('service.agency.consultants.json').then( + (agencyConsultants) => { + cy.willReturn( + 'agencyConsultants', + agencyConsultants.map((c, k) => ({ + ...c, + agencies: agencies.filter( + (a) => a.consultingType === k + 1 + ) + })) + ); + } + ); + }); + }); + describe('With valid cid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType1/registration?cid=8a81117b-d875-4ba4-8696-d62c3a2dae91' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show preselected agency', () => { + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-13' + ).should('exist'); + }); + }); + describe('With valid cid and aid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType1/registration?cid=8a81117b-d875-4ba4-8696-d62c3a2dae91&aid=11' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@service.agencies.id'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show preselected agency', () => { + // Check if both agencies from consultingType2 are listed + cy.get('.preselectedAgency__item').should('have.length', 1); + // Check if one agency from consultingType1 is visible + cy.get( + '.preselectedAgency__item .radioButton__input#11' + ).should('exist'); + }); + }); + describe('With valid cid and invalid aid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType1/registration?cid=8a81117b-d875-4ba4-8696-d62c3a2dae91&aid=21' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.wait('@service.agencies.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show all consultant agencies', () => { + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-13' + ).should('exist'); + }); + }); + describe('With valid cid from other consultingType parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType1/registration?cid=a5dc222c-94c0-4c1b-9654-0a5c34008de6' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType', () => { + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-21' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-22' + ).should('exist'); + }); + }); + describe('With valid cid from non existent consultingType parameters', () => { + beforeEach(() => { + cy.visit( + '/unknown/registration?cid=8a81117b-d875-4ba4-8696-d62c3a2dae91' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType', () => { + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-13' + ).should('exist'); + }); + }); + }); + describe('Consultant [2 agency, multiple consultingTypes', () => { + beforeEach(() => { + cy.willReturn('agencies').then((agencies) => { + cy.fixture('service.agency.consultants.json').then( + (agencyConsultants) => { + cy.willReturn( + 'agencyConsultants', + agencyConsultants.map((c) => ({ + ...c, + agencies: agencies + })) + ); + } + ); + }); + }); + describe('With valid cid parameters without consultingType', () => { + beforeEach(() => { + cy.visit( + '/registration?cid=8a81117b-d875-4ba4-8696-d62c3a2dae91' + ); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show agencies with consultingtype dropdown', () => { + cy.get('#consultingTypeSelection').should('exist'); + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-13' + ).should('exist'); + + cy.get('#consultingTypeSelection').click(); + cy.get('#consultingTypeSelection .select__input__option') + .eq(1) + .click(); + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-21' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-22' + ).should('exist'); + }); + }); + describe('With valid cid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType1/registration?cid=8a81117b-d875-4ba4-8696-d62c3a2dae91' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show preselected agency', () => { + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-13' + ).should('exist'); + }); + }); + describe('With valid cid and aid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType1/registration?cid=8a81117b-d875-4ba4-8696-d62c3a2dae91&aid=11' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@service.agencies.id'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show preselected agency', () => { + cy.get('#consultingTypeSelection').should('not.exist'); + // Check if both agencies from consultingType2 are listed + cy.get('.preselectedAgency__item').should('have.length', 1); + // Check if one agency from consultingType1 is visible + cy.get( + '.preselectedAgency__item .radioButton__input#11' + ).should('exist'); + }); + }); + describe('With valid cid and invalid aid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType1/registration?cid=8a81117b-d875-4ba4-8696-d62c3a2dae91&aid=21' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.wait('@service.agencies.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show all consultant agencies', () => { + cy.get('#consultingTypeSelection').should('not.exist'); + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-13' + ).should('exist'); + }); + }); + describe('With valid cid from other consultingType parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType2/registration?cid=a5dc222c-94c0-4c1b-9654-0a5c34008de6' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType', () => { + cy.get('#consultingTypeSelection').should('not.exist'); + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-21' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-22' + ).should('exist'); + }); + }); + describe('With valid cid from non existent consultingType parameters', () => { + beforeEach(() => { + cy.visit( + '/unknown/registration?cid=8a81117b-d875-4ba4-8696-d62c3a2dae91' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType', () => { + cy.get('#consultingTypeSelection').should('exist'); + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-13' + ).should('exist'); + + cy.get('#consultingTypeSelection').click(); + cy.get('#consultingTypeSelection .select__input__option') + .eq(1) + .click(); + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-21' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-22' + ).should('exist'); + }); + }); + }); + describe('With invalid cid parameter', () => { + beforeEach(() => { + cy.visit( + '/consultingType1/registration?cid=xxxx-xxxx-xxxx-xxxx' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType', () => { + // Check if no agency are preselected + cy.get('.preselectedAgency__item').should('not.exist'); + // Check if search for agencies is working + cy.get('input#postcode').type('12345', { force: true }); + cy.wait('@service.agencies'); + // Check if both agencies from consultingType2 are listed + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + // Check if one agency from consultingType1 is visible + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('exist'); + // Check if external agency from consultingType1 is hidden + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-13' + ).should('exist'); + // Check if one agency from other consultingType is hidden + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-21' + ).should('not.exist'); + }); + }); + describe('With invalid cid and valid aid parameter', () => { + beforeEach(() => { + cy.visit( + '/consultingType1/registration?cid=xxxx-xxxx-xxxx-xxxx&aid=11' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.wait('@service.agencies.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + }); + + describe('agency search', () => { + beforeEach(() => { + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType', () => { + // Check if both agencies from consultingType2 are listed + cy.get('.preselectedAgency__item').should('have.length', 1); + // Check if one agency from consultingType1 is visible + cy.get( + '.preselectedAgency__item .radioButton__input#11' + ).should('exist'); + }); + }); + }); + + describe('agency search without autoselect postcode should hide external agency', () => { + beforeEach(() => { + cy.visit('/consultingType3/registration'); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType without external', () => { + cy.get('input#postcode').should('exist'); + cy.get('input#postcode').type('12345', { force: true }); + cy.wait('@service.agencies'); + // Check if no agencies found because external should be hidden without autoselectpostcode + cy.get('.registrationForm__no-agency-found').should('exist'); + }); + }); + + describe('agency search with autoselect postcode should show external agency', () => { + beforeEach(() => { + cy.visit('/consultingType4/registration'); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType without external', () => { + cy.get('input#postcode').should('not.exist'); + cy.wait('@service.agencies'); + // Check if no agencies found because external should be hidden without autoselectpostcode + cy.get('.registrationForm__no-agency-found').should( + 'not.exist' + ); + // Check if both agencies from consultingType2 are listed + cy.get('.preselectedAgency__item').should('have.length', 1); + // Check if one agency from consultingType1 is visible + cy.get( + '.preselectedAgency__item .radioButton__input#41' + ).should('exist'); + }); + }); + + describe('agency search without autoselect postcode should hide external agency [valid aid]', () => { + beforeEach(() => { + cy.visit('/consultingType3/registration?aid=11'); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@service.agencies.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType without external', () => { + cy.get('input#postcode').should('exist'); + cy.get('input#postcode').type('12345', { force: true }); + cy.wait('@service.agencies'); + // Check if no agencies found because external should be hidden without autoselectpostcode + cy.get('.registrationForm__no-agency-found').should('exist'); + }); + }); + + describe('agency search with autoselect postcode should show external agency [invalid aid]', () => { + beforeEach(() => { + cy.visit('/consultingType4/registration?aid=21'); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType without external', () => { + cy.get('input#postcode').should('not.exist'); + // Check if no agencies found because external should be hidden without autoselectpostcode + cy.get('.registrationForm__no-agency-found').should( + 'not.exist' + ); + // Check if both agencies from consultingType2 are listed + cy.get('.preselectedAgency__item').should('have.length', 1); + // Check if one agency from consultingType1 is visible + cy.get( + '.preselectedAgency__item .radioButton__input#41' + ).should('exist'); + }); + }); + }); +}); diff --git a/cypress/e2e/registration/topic.cy.ts b/cypress/e2e/registration/topic.cy.ts new file mode 100644 index 000000000..2f79f17c4 --- /dev/null +++ b/cypress/e2e/registration/topic.cy.ts @@ -0,0 +1,1358 @@ +import merge from 'lodash.merge'; +import { + closeWebSocketServer, + mockWebSocket, + startWebSocketServer +} from '../../support/websocket'; +import { config } from '../../../src/resources/scripts/config'; + +const generateConsultingTypes = (base, variations) => + variations.map((variation, i) => merge({}, base, { id: i + 1 }, variation)); + +const generateTopics = (base, variations) => + variations.map((variation, i) => merge({}, base, { id: i + 1 }, variation)); + +const generateAgencies = (base, variations) => + variations.map((variation, i) => merge({}, base, { id: i + 1 }, variation)); + +let consultingTypes, agencies, topics; + +describe('Registration', () => { + before(() => { + Cypress.env('TENANT_ENABLED', '1'); + startWebSocketServer(); + }); + + after(() => { + closeWebSocketServer(); + }); + + beforeEach(() => { + mockWebSocket(); + + cy.willReturn( + 'frontend.settings', + { + useTenantService: true, + registration: { + useConsultingTypeSlug: 1 + } + }, + true + ); + cy.willReturn( + 'service.tenant.public', + { + settings: { + featureTopicsEnabled: true, + topicsInRegistrationEnabled: true + } + }, + true + ); + cy.willReturn( + 'settings', + { + multitenancyWithSingleDomainEnabled: { + value: true, + readOnly: true + }, + useTenantService: { + value: true, + readOnly: true + } + }, + true + ); + }); + + describe('Topic', () => { + beforeEach(() => { + cy.fixture('registration/consultingType') + .then((consultingType) => { + consultingTypes = generateConsultingTypes(consultingType, [ + { + id: 1, + slug: 'consultingType', + titles: { + welcome: 'Test Title Consulting Type 1' + } + }, + { + id: 2, + slug: 'consultingType', + titles: { + welcome: 'Test Title Consulting Type 2' + } + }, + { + id: 3, + slug: 'consultingType' + }, + { + id: 4, + slug: 'consultingType', + registration: { + autoSelectPostcode: true + } + } + ]); + cy.willReturn('consultingTypes', consultingTypes); + }) + .as('consultingTypeFixture'); + cy.fixture('registration/topic') + .then((topic) => { + topics = generateTopics(topic, [ + { + id: 11, + name: 'Topic 11' + }, + { + id: 12, + name: 'Topic 12' + }, + { + id: 21, + name: 'Topic 21' + }, + { + id: 22, + name: 'Topic 22' + }, + { + id: 31, + name: 'Topic 31' + }, + { + id: 41, + name: 'Topic 41' + } + ]); + cy.willReturn('topics', topics); + }) + .as('topicFixture'); + cy.fixture('registration/agency') + .then((agency) => { + agencies = generateAgencies(agency, [ + { + id: 11, + name: 'Agency 11', + consultingType: 1, + topicIds: [11] + }, + { + id: 12, + name: 'Agency 12', + consultingType: 1, + external: true, + topicIds: [12] + }, + { + id: 13, + name: 'Agency 13', + consultingType: 1, + topicIds: [11, 12] + }, + { + id: 21, + name: 'Agency 21', + consultingType: 2, + topicIds: [21, 22] + }, + { + id: 22, + name: 'Agency 22', + consultingType: 2, + topicIds: [21, 22] + }, + { + id: 23, + name: 'Agency 23', + consultingType: 2 + }, + { + id: 24, + name: 'Agency 24', + consultingType: 2, + external: true, + topicIds: [21, 22] + }, + { + id: 31, + name: 'Agency 31', + consultingType: 3, + external: true + }, + { + id: 41, + name: 'Agency 41', + consultingType: 4, + external: true, + topicIds: [41] + } + ]); + cy.willReturn('agencies', agencies); + }) + .as('agencyFixture'); + }); + + describe('Without parameters', () => { + beforeEach(() => { + cy.visit('/consultingType/registration'); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.get('.stage').should('have.class', 'stage--ready'); + }); + + it('should have consulting type loaded with title', () => { + cy.window() + .its('i18n') + .then((i18n) => { + i18n.changeLanguage('cimode'); + }); + cy.willReturn('consultingTypes').then((consultingTypes) => { + cy.get('.registrationWelcome .headline').should( + 'have.text', + consultingTypes[0].titles.welcome + ); + }); + }); + + it('should have registration steps', () => { + cy.get('[data-cy=close-welcome-screen]').click(); + cy.get('.formAccordionItem').should('have.length', 5); + }); + + describe('agency search', () => { + beforeEach(() => { + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + }); + + it('should find agencies for all consultingTypes without external', () => { + cy.get('.mainTopicSelection').should('exist'); + cy.get('.formAccordionItem').eq(2).click(); + cy.get( + '.mainTopicSelection .mainTopicSelection__topic' + ).should('have.length', 6); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-31-31' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-41-41' + ).should('exist'); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).click(); + + cy.get('.formAccordionItem').eq(3).click(); + cy.get('input#postcode').type('12345', { force: true }); + cy.wait('@service.agencies'); + + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-21' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-22' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-23' + ).should('not.exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-24' + ).should('not.exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('not.exist'); + }); + }); + }); + + describe('With valid aid parameters', () => { + beforeEach(() => { + cy.visit('/consultingType/registration?aid=11'); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@service.agencies.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should filter topics show preselected agency', () => { + cy.get('.mainTopicSelection .mainTopicSelection__topic').should( + 'have.length', + 1 + ); + // Check if one agency from consultingType1 is visible + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-12-12' + ).should('not.exist'); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).click(); + + cy.get('.formAccordionItem').eq(3).click(); + + // Check if both agencies from consultingType2 are listed + cy.get('.preselectedAgency__item').should('have.length', 1); + // Check if one agency from consultingType1 is visible + cy.get( + '.preselectedAgency__item .radioButton__input#11' + ).should('exist'); + }); + }); + + describe('With valid aid with multiple topics', () => { + beforeEach(() => { + cy.visit('/consultingType/registration?aid=13'); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@service.agencies.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType', () => { + cy.get('.mainTopicSelection .mainTopicSelection__topic').should( + 'have.length', + 2 + ); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-12-12' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).should('not.exist'); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-12-12' + ).click(); + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('.preselectedAgency__item').should('have.length', 1); + cy.get( + '.preselectedAgency__item .radioButton__input#13' + ).should('exist'); + }); + }); + + describe('With invalid aid parameter', () => { + beforeEach(() => { + cy.visit('/consultingType/registration?aid=999'); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@service.agencies.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show all topics and agencies', () => { + // Check if both agencies from consultingType2 are listed + cy.get('.mainTopicSelection').should('exist'); + cy.get('.formAccordionItem').eq(2).click(); + cy.get('.mainTopicSelection .mainTopicSelection__topic').should( + 'have.length', + 6 + ); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-31-31' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-41-41' + ).should('exist'); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).click(); + + cy.get('.formAccordionItem').eq(3).click(); + cy.get('input#postcode').type('12345', { force: true }); + cy.wait('@service.agencies'); + + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-21' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-22' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-23' + ).should('not.exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-24' + ).should('not.exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('not.exist'); + }); + }); + + describe('With all (cid, tid, aid) invalid parameter', () => { + it('should redirect to config.urls.landingpage if no conditions for registration', () => { + cy.visit( + '/unknown/registration?cid=xxxx-xxxx-xxxx-xxxx&aid=999&tid=999' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@service.agencies.id'); + cy.wait('@agencyConsultants.id'); + cy.url().should('contain', config.urls.toRegistration); + }); + }); + + describe('Consultant [1 agency, 1 topic]', () => { + beforeEach(() => { + cy.willReturn('agencies').then((agencies) => { + cy.fixture('service.agency.consultants.json').then( + (agencyConsultants) => { + cy.willReturn( + 'agencyConsultants', + agencyConsultants.map((c, k) => ({ + ...c, + agencies: [ + agencies.find((a) => + a.topicIds?.some( + (tid) => + tid >= (k + 1) * 10 && + tid < (k + 2) * 10 + ) + ) + ] + })) + ); + } + ); + }); + }); + describe('With valid cid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType/registration?cid=8a81117b-d875-4ba4-8696-d62c3a2dae91' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show preselected agency', () => { + cy.get( + '.mainTopicSelection .mainTopicSelection__topic' + ).should('have.length', 1); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('.preselectedAgency__item').should('have.length', 1); + cy.get( + '.preselectedAgency__item .radioButton__input#11' + ).should('exist'); + }); + }); + describe('With valid cid and aid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType/registration?tid=11&cid=8a81117b-d875-4ba4-8696-d62c3a2dae91&aid=11' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@service.agencies.id'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show preselected agency', () => { + cy.get( + '.mainTopicSelection .mainTopicSelection__topic' + ).should('have.length', 1); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('.preselectedAgency__item').should('have.length', 1); + cy.get( + '.preselectedAgency__item .radioButton__input#11' + ).should('exist'); + }); + }); + + describe('With valid tid & cid and invalid aid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType/registration?tid=11&cid=8a81117b-d875-4ba4-8696-d62c3a2dae91&aid=21' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@service.agencies.id'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show all consultant agencies', () => { + cy.get( + '.mainTopicSelection .mainTopicSelection__topic' + ).should('have.length', 1); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('.preselectedAgency__item').should('have.length', 1); + cy.get( + '.preselectedAgency__item .radioButton__input#11' + ).should('exist'); + }); + }); + + describe('With valid cid from other topic parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType/registration?tid=11&cid=a5dc222c-94c0-4c1b-9654-0a5c34008de6' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for tid', () => { + cy.get( + '.mainTopicSelection .mainTopicSelection__topic' + ).should('have.length', 2); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('not.exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).should('exist'); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).click(); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('.preselectedAgency__item').should('have.length', 1); + cy.get( + '.preselectedAgency__item .radioButton__input#21' + ).should('exist'); + }); + }); + describe('With valid cid from non existent tid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType/registration?tid=999&cid=8a81117b-d875-4ba4-8696-d62c3a2dae91' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType', () => { + cy.get( + '.mainTopicSelection .mainTopicSelection__topic' + ).should('have.length', 1); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('exist'); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('.preselectedAgency__item').should('have.length', 1); + cy.get( + '.preselectedAgency__item .radioButton__input#11' + ).should('exist'); + }); + }); + }); + describe('Consultant [2 agency, 1 topic', () => { + beforeEach(() => { + cy.willReturn('agencies').then((agencies) => { + cy.fixture('service.agency.consultants.json').then( + (agencyConsultants) => { + cy.willReturn( + 'agencyConsultants', + agencyConsultants.map((c, k) => ({ + ...c, + agencies: agencies.filter((a) => + a.topicIds?.some( + (tid) => + tid >= (k + 1) * 10 && + tid < (k + 2) * 10 + ) + ) + })) + ); + } + ); + }); + }); + describe('With valid cid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType/registration?tid=21&cid=a5dc222c-94c0-4c1b-9654-0a5c34008de6' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show preselected agency', () => { + cy.get( + '.mainTopicSelection .mainTopicSelection__topic' + ).should('have.length', 1); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-22-22' + ).should('not.exist'); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-21' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-22' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('not.exist'); + }); + }); + describe('With valid cid and aid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType/registration?tid=21&cid=a5dc222c-94c0-4c1b-9654-0a5c34008de6&aid=21' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.wait('@service.agencies.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show preselected agency', () => { + cy.get( + '.mainTopicSelection .mainTopicSelection__topic' + ).should('have.length', 1); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('not.exist'); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('.preselectedAgency__item').should('have.length', 1); + cy.get( + '.preselectedAgency__item .radioButton__input#21' + ).should('exist'); + }); + }); + describe('With valid cid and invalid aid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType/registration?tid=21&cid=a5dc222c-94c0-4c1b-9654-0a5c34008de6&aid=11' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.wait('@service.agencies.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show all consultant agencies', () => { + cy.get( + '.mainTopicSelection .mainTopicSelection__topic' + ).should('have.length', 1); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('not.exist'); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-21' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-22' + ).should('exist'); + }); + }); + describe('With valid cid from other tid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType/registration?tid=11&cid=a5dc222c-94c0-4c1b-9654-0a5c34008de6' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType', () => { + cy.get( + '.mainTopicSelection .mainTopicSelection__topic' + ).should('have.length', 2); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('not.exist'); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).click(); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-21' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-23' + ).should('not.exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('not.exist'); + }); + }); + describe('With valid cid from non existent tid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType/registration?tid=999&cid=a5dc222c-94c0-4c1b-9654-0a5c34008de6' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType', () => { + cy.get( + '.mainTopicSelection .mainTopicSelection__topic' + ).should('have.length', 2); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('not.exist'); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).click(); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-21' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-23' + ).should('not.exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('not.exist'); + }); + }); + }); + describe('Consultant [2 agency, multiple topics', () => { + beforeEach(() => { + cy.willReturn('agencies').then((agencies) => { + cy.fixture('service.agency.consultants.json').then( + (agencyConsultants) => { + cy.willReturn( + 'agencyConsultants', + agencyConsultants.map((c) => ({ + ...c, + agencies: agencies + })) + ); + } + ); + }); + }); + describe('With valid cid parameters without tid', () => { + beforeEach(() => { + cy.visit( + '/registration?cid=8a81117b-d875-4ba4-8696-d62c3a2dae91' + ); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show agencies with topic select', () => { + cy.get( + '.mainTopicSelection .mainTopicSelection__topic' + ).should('have.length', 5); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).should('exist'); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).click(); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 5 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-13' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-21' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-22' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-23' + ).should('exist'); + }); + }); + describe('With valid cid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType/registration?tid=11&cid=8a81117b-d875-4ba4-8696-d62c3a2dae91' + ); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show preselected agency', () => { + cy.get( + '.mainTopicSelection .mainTopicSelection__topic' + ).should('have.length', 1); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).should('not.exist'); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).click(); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-13' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-21' + ).should('not.exist'); + }); + }); + describe('With valid cid and aid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType/registration?tid=11&cid=8a81117b-d875-4ba4-8696-d62c3a2dae91&aid=11' + ); + cy.wait('@service.agencies.id'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show preselected agency', () => { + cy.get( + '.mainTopicSelection .mainTopicSelection__topic' + ).should('have.length', 1); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).should('not.exist'); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('.preselectedAgency__item').should('have.length', 1); + cy.get( + '.preselectedAgency__item .radioButton__input#11' + ).should('exist'); + }); + }); + describe('With valid cid and invalid aid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType/registration?tid=11&cid=8a81117b-d875-4ba4-8696-d62c3a2dae91&aid=21' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.wait('@service.agencies.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should show all consultant agencies', () => { + cy.get( + '.mainTopicSelection .mainTopicSelection__topic' + ).should('have.length', 1); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).should('not.exist'); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-13' + ).should('exist'); + }); + }); + describe('With valid cid from other tid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType/registration?tid=11&cid=a5dc222c-94c0-4c1b-9654-0a5c34008de6' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType', () => { + cy.get( + '.mainTopicSelection .mainTopicSelection__topic' + ).should('have.length', 1); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).should('not.exist'); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-13' + ).should('exist'); + }); + }); + describe('With valid cid from non existent tid parameters', () => { + beforeEach(() => { + cy.visit( + '/consultingType/registration?tid=99&cid=8a81117b-d875-4ba4-8696-d62c3a2dae91' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType', () => { + cy.get( + '.mainTopicSelection .mainTopicSelection__topic' + ).should('have.length', 5); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).should('exist'); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).click(); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 5 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-13' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-21' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-22' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-23' + ).should('exist'); + }); + }); + }); + describe('With invalid cid parameter', () => { + beforeEach(() => { + cy.visit( + '/consultingType/registration?tid=11&cid=xxxx-xxxx-xxxx-xxxx' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType', () => { + cy.get('.mainTopicSelection .mainTopicSelection__topic').should( + 'have.length', + 1 + ); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).should('not.exist'); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('input#postcode').type('12345', { force: true }); + cy.wait('@service.agencies'); + + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-13' + ).should('exist'); + }); + }); + describe('With invalid cid and valid aid parameter', () => { + beforeEach(() => { + cy.visit( + '/consultingType/registration?tid=11&cid=xxxx-xxxx-xxxx-xxxx&aid=11' + ); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@agencyConsultants.id'); + cy.wait('@service.agencies.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType', () => { + cy.get('.mainTopicSelection .mainTopicSelection__topic').should( + 'have.length', + 1 + ); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).should('not.exist'); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('.preselectedAgency__item').should('have.length', 1); + cy.get( + '.preselectedAgency__item .radioButton__input#11' + ).should('exist'); + }); + }); + + describe('agency search without autoselect postcode should hide external agency', () => { + beforeEach(() => { + cy.visit('/consultingType/registration?tid=11'); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType without external', () => { + cy.get('.mainTopicSelection .mainTopicSelection__topic').should( + 'have.length', + 1 + ); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('exist'); + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-21-21' + ).should('not.exist'); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('input#postcode').should('exist'); + cy.get('input#postcode').type('12345', { force: true }); + cy.wait('@service.agencies'); + + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-13' + ).should('exist'); + }); + }); + + describe('agency search with autoselect postcode should show external agency', () => { + beforeEach(() => { + cy.willReturn('consultingTypes').then((consultingTypes) => { + cy.willReturn( + 'consultingTypes', + consultingTypes.map((c) => ({ + ...c, + registration: { + autoSelectPostcode: true + } + })) + ); + }); + + cy.visit('/consultingType/registration?tid=41'); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType without external', () => { + cy.get('.mainTopicSelection .mainTopicSelection__topic').should( + 'have.length', + 1 + ); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-41-41' + ).should('exist'); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('input#postcode').should('not.exist'); + + cy.get( + '.preselectedAgency__item .radioButton__input#41' + ).should('exist'); + }); + }); + + describe('agency search without autoselect postcode should hide external agency [valid aid]', () => { + beforeEach(() => { + cy.visit('/consultingType/registration?tid=11&aid=12'); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@service.agencies.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType without external', () => { + cy.get('.mainTopicSelection .mainTopicSelection__topic').should( + 'have.length', + 1 + ); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('exist'); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('input#postcode').type('12345', { force: true }); + cy.wait('@service.agencies'); + + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-13' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-12' + ).should('not.exist'); + + cy.get( + '.preselectedAgency__item .radioButton__input#12' + ).should('not.exist'); + }); + }); + + describe('agency search with autoselect postcode should show external agency [invalid aid]', () => { + beforeEach(() => { + cy.visit('/consultingType/registration?tid=11&aid=21'); + cy.wait('@consultingTypeServiceBySlugFull'); + cy.wait('@service.agencies.id'); + cy.get('.stage').should('have.class', 'stage--ready'); + cy.get('[data-cy=close-welcome-screen]').click(); + cy.wait('@topics'); + cy.get('.formAccordionItem').eq(2).click(); + }); + + it('should find agencies for consultingType without external', () => { + cy.get('.mainTopicSelection .mainTopicSelection__topic').should( + 'have.length', + 1 + ); + + cy.get( + '.mainTopicSelection__topic .radioButton__input#topic-11-11' + ).should('exist'); + + cy.get('.formAccordionItem').eq(3).click(); + + cy.get('input#postcode').type('12345', { force: true }); + cy.wait('@service.agencies'); + + cy.get('.agencySelection__proposedAgency').should( + 'have.length', + 2 + ); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-11' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-13' + ).should('exist'); + cy.get( + '.agencySelection__proposedAgency .radioButton__input#agency-21' + ).should('not.exist'); + + cy.get( + '.preselectedAgency__item .radioButton__input#21' + ).should('not.exist'); + }); + }); + }); +}); diff --git a/cypress/e2e/release-notes.cy.ts b/cypress/e2e/release-notes.cy.ts index f1eb1819b..5fa0d186d 100644 --- a/cypress/e2e/release-notes.cy.ts +++ b/cypress/e2e/release-notes.cy.ts @@ -1,4 +1,4 @@ -import { USER_CONSULTANT } from '../support/commands/login'; +import { USER_CONSULTANT } from '../support/commands/mockApi'; import { closeWebSocketServer, mockWebSocket, @@ -15,7 +15,6 @@ describe('release-note', () => { }); beforeEach(() => { - cy.mockApi(); mockWebSocket(); }); @@ -45,7 +44,7 @@ describe('release-note', () => { }); cy.fastLogin({ - username: USER_CONSULTANT + userId: USER_CONSULTANT }); cy.wait('@consultingTypeServiceBaseBasic'); cy.wait('@releases'); @@ -59,7 +58,7 @@ describe('release-note', () => { cy.get('.releaseNote').should('not.exist'); cy.fastLogin({ - username: USER_CONSULTANT + userId: USER_CONSULTANT }); cy.get('.releaseNote').should('not.exist'); @@ -87,7 +86,7 @@ describe('release-note', () => { }); cy.fastLogin({ - username: USER_CONSULTANT + userId: USER_CONSULTANT }); cy.wait('@consultingTypeServiceBaseBasic'); cy.wait('@releases'); @@ -100,7 +99,7 @@ describe('release-note', () => { cy.get('.releaseNote').should('not.exist'); cy.fastLogin({ - username: USER_CONSULTANT + userId: USER_CONSULTANT }); cy.get('.releaseNote').should('exist'); @@ -108,7 +107,7 @@ describe('release-note', () => { it('should not show the release note overlay if there is no file', () => { cy.fastLogin({ - username: USER_CONSULTANT + userId: USER_CONSULTANT }); cy.wait('@consultingTypeServiceBaseBasic'); diff --git a/cypress/e2e/sessions.cy.ts b/cypress/e2e/sessions.cy.ts index 7308a5887..53a90ff86 100644 --- a/cypress/e2e/sessions.cy.ts +++ b/cypress/e2e/sessions.cy.ts @@ -11,7 +11,7 @@ import { MAX_ITEMS_TO_SHOW_WELCOME_ILLUSTRATION, SCROLL_PAGINATE_THRESHOLD } from '../../src/components/sessionsList/sessionsListConfig'; -import { USER_CONSULTANT } from '../support/commands/login'; +import { USER_CONSULTANT } from '../support/commands/mockApi'; describe('Sessions', () => { before(() => { @@ -23,7 +23,6 @@ describe('Sessions', () => { }); beforeEach(() => { - cy.mockApi(); mockWebSocket(); }); @@ -32,7 +31,7 @@ describe('Sessions', () => { generateMultipleConsultantSessions(5); cy.fastLogin({ - username: USER_CONSULTANT + userId: USER_CONSULTANT }); cy.wait('@consultingTypeServiceBaseBasic'); @@ -60,7 +59,7 @@ describe('Sessions', () => { generateMultipleConsultantSessions(3); cy.fastLogin({ - username: USER_CONSULTANT + userId: USER_CONSULTANT }); cy.wait('@consultingTypeServiceBaseBasic'); @@ -72,7 +71,7 @@ describe('Sessions', () => { generateMultipleConsultantSessions(100); cy.fastLogin({ - username: USER_CONSULTANT + userId: USER_CONSULTANT }); cy.wait('@consultingTypeServiceBaseBasic'); @@ -101,7 +100,7 @@ describe('Sessions', () => { generateMultipleConsultantSessions(100); cy.fastLogin({ - username: USER_CONSULTANT + userId: USER_CONSULTANT }); cy.wait('@consultingTypeServiceBaseBasic'); @@ -135,7 +134,7 @@ describe('Sessions', () => { generateMultipleConsultantSessions(16); cy.fastLogin({ - username: USER_CONSULTANT + userId: USER_CONSULTANT }); cy.wait('@rcSettingsPublic'); cy.wait('@consultingTypeServiceBaseBasic'); @@ -145,7 +144,9 @@ describe('Sessions', () => { cy.get('.sessionsListItem.skeleton').should('not.exist'); cy.get('.sessionsListItem').should('exist'); - cy.willReturn('consultantSessions', 401); + cy.willReturn('consultantSessions', { + statusCode: 401 + }); cy.get('.sessionsList__scrollContainer').scrollTo('bottom'); cy.wait('@consultantSessions'); diff --git a/cypress/e2e/tokens.cy.ts b/cypress/e2e/tokens.cy.ts index 56c554aa8..04be35767 100644 --- a/cypress/e2e/tokens.cy.ts +++ b/cypress/e2e/tokens.cy.ts @@ -1,5 +1,8 @@ import { RENEW_BEFORE_EXPIRY_IN_MS } from '../../src/components/auth/auth'; -import { getTokenExpiryFromLocalStorage } from '../../src/components/sessionCookie/accessSessionLocalStorage'; +import { + getLocalStorageItem, + getTokenExpiryFromLocalStorage +} from '../../src/components/sessionCookie/accessSessionLocalStorage'; import { closeWebSocketServer, mockWebSocket, @@ -24,8 +27,6 @@ describe('Keycloak Tokens', () => { }); beforeEach(() => { - cy.mockApi(); - cy.fixture('auth.token.json').then((fixture) => { authTokenJson = fixture; }); @@ -34,15 +35,18 @@ describe('Keycloak Tokens', () => { it('should get and store tokens and expiry time on login', () => { cy.login(); - cy.wait('@askerSessions'); + cy.wait('@usersData'); + cy.wait('@askerSessions'); cy.get('#appRoot').then(() => { cy.getCookie('keycloak').should('exist'); cy.getCookie('refreshToken').should('exist'); const tokenExpiry = getTokenExpiryFromLocalStorage(); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions expect(tokenExpiry.accessTokenValidUntilTime).to.exist; + // eslint-disable-next-line @typescript-eslint/no-unused-expressions expect(tokenExpiry.refreshTokenValidUntilTime).to.exist; }); }); @@ -50,8 +54,8 @@ describe('Keycloak Tokens', () => { it('should keep refreshing access token before it expires', () => { cy.clock(); cy.login(); - cy.wait('@askerSessions'); cy.wait('@usersData'); + cy.wait('@askerSessions'); for (let check = 0; check < 3; check++) { waitForTokenProcessing(); @@ -72,8 +76,8 @@ describe('Keycloak Tokens', () => { cy.clock(); cy.login(); - cy.wait('@askerSessions'); cy.wait('@usersData'); + cy.wait('@askerSessions'); cy.clock().then((clock) => { clock.restore(); @@ -92,11 +96,11 @@ describe('Keycloak Tokens', () => { cy.get('#appRoot').should('exist'); }); - it.skip('should logout if refresh token is already expired when loading the app', () => { + it('should logout if refresh token is already expired when loading the app', () => { cy.clock(); cy.login(); - cy.wait('@askerSessions'); cy.wait('@usersData'); + cy.wait('@askerSessions'); cy.clock().then((clock) => { clock.restore(); @@ -106,23 +110,30 @@ describe('Keycloak Tokens', () => { cy.get('#appRoot'); waitForTokenProcessing(); - cy.tick(1000); // logout() call uses setTimeout + cy.wait('@apiLogout'); + cy.wait('@authLogout'); + // Wait to get cookies processed and timeout is started + cy.wait(100); // eslint-disable-line cypress/no-unnecessary-waiting + cy.tick(2000); // logout() call uses setTimeout cy.get('.loginForm').should('exist'); }); - //TODO: inspect this test, as there seems to be a race condition - it.skip('should logout if refresh token is expired while the app is loaded', () => { + it('should logout if refresh token is expired while the app is loaded', () => { cy.clock(); cy.login(); - cy.wait('@askerSessions'); cy.wait('@usersData'); + cy.wait('@askerSessions'); waitForTokenProcessing(); cy.tick(authTokenJson.refresh_expires_in * 1000 + 1); waitForTokenProcessing(); - cy.tick(1000); // logout() call uses setTimeout + cy.wait('@apiLogout'); + cy.wait('@authLogout'); + // Wait to get cookies processed and timeout is started + cy.wait(100); // eslint-disable-line cypress/no-unnecessary-waiting + cy.tick(2000); // logout() call uses setTimeout cy.get('.loginForm').should('exist'); }); @@ -131,8 +142,8 @@ describe('Keycloak Tokens', () => { cy.login({ auth: { expires_in: 1800, refresh_expires_in: 600 } }); - cy.wait('@askerSessions'); cy.wait('@usersData'); + cy.wait('@askerSessions'); waitForTokenProcessing(); cy.tick(600 * 1000); @@ -149,8 +160,8 @@ describe('Keycloak Tokens', () => { cy.login({ auth: { expires_in: 1800, refresh_expires_in: refreshExpiresIn } }); - cy.wait('@askerSessions'); cy.wait('@usersData'); + cy.wait('@askerSessions'); cy.clock().then((clock) => { clock.restore(); diff --git a/cypress/e2e/video-calls.cy.ts b/cypress/e2e/video-calls.cy.ts index 1bd281d3e..d20be2041 100644 --- a/cypress/e2e/video-calls.cy.ts +++ b/cypress/e2e/video-calls.cy.ts @@ -7,7 +7,7 @@ import { generateMultipleAskerSessions, generateMultipleConsultantSessions } from '../support/sessions'; -import { USER_VIDEO } from '../support/commands/login'; +import { USER_VIDEO } from '../support/commands/mockApi'; xdescribe('Video calls', () => { before(() => { @@ -19,7 +19,6 @@ xdescribe('Video calls', () => { }); beforeEach(() => { - cy.mockApi(); mockWebSocket(); }); @@ -385,7 +384,7 @@ xdescribe('Video calls', () => { }); cy.fastLogin({ - username: USER_VIDEO + userId: USER_VIDEO }); cy.wait('@consultingTypeServiceBaseBasic'); @@ -511,7 +510,7 @@ xdescribe('Video calls', () => { }); cy.fastLogin({ - username: USER_VIDEO + userId: USER_VIDEO }); cy.wait('@consultingTypeServiceBaseBasic'); diff --git a/cypress/e2e/videoconference.cy.ts b/cypress/e2e/videoconference.cy.ts index 921b94a2d..fa0873d2c 100644 --- a/cypress/e2e/videoconference.cy.ts +++ b/cypress/e2e/videoconference.cy.ts @@ -1,12 +1,12 @@ import { v4 as uuid } from 'uuid'; import { config } from '../../src/resources/scripts/config'; -import { USER_CONSULTANT, USER_VIDEO } from '../support/commands/login'; +import { USER_CONSULTANT, USER_VIDEO } from '../support/commands/mockApi'; import { closeWebSocketServer, mockWebSocket, startWebSocketServer } from '../support/websocket'; -import { AppointmentsDataInterface } from '../../src/globalState/interfaces/AppointmentsDataInterface'; +import { AppointmentsDataInterface } from '../../src/globalState/interfaces'; class FakeJitsiMeetExternalAPI { private _handler: { @@ -43,7 +43,6 @@ describe('videoconference', () => { }); beforeEach(() => { - cy.mockApi(); mockWebSocket(); const today = new Date(); @@ -164,7 +163,7 @@ describe('videoconference', () => { describe('Consultant', () => { beforeEach(() => { cy.fastLogin({ - username: USER_CONSULTANT + userId: USER_CONSULTANT }); }); @@ -270,7 +269,7 @@ describe('videoconference', () => { describe('Video Consultant', () => { beforeEach(() => { cy.fastLogin({ - username: USER_VIDEO + userId: USER_VIDEO }); }); diff --git a/cypress/fixtures/registration/agency.json b/cypress/fixtures/registration/agency.json new file mode 100644 index 000000000..83a44d3bc --- /dev/null +++ b/cypress/fixtures/registration/agency.json @@ -0,0 +1,11 @@ +{ + "id": 1, + "name": "name", + "postcode": "postcode", + "city": "city", + "description": "description", + "teamAgency": true, + "offline": false, + "consultingType": 1, + "topicIds": null +} diff --git a/cypress/fixtures/registration/consultingType.json b/cypress/fixtures/registration/consultingType.json new file mode 100644 index 000000000..7235f05f6 --- /dev/null +++ b/cypress/fixtures/registration/consultingType.json @@ -0,0 +1,70 @@ +{ + "id": 0, + "titles": { + "default": "Suchtberatung", + "short": "Sucht", + "long": "Suchtberatung", + "welcome": "Willkommen bei der Suchtberatung!", + "registrationDropdown": "Suchtberatung" + }, + "urls": {}, + "registration": { + "minPostcodeSize": 5, + "autoSelectAgency": false, + "autoSelectPostcode": false, + "notes": {}, + "mandatoryFields": { + "age": false, + "state": false + } + }, + "isSubsequentRegistrationAllowed": true, + "isAnonymousConversationAllowed": true, + "isSetEmailAllowed": true, + "slug": "suchtberatung", + "languageFormal": true, + "lockedAgencies": false, + "excludeNonMainConsultantsFromTeamSessions": false, + "whiteSpot": { + "whiteSpotAgencyAssigned": true, + "whiteSpotAgencyId": 100 + }, + "groupChat": { + "isGroupChat": false, + "groupChatRules": [] + }, + "consultantBoundedToConsultingType": false, + "welcomeMessage": { + "sendWelcomeMessage": false + }, + "sendFurtherStepsMessage": true, + "sendSaveSessionDataMessage": true, + "sessionDataInitializing": { + "addictiveDrugs": true, + "age": true, + "gender": true, + "relation": true, + "state": false + }, + "initializeFeedbackChat": false, + "roles": { + "consultant": { + "main": ["consultant"], + "peer": ["consultant"] + } + }, + "notifications": { + "teamSessions": { + "newMessage": { + "allTeamConsultants": false + } + } + }, + "showAskerProfile": true, + "welcomeScreen": { + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + } +} diff --git a/cypress/fixtures/registration/topic.json b/cypress/fixtures/registration/topic.json new file mode 100644 index 000000000..a0e9e66a6 --- /dev/null +++ b/cypress/fixtures/registration/topic.json @@ -0,0 +1,7 @@ +{ + "id": 0, + "name": "Topic 0", + "description": "Description 0", + "internalIdentifier": "Topic0", + "status": "ACTIVE" +} diff --git a/cypress/fixtures/service.settings.json b/cypress/fixtures/service.settings.json new file mode 100644 index 000000000..bf736d3a7 --- /dev/null +++ b/cypress/fixtures/service.settings.json @@ -0,0 +1,59 @@ +{ + "multitenancyWithSingleDomainEnabled": { + "value": true, + "readOnly": true + }, + "multitenancyEnabled": { + "value": false, + "readOnly": true + }, + "useTenantService": { + "value": false, + "readOnly": false + }, + "useConsultingTypesForAgencies": null, + "enableWalkthrough": { + "value": false, + "readOnly": false + }, + "disableVideoAppointments": { + "value": false, + "readOnly": false + }, + "mainTenantSubdomainForSingleDomainMultitenancy": { + "value": "app", + "readOnly": false + }, + "useOverviewPage": { + "value": false, + "readOnly": false + }, + "calcomUrl": { + "value": "calcomUrl", + "readOnly": false + }, + "budibaseAuthClientId": { + "value": "budibaseAuthClientId", + "readOnly": false + }, + "budibaseUrl": { + "value": "budibaseUrl", + "readOnly": false + }, + "calendarAppUrl": { + "value": "calendarAppUrl", + "readOnly": false + }, + "legalContentChangesBySingleTenantAdminsAllowed": { + "value": false, + "readOnly": null + }, + "documentationEnabled": { + "value": false, + "readOnly": false + }, + "releaseToggles": { + "enableNewNotifications": false, + "featureVideoGroupChatsEnabled": false + } +} diff --git a/cypress/fixtures/service.tenant.public.json b/cypress/fixtures/service.tenant.public.json new file mode 100644 index 000000000..63bcbea13 --- /dev/null +++ b/cypress/fixtures/service.tenant.public.json @@ -0,0 +1,32 @@ +{ + "id": 1, + "name": "Name 1", + "subdomain": "app", + "theming": { + "logo": "", + "primaryColor": "#00ff00", + "secondaryColor": "#0000ff" + }, + "content": { + "impressum": "", + "claim": "Claim", + "privacy": "", + "renderedPrivacy": "", + "termsAndConditionsConfirmation": "", + "dataPrivacyConfirmation": "", + "dataProtectionContactTemplate": { + "agencyContext": { + "responsibleContact": "", + "dataProtectionOfficer": { + "agencyResponsibleContact": "", + "alternativeRepresentativeContact": "", + "dataProtectionOfficerContact": "" + } + }, + "noAgencyContext": { + "responsibleContact": "", + "dataProtectionOfficerContact": "" + } + } + } +} diff --git a/cypress/fixtures/service.users.data.askers.json b/cypress/fixtures/service.users.data.askers.json deleted file mode 100644 index c7491251e..000000000 --- a/cypress/fixtures/service.users.data.askers.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "userId": "asker", - "userName": "asker1", - "firstName": null, - "lastName": null, - "email": null, - "absenceMessage": null, - "agencies": null, - "grantedAuthorities": ["AUTHORIZATION_USER_DEFAULT"], - "consultingTypes": { - "0": { "sessionData": null, "isRegistered": false, "agency": null }, - "1": { - "sessionData": { "age": null, "gender": null, "state": null }, - "isRegistered": true, - "agency": { - "id": 1, - "name": "agency name", - "postcode": "12345", - "city": "city", - "description": null, - "teamAgency": true, - "offline": false, - "consultingType": 1 - } - }, - "17": { "sessionData": null, "isRegistered": false, "agency": null } - }, - "hasAnonymousConversations": false, - "formalLanguage": true, - "absent": false, - "inTeamAgency": false -} diff --git a/cypress/fixtures/service.users.data.consultants.json b/cypress/fixtures/service.users.data.json similarity index 65% rename from cypress/fixtures/service.users.data.consultants.json rename to cypress/fixtures/service.users.data.json index 6e2fe7762..eec6202ed 100644 --- a/cypress/fixtures/service.users.data.consultants.json +++ b/cypress/fixtures/service.users.data.json @@ -69,5 +69,37 @@ "formalLanguage": true, "absent": false, "inTeamAgency": true + }, + { + "userId": "asker", + "userName": "asker1", + "firstName": null, + "lastName": null, + "email": null, + "absenceMessage": null, + "agencies": null, + "grantedAuthorities": ["AUTHORIZATION_USER_DEFAULT"], + "consultingTypes": { + "0": { "sessionData": null, "isRegistered": false, "agency": null }, + "1": { + "sessionData": { "age": null, "gender": null, "state": null }, + "isRegistered": true, + "agency": { + "id": 1, + "name": "agency name", + "postcode": "12345", + "city": "city", + "description": null, + "teamAgency": true, + "offline": false, + "consultingType": 1 + } + }, + "17": { "sessionData": null, "isRegistered": false, "agency": null } + }, + "hasAnonymousConversations": false, + "formalLanguage": true, + "absent": false, + "inTeamAgency": false } ] diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 1e200734b..716bc4d29 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -1,40 +1,6 @@ -import './commands/askerSessions'; -import './commands/consultantSessions'; -import './commands/login'; -import './commands/messages'; import './commands/mockApi'; import './commands/socket'; -import { LoginArgs } from './commands/login'; -import { AppointmentsDataInterface } from '../../src/globalState/interfaces/AppointmentsDataInterface'; - -declare global { - namespace Cypress { - interface Chainable { - login(args?: LoginArgs): Chainable; - fastLogin(args?: LoginArgs): Chainable; - appointments( - args?: Partial, - index?: number - ): Chainable; - askerSession( - args?: { [key: string]: any }, - index?: number - ): Chainable; - consultantSession( - args?: { [key: string]: any }, - index?: number - ): Chainable; - addMessage(props?: { [key: string]: any }, index?: number); - mockApi(): Chainable; - willReturn(name: string, data: any): Chainable; - emitDirectMessage(index?: number): Chainable; - emitVideoCallRequest(): Chainable; - waitForSubscriptions(events: string[]): Chainable; - } - } -} - let sessions = []; export const getSessions = () => sessions; diff --git a/cypress/support/commands/api/agencies.ts b/cypress/support/commands/api/agencies.ts new file mode 100644 index 000000000..02b82c817 --- /dev/null +++ b/cypress/support/commands/api/agencies.ts @@ -0,0 +1,37 @@ +import { endpoints } from '../../../../src/resources/scripts/endpoints'; + +const agenciesApi = (cy, getWillReturn, setWillReturn) => { + cy.intercept('GET', `${endpoints.agencyServiceBase}/*`, (req) => { + const agencies = getWillReturn('agencies'); + const aid = new URL(req.url).pathname.split('/')[3]; + req.reply( + agencies.filter((a) => a.id === parseInt(aid)) || { + statusCode: 404 + } + ); + }).as('service.agencies.id'); + + cy.intercept('GET', `${endpoints.agencyServiceBase}*`, (req) => { + const searchParams = new URL(req.url).searchParams; + let agencies = getWillReturn('agencies'); + console.log( + agencies, + searchParams.get('topicId'), + searchParams.get('consultingType') + ); + if (searchParams.has('topicId')) { + agencies = agencies.filter((a) => + a.topicIds?.includes(parseInt(searchParams.get('topicId'))) + ); + } else if (searchParams.has('consultingType')) { + agencies = agencies.filter( + (a) => + a.consultingType === + parseInt(searchParams.get('consultingType')) + ); + } + req.reply(agencies); + }).as('service.agencies'); +}; + +export default agenciesApi; diff --git a/cypress/support/commands/api/appointments.ts b/cypress/support/commands/api/appointments.ts index 8bb8f761d..0a48ade1c 100644 --- a/cypress/support/commands/api/appointments.ts +++ b/cypress/support/commands/api/appointments.ts @@ -3,7 +3,7 @@ import { getAppointments, setAppointments, updateAppointment -} from '../appointments'; +} from '../helper/appointments'; const appointmentsApi = (cy) => { cy.intercept('GET', `${endpoints.appointmentsServiceBase}/*`, (req) => { diff --git a/cypress/support/commands/api/consultTypes.ts b/cypress/support/commands/api/consultTypes.ts new file mode 100644 index 000000000..cf824668f --- /dev/null +++ b/cypress/support/commands/api/consultTypes.ts @@ -0,0 +1,54 @@ +import { endpoints } from '../../../../src/resources/scripts/endpoints'; + +const consultingTypesApi = (cy, getWillReturn, setWillReturn) => { + cy.intercept( + `${endpoints.consultingTypeServiceBase}/byslug/*/full`, + (req) => { + const slug = new URL(req.url).pathname.split('/')[4]; + + const consultingTypes = getWillReturn('consultingTypes'); + const consultingType = + consultingTypes.find( + (consultingType) => consultingType.slug === slug + ) || + getWillReturn(`consultingType.${slug}`) || + getWillReturn('consultingType'); + req.reply(consultingType || { statusCode: 404 }); + /* + req.reply({ + ...( + consultingTypes.find((consultingType) => consultingType.slug === slug) || {} + ), + ...(getWillReturn('consultingType')), + ...(getWillReturn(`consultingType.${slug}`)), + }); + */ + } + ).as('consultingTypeServiceBySlugFull'); + + cy.intercept(`${endpoints.consultingTypeServiceBase}/*/full`, (req) => { + const id = parseInt(new URL(req.url).pathname.split('/')[3]); + + const consultingTypes = getWillReturn('consultingTypes'); + const consultingType = + consultingTypes.find( + (consultingType) => consultingType.id === id + ) || + getWillReturn(`consultingType.${id}`) || + getWillReturn('consultingType'); + req.reply(consultingType || { statusCode: 404 }); + /* + req.reply({ + ...(consultingTypes.find((consultingType) => consultingType.id === id) || {}), + ...(getWillReturn('consultingType')), + ...(getWillReturn(`consultingType.${id}`)), + }); + */ + }).as('consultingTypeServiceBaseFull'); + + cy.intercept(`${endpoints.consultingTypeServiceBase}/basic`, (req) => { + req.reply(getWillReturn('consultingTypes')); + }).as('consultingTypeServiceBaseBasic'); +}; + +export default consultingTypesApi; diff --git a/cypress/support/commands/api/messages.ts b/cypress/support/commands/api/messages.ts new file mode 100644 index 000000000..0e5d6a909 --- /dev/null +++ b/cypress/support/commands/api/messages.ts @@ -0,0 +1,30 @@ +/* +/service/users/consultants/adsf-asdf-asdf + */ +import { endpoints } from '../../../../src/resources/scripts/endpoints'; +import { generateMessagesReply } from '../../sessions'; +import { getMessages } from '../helper/messages'; + +const messagesApi = (cy, getWillReturn, setWillReturn) => { + cy.intercept('GET', endpoints.draftMessages, {}).as('draftMessages'); + + cy.intercept('GET', `${endpoints.messages.get}*`, (req) => { + const messages = getWillReturn['messages']; + if (messages) { + return req.reply(messages); + } + + const url = new URL(req.url); + + req.reply( + generateMessagesReply( + getMessages().filter( + (message) => + message.rid === url.searchParams.get('rcGroupId') + ) + ) + ); + }).as('messages'); +}; + +export default messagesApi; diff --git a/cypress/support/commands/api/rc.ts b/cypress/support/commands/api/rc.ts new file mode 100644 index 000000000..07ad7de23 --- /dev/null +++ b/cypress/support/commands/api/rc.ts @@ -0,0 +1,109 @@ +/* +/service/users/consultants/adsf-asdf-asdf + */ +import { endpoints } from '../../../../src/resources/scripts/endpoints'; +import { + SETTING_E2E_ENABLE, + SETTING_FILEUPLOAD_MAXFILESIZE, + SETTING_MESSAGE_MAXALLOWEDSIZE +} from '../../../../src/api/apiRocketChatSettingsPublic'; +import { getAskerSessions, updateAskerSession } from '../helper/askerSessions'; +import { + getConsultantSessions, + updateConsultantSession +} from '../helper/consultantSessions'; +import { decodeUsername } from '../../../../src/utils/encryptionHelpers'; +import { deepMerge } from '../../helpers'; + +const rcApi = (cy, getWillReturn, setWillReturn) => { + cy.intercept('GET', endpoints.rc.e2ee.fetchMyKeys, (req) => { + // keys from dev user pregnancy + req.reply({ + public_key: + '{"alg":"RSA-OAEP-256","e":"AQAB","ext":true,"key_ops":["encrypt"],"kty":"RSA","n":"o1hPIUjtf_kN1vHPfjq-LxXOkqycRbJp9UT8WNjA9c_z3hswAje3NC3E0QJG1eIe_yOwAYhjPtvEZ5aUfYQhPx1dlBL-vnaN4L_TsimgWBIpTpG4rQTY0X8eAF5nVBCBPKne70X4MH32Ol1RLP6Y7d7k9BiDYaJj0XYF_3HZKOfcAUGb34tWJy6dg3kg7pOEjKoHLHHbMn11VHwenMHnhh9JYltkixTy1BO0rRlORkXo680TQIPxEm9y8rsZWEccATu0ZKSlDSr4dYE09sCG_xUH5AGNGECbpnC_Ze7zUk1RRGFAWF6nmLaAPO7hMlVmQ802eF7HTtDdOexqwaIY7Q"}', + private_key: + '{"0":2,"1":107,"2":187,"3":21,"4":27,"5":7,"6":21,"7":97,"8":208,"9":87,"10":240,"11":132,"12":168,"13":122,"14":207,"15":152,"16":128,"17":197,"18":38,"19":181,"20":168,"21":237,"22":223,"23":203,"24":39,"25":255,"26":193,"27":80,"28":34,"29":201,"30":111,"31":236,"32":182,"33":89,"34":214,"35":178,"36":119,"37":187,"38":222,"39":165,"40":194,"41":155,"42":137,"43":214,"44":69,"45":145,"46":32,"47":9,"48":159,"49":83,"50":192,"51":193,"52":191,"53":33,"54":83,"55":18,"56":81,"57":243,"58":70,"59":223,"60":101,"61":8,"62":184,"63":180,"64":187,"65":33,"66":72,"67":220,"68":99,"69":48,"70":255,"71":107,"72":12,"73":174,"74":41,"75":27,"76":77,"77":155,"78":55,"79":110,"80":227,"81":76,"82":43,"83":255,"84":194,"85":216,"86":73,"87":172,"88":4,"89":217,"90":24,"91":183,"92":61,"93":94,"94":235,"95":177,"96":52,"97":103,"98":171,"99":156,"100":177,"101":146,"102":218,"103":204,"104":198,"105":79,"106":170,"107":152,"108":124,"109":16,"110":11,"111":224,"112":237,"113":81,"114":141,"115":53,"116":247,"117":113,"118":98,"119":113,"120":56,"121":37,"122":221,"123":171,"124":200,"125":20,"126":253,"127":66,"128":249,"129":244,"130":194,"131":100,"132":101,"133":141,"134":225,"135":32,"136":172,"137":60,"138":97,"139":74,"140":30,"141":153,"142":237,"143":25,"144":190,"145":84,"146":175,"147":245,"148":83,"149":102,"150":126,"151":92,"152":41,"153":162,"154":148,"155":147,"156":151,"157":253,"158":166,"159":227,"160":209,"161":161,"162":54,"163":189,"164":204,"165":57,"166":98,"167":248,"168":2,"169":162,"170":77,"171":61,"172":161,"173":73,"174":190,"175":144,"176":10,"177":57,"178":73,"179":120,"180":113,"181":185,"182":13,"183":101,"184":201,"185":128,"186":222,"187":82,"188":205,"189":52,"190":129,"191":97,"192":144,"193":128,"194":238,"195":146,"196":84,"197":13,"198":86,"199":1,"200":73,"201":25,"202":67,"203":223,"204":40,"205":50,"206":92,"207":250,"208":190,"209":94,"210":17,"211":100,"212":75,"213":100,"214":0,"215":106,"216":107,"217":82,"218":168,"219":185,"220":101,"221":65,"222":167,"223":1,"224":94,"225":42,"226":147,"227":47,"228":104,"229":2,"230":68,"231":171,"232":129,"233":32,"234":149,"235":154,"236":216,"237":179,"238":65,"239":242,"240":72,"241":30,"242":90,"243":147,"244":186,"245":148,"246":96,"247":129,"248":189,"249":56,"250":179,"251":0,"252":0,"253":63,"254":147,"255":28,"256":136,"257":248,"258":79,"259":33,"260":235,"261":156,"262":13,"263":236,"264":77,"265":237,"266":216,"267":164,"268":191,"269":164,"270":218,"271":104,"272":178,"273":55,"274":10,"275":65,"276":118,"277":164,"278":183,"279":130,"280":39,"281":187,"282":21,"283":194,"284":144,"285":113,"286":208,"287":181,"288":27,"289":112,"290":163,"291":146,"292":173,"293":93,"294":218,"295":161,"296":246,"297":210,"298":36,"299":140,"300":201,"301":1,"302":175,"303":160,"304":17,"305":254,"306":17,"307":82,"308":107,"309":31,"310":104,"311":161,"312":33,"313":67,"314":81,"315":162,"316":118,"317":196,"318":32,"319":255,"320":63,"321":54,"322":69,"323":98,"324":4,"325":104,"326":123,"327":68,"328":96,"329":28,"330":197,"331":47,"332":139,"333":141,"334":217,"335":194,"336":156,"337":156,"338":23,"339":90,"340":44,"341":205,"342":131,"343":95,"344":227,"345":26,"346":139,"347":161,"348":200,"349":91,"350":201,"351":36,"352":145,"353":62,"354":163,"355":229,"356":211,"357":164,"358":65,"359":131,"360":170,"361":146,"362":109,"363":177,"364":43,"365":19,"366":185,"367":223,"368":137,"369":229,"370":82,"371":43,"372":100,"373":69,"374":69,"375":114,"376":252,"377":98,"378":218,"379":66,"380":36,"381":178,"382":252,"383":171,"384":229,"385":187,"386":209,"387":27,"388":32,"389":172,"390":29,"391":49,"392":26,"393":4,"394":212,"395":172,"396":80,"397":201,"398":202,"399":108,"400":4,"401":124,"402":190,"403":189,"404":218,"405":223,"406":22,"407":87,"408":4,"409":238,"410":243,"411":22,"412":178,"413":59,"414":168,"415":133,"416":13,"417":72,"418":216,"419":124,"420":202,"421":70,"422":153,"423":169,"424":17,"425":29,"426":72,"427":19,"428":73,"429":225,"430":175,"431":87,"432":178,"433":115,"434":105,"435":56,"436":158,"437":128,"438":23,"439":86,"440":239,"441":102,"442":211,"443":110,"444":197,"445":99,"446":193,"447":239,"448":117,"449":236,"450":211,"451":31,"452":222,"453":91,"454":140,"455":154,"456":24,"457":137,"458":216,"459":204,"460":203,"461":164,"462":60,"463":53,"464":118,"465":222,"466":173,"467":64,"468":187,"469":105,"470":10,"471":85,"472":161,"473":197,"474":244,"475":18,"476":251,"477":212,"478":187,"479":8,"480":217,"481":194,"482":24,"483":174,"484":224,"485":85,"486":218,"487":218,"488":9,"489":54,"490":204,"491":117,"492":150,"493":60,"494":172,"495":57,"496":153,"497":184,"498":215,"499":86,"500":53,"501":88,"502":70,"503":148,"504":25,"505":20,"506":98,"507":22,"508":234,"509":201,"510":118,"511":34,"512":55,"513":129,"514":97,"515":35,"516":82,"517":118,"518":143,"519":230,"520":140,"521":246,"522":86,"523":189,"524":148,"525":233,"526":10,"527":56,"528":224,"529":187,"530":37,"531":140,"532":97,"533":108,"534":6,"535":47,"536":55,"537":158,"538":230,"539":141,"540":83,"541":211,"542":221,"543":200,"544":217,"545":238,"546":222,"547":135,"548":153,"549":224,"550":219,"551":173,"552":82,"553":23,"554":92,"555":148,"556":107,"557":51,"558":1,"559":23,"560":1,"561":10,"562":12,"563":224,"564":140,"565":1,"566":117,"567":68,"568":168,"569":196,"570":153,"571":82,"572":225,"573":143,"574":188,"575":136,"576":56,"577":110,"578":122,"579":246,"580":160,"581":180,"582":118,"583":131,"584":38,"585":2,"586":188,"587":250,"588":207,"589":190,"590":48,"591":192,"592":193,"593":47,"594":236,"595":255,"596":254,"597":98,"598":60,"599":218,"600":232,"601":38,"602":6,"603":163,"604":203,"605":135,"606":95,"607":130,"608":130,"609":2,"610":189,"611":100,"612":173,"613":60,"614":73,"615":172,"616":3,"617":221,"618":23,"619":22,"620":133,"621":170,"622":240,"623":127,"624":161,"625":82,"626":124,"627":54,"628":77,"629":178,"630":225,"631":77,"632":147,"633":28,"634":181,"635":57,"636":227,"637":231,"638":247,"639":231,"640":170,"641":250,"642":218,"643":43,"644":243,"645":160,"646":103,"647":55,"648":75,"649":131,"650":251,"651":9,"652":48,"653":8,"654":65,"655":152,"656":69,"657":29,"658":251,"659":13,"660":95,"661":123,"662":42,"663":75,"664":227,"665":152,"666":196,"667":245,"668":236,"669":172,"670":80,"671":220,"672":80,"673":205,"674":32,"675":135,"676":60,"677":253,"678":194,"679":6,"680":6,"681":28,"682":239,"683":160,"684":227,"685":229,"686":16,"687":2,"688":42,"689":129,"690":130,"691":232,"692":145,"693":183,"694":4,"695":129,"696":64,"697":123,"698":2,"699":71,"700":199,"701":13,"702":174,"703":228,"704":135,"705":188,"706":250,"707":201,"708":137,"709":247,"710":220,"711":244,"712":199,"713":247,"714":176,"715":124,"716":53,"717":69,"718":58,"719":85,"720":172,"721":182,"722":228,"723":57,"724":196,"725":35,"726":177,"727":104,"728":199,"729":58,"730":193,"731":155,"732":88,"733":203,"734":228,"735":12,"736":14,"737":85,"738":115,"739":234,"740":35,"741":114,"742":181,"743":247,"744":119,"745":226,"746":5,"747":250,"748":195,"749":201,"750":211,"751":100,"752":89,"753":180,"754":26,"755":112,"756":234,"757":125,"758":208,"759":29,"760":106,"761":244,"762":127,"763":13,"764":38,"765":250,"766":231,"767":237,"768":86,"769":168,"770":126,"771":69,"772":28,"773":229,"774":228,"775":93,"776":153,"777":166,"778":177,"779":171,"780":108,"781":157,"782":62,"783":145,"784":199,"785":10,"786":146,"787":42,"788":177,"789":33,"790":116,"791":96,"792":200,"793":157,"794":121,"795":64,"796":154,"797":12,"798":63,"799":22,"800":93,"801":232,"802":181,"803":62,"804":186,"805":5,"806":66,"807":95,"808":6,"809":195,"810":122,"811":151,"812":116,"813":51,"814":11,"815":248,"816":37,"817":94,"818":16,"819":34,"820":174,"821":218,"822":162,"823":204,"824":167,"825":228,"826":232,"827":108,"828":154,"829":225,"830":61,"831":106,"832":134,"833":205,"834":209,"835":9,"836":85,"837":64,"838":186,"839":23,"840":154,"841":135,"842":150,"843":101,"844":218,"845":132,"846":135,"847":174,"848":102,"849":105,"850":135,"851":184,"852":254,"853":250,"854":185,"855":29,"856":204,"857":77,"858":227,"859":34,"860":38,"861":253,"862":50,"863":26,"864":217,"865":176,"866":172,"867":88,"868":47,"869":146,"870":43,"871":204,"872":92,"873":154,"874":71,"875":63,"876":192,"877":47,"878":156,"879":116,"880":158,"881":126,"882":130,"883":123,"884":133,"885":101,"886":79,"887":76,"888":224,"889":134,"890":202,"891":121,"892":94,"893":164,"894":210,"895":130,"896":21,"897":129,"898":69,"899":135,"900":74,"901":174,"902":180,"903":126,"904":10,"905":187,"906":231,"907":113,"908":64,"909":222,"910":16,"911":40,"912":23,"913":133,"914":219,"915":2,"916":170,"917":54,"918":155,"919":49,"920":165,"921":95,"922":148,"923":31,"924":151,"925":12,"926":141,"927":175,"928":57,"929":232,"930":186,"931":3,"932":48,"933":61,"934":38,"935":8,"936":238,"937":203,"938":230,"939":62,"940":155,"941":43,"942":150,"943":207,"944":195,"945":221,"946":94,"947":17,"948":0,"949":250,"950":176,"951":240,"952":50,"953":50,"954":176,"955":89,"956":183,"957":173,"958":253,"959":15,"960":82,"961":9,"962":162,"963":198,"964":30,"965":18,"966":178,"967":14,"968":65,"969":182,"970":235,"971":110,"972":250,"973":152,"974":145,"975":150,"976":237,"977":77,"978":144,"979":167,"980":116,"981":114,"982":180,"983":44,"984":38,"985":226,"986":191,"987":39,"988":175,"989":145,"990":198,"991":130,"992":185,"993":118,"994":95,"995":222,"996":37,"997":44,"998":138,"999":101,"1000":211,"1001":31,"1002":155,"1003":214,"1004":143,"1005":225,"1006":96,"1007":69,"1008":79,"1009":180,"1010":171,"1011":124,"1012":40,"1013":253,"1014":162,"1015":134,"1016":118,"1017":40,"1018":216,"1019":2,"1020":164,"1021":165,"1022":94,"1023":34,"1024":122,"1025":86,"1026":16,"1027":209,"1028":213,"1029":84,"1030":91,"1031":184,"1032":120,"1033":111,"1034":200,"1035":162,"1036":239,"1037":214,"1038":151,"1039":226,"1040":117,"1041":137,"1042":177,"1043":182,"1044":112,"1045":192,"1046":46,"1047":213,"1048":216,"1049":117,"1050":64,"1051":149,"1052":95,"1053":237,"1054":217,"1055":77,"1056":111,"1057":69,"1058":109,"1059":118,"1060":255,"1061":64,"1062":222,"1063":134,"1064":124,"1065":34,"1066":100,"1067":191,"1068":92,"1069":197,"1070":182,"1071":59,"1072":20,"1073":218,"1074":168,"1075":27,"1076":193,"1077":193,"1078":151,"1079":4,"1080":26,"1081":164,"1082":48,"1083":83,"1084":45,"1085":95,"1086":218,"1087":134,"1088":65,"1089":107,"1090":207,"1091":118,"1092":5,"1093":175,"1094":76,"1095":47,"1096":70,"1097":179,"1098":219,"1099":230,"1100":130,"1101":30,"1102":225,"1103":3,"1104":142,"1105":120,"1106":141,"1107":89,"1108":37,"1109":228,"1110":95,"1111":167,"1112":153,"1113":47,"1114":169,"1115":36,"1116":235,"1117":41,"1118":213,"1119":163,"1120":19,"1121":14,"1122":67,"1123":19,"1124":190,"1125":14,"1126":89,"1127":126,"1128":22,"1129":60,"1130":185,"1131":64,"1132":211,"1133":138,"1134":149,"1135":242,"1136":229,"1137":76,"1138":36,"1139":29,"1140":163,"1141":209,"1142":100,"1143":189,"1144":159,"1145":43,"1146":157,"1147":167,"1148":203,"1149":200,"1150":201,"1151":71,"1152":37,"1153":249,"1154":73,"1155":10,"1156":201,"1157":87,"1158":72,"1159":0,"1160":145,"1161":139,"1162":92,"1163":246,"1164":224,"1165":125,"1166":125,"1167":186,"1168":71,"1169":236,"1170":246,"1171":68,"1172":172,"1173":61,"1174":159,"1175":106,"1176":105,"1177":108,"1178":186,"1179":53,"1180":220,"1181":73,"1182":76,"1183":9,"1184":149,"1185":244,"1186":247,"1187":15,"1188":43,"1189":27,"1190":238,"1191":190,"1192":203,"1193":199,"1194":203,"1195":204,"1196":94,"1197":212,"1198":114,"1199":243,"1200":179,"1201":71,"1202":205,"1203":125,"1204":194,"1205":207,"1206":161,"1207":199,"1208":157,"1209":109,"1210":197,"1211":33,"1212":164,"1213":21,"1214":69,"1215":68,"1216":188,"1217":252,"1218":6,"1219":107,"1220":90,"1221":89,"1222":219,"1223":21,"1224":159,"1225":40,"1226":131,"1227":198,"1228":252,"1229":199,"1230":147,"1231":36,"1232":116,"1233":20,"1234":111,"1235":19,"1236":156,"1237":82,"1238":145,"1239":189,"1240":24,"1241":186,"1242":208,"1243":3,"1244":159,"1245":8,"1246":67,"1247":72,"1248":82,"1249":93,"1250":225,"1251":55,"1252":137,"1253":119,"1254":85,"1255":238,"1256":3,"1257":188,"1258":255,"1259":102,"1260":50,"1261":163,"1262":148,"1263":109,"1264":203,"1265":188,"1266":109,"1267":99,"1268":49,"1269":247,"1270":53,"1271":217,"1272":236,"1273":90,"1274":74,"1275":80,"1276":3,"1277":175,"1278":126,"1279":33,"1280":97,"1281":254,"1282":193,"1283":54,"1284":185,"1285":68,"1286":68,"1287":165,"1288":214,"1289":56,"1290":119,"1291":174,"1292":1,"1293":137,"1294":124,"1295":231,"1296":122,"1297":118,"1298":77,"1299":170,"1300":125,"1301":210,"1302":53,"1303":104,"1304":99,"1305":157,"1306":45,"1307":7,"1308":30,"1309":80,"1310":194,"1311":230,"1312":26,"1313":255,"1314":123,"1315":143,"1316":107,"1317":139,"1318":126,"1319":119,"1320":52,"1321":178,"1322":124,"1323":29,"1324":200,"1325":65,"1326":87,"1327":183,"1328":35,"1329":133,"1330":10,"1331":233,"1332":58,"1333":129,"1334":252,"1335":203,"1336":191,"1337":252,"1338":3,"1339":34,"1340":132,"1341":45,"1342":221,"1343":195,"1344":232,"1345":186,"1346":183,"1347":61,"1348":17,"1349":47,"1350":26,"1351":80,"1352":62,"1353":199,"1354":247,"1355":154,"1356":244,"1357":248,"1358":167,"1359":128,"1360":190,"1361":231,"1362":168,"1363":219,"1364":165,"1365":6,"1366":136,"1367":178,"1368":83,"1369":156,"1370":209,"1371":98,"1372":200,"1373":113,"1374":235,"1375":234,"1376":61,"1377":213,"1378":53,"1379":117,"1380":108,"1381":73,"1382":193,"1383":158,"1384":37,"1385":136,"1386":106,"1387":251,"1388":187,"1389":44,"1390":105,"1391":185,"1392":232,"1393":96,"1394":209,"1395":58,"1396":18,"1397":149,"1398":25,"1399":37,"1400":42,"1401":118,"1402":243,"1403":7,"1404":58,"1405":214,"1406":177,"1407":62,"1408":248,"1409":201,"1410":5,"1411":11,"1412":61,"1413":104,"1414":176,"1415":71,"1416":169,"1417":233,"1418":147,"1419":98,"1420":144,"1421":65,"1422":12,"1423":7,"1424":88,"1425":159,"1426":177,"1427":176,"1428":123,"1429":36,"1430":45,"1431":127,"1432":140,"1433":108,"1434":167,"1435":190,"1436":212,"1437":68,"1438":99,"1439":221,"1440":75,"1441":42,"1442":103,"1443":246,"1444":6,"1445":220,"1446":148,"1447":137,"1448":12,"1449":212,"1450":35,"1451":38,"1452":140,"1453":186,"1454":2,"1455":83,"1456":38,"1457":236,"1458":75,"1459":241,"1460":183,"1461":183,"1462":17,"1463":67,"1464":39,"1465":5,"1466":58,"1467":109,"1468":160,"1469":12,"1470":89,"1471":196,"1472":73,"1473":76,"1474":69,"1475":30,"1476":211,"1477":243,"1478":79,"1479":248,"1480":189,"1481":232,"1482":206,"1483":39,"1484":116,"1485":223,"1486":65,"1487":66,"1488":17,"1489":16,"1490":95,"1491":228,"1492":125,"1493":235,"1494":197,"1495":179,"1496":200,"1497":98,"1498":7,"1499":96,"1500":253,"1501":100,"1502":10,"1503":188,"1504":62,"1505":102,"1506":91,"1507":124,"1508":188,"1509":148,"1510":172,"1511":156,"1512":50,"1513":144,"1514":57,"1515":89,"1516":57,"1517":131,"1518":220,"1519":57,"1520":236,"1521":203,"1522":71,"1523":130,"1524":101,"1525":244,"1526":129,"1527":155,"1528":19,"1529":12,"1530":45,"1531":194,"1532":160,"1533":37,"1534":89,"1535":198,"1536":215,"1537":175,"1538":46,"1539":100,"1540":13,"1541":73,"1542":212,"1543":57,"1544":19,"1545":33,"1546":143,"1547":251,"1548":148,"1549":155,"1550":165,"1551":194,"1552":160,"1553":129,"1554":213,"1555":21,"1556":55,"1557":49,"1558":65,"1559":126,"1560":145,"1561":108,"1562":37,"1563":194,"1564":98,"1565":115,"1566":4,"1567":43,"1568":124,"1569":131,"1570":163,"1571":58,"1572":235,"1573":198,"1574":155,"1575":102,"1576":50,"1577":211,"1578":186,"1579":199,"1580":220,"1581":34,"1582":108,"1583":54,"1584":204,"1585":101,"1586":166,"1587":76,"1588":178,"1589":248,"1590":177,"1591":60,"1592":89,"1593":251,"1594":170,"1595":2,"1596":77,"1597":43,"1598":128,"1599":171,"1600":133,"1601":57,"1602":197,"1603":203,"1604":131,"1605":181,"1606":227,"1607":98,"1608":229,"1609":234,"1610":184,"1611":4,"1612":142,"1613":65,"1614":191,"1615":41,"1616":93,"1617":32,"1618":242,"1619":93,"1620":229,"1621":94,"1622":9,"1623":122,"1624":38,"1625":122,"1626":40,"1627":165,"1628":177,"1629":4,"1630":50,"1631":56,"1632":205,"1633":212,"1634":159,"1635":88,"1636":192,"1637":97,"1638":15,"1639":82,"1640":132,"1641":105,"1642":54,"1643":71,"1644":167,"1645":75,"1646":46,"1647":169,"1648":56,"1649":21,"1650":57,"1651":74,"1652":14,"1653":97,"1654":214,"1655":223,"1656":205,"1657":21,"1658":141,"1659":33,"1660":32,"1661":55,"1662":5,"1663":97,"1664":178,"1665":96,"1666":248,"1667":203,"1668":255,"1669":199,"1670":14,"1671":124,"1672":75,"1673":193,"1674":96,"1675":243,"1676":205,"1677":8,"1678":80,"1679":20,"1680":246,"1681":57,"1682":25,"1683":163,"1684":244,"1685":137,"1686":21,"1687":175,"1688":199,"1689":2,"1690":96,"1691":246,"1692":253,"1693":212,"1694":14,"1695":179}', + success: true + }); + }).as('fetchMyKeys'); + + cy.intercept( + 'POST', + endpoints.rc.e2ee.setUserPublicAndPrivateKeys, + (req) => { + req.reply({ + success: true + }); + } + ).as('setUserPublicAndPrivateKeys'); + + cy.intercept('POST', endpoints.rc.users.resetE2EKey, (req) => { + req.reply({ + success: true + }); + }).as('resetE2EKey'); + + cy.intercept('POST', endpoints.rc.logout, JSON.stringify({})).as( + 'apiLogout' + ); + + cy.intercept( + 'GET', + `${endpoints.rc.settings.public}*`, + JSON.stringify({ + settings: [ + { _id: SETTING_E2E_ENABLE, value: true, enterprise: false }, + { + _id: SETTING_MESSAGE_MAXALLOWEDSIZE, + value: 999999, + enterprise: false + }, + { + _id: SETTING_FILEUPLOAD_MAXFILESIZE, + value: 99999999, + enterprise: false + } + ], + count: 1, + offset: 0, + total: 1, + success: true + }) + ).as('rcSettingsPublic'); + + cy.intercept( + 'GET', + `${endpoints.rc.users.getStatus}*`, + JSON.stringify({ + _id: 'HxWJQQtvcYfrdW5FD', + connectionStatus: 'online', + status: 'busy', + success: true + }) + ); + + cy.intercept('POST', endpoints.rc.subscriptions.read, (req) => { + getAskerSessions().forEach((session, index) => { + if (session.session.groupId === req.body.rid) { + updateAskerSession({ session: { messagesRead: true } }, index); + } + }); + + getConsultantSessions().forEach((session, index) => { + if (session.session.groupId === req.body.rid) { + updateConsultantSession( + { session: { messagesRead: true } }, + index + ); + } + }); + + req.reply('{}'); + }).as('sessionRead'); + + cy.intercept('POST', endpoints.rc.accessToken, (req) => { + req.reply(getWillReturn('rcLogin')); + }); +}; + +export default rcApi; diff --git a/cypress/support/commands/api/topic.ts b/cypress/support/commands/api/topic.ts new file mode 100644 index 000000000..3dd6653d0 --- /dev/null +++ b/cypress/support/commands/api/topic.ts @@ -0,0 +1,9 @@ +import { endpoints } from '../../../../src/resources/scripts/endpoints'; + +const topicsApi = (cy, getWillReturn, setWillReturn) => { + cy.intercept('GET', endpoints.topicsData, (req) => { + req.reply(getWillReturn('topics') || { statusCode: 404 }); + }).as('topics'); +}; + +export default topicsApi; diff --git a/cypress/support/commands/api/uploads.ts b/cypress/support/commands/api/uploads.ts new file mode 100644 index 000000000..b8796c269 --- /dev/null +++ b/cypress/support/commands/api/uploads.ts @@ -0,0 +1,12 @@ +/* +/service/users/consultants/adsf-asdf-asdf + */ +import { endpoints } from '../../../../src/resources/scripts/endpoints'; + +const uploadsApi = (cy, getWillReturn, setWillReturn) => { + cy.intercept('POST', `${endpoints.attachmentUpload}*`, (req) => + req.reply(getWillReturn('attachmentUpload')) + ).as('attachmentUpload'); +}; + +export default uploadsApi; diff --git a/cypress/support/commands/api/users/chat.ts b/cypress/support/commands/api/users/chat.ts new file mode 100644 index 000000000..2c8283ebb --- /dev/null +++ b/cypress/support/commands/api/users/chat.ts @@ -0,0 +1,12 @@ +/* +/service/users/consultants/adsf-asdf-asdf + */ +import { endpoints } from '../../../../../src/resources/scripts/endpoints'; + +const usersChatApi = (cy, getWillReturn, setWillReturn) => { + cy.intercept('PUT', endpoints.userUpdateE2EKey, { + statusCode: 200 + }); +}; + +export default usersChatApi; diff --git a/cypress/support/commands/api/users/consultants.ts b/cypress/support/commands/api/users/consultants.ts new file mode 100644 index 000000000..57dc8d88d --- /dev/null +++ b/cypress/support/commands/api/users/consultants.ts @@ -0,0 +1,32 @@ +/* +/service/users/consultants/adsf-asdf-asdf + */ +import { endpoints } from '../../../../../src/resources/scripts/endpoints'; + +const usersConsultantsApi = (cy, getWillReturn, setWillReturn) => { + cy.intercept('GET', endpoints.consultantsLanguages, (req) => { + req.reply(getWillReturn('agencyConsultantsLanguages')); + }).as('agencyConsultants'); + + cy.intercept('PUT', endpoints.setAbsence, (req) => { + setWillReturn('userData', { + ...getWillReturn('userData'), + absenceMessage: req.body.message, + absent: req.body.absent + }); + req.reply({}); + }).as('putSetAbsence'); + + cy.intercept('GET', `${endpoints.agencyConsultants}/*`, (req) => { + const cid = new URL(req.url).pathname.split('/')[4]; + const consultants = getWillReturn('agencyConsultants'); + const consultant = consultants.find((c) => c.consultantId === cid); + req.reply(consultant || { statusCode: 404 }); + }).as('agencyConsultants.id'); + + cy.intercept('GET', `${endpoints.agencyConsultants}*`, (req) => { + req.reply(getWillReturn('agencyConsultants')); + }).as('agencyConsultants'); +}; + +export default usersConsultantsApi; diff --git a/cypress/support/commands/api/users/data.ts b/cypress/support/commands/api/users/data.ts new file mode 100644 index 000000000..7f39ca8d8 --- /dev/null +++ b/cypress/support/commands/api/users/data.ts @@ -0,0 +1,22 @@ +import { endpoints } from '../../../../../src/resources/scripts/endpoints'; + +const usersDataApi = ( + cy: Cypress.cy & CyEventEmitter, + getWillReturn, + setWillReturn +) => { + cy.intercept('GET', endpoints.userData, (req) => { + req.reply(getWillReturn('userData')); + }).as('usersData'); + + cy.intercept('PATCH', endpoints.userData, (req) => { + console.log(getWillReturn('userData'), req.body); + setWillReturn('userData', { + ...getWillReturn('userData'), + ...req.body + }); + req.reply({}); + }).as('patchUsersData'); +}; + +export default usersDataApi; diff --git a/cypress/support/commands/api/users/sessions.ts b/cypress/support/commands/api/users/sessions.ts new file mode 100644 index 000000000..15f44e79b --- /dev/null +++ b/cypress/support/commands/api/users/sessions.ts @@ -0,0 +1,62 @@ +import { endpoints } from '../../../../../src/resources/scripts/endpoints'; +import { sessionsReply } from '../../../sessions'; + +const usersSessionsApi = (cy, getWillReturn, setWillReturn) => { + cy.intercept('GET', `${endpoints.sessionRooms}*`, (req) => { + const rcGroupId = new URL(req.url).searchParams.get('rcGroupIds'); + const askerSessions = getWillReturn('askerSessions'); + let foundSession = null; + askerSessions.forEach((session, index) => { + if (session.session.groupId === rcGroupId) { + foundSession = session.session; + } + }); + + const consultantSessions = getWillReturn('consultantSessions'); + consultantSessions.forEach((session, index) => { + if (session.session.groupId === rcGroupId) { + foundSession = session.session; + } + }); + + const data = getWillReturn('sessionRooms'); + data.body.sessions[0].session = { + ...foundSession + }; + + req.reply(data); + }).as('sessionRooms'); + + cy.intercept('GET', endpoints.askerSessions, (req) => { + const sessionsRes = getWillReturn('askerSessions'); + if (sessionsRes?.statusCode) { + return req.reply(sessionsRes); + } + + req.reply({ + sessions: sessionsRes + }); + }).as('askerSessions'); + + cy.intercept('GET', `${endpoints.consultantSessions}*`, (req) => { + const sessionsRes = getWillReturn('consultantSessions'); + + if (sessionsRes?.statusCode) { + return req.reply(sessionsRes); + } + + const url = new URL(req.url); + const offset = parseInt(url.searchParams.get('offset')) || 0; + const count = parseInt(url.searchParams.get('count')) || 15; + + req.reply( + sessionsReply({ + sessions: sessionsRes, + offset, + count + }) + ); + }).as('consultantSessions'); +}; + +export default usersSessionsApi; diff --git a/cypress/support/commands/api/videocalls.ts b/cypress/support/commands/api/videocalls.ts index 15ce78ceb..b4d3b6b57 100644 --- a/cypress/support/commands/api/videocalls.ts +++ b/cypress/support/commands/api/videocalls.ts @@ -7,6 +7,12 @@ const videocallsApi = (cy) => { jwt: 'any_token' }); }).as('videocalls_jwt_get'); + + cy.intercept('POST', endpoints.startVideoCall, { + fixture: 'service.videocalls.new' + }).as('startVideoCall'); + + cy.intercept('POST', endpoints.rejectVideoCall, {}).as('rejectVideoCall'); }; export default videocallsApi; diff --git a/cypress/support/commands/appointments.ts b/cypress/support/commands/helper/appointments.ts similarity index 85% rename from cypress/support/commands/appointments.ts rename to cypress/support/commands/helper/appointments.ts index 7c35d727f..04b8f0c4d 100644 --- a/cypress/support/commands/appointments.ts +++ b/cypress/support/commands/helper/appointments.ts @@ -1,6 +1,6 @@ import { v4 as uuid } from 'uuid'; -import { deepMerge } from '../helpers'; -import { AppointmentsDataInterface } from '../../../src/globalState/interfaces/AppointmentsDataInterface'; +import { deepMerge } from '../../helpers'; +import { AppointmentsDataInterface } from '../../../../src/globalState/interfaces'; export let appointments: AppointmentsDataInterface[] = []; @@ -31,7 +31,7 @@ export const updateAppointment = ( Cypress.Commands.add( 'appointments', (props?: { [key: string]: any }, index?: number) => - new Promise((resolve) => { + new Cypress.Promise((resolve) => { let appointment = undefined; if (!props) { setAppointments([]); diff --git a/cypress/support/commands/askerSessions.ts b/cypress/support/commands/helper/askerSessions.ts similarity index 52% rename from cypress/support/commands/askerSessions.ts rename to cypress/support/commands/helper/askerSessions.ts index 42c9c2d5c..81ff65425 100644 --- a/cypress/support/commands/askerSessions.ts +++ b/cypress/support/commands/helper/askerSessions.ts @@ -1,5 +1,5 @@ -import { deepMerge } from '../helpers'; -import { generateAskerSession } from '../sessions'; +import { deepMerge } from '../../helpers'; +import { generateAskerSession } from '../../sessions'; export let askerSessions: UserService.Schemas.UserSessionResponseDTO[] = []; @@ -17,11 +17,15 @@ export const updateAskerSession = ( } }; -Cypress.Commands.add( - 'askerSession', - (props: { [key: string]: any } = {}, index?: number) => - new Promise((resolve) => { - updateAskerSession(props, index); - resolve(undefined); - }) -); +const askersSessionsCommand = (getWillReturn, setWillReturn) => + Cypress.Commands.add( + 'askerSession', + (props: { [key: string]: any } = {}, index?: number) => + new Cypress.Promise((resolve) => { + updateAskerSession(props, index); + setWillReturn('askerSessions', askerSessions); + resolve(undefined); + }) + ); + +export default askersSessionsCommand; diff --git a/cypress/support/commands/consultantSessions.ts b/cypress/support/commands/helper/consultantSessions.ts similarity index 54% rename from cypress/support/commands/consultantSessions.ts rename to cypress/support/commands/helper/consultantSessions.ts index c0f0b75ff..3ee30eb72 100644 --- a/cypress/support/commands/consultantSessions.ts +++ b/cypress/support/commands/helper/consultantSessions.ts @@ -1,5 +1,5 @@ -import { deepMerge } from '../helpers'; -import { generateConsultantSession } from '../sessions'; +import { deepMerge } from '../../helpers'; +import { generateConsultantSession } from '../../sessions'; let consultantSessions: UserService.Schemas.ConsultantSessionResponseDTO[] = []; @@ -23,11 +23,14 @@ export const updateConsultantSession = ( } }; -Cypress.Commands.add( - 'consultantSession', - (props: { [key: string]: any } = {}, index?: number) => - new Promise((resolve) => { - updateConsultantSession(props, index); - resolve(undefined); - }) -); +const consultantSessionsCommand = (getWillReturn, setWillReturn) => + Cypress.Commands.add( + 'consultantSession', + (props: { [key: string]: any } = {}, index?: number) => + new Cypress.Promise((resolve) => { + updateConsultantSession(props, index); + setWillReturn('consultantSessions', consultantSessions); + resolve(undefined); + }) + ); +export default consultantSessionsCommand; diff --git a/cypress/support/commands/helper/fastLogin.ts b/cypress/support/commands/helper/fastLogin.ts new file mode 100644 index 000000000..6dc722bf4 --- /dev/null +++ b/cypress/support/commands/helper/fastLogin.ts @@ -0,0 +1,58 @@ +import { LoginArgs, USER_ASKER } from '../mockApi'; + +const fastLoginCommand = (getWillReturn, setWillReturn) => + Cypress.Commands.add( + 'fastLogin', + ( + args: LoginArgs = { + userId: USER_ASKER + } + ) => { + const userId = args.userId || USER_ASKER; + + cy.fixture('service.users.data').then((usersData) => { + const userData = usersData.find((u) => u.userId === userId); + setWillReturn('userData', userData, true); + cy.setCookie('cy_username', userData.userName); + cy.setCookie('cy_userId', userData.userId); + }); + + cy.window().then((window) => { + cy.fixture('api.v1.login').then((res) => { + if (res.data.authToken) { + cy.setCookie('rc_token', res.data.authToken); + } + if (res.data.userId) { + cy.setCookie('rc_uid', res.data.userId); + // masterkey dev user pregnancy + window.localStorage.setItem( + `mk_${res.data.userId}`, + '[225,59,174,132,235,143,199,190,136,68,11,58,123,91,159,241,78,226,65,110,22,100,84,127,59,84,180,138,210,94,176,144]' + ); + } + }); + + const tomorrow = new Date(); + tomorrow.setDate(tomorrow.getDate() + 1); + + window.localStorage.setItem( + 'auth.access_token_valid_until', + tomorrow.getTime().toString() + ); + window.localStorage.setItem( + 'auth.refresh_token_valid_until', + tomorrow.getTime().toString() + ); + + cy.visit('/app'); + cy.wait('@usersData'); + if (userId === USER_ASKER) { + cy.wait('@askerSessions'); + } else { + cy.wait('@consultantEnquiriesBase'); + } + }); + } + ); + +export default fastLoginCommand; diff --git a/cypress/support/commands/helper/login.ts b/cypress/support/commands/helper/login.ts new file mode 100644 index 000000000..919f7e059 --- /dev/null +++ b/cypress/support/commands/helper/login.ts @@ -0,0 +1,43 @@ +import { deepMerge } from '../../helpers'; +import { LoginArgs, USER_ASKER } from '../mockApi'; + +const loginCommand = (getWillReturn, setWillReturn) => + Cypress.Commands.add( + 'login', + ( + args: LoginArgs = { + userId: USER_ASKER + } + ) => { + const userId = args.userId || USER_ASKER; + + cy.fixture('service.users.data').then((usersData) => { + const userData = usersData.find((u) => u.userId === userId); + setWillReturn('userData', userData, true); + cy.setCookie('cy_username', userData.userName); + cy.setCookie('cy_userId', userData.userId); + + cy.fixture('api.v1.login').then((rcUserData) => { + setWillReturn( + 'rcLogin', + deepMerge(rcUserData, { + data: { + userId: userData.userId, + userName: userData.userName + } + }) + ); + }); + + cy.visit('/login'); + cy.get('.loginForm'); + cy.get('#username').type(userData.userName, { force: true }); + cy.get('#passwordInput').type('password', { force: true }); + cy.get('.button__primary').click(); + cy.wait('@authToken'); + cy.get('#appRoot').should('be.visible'); + }); + } + ); + +export default loginCommand; diff --git a/cypress/support/commands/messages.ts b/cypress/support/commands/helper/messages.ts similarity index 60% rename from cypress/support/commands/messages.ts rename to cypress/support/commands/helper/messages.ts index de4a48065..c72c65dad 100644 --- a/cypress/support/commands/messages.ts +++ b/cypress/support/commands/helper/messages.ts @@ -1,5 +1,5 @@ -import { generateMessage } from '../sessions'; -import { getAskerSessions } from './askerSessions'; +import { generateMessage } from '../../sessions'; +import { askerSessions, getAskerSessions } from './askerSessions'; import { getConsultantSessions } from './consultantSessions'; export let messages = []; @@ -32,11 +32,14 @@ export const addMessage = ( } }; -Cypress.Commands.add( - 'addMessage', - (props: { [key: string]: any } = {}, index?: number) => - new Promise((resolve) => { - addMessage(props, index); - resolve(undefined); - }) -); +const messageCommand = (getWillReturn, setWillReturn) => + Cypress.Commands.add( + 'addMessage', + (props: { [key: string]: any } = {}, index?: number) => + new Cypress.Promise((resolve) => { + addMessage(props, index); + setWillReturn('messages', messages); + resolve(undefined); + }) + ); +export default messageCommand; diff --git a/cypress/support/commands/login.ts b/cypress/support/commands/login.ts deleted file mode 100644 index 375cbe913..000000000 --- a/cypress/support/commands/login.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { UserDataInterface } from '../../../src/globalState'; -import { CyHttpMessages, RouteHandler } from 'cypress/types/net-stubbing'; - -export const USER_ASKER = 'asker'; -export const USER_CONSULTANT = 'consultant'; -export const USER_VIDEO = 'video'; - -export interface LoginArgs { - username?: typeof USER_ASKER | typeof USER_CONSULTANT | typeof USER_VIDEO; - auth?: { - expires_in?: number; - refresh_expires_in?: number; - }; - // TODO: why is this type not available in userservice's openapi spec? - userData?: Partial; - attachmentUpload?: Partial; - sessions?: - | UserService.Schemas.UserSessionResponseDTO[] - | UserService.Schemas.ConsultantSessionResponseDTO[]; - messages?: MessageService.Schemas.MessagesDTO[]; - userSessionsTimeout?: number; - sessionsCallback?: RouteHandler; -} - -Cypress.Commands.add( - 'login', - ( - args: LoginArgs = { - username: USER_ASKER - } - ) => { - cy.visit('/login'); - - cy.get('.loginForm'); - cy.get('#username').type(args.username || USER_ASKER, { force: true }); - cy.get('#passwordInput').type('password', { force: true }); - cy.get('.button__primary').click(); - cy.wait('@authToken'); - cy.get('#appRoot').should('be.visible'); - } -); diff --git a/cypress/support/commands/mockApi.ts b/cypress/support/commands/mockApi.ts index 804644eef..4956be8af 100644 --- a/cypress/support/commands/mockApi.ts +++ b/cypress/support/commands/mockApi.ts @@ -1,6 +1,8 @@ +import merge from 'lodash.merge'; import { generateAskerSession, generateConsultantSession, + generateMessage, generateMessagesReply, sessionsReply } from '../sessions'; @@ -9,23 +11,38 @@ import { getAskerSessions, setAskerSessions, updateAskerSession -} from './askerSessions'; +} from './helper/askerSessions'; import { getConsultantSessions, setConsultantSessions, updateConsultantSession -} from './consultantSessions'; -import { LoginArgs, USER_ASKER } from './login'; +} from './helper/consultantSessions'; import { deepMerge } from '../helpers'; import { decodeUsername } from '../../../src/utils/encryptionHelpers'; -import { getMessages, setMessages } from './messages'; -import apiAppointments from './api/appointments'; -import apiVideocalls from './api/videocalls'; +import { getMessages, setMessages } from './helper/messages'; import { SETTING_E2E_ENABLE, SETTING_FILEUPLOAD_MAXFILESIZE, SETTING_MESSAGE_MAXALLOWEDSIZE } from '../../../src/api/apiRocketChatSettingsPublic'; +import { config } from '../../../src/resources/scripts/config'; +import usersChatApi from './api/users/chat'; +import usersConsultantsApi from './api/users/consultants'; +import usersDataApi from './api/users/data'; +import usersSessionsApi from './api/users/sessions'; +import apiAgencies from './api/agencies'; +import apiAppointments from './api/appointments'; +import apiConsultingTypes from './api/consultTypes'; +import apiMessages from './api/messages'; +import apiRc from './api/rc'; +import apiUploads from './api/uploads'; +import apiVideocalls from './api/videocalls'; +import loginCommand from './helper/login'; +import fastLoginCommand from './helper/fastLogin'; +import askerSessionsCommand from './helper/askerSessions'; +import consultantSessionsCommand from './helper/consultantSessions'; +import messagesCommand from './helper/messages'; +import apiTopics from './api/topic'; let overrides = {}; @@ -49,8 +66,10 @@ const defaultReturns = { } ] }, + 'agencies': [], 'consultingTypes': [], 'settings': {}, + 'service.tenant.public': {}, 'releases': { statusCode: 404 }, @@ -63,24 +82,53 @@ const defaultReturns = { sessions: [] } }, - 'frontend.settings': {}, + 'frontend.settings': config, 'agencyConsultants': [], - 'agencyConsultantsLanguages': ['de'] + 'agencyConsultantsLanguages': ['de'], + 'messages': [] }; -Cypress.Commands.add('willReturn', (name: string, data: any) => { +const setWillReturn = (name: string, data: any, mergeData: boolean = false) => { + if (mergeData) { + overrides[name] = merge( + Array.isArray(overrides[name] || defaultReturns[name]) ? [] : {}, + overrides[name] || defaultReturns[name] || {}, + data || {} + ); + return; + } + overrides[name] = data; -}); +}; + +Cypress.Commands.add( + 'willReturn', + (name: string, data?: any, mergeData: boolean = false) => + data === undefined + ? getWillReturn(name) + : setWillReturn(name, data, mergeData) +); -let username = null; +const getWillReturn = (name: string) => { + return overrides[name] || defaultReturns[name] || null; +}; + +loginCommand(getWillReturn, setWillReturn); +fastLoginCommand(getWillReturn, setWillReturn); +consultantSessionsCommand(getWillReturn, setWillReturn); +askerSessionsCommand(getWillReturn, setWillReturn); +messagesCommand(getWillReturn, setWillReturn); Cypress.Commands.add('mockApi', () => { // Empty overrides overrides = {}; + defaultReturns['messages'] = []; + // Generate 1 default sessions setAskerSessions([]); cy.askerSession(generateAskerSession()); + // Generate 3 default sessions setConsultantSessions([]); cy.consultantSession(generateConsultantSession()); cy.consultantSession(generateConsultantSession()); @@ -94,119 +142,48 @@ Cypress.Commands.add('mockApi', () => { // ConsultingTypes cy.fixture('service.consultingtypes.emigration.json').then( (consultingType) => { - defaultReturns['consultingTypes'].push(consultingType); + overrides['consultingTypes'] = [ + ...(overrides['consultingTypes'] || []), + consultingType + ]; } ); cy.fixture('service.consultingtypes.addiction.json').then( (consultingType) => { - defaultReturns['consultingTypes'].push(consultingType); + overrides['consultingTypes'] = [ + ...(overrides['consultingTypes'] || []), + consultingType + ]; } ); cy.fixture('service.consultingtypes.pregnancy.json').then( (consultingType) => { - defaultReturns['consultingTypes'].push(consultingType); + overrides['consultingTypes'] = [ + ...(overrides['consultingTypes'] || []), + consultingType + ]; } ); cy.fixture('service.consultingtypes.u25.json').then((consultingType) => { - defaultReturns['consultingTypes'].push(consultingType); - }); - - cy.fixture('api.v1.login').then((data) => { - cy.intercept('POST', endpoints.rc.accessToken, (req) => { - username = decodeUsername(req.body.username); - req.reply( - deepMerge(data, { - data: { userId: decodeUsername(req.body.username) } - }) - ); - }); + overrides['consultingTypes'] = [ + ...(overrides['consultingTypes'] || []), + consultingType + ]; }); cy.fixture('service.users.sessions.room.json').then((session) => { - defaultReturns['sessionRooms'].body.sessions.push(session); + const rooms = defaultReturns['sessionRooms']; + rooms.body.sessions.push(session); + overrides['sessionRooms'] = rooms; }); cy.fixture('service.agency.consultants.json').then((agencyConsultants) => { - defaultReturns['agencyConsultants'].push(agencyConsultants); + overrides['agencyConsultants'] = agencyConsultants; }); cy.fixture('auth.token').then((auth) => { - defaultReturns['auth'] = auth; - }); - - cy.fixture('service.users.data.consultants').then((usersData) => { - usersData.forEach((userData) => { - defaultReturns['userData'][userData.userId] = userData; - }); + overrides['auth'] = auth; }); - cy.fixture('service.users.data.askers').then((userData) => { - defaultReturns['userData'][USER_ASKER] = userData; - }); - - cy.intercept('GET', `${endpoints.consultantSessions}*`, (req) => { - if (overrides['consultantSessions']) { - return req.reply(overrides['consultantSessions']); - } - - const url = new URL(req.url); - - const offset = parseInt(url.searchParams.get('offset')) || 0; - const count = parseInt(url.searchParams.get('count')) || 15; - - req.reply( - sessionsReply({ - sessions: getConsultantSessions(), - offset, - count - }) - ); - }).as('consultantSessions'); - - cy.intercept('GET', endpoints.askerSessions, (req) => { - if (overrides['askerSessions']) { - return req.reply(overrides['askerSessions']); - } - - req.reply({ - sessions: getAskerSessions() - }); - }).as('askerSessions'); - - cy.intercept('GET', `${endpoints.messages.get}*`, (req) => { - if (overrides['messages']) { - return req.reply(overrides['messages']); - } - - const url = new URL(req.url); - - req.reply( - generateMessagesReply( - getMessages().filter( - (message) => - message.rid === url.searchParams.get('rcGroupId') - ) - ) - ); - }).as('messages'); - - cy.intercept('POST', endpoints.rc.subscriptions.read, (req) => { - getAskerSessions().forEach((session, index) => { - if (session.session.groupId === req.body.rid) { - updateAskerSession({ session: { messagesRead: true } }, index); - } - }); - - getConsultantSessions().forEach((session, index) => { - if (session.session.groupId === req.body.rid) { - updateConsultantSession( - { session: { messagesRead: true } }, - index - ); - } - }); - - req.reply('{}'); - }).as('sessionRead'); cy.intercept('GET', `${endpoints.consultantEnquiriesBase}*`, {}).as( 'consultantEnquiriesBase' @@ -214,58 +191,14 @@ Cypress.Commands.add('mockApi', () => { cy.intercept('POST', endpoints.keycloakLogout, {}).as('authLogout'); - cy.intercept( - 'GET', - `${endpoints.rc.users.getStatus}*`, - JSON.stringify({ - _id: 'HxWJQQtvcYfrdW5FD', - connectionStatus: 'online', - status: 'busy', - success: true - }) - ); - cy.intercept('GET', endpoints.frontend.settings, (req) => - req.reply( - JSON.stringify({ - ...defaultReturns['frontend.settings'], - ...(overrides['frontend.settings'] || {}) - }) - ) + req.reply(JSON.stringify(getWillReturn('frontend.settings'))) ); - cy.intercept( - 'GET', - `${endpoints.rc.settings.public}*`, - JSON.stringify({ - settings: [ - { _id: SETTING_E2E_ENABLE, value: true, enterprise: false }, - { - _id: SETTING_MESSAGE_MAXALLOWEDSIZE, - value: 999999, - enterprise: false - }, - { - _id: SETTING_FILEUPLOAD_MAXFILESIZE, - value: 99999999, - enterprise: false - } - ], - count: 1, - offset: 0, - total: 1, - success: true - }) - ).as('rcSettingsPublic'); - cy.intercept('POST', endpoints.keycloakLogout, { statusCode: 204 }).as('authLogout'); - cy.intercept('POST', endpoints.rc.logout, JSON.stringify({})).as( - 'apiLogout' - ); - cy.intercept( `${endpoints.liveservice}/**/*`, JSON.stringify({ @@ -276,221 +209,45 @@ Cypress.Commands.add('mockApi', () => { }) ).as('liveService'); - cy.intercept('GET', endpoints.draftMessages, {}).as('draftMessages'); - - cy.intercept('POST', endpoints.startVideoCall, { - fixture: 'service.videocalls.new' - }).as('startVideoCall'); - - cy.intercept('POST', endpoints.rejectVideoCall, {}).as('rejectVideoCall'); - - cy.intercept('POST', `${endpoints.attachmentUpload}*`, (req) => - req.reply({ - ...defaultReturns['attachmentUpload'], - ...(overrides['attachmentUpload'] || {}) - }) - ).as('attachmentUpload'); - cy.intercept('POST', endpoints.keycloakAccessToken, (req) => { - req.reply({ - ...defaultReturns['auth'], - ...(overrides['auth'] || {}) - }); + req.reply(getWillReturn('auth')); }).as('authToken'); - cy.intercept('PATCH', endpoints.userData, (req) => { - overrides['userData'] = { - ...overrides['userData'], - ...req.body - }; - req.reply({}); - }).as('patchUsersData'); - - cy.intercept('PUT', endpoints.setAbsence, (req) => { - overrides['userData'] = { - ...overrides['userData'], - absenceMessage: req.body.message, - absent: req.body.absent - }; - req.reply({}); - }).as('putSetAbsence'); - - cy.intercept('GET', endpoints.userData, (req) => { - req.reply({ - ...defaultReturns['userData'][username], - ...(overrides['userData'] || {}) - }); - }).as('usersData'); - - cy.intercept('GET', endpoints.consultantsLanguages, (req) => { - req.reply([ - ...defaultReturns['agencyConsultantsLanguages'], - ...(overrides['agencyConsultantsLanguages'] || []) - ]); - }).as('agencyConsultants'); - - cy.intercept('GET', `${endpoints.agencyConsultants}*`, (req) => { - req.reply( - ...defaultReturns['agencyConsultants'], - ...(overrides['agencyConsultants'] || []) - ); - }).as('agencyConsultants'); - - cy.intercept( - `${endpoints.consultingTypeServiceBase}/byslug/*/full`, - (req) => { - const slug = new URL(req.url).pathname.split('/')[4]; - - req.reply({ - ...(defaultReturns['consultingTypes'].find( - (consultingType) => consultingType.slug === slug - ) || {}), - ...(overrides['consultingType'] || {}) - }); - } - ).as('consultingTypeServiceBySlugFull'); - - cy.intercept(`${endpoints.consultingTypeServiceBase}/*/full`, (req) => { - const id = parseInt(new URL(req.url).pathname.split('/')[3]); - - req.reply({ - ...(defaultReturns['consultingTypes'].find( - (consultingType) => consultingType.id === id - ) || {}), - ...(overrides['consultingType'] || {}) - }); - }).as('consultingTypeServiceBaseFull'); - - cy.intercept(`${endpoints.consultingTypeServiceBase}/basic`, (req) => { - req.reply([ - ...defaultReturns['consultingTypes'], - ...(overrides['consultingTypes'] || []) - ]); - }).as('consultingTypeServiceBaseBasic'); - cy.intercept('GET', `${endpoints.serviceSettings}`, (req) => { - req.reply( - JSON.stringify({ - ...defaultReturns['settings'], - ...(overrides['settings'] || {}) - }) - ); + req.reply(JSON.stringify(getWillReturn('settings'))); }).as('settings'); + cy.intercept('GET', `${endpoints.tenantServiceBase}/public/`, (req) => { + req.reply(JSON.stringify(getWillReturn('service.tenant.public'))); + }).as('service.tenant.public'); + cy.intercept('GET', '/releases/*.json**', (req) => { - req.reply({ - ...defaultReturns['releases'], - ...(overrides['releases'] || {}) - }); + req.reply(getWillReturn('releases')); }).as('releases'); cy.intercept('GET', '/releases/*.md**', (req) => { - req.reply({ - ...defaultReturns['releases_markup'], - ...(overrides['releases_markup'] || {}) - }); + req.reply(getWillReturn('releases_markup')); }).as('releases_markup'); + usersChatApi(cy, getWillReturn, setWillReturn); + usersConsultantsApi(cy, getWillReturn, setWillReturn); + usersDataApi(cy, getWillReturn, setWillReturn); + usersSessionsApi(cy, getWillReturn, setWillReturn); + apiAgencies(cy, getWillReturn, setWillReturn); apiAppointments(cy); + apiConsultingTypes(cy, getWillReturn, setWillReturn); + apiMessages(cy, getWillReturn, setWillReturn); + apiRc(cy, getWillReturn, setWillReturn); + apiTopics(cy, getWillReturn, setWillReturn); + apiUploads(cy, getWillReturn, setWillReturn); apiVideocalls(cy); - - cy.intercept('GET', endpoints.rc.e2ee.fetchMyKeys, (req) => { - // keys from dev user pregnancy - req.reply({ - public_key: - '{"alg":"RSA-OAEP-256","e":"AQAB","ext":true,"key_ops":["encrypt"],"kty":"RSA","n":"o1hPIUjtf_kN1vHPfjq-LxXOkqycRbJp9UT8WNjA9c_z3hswAje3NC3E0QJG1eIe_yOwAYhjPtvEZ5aUfYQhPx1dlBL-vnaN4L_TsimgWBIpTpG4rQTY0X8eAF5nVBCBPKne70X4MH32Ol1RLP6Y7d7k9BiDYaJj0XYF_3HZKOfcAUGb34tWJy6dg3kg7pOEjKoHLHHbMn11VHwenMHnhh9JYltkixTy1BO0rRlORkXo680TQIPxEm9y8rsZWEccATu0ZKSlDSr4dYE09sCG_xUH5AGNGECbpnC_Ze7zUk1RRGFAWF6nmLaAPO7hMlVmQ802eF7HTtDdOexqwaIY7Q"}', - private_key: - '{"0":2,"1":107,"2":187,"3":21,"4":27,"5":7,"6":21,"7":97,"8":208,"9":87,"10":240,"11":132,"12":168,"13":122,"14":207,"15":152,"16":128,"17":197,"18":38,"19":181,"20":168,"21":237,"22":223,"23":203,"24":39,"25":255,"26":193,"27":80,"28":34,"29":201,"30":111,"31":236,"32":182,"33":89,"34":214,"35":178,"36":119,"37":187,"38":222,"39":165,"40":194,"41":155,"42":137,"43":214,"44":69,"45":145,"46":32,"47":9,"48":159,"49":83,"50":192,"51":193,"52":191,"53":33,"54":83,"55":18,"56":81,"57":243,"58":70,"59":223,"60":101,"61":8,"62":184,"63":180,"64":187,"65":33,"66":72,"67":220,"68":99,"69":48,"70":255,"71":107,"72":12,"73":174,"74":41,"75":27,"76":77,"77":155,"78":55,"79":110,"80":227,"81":76,"82":43,"83":255,"84":194,"85":216,"86":73,"87":172,"88":4,"89":217,"90":24,"91":183,"92":61,"93":94,"94":235,"95":177,"96":52,"97":103,"98":171,"99":156,"100":177,"101":146,"102":218,"103":204,"104":198,"105":79,"106":170,"107":152,"108":124,"109":16,"110":11,"111":224,"112":237,"113":81,"114":141,"115":53,"116":247,"117":113,"118":98,"119":113,"120":56,"121":37,"122":221,"123":171,"124":200,"125":20,"126":253,"127":66,"128":249,"129":244,"130":194,"131":100,"132":101,"133":141,"134":225,"135":32,"136":172,"137":60,"138":97,"139":74,"140":30,"141":153,"142":237,"143":25,"144":190,"145":84,"146":175,"147":245,"148":83,"149":102,"150":126,"151":92,"152":41,"153":162,"154":148,"155":147,"156":151,"157":253,"158":166,"159":227,"160":209,"161":161,"162":54,"163":189,"164":204,"165":57,"166":98,"167":248,"168":2,"169":162,"170":77,"171":61,"172":161,"173":73,"174":190,"175":144,"176":10,"177":57,"178":73,"179":120,"180":113,"181":185,"182":13,"183":101,"184":201,"185":128,"186":222,"187":82,"188":205,"189":52,"190":129,"191":97,"192":144,"193":128,"194":238,"195":146,"196":84,"197":13,"198":86,"199":1,"200":73,"201":25,"202":67,"203":223,"204":40,"205":50,"206":92,"207":250,"208":190,"209":94,"210":17,"211":100,"212":75,"213":100,"214":0,"215":106,"216":107,"217":82,"218":168,"219":185,"220":101,"221":65,"222":167,"223":1,"224":94,"225":42,"226":147,"227":47,"228":104,"229":2,"230":68,"231":171,"232":129,"233":32,"234":149,"235":154,"236":216,"237":179,"238":65,"239":242,"240":72,"241":30,"242":90,"243":147,"244":186,"245":148,"246":96,"247":129,"248":189,"249":56,"250":179,"251":0,"252":0,"253":63,"254":147,"255":28,"256":136,"257":248,"258":79,"259":33,"260":235,"261":156,"262":13,"263":236,"264":77,"265":237,"266":216,"267":164,"268":191,"269":164,"270":218,"271":104,"272":178,"273":55,"274":10,"275":65,"276":118,"277":164,"278":183,"279":130,"280":39,"281":187,"282":21,"283":194,"284":144,"285":113,"286":208,"287":181,"288":27,"289":112,"290":163,"291":146,"292":173,"293":93,"294":218,"295":161,"296":246,"297":210,"298":36,"299":140,"300":201,"301":1,"302":175,"303":160,"304":17,"305":254,"306":17,"307":82,"308":107,"309":31,"310":104,"311":161,"312":33,"313":67,"314":81,"315":162,"316":118,"317":196,"318":32,"319":255,"320":63,"321":54,"322":69,"323":98,"324":4,"325":104,"326":123,"327":68,"328":96,"329":28,"330":197,"331":47,"332":139,"333":141,"334":217,"335":194,"336":156,"337":156,"338":23,"339":90,"340":44,"341":205,"342":131,"343":95,"344":227,"345":26,"346":139,"347":161,"348":200,"349":91,"350":201,"351":36,"352":145,"353":62,"354":163,"355":229,"356":211,"357":164,"358":65,"359":131,"360":170,"361":146,"362":109,"363":177,"364":43,"365":19,"366":185,"367":223,"368":137,"369":229,"370":82,"371":43,"372":100,"373":69,"374":69,"375":114,"376":252,"377":98,"378":218,"379":66,"380":36,"381":178,"382":252,"383":171,"384":229,"385":187,"386":209,"387":27,"388":32,"389":172,"390":29,"391":49,"392":26,"393":4,"394":212,"395":172,"396":80,"397":201,"398":202,"399":108,"400":4,"401":124,"402":190,"403":189,"404":218,"405":223,"406":22,"407":87,"408":4,"409":238,"410":243,"411":22,"412":178,"413":59,"414":168,"415":133,"416":13,"417":72,"418":216,"419":124,"420":202,"421":70,"422":153,"423":169,"424":17,"425":29,"426":72,"427":19,"428":73,"429":225,"430":175,"431":87,"432":178,"433":115,"434":105,"435":56,"436":158,"437":128,"438":23,"439":86,"440":239,"441":102,"442":211,"443":110,"444":197,"445":99,"446":193,"447":239,"448":117,"449":236,"450":211,"451":31,"452":222,"453":91,"454":140,"455":154,"456":24,"457":137,"458":216,"459":204,"460":203,"461":164,"462":60,"463":53,"464":118,"465":222,"466":173,"467":64,"468":187,"469":105,"470":10,"471":85,"472":161,"473":197,"474":244,"475":18,"476":251,"477":212,"478":187,"479":8,"480":217,"481":194,"482":24,"483":174,"484":224,"485":85,"486":218,"487":218,"488":9,"489":54,"490":204,"491":117,"492":150,"493":60,"494":172,"495":57,"496":153,"497":184,"498":215,"499":86,"500":53,"501":88,"502":70,"503":148,"504":25,"505":20,"506":98,"507":22,"508":234,"509":201,"510":118,"511":34,"512":55,"513":129,"514":97,"515":35,"516":82,"517":118,"518":143,"519":230,"520":140,"521":246,"522":86,"523":189,"524":148,"525":233,"526":10,"527":56,"528":224,"529":187,"530":37,"531":140,"532":97,"533":108,"534":6,"535":47,"536":55,"537":158,"538":230,"539":141,"540":83,"541":211,"542":221,"543":200,"544":217,"545":238,"546":222,"547":135,"548":153,"549":224,"550":219,"551":173,"552":82,"553":23,"554":92,"555":148,"556":107,"557":51,"558":1,"559":23,"560":1,"561":10,"562":12,"563":224,"564":140,"565":1,"566":117,"567":68,"568":168,"569":196,"570":153,"571":82,"572":225,"573":143,"574":188,"575":136,"576":56,"577":110,"578":122,"579":246,"580":160,"581":180,"582":118,"583":131,"584":38,"585":2,"586":188,"587":250,"588":207,"589":190,"590":48,"591":192,"592":193,"593":47,"594":236,"595":255,"596":254,"597":98,"598":60,"599":218,"600":232,"601":38,"602":6,"603":163,"604":203,"605":135,"606":95,"607":130,"608":130,"609":2,"610":189,"611":100,"612":173,"613":60,"614":73,"615":172,"616":3,"617":221,"618":23,"619":22,"620":133,"621":170,"622":240,"623":127,"624":161,"625":82,"626":124,"627":54,"628":77,"629":178,"630":225,"631":77,"632":147,"633":28,"634":181,"635":57,"636":227,"637":231,"638":247,"639":231,"640":170,"641":250,"642":218,"643":43,"644":243,"645":160,"646":103,"647":55,"648":75,"649":131,"650":251,"651":9,"652":48,"653":8,"654":65,"655":152,"656":69,"657":29,"658":251,"659":13,"660":95,"661":123,"662":42,"663":75,"664":227,"665":152,"666":196,"667":245,"668":236,"669":172,"670":80,"671":220,"672":80,"673":205,"674":32,"675":135,"676":60,"677":253,"678":194,"679":6,"680":6,"681":28,"682":239,"683":160,"684":227,"685":229,"686":16,"687":2,"688":42,"689":129,"690":130,"691":232,"692":145,"693":183,"694":4,"695":129,"696":64,"697":123,"698":2,"699":71,"700":199,"701":13,"702":174,"703":228,"704":135,"705":188,"706":250,"707":201,"708":137,"709":247,"710":220,"711":244,"712":199,"713":247,"714":176,"715":124,"716":53,"717":69,"718":58,"719":85,"720":172,"721":182,"722":228,"723":57,"724":196,"725":35,"726":177,"727":104,"728":199,"729":58,"730":193,"731":155,"732":88,"733":203,"734":228,"735":12,"736":14,"737":85,"738":115,"739":234,"740":35,"741":114,"742":181,"743":247,"744":119,"745":226,"746":5,"747":250,"748":195,"749":201,"750":211,"751":100,"752":89,"753":180,"754":26,"755":112,"756":234,"757":125,"758":208,"759":29,"760":106,"761":244,"762":127,"763":13,"764":38,"765":250,"766":231,"767":237,"768":86,"769":168,"770":126,"771":69,"772":28,"773":229,"774":228,"775":93,"776":153,"777":166,"778":177,"779":171,"780":108,"781":157,"782":62,"783":145,"784":199,"785":10,"786":146,"787":42,"788":177,"789":33,"790":116,"791":96,"792":200,"793":157,"794":121,"795":64,"796":154,"797":12,"798":63,"799":22,"800":93,"801":232,"802":181,"803":62,"804":186,"805":5,"806":66,"807":95,"808":6,"809":195,"810":122,"811":151,"812":116,"813":51,"814":11,"815":248,"816":37,"817":94,"818":16,"819":34,"820":174,"821":218,"822":162,"823":204,"824":167,"825":228,"826":232,"827":108,"828":154,"829":225,"830":61,"831":106,"832":134,"833":205,"834":209,"835":9,"836":85,"837":64,"838":186,"839":23,"840":154,"841":135,"842":150,"843":101,"844":218,"845":132,"846":135,"847":174,"848":102,"849":105,"850":135,"851":184,"852":254,"853":250,"854":185,"855":29,"856":204,"857":77,"858":227,"859":34,"860":38,"861":253,"862":50,"863":26,"864":217,"865":176,"866":172,"867":88,"868":47,"869":146,"870":43,"871":204,"872":92,"873":154,"874":71,"875":63,"876":192,"877":47,"878":156,"879":116,"880":158,"881":126,"882":130,"883":123,"884":133,"885":101,"886":79,"887":76,"888":224,"889":134,"890":202,"891":121,"892":94,"893":164,"894":210,"895":130,"896":21,"897":129,"898":69,"899":135,"900":74,"901":174,"902":180,"903":126,"904":10,"905":187,"906":231,"907":113,"908":64,"909":222,"910":16,"911":40,"912":23,"913":133,"914":219,"915":2,"916":170,"917":54,"918":155,"919":49,"920":165,"921":95,"922":148,"923":31,"924":151,"925":12,"926":141,"927":175,"928":57,"929":232,"930":186,"931":3,"932":48,"933":61,"934":38,"935":8,"936":238,"937":203,"938":230,"939":62,"940":155,"941":43,"942":150,"943":207,"944":195,"945":221,"946":94,"947":17,"948":0,"949":250,"950":176,"951":240,"952":50,"953":50,"954":176,"955":89,"956":183,"957":173,"958":253,"959":15,"960":82,"961":9,"962":162,"963":198,"964":30,"965":18,"966":178,"967":14,"968":65,"969":182,"970":235,"971":110,"972":250,"973":152,"974":145,"975":150,"976":237,"977":77,"978":144,"979":167,"980":116,"981":114,"982":180,"983":44,"984":38,"985":226,"986":191,"987":39,"988":175,"989":145,"990":198,"991":130,"992":185,"993":118,"994":95,"995":222,"996":37,"997":44,"998":138,"999":101,"1000":211,"1001":31,"1002":155,"1003":214,"1004":143,"1005":225,"1006":96,"1007":69,"1008":79,"1009":180,"1010":171,"1011":124,"1012":40,"1013":253,"1014":162,"1015":134,"1016":118,"1017":40,"1018":216,"1019":2,"1020":164,"1021":165,"1022":94,"1023":34,"1024":122,"1025":86,"1026":16,"1027":209,"1028":213,"1029":84,"1030":91,"1031":184,"1032":120,"1033":111,"1034":200,"1035":162,"1036":239,"1037":214,"1038":151,"1039":226,"1040":117,"1041":137,"1042":177,"1043":182,"1044":112,"1045":192,"1046":46,"1047":213,"1048":216,"1049":117,"1050":64,"1051":149,"1052":95,"1053":237,"1054":217,"1055":77,"1056":111,"1057":69,"1058":109,"1059":118,"1060":255,"1061":64,"1062":222,"1063":134,"1064":124,"1065":34,"1066":100,"1067":191,"1068":92,"1069":197,"1070":182,"1071":59,"1072":20,"1073":218,"1074":168,"1075":27,"1076":193,"1077":193,"1078":151,"1079":4,"1080":26,"1081":164,"1082":48,"1083":83,"1084":45,"1085":95,"1086":218,"1087":134,"1088":65,"1089":107,"1090":207,"1091":118,"1092":5,"1093":175,"1094":76,"1095":47,"1096":70,"1097":179,"1098":219,"1099":230,"1100":130,"1101":30,"1102":225,"1103":3,"1104":142,"1105":120,"1106":141,"1107":89,"1108":37,"1109":228,"1110":95,"1111":167,"1112":153,"1113":47,"1114":169,"1115":36,"1116":235,"1117":41,"1118":213,"1119":163,"1120":19,"1121":14,"1122":67,"1123":19,"1124":190,"1125":14,"1126":89,"1127":126,"1128":22,"1129":60,"1130":185,"1131":64,"1132":211,"1133":138,"1134":149,"1135":242,"1136":229,"1137":76,"1138":36,"1139":29,"1140":163,"1141":209,"1142":100,"1143":189,"1144":159,"1145":43,"1146":157,"1147":167,"1148":203,"1149":200,"1150":201,"1151":71,"1152":37,"1153":249,"1154":73,"1155":10,"1156":201,"1157":87,"1158":72,"1159":0,"1160":145,"1161":139,"1162":92,"1163":246,"1164":224,"1165":125,"1166":125,"1167":186,"1168":71,"1169":236,"1170":246,"1171":68,"1172":172,"1173":61,"1174":159,"1175":106,"1176":105,"1177":108,"1178":186,"1179":53,"1180":220,"1181":73,"1182":76,"1183":9,"1184":149,"1185":244,"1186":247,"1187":15,"1188":43,"1189":27,"1190":238,"1191":190,"1192":203,"1193":199,"1194":203,"1195":204,"1196":94,"1197":212,"1198":114,"1199":243,"1200":179,"1201":71,"1202":205,"1203":125,"1204":194,"1205":207,"1206":161,"1207":199,"1208":157,"1209":109,"1210":197,"1211":33,"1212":164,"1213":21,"1214":69,"1215":68,"1216":188,"1217":252,"1218":6,"1219":107,"1220":90,"1221":89,"1222":219,"1223":21,"1224":159,"1225":40,"1226":131,"1227":198,"1228":252,"1229":199,"1230":147,"1231":36,"1232":116,"1233":20,"1234":111,"1235":19,"1236":156,"1237":82,"1238":145,"1239":189,"1240":24,"1241":186,"1242":208,"1243":3,"1244":159,"1245":8,"1246":67,"1247":72,"1248":82,"1249":93,"1250":225,"1251":55,"1252":137,"1253":119,"1254":85,"1255":238,"1256":3,"1257":188,"1258":255,"1259":102,"1260":50,"1261":163,"1262":148,"1263":109,"1264":203,"1265":188,"1266":109,"1267":99,"1268":49,"1269":247,"1270":53,"1271":217,"1272":236,"1273":90,"1274":74,"1275":80,"1276":3,"1277":175,"1278":126,"1279":33,"1280":97,"1281":254,"1282":193,"1283":54,"1284":185,"1285":68,"1286":68,"1287":165,"1288":214,"1289":56,"1290":119,"1291":174,"1292":1,"1293":137,"1294":124,"1295":231,"1296":122,"1297":118,"1298":77,"1299":170,"1300":125,"1301":210,"1302":53,"1303":104,"1304":99,"1305":157,"1306":45,"1307":7,"1308":30,"1309":80,"1310":194,"1311":230,"1312":26,"1313":255,"1314":123,"1315":143,"1316":107,"1317":139,"1318":126,"1319":119,"1320":52,"1321":178,"1322":124,"1323":29,"1324":200,"1325":65,"1326":87,"1327":183,"1328":35,"1329":133,"1330":10,"1331":233,"1332":58,"1333":129,"1334":252,"1335":203,"1336":191,"1337":252,"1338":3,"1339":34,"1340":132,"1341":45,"1342":221,"1343":195,"1344":232,"1345":186,"1346":183,"1347":61,"1348":17,"1349":47,"1350":26,"1351":80,"1352":62,"1353":199,"1354":247,"1355":154,"1356":244,"1357":248,"1358":167,"1359":128,"1360":190,"1361":231,"1362":168,"1363":219,"1364":165,"1365":6,"1366":136,"1367":178,"1368":83,"1369":156,"1370":209,"1371":98,"1372":200,"1373":113,"1374":235,"1375":234,"1376":61,"1377":213,"1378":53,"1379":117,"1380":108,"1381":73,"1382":193,"1383":158,"1384":37,"1385":136,"1386":106,"1387":251,"1388":187,"1389":44,"1390":105,"1391":185,"1392":232,"1393":96,"1394":209,"1395":58,"1396":18,"1397":149,"1398":25,"1399":37,"1400":42,"1401":118,"1402":243,"1403":7,"1404":58,"1405":214,"1406":177,"1407":62,"1408":248,"1409":201,"1410":5,"1411":11,"1412":61,"1413":104,"1414":176,"1415":71,"1416":169,"1417":233,"1418":147,"1419":98,"1420":144,"1421":65,"1422":12,"1423":7,"1424":88,"1425":159,"1426":177,"1427":176,"1428":123,"1429":36,"1430":45,"1431":127,"1432":140,"1433":108,"1434":167,"1435":190,"1436":212,"1437":68,"1438":99,"1439":221,"1440":75,"1441":42,"1442":103,"1443":246,"1444":6,"1445":220,"1446":148,"1447":137,"1448":12,"1449":212,"1450":35,"1451":38,"1452":140,"1453":186,"1454":2,"1455":83,"1456":38,"1457":236,"1458":75,"1459":241,"1460":183,"1461":183,"1462":17,"1463":67,"1464":39,"1465":5,"1466":58,"1467":109,"1468":160,"1469":12,"1470":89,"1471":196,"1472":73,"1473":76,"1474":69,"1475":30,"1476":211,"1477":243,"1478":79,"1479":248,"1480":189,"1481":232,"1482":206,"1483":39,"1484":116,"1485":223,"1486":65,"1487":66,"1488":17,"1489":16,"1490":95,"1491":228,"1492":125,"1493":235,"1494":197,"1495":179,"1496":200,"1497":98,"1498":7,"1499":96,"1500":253,"1501":100,"1502":10,"1503":188,"1504":62,"1505":102,"1506":91,"1507":124,"1508":188,"1509":148,"1510":172,"1511":156,"1512":50,"1513":144,"1514":57,"1515":89,"1516":57,"1517":131,"1518":220,"1519":57,"1520":236,"1521":203,"1522":71,"1523":130,"1524":101,"1525":244,"1526":129,"1527":155,"1528":19,"1529":12,"1530":45,"1531":194,"1532":160,"1533":37,"1534":89,"1535":198,"1536":215,"1537":175,"1538":46,"1539":100,"1540":13,"1541":73,"1542":212,"1543":57,"1544":19,"1545":33,"1546":143,"1547":251,"1548":148,"1549":155,"1550":165,"1551":194,"1552":160,"1553":129,"1554":213,"1555":21,"1556":55,"1557":49,"1558":65,"1559":126,"1560":145,"1561":108,"1562":37,"1563":194,"1564":98,"1565":115,"1566":4,"1567":43,"1568":124,"1569":131,"1570":163,"1571":58,"1572":235,"1573":198,"1574":155,"1575":102,"1576":50,"1577":211,"1578":186,"1579":199,"1580":220,"1581":34,"1582":108,"1583":54,"1584":204,"1585":101,"1586":166,"1587":76,"1588":178,"1589":248,"1590":177,"1591":60,"1592":89,"1593":251,"1594":170,"1595":2,"1596":77,"1597":43,"1598":128,"1599":171,"1600":133,"1601":57,"1602":197,"1603":203,"1604":131,"1605":181,"1606":227,"1607":98,"1608":229,"1609":234,"1610":184,"1611":4,"1612":142,"1613":65,"1614":191,"1615":41,"1616":93,"1617":32,"1618":242,"1619":93,"1620":229,"1621":94,"1622":9,"1623":122,"1624":38,"1625":122,"1626":40,"1627":165,"1628":177,"1629":4,"1630":50,"1631":56,"1632":205,"1633":212,"1634":159,"1635":88,"1636":192,"1637":97,"1638":15,"1639":82,"1640":132,"1641":105,"1642":54,"1643":71,"1644":167,"1645":75,"1646":46,"1647":169,"1648":56,"1649":21,"1650":57,"1651":74,"1652":14,"1653":97,"1654":214,"1655":223,"1656":205,"1657":21,"1658":141,"1659":33,"1660":32,"1661":55,"1662":5,"1663":97,"1664":178,"1665":96,"1666":248,"1667":203,"1668":255,"1669":199,"1670":14,"1671":124,"1672":75,"1673":193,"1674":96,"1675":243,"1676":205,"1677":8,"1678":80,"1679":20,"1680":246,"1681":57,"1682":25,"1683":163,"1684":244,"1685":137,"1686":21,"1687":175,"1688":199,"1689":2,"1690":96,"1691":246,"1692":253,"1693":212,"1694":14,"1695":179}', - success: true - }); - }).as('fetchMyKeys'); - - cy.intercept( - 'POST', - endpoints.rc.e2ee.setUserPublicAndPrivateKeys, - (req) => { - req.reply({ - success: true - }); - } - ).as('setUserPublicAndPrivateKeys'); - - cy.intercept('POST', endpoints.rc.users.resetE2EKey, (req) => { - req.reply({ - success: true - }); - }).as('resetE2EKey'); - - cy.intercept('PUT', endpoints.userUpdateE2EKey, { - statusCode: 200 - }); - - cy.intercept('GET', `${endpoints.sessionRooms}*`, (req) => { - const data = { ...defaultReturns['sessionRooms'] }; - const rcGroupId = new URL(req.url).searchParams.get('rcGroupIds'); - let foundSession = null; - getAskerSessions().forEach((session, index) => { - if (session.session.groupId === rcGroupId) { - foundSession = session.session; - } - }); - - getConsultantSessions().forEach((session, index) => { - if (session.session.groupId === rcGroupId) { - foundSession = session.session; - } - }); - - data.body.sessions[0].session = { - ...foundSession, - ...overrides['sessionRooms'] - }; - - req.reply(data); - }).as('sessionRooms'); }); -Cypress.Commands.add( - 'fastLogin', - ( - args: LoginArgs = { - username: USER_ASKER - } - ) => { - username = args.username || USER_ASKER; - - cy.fixture('api.v1.login').then((res) => { - if (res.data.authToken) { - cy.setCookie('rc_token', res.data.authToken); - } - if (res.data.userId) { - cy.setCookie('rc_uid', res.data.userId); - // masterkey dev user pregnancy - window.localStorage.setItem( - `mk_${res.data.userId}`, - '[225,59,174,132,235,143,199,190,136,68,11,58,123,91,159,241,78,226,65,110,22,100,84,127,59,84,180,138,210,94,176,144]' - ); - } - }); - - const tomorrow = new Date(); - tomorrow.setDate(tomorrow.getDate() + 1); +export const USER_ASKER = 'asker'; +export const USER_CONSULTANT = 'consultant'; +export const USER_VIDEO = 'video'; - window.localStorage.setItem( - 'auth.access_token_valid_until', - tomorrow.getTime().toString() - ); - window.localStorage.setItem( - 'auth.refresh_token_valid_until', - tomorrow.getTime().toString() - ); - - cy.visit('/app'); - cy.wait('@usersData'); - if (username === USER_ASKER) { - cy.wait('@askerSessions'); - } else { - cy.wait('@consultantEnquiriesBase'); - } - } -); +export interface LoginArgs { + userId?: typeof USER_ASKER | typeof USER_CONSULTANT | typeof USER_VIDEO; + auth?: { expires_in: number; refresh_expires_in: number }; +} diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts index 6b5e9b2d7..51ed4097d 100644 --- a/cypress/support/e2e.ts +++ b/cypress/support/e2e.ts @@ -5,6 +5,14 @@ beforeEach(() => { window.localStorage.setItem('locale', 'de'); window.localStorage.setItem('showDevTools', '0'); window.localStorage.setItem('e2ee_disabled', '1'); + + cy.mockApi(); + cy.fixture('service.settings.json').then((content) => { + cy.willReturn('settings', content); + }); + cy.fixture('service.tenant.public.json').then((content) => { + cy.willReturn('service.tenant.public', content); + }); }); afterEach(() => { diff --git a/cypress/support/helpers.ts b/cypress/support/helpers.ts index e0d050702..8f0c95fc4 100644 --- a/cypress/support/helpers.ts +++ b/cypress/support/helpers.ts @@ -16,3 +16,14 @@ export const deepMerge = ( return obj; }; + +export const parseCookieStr = (str: string): { [key: string]: string } => + str + .split(';') + .map((v) => v.split('=')) + .reduce((acc, v) => { + acc[decodeURIComponent(v[0].trim())] = decodeURIComponent( + v[1].trim() + ); + return acc; + }, {}); diff --git a/cypress/support/index.d.ts b/cypress/support/index.d.ts new file mode 100644 index 000000000..0030bb35b --- /dev/null +++ b/cypress/support/index.d.ts @@ -0,0 +1,50 @@ +/// + +import { LoginArgs } from './commands/mockApi'; +import { AppointmentsDataInterface } from '../../src/globalState/interfaces'; +import * as Bluebird from 'cypress/types/bluebird'; + +declare global { + namespace Cypress { + interface Chainable { + login(args?: LoginArgs): Chainable; + + fastLogin(args?: LoginArgs): Chainable; + + appointments( + args?: Partial, + index?: number + ): Bluebird; + + askerSession( + args?: { [key: string]: any }, + index?: number + ): Bluebird; + + consultantSession( + args?: { [key: string]: any }, + index?: number + ): Bluebird; + + addMessage( + props?: { [key: string]: any }, + index?: number + ): Bluebird; + + mockApi(): Chainable; + + willReturn( + name: string, + data: any, + mergeData?: boolean + ): Chainable; + willReturn(name: string): Chainable; + + emitDirectMessage(index?: number): Chainable; + + emitVideoCallRequest(): Chainable; + + waitForSubscriptions(events: string[]): Chainable; + } + } +} diff --git a/cypress/support/sessions.ts b/cypress/support/sessions.ts index 781ee6d99..7f881da46 100644 --- a/cypress/support/sessions.ts +++ b/cypress/support/sessions.ts @@ -1,6 +1,6 @@ import { v4 as uuid } from 'uuid'; import { SESSION_LIST_TYPES } from '../../src/components/session/sessionHelpers'; -import { SessionUserDataInterface } from '../../src/globalState'; +import { SessionUserDataInterface } from '../../src/globalState/interfaces'; export const generateConsultantSession = ({ type, diff --git a/cypress/support/websocket.ts b/cypress/support/websocket.ts index d14840f42..c93e8a6d9 100644 --- a/cypress/support/websocket.ts +++ b/cypress/support/websocket.ts @@ -208,29 +208,26 @@ export const startWebSocketServer = () => { JSON.stringify({ id: parsedMessage.id, msg: 'result', - result: { - total: 2, - records: [ - { - _id: 'asker1', - username: 'asker1', - status: 'busy', - _updatedAt: { - $date: 1677018431963 - }, - name: null + result: [ + { + _id: 'asker1', + username: 'asker1', + status: 'busy', + _updatedAt: { + $date: 1677018431963 }, - { - _id: 'consultant1', - username: 'consultant1', - status: 'offline', - name: 'consultant1', - _updatedAt: { - $date: 1677016800740 - } + name: null + }, + { + _id: 'consultant1', + username: 'consultant1', + status: 'offline', + name: 'consultant1', + _updatedAt: { + $date: 1677016800740 } - ] - } + } + ] }) ); break; diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json index 13b9a21df..fa419798d 100644 --- a/cypress/tsconfig.json +++ b/cypress/tsconfig.json @@ -5,5 +5,9 @@ "types": ["cypress"], "moduleResolution": "node" }, - "include": ["**/*.ts", "../src/generated/**/*.ts"] + "include": [ + "**/*.ts", + "../src/generated/**/*.ts", + "../src/extensions/**/*.cy.ts" + ] } diff --git a/proxy/config.js b/proxy/config.js index 12e24da94..9b5d9e9b2 100644 --- a/proxy/config.js +++ b/proxy/config.js @@ -14,14 +14,8 @@ module.exports = { } }, registration: { - directlink: { - fallbackLoader: { - enabled: !!parseInt( - process.env - .FRONTEND_REGISTRATION_DIRECTLINK_FALLBACKLOADER_ENABLED || - '1' - ) - } - } + useConsultingTypeSlug: !!parseInt( + process.env.FRONTEND_REGISTRATION_USE_CONSULTINGTYPE_SLUG || '0' + ) } }; diff --git a/src/api/apiAgencySelection.ts b/src/api/apiAgencySelection.ts index 18eb3cfb4..21284ee86 100644 --- a/src/api/apiAgencySelection.ts +++ b/src/api/apiAgencySelection.ts @@ -2,12 +2,20 @@ import { endpoints } from '../resources/scripts/endpoints'; import { fetchData, FETCH_METHODS, FETCH_ERRORS } from './fetchData'; import { VALID_POSTCODE_LENGTH } from '../components/agencySelection/agencySelectionHelpers'; import { AgencyDataInterface } from '../globalState'; +import { loadConsultingTypeForAgency } from '../utils/loadConsultingTypeForAgency'; export const apiAgencySelection = async ( - params: { + { + fetchConsultingTypeDetails, + ...params + }: { postcode: string; consultingType: number | undefined; topicId?: number; + age?: number; + gender?: string; + counsellingRelation?: string; + fetchConsultingTypeDetails?: boolean; }, signal?: AbortSignal ): Promise | null> => { @@ -24,22 +32,35 @@ export const apiAgencySelection = async ( skipAuth: true, responseHandling: [FETCH_ERRORS.EMPTY], ...(signal && { signal: signal }) - }).then((result) => { - if (result) { - // External agencies should only be returned - // if there are no internal ones. - const internalAgencies = result.filter( - (agency) => !agency.external - ); - if (internalAgencies.length > 0) { - return internalAgencies; + }) + .then((result) => { + if (result) { + // External agencies should only be returned + // if there are no internal ones. + const internalAgencies = result.filter( + (agency) => !agency.external + ); + if (internalAgencies.length > 0) { + return internalAgencies; + } else { + return result; + } } else { return result; } - } else { - return result; - } - }); + }) + .then((agencies) => { + if (!fetchConsultingTypeDetails) { + return agencies; + } + + return Promise.all( + agencies.map( + async (agency) => + await loadConsultingTypeForAgency(agency) + ) + ); + }); } else { return null; } diff --git a/src/api/apiGetAgencyId.ts b/src/api/apiGetAgencyId.ts index 73d95bc68..b36f96b64 100644 --- a/src/api/apiGetAgencyId.ts +++ b/src/api/apiGetAgencyId.ts @@ -1,9 +1,11 @@ import { endpoints } from '../resources/scripts/endpoints'; import { fetchData, FETCH_METHODS, FETCH_ERRORS } from './fetchData'; import { AgencyDataInterface } from '../globalState'; +import { loadConsultingTypeForAgency } from '../utils/loadConsultingTypeForAgency'; export const apiGetAgencyById = async ( - agencyId: any + agencyId: number, + fetchConsultingTypeDetails?: boolean ): Promise => { const url = endpoints.agencyServiceBase + '/' + agencyId; @@ -12,5 +14,13 @@ export const apiGetAgencyById = async ( method: FETCH_METHODS.GET, skipAuth: true, responseHandling: [FETCH_ERRORS.EMPTY, FETCH_ERRORS.NO_MATCH] - }).then((response) => response[0]); + }) + .then((response) => response[0]) + .then(async (agency) => { + if (!fetchConsultingTypeDetails || !agency) { + return agency; + } + + return await loadConsultingTypeForAgency(agency); + }); }; diff --git a/src/api/apiGetConsultant.ts b/src/api/apiGetConsultant.ts index 45430fb99..263df069c 100644 --- a/src/api/apiGetConsultant.ts +++ b/src/api/apiGetConsultant.ts @@ -1,13 +1,11 @@ import { endpoints } from '../resources/scripts/endpoints'; import { fetchData, FETCH_METHODS, FETCH_ERRORS } from './fetchData'; import { ConsultantDataInterface } from '../globalState'; -import { apiGetConsultingType } from './apiGetConsultingType'; -import { apiGetConsultingTypes } from './apiGetConsultingTypes'; +import { loadConsultingTypeForAgency } from '../utils/loadConsultingTypeForAgency'; export const apiGetConsultant = async ( - consultantId: any, - fetchConsultingTypes?: boolean, - consultingTypeDetail: 'full' | 'basic' = 'full' + consultantId: string, + fetchConsultingTypeDetails?: boolean ): Promise => { const url = endpoints.agencyConsultants + '/' + consultantId; @@ -15,45 +13,21 @@ export const apiGetConsultant = async ( url: url, method: FETCH_METHODS.GET, skipAuth: true, - responseHandling: [FETCH_ERRORS.EMPTY, FETCH_ERRORS.NO_MATCH] + responseHandling: [FETCH_ERRORS.CATCH_ALL] }).then((user) => { - if (!fetchConsultingTypes) { + if (!fetchConsultingTypeDetails) { return user; } - if (consultingTypeDetail === 'full') { - return Promise.all( - user.agencies.map(async (agency) => ({ - ...agency, - consultingTypeRel: await apiGetConsultingType({ - consultingTypeId: agency?.consultingType - }) - })) - ).then((agencies): ConsultantDataInterface => { - return { - ...user, - agencies - }; - }); - } - - if (consultingTypeDetail === 'basic') { - return apiGetConsultingTypes().then((consultingTypes) => { - const mappedUserAgencies = user.agencies.map((agency) => { - const consultingTypeRel = consultingTypes.filter( - (type) => type.id === agency.consultingType - )[0]; - return { - ...agency, - consultingTypeRel: { ...consultingTypeRel } - }; - }); - - return { - ...user, - agencies: mappedUserAgencies - }; - }); - } + return Promise.all( + user.agencies.map( + async (agency) => await loadConsultingTypeForAgency(agency) + ) + ).then( + (agencies): ConsultantDataInterface => ({ + ...user, + agencies + }) + ); }); }; diff --git a/src/api/apiRegistrationNewConsultingTypes.ts b/src/api/apiRegistrationNewConsultingTypes.ts index 28ee37922..9308dffc6 100644 --- a/src/api/apiRegistrationNewConsultingTypes.ts +++ b/src/api/apiRegistrationNewConsultingTypes.ts @@ -14,14 +14,16 @@ export const apiRegistrationNewConsultingTypes = async ( consultingType: number, agencyId: number, postcode: string, - consultantId?: string + consultantId?: string, + topicIds?: number[] ): Promise => { const url = endpoints.registerAskerNewConsultingType; const data = JSON.stringify({ postcode, agencyId, consultingType, - consultantId + consultantId, + ...(topicIds ? { topicIds: topicIds } : {}) }); return fetchData({ diff --git a/src/api/fetchData.ts b/src/api/fetchData.ts index a2773815e..c3720a3d4 100644 --- a/src/api/fetchData.ts +++ b/src/api/fetchData.ts @@ -223,6 +223,7 @@ export const fetchData = ({ ) { reject(new Error(FETCH_ERRORS.GATEWAY_TIMEOUT)); } else if (response.status === 401) { + console.log(url); logout(true, appConfig.urls.toLogin); } } else { diff --git a/src/components/app/app.tsx b/src/components/app/app.tsx index 068e9239d..0e3bb6abe 100644 --- a/src/components/app/app.tsx +++ b/src/components/app/app.tsx @@ -1,6 +1,5 @@ import '../../polyfill'; import * as React from 'react'; -import { useHistory } from 'react-router-dom'; import { ComponentType, useState, lazy, Suspense, useContext } from 'react'; import { BrowserRouter as Router, @@ -17,13 +16,13 @@ import ErrorBoundary from './ErrorBoundary'; import { LanguagesProvider } from '../../globalState/provider/LanguagesProvider'; import { TenantThemingLoader } from './TenantThemingLoader'; import { - AppConfigInterface, AppConfigProvider, InformalProvider, - LegalLinkInterface, LocaleProvider, NotificationsContext, - TenantProvider + TenantProvider, + AppConfigInterface, + LegalLinkInterface } from '../../globalState'; import { LegalLinksProvider } from '../../globalState/provider/LegalLinksProvider'; import { useAppConfig } from '../../hooks/useAppConfig'; @@ -120,7 +119,6 @@ interface RouterWrapperProps { } const RouterWrapper = ({ extraRoutes, entryPoint }: RouterWrapperProps) => { - const history = useHistory(); const settings = useAppConfig(); const [startWebsocket, setStartWebsocket] = useState(false); @@ -171,22 +169,12 @@ const RouterWrapper = ({ extraRoutes, entryPoint }: RouterWrapperProps) => { ]} > - - history.push('/login') - } - handleUnmatchConsultant={() => - history.push('/login') - } - /> + - history.push('/login') - } onAnonymousRegistration={() => setStartWebsocket(true) } diff --git a/src/components/consultingTypeSelection/ConsultingTypeAgencySelection.tsx b/src/components/consultingTypeSelection/ConsultingTypeAgencySelection.tsx index dfb35f333..14b451b57 100644 --- a/src/components/consultingTypeSelection/ConsultingTypeAgencySelection.tsx +++ b/src/components/consultingTypeSelection/ConsultingTypeAgencySelection.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { useEffect, useState } from 'react'; +import { useCallback, useContext, useEffect, useMemo, useState } from 'react'; import { AgencyDataInterface } from '../../globalState'; import './consultingTypeAgencySelection.styles'; import '../profile/profile.styles'; @@ -17,8 +17,10 @@ import { import { Text } from '../text/Text'; import { AgencyLanguages } from '../agencySelection/AgencyLanguages'; import { useTranslation } from 'react-i18next'; -import { useAppConfig } from '../../hooks/useAppConfig'; -import { useConsultantAgenciesAndConsultingTypes } from '../../containers/registration/hooks/useConsultantAgenciesAndConsultingTypes'; +import { useConsultantRegistrationData } from '../../containers/registration/hooks/useConsultantRegistrationData'; +import { apiGetTopicsData } from '../../api/apiGetTopicsData'; +import { useTenant } from '../../globalState'; +import { UrlParamsContext } from '../../globalState/provider/UrlParamsProvider'; export interface ConsultingTypeAgencySelectionProps { onChange: Function; @@ -34,20 +36,66 @@ export const ConsultingTypeAgencySelection = ({ onKeyDown }: ConsultingTypeAgencySelectionProps) => { const { t: translate } = useTranslation(['common', 'consultingTypes']); - const settings = useAppConfig(); + const tenantData = useTenant(); + const { agency: preselectedAgency, topic: preselectedTopic } = + useContext(UrlParamsContext); + const [selectedConsultingTypeOption, setSelectedConsultingTypeOption] = useState(null); + const [selectedTopicOption, setSelectedTopicOption] = + useState(null); const [consultingTypeOptions, setConsultingTypeOptions] = useState< SelectOption[] >([]); const [agencyOptions, setAgencyOptions] = useState( [] ); + const [topicOptions, setTopicOptions] = useState([]); + + const topicsAreRequired = useMemo( + () => + tenantData?.settings?.topicsInRegistrationEnabled && + tenantData?.settings?.featureTopicsEnabled, + [ + tenantData?.settings?.topicsInRegistrationEnabled, + tenantData?.settings?.featureTopicsEnabled + ] + ); const { agencies: possibleAgencies, - consultingTypes: possibleConsultingTypes - } = useConsultantAgenciesAndConsultingTypes(); + consultingTypes: possibleConsultingTypes, + topicIds: possibleTopicIds + } = useConsultantRegistrationData(); + + useEffect(() => { + apiGetTopicsData() + // Filter topic by preselected topic + .then((topics) => + topics.filter( + (t) => !preselectedTopic || preselectedTopic.id === t.id + ) + ) + // Filter topics by consultant topics + .then((topics) => + topics.filter((t) => possibleTopicIds.includes(t.id)) + ) + // Filter topics by preselected agency + .then((topics) => + topics.filter( + (t) => + !preselectedAgency || + preselectedAgency.topicIds?.includes(t.id) + ) + ) + .then((topics) => + topics.map((t) => ({ + value: t.id.toString(), + label: t.name + })) + ) + .then(setTopicOptions); + }, [possibleTopicIds, preselectedAgency, preselectedTopic]); useEffect(() => { const consultingTypeOptions = possibleConsultingTypes.map( @@ -56,6 +104,7 @@ export const ConsultingTypeAgencySelection = ({ label: translate( [ `consultingType.${consultingType.id}.titles.long`, + `consultingType.fallback.titles.long`, consultingType.titles.long ], { ns: 'consultingTypes' } @@ -67,19 +116,21 @@ export const ConsultingTypeAgencySelection = ({ }, [possibleConsultingTypes, translate]); useEffect(() => { - if (!selectedConsultingTypeOption) { + if ( + !selectedConsultingTypeOption || + (topicsAreRequired && !selectedTopicOption) + ) { setAgencyOptions([]); onChange(null); return; } - const agencyOptions = settings.multitenancyWithSingleDomainEnabled - ? possibleAgencies - : possibleAgencies.filter( - (agency) => - agency.consultingType.toString() === - selectedConsultingTypeOption.value - ); + const agencyOptions = possibleAgencies.filter( + (agency) => + agency.consultingType.toString() === + selectedConsultingTypeOption.value && + agency.topicIds.includes(parseInt(selectedTopicOption.value)) + ); setAgencyOptions(agencyOptions); if (agencyOptions.length >= 1) { @@ -89,7 +140,8 @@ export const ConsultingTypeAgencySelection = ({ onChange, possibleAgencies, selectedConsultingTypeOption, - settings.multitenancyWithSingleDomainEnabled + topicsAreRequired, + selectedTopicOption ]); useEffect(() => { @@ -99,6 +151,18 @@ export const ConsultingTypeAgencySelection = ({ onValidityChange(agency ? VALIDITY_VALID : VALIDITY_INVALID); }, [agency]); // eslint-disable-line react-hooks/exhaustive-deps + const handleChange = useCallback( + (agency) => { + onChange({ + ...agency, + ...(topicsAreRequired + ? { topicIds: [parseInt(selectedTopicOption?.value)] } + : {}) + }); + }, + [onChange, selectedTopicOption?.value, topicsAreRequired] + ); + const consultingTypeSelect: SelectDropdownItem = { id: 'consultingTypeSelection', selectedOptions: consultingTypeOptions, @@ -110,12 +174,35 @@ export const ConsultingTypeAgencySelection = ({ defaultValue: selectedConsultingTypeOption }; + const topicSelect: SelectDropdownItem = { + id: 'topicSelection', + selectedOptions: topicOptions, + handleDropdownSelect: setSelectedTopicOption, + selectInputLabel: translate( + 'registration.consultingTypeAgencySelection.topic.select.label' + ), + menuPlacement: 'bottom', + defaultValue: selectedTopicOption + }; + if (possibleAgencies.length <= 1 && possibleConsultingTypes.length <= 1) { return null; } return (
+ {topicOptions.length > 1 && ( +
+ + +
+ )} + {consultingTypeOptions.length > 1 && (
diff --git a/src/components/formAccordion/FormAccordion.tsx b/src/components/formAccordion/FormAccordion.tsx index 150379ffd..0ab3c1b51 100644 --- a/src/components/formAccordion/FormAccordion.tsx +++ b/src/components/formAccordion/FormAccordion.tsx @@ -32,7 +32,7 @@ import { Button, BUTTON_TYPES, ButtonItem } from '../button/Button'; import { FormAccordionRegistrationText } from './FormAccordionRegistrationText'; import { setValueInCookie } from '../sessionCookie/accessSessionCookie'; import { ProposedAgencies } from '../../containers/registration/components/ProposedAgencies/ProposedAgencies'; -import { useConsultantAgenciesAndConsultingTypes } from '../../containers/registration/hooks/useConsultantAgenciesAndConsultingTypes'; +import { useConsultantRegistrationData } from '../../containers/registration/hooks/useConsultantRegistrationData'; import { FormAccordionData } from '../registration/RegistrationForm'; import { UrlParamsContext } from '../../globalState/provider/UrlParamsProvider'; import { TProvidedLegalLink } from '../../globalState/provider/LegalLinksProvider'; @@ -71,7 +71,7 @@ export const FormAccordion = ({ const { setSpecificAgency, specificAgency } = useContext( AgencySpecificContext ); - const { consultingTypes } = useConsultantAgenciesAndConsultingTypes(); + const { consultingTypes } = useConsultantRegistrationData(); const [activeItem, setActiveItem] = useState(1); diff --git a/src/components/login/Login.tsx b/src/components/login/Login.tsx index 2bbb322f7..2f439a12d 100644 --- a/src/components/login/Login.tsx +++ b/src/components/login/Login.tsx @@ -28,8 +28,10 @@ import { RocketChatGlobalSettingsContext, TenantContext, UserDataContext, - UserDataInterface, - LocaleContext + LocaleContext, + useTenant, + AgencyDataInterface, + UserDataInterface } from '../../globalState'; import '../../resources/styles/styles'; import './login.styles'; @@ -60,7 +62,7 @@ import { useSearchParam } from '../../hooks/useSearchParams'; import { getTenantSettings } from '../../utils/tenantSettingsHelper'; import { budibaseLogout } from '../budibase/budibaseLogout'; import { GlobalComponentContext } from '../../globalState/provider/GlobalComponentContext'; -import { useConsultantAgenciesAndConsultingTypes } from '../../containers/registration/hooks/useConsultantAgenciesAndConsultingTypes'; +import { useConsultantRegistrationData } from '../../containers/registration/hooks/useConsultantRegistrationData'; import { UrlParamsContext } from '../../globalState/provider/UrlParamsProvider'; const regexAccountDeletedError = /account disabled/i; @@ -69,6 +71,7 @@ export const Login = () => { const settings = useAppConfig(); const { t: translate } = useTranslation(); const history = useHistory(); + const tenantData = useTenant(); const { locale, initLocale } = useContext(LocaleContext); const { tenant } = useContext(TenantContext); @@ -134,7 +137,7 @@ export const Login = () => { } }, [featureToolsEnabled, gcid]); - const [agency, setAgency] = useState(null); + const [agency, setAgency] = useState(null); const [validity, setValidity] = useState(VALIDITY_INITIAL); const [registerOverlayActive, setRegisterOverlayActive] = useState(false); const [pwResetOverlayActive, setPwResetOverlayActive] = useState(false); @@ -191,8 +194,9 @@ export const Login = () => { const { agencies: possibleAgencies, - consultingTypes: possibleConsultingTypes - } = useConsultantAgenciesAndConsultingTypes(); + consultingTypes: possibleConsultingTypes, + topicIds: possibleTopicIds + } = useConsultantRegistrationData(); const registerOverlay = useMemo( (): OverlayItem => ({ @@ -229,7 +233,8 @@ export const Login = () => { agency.consultingTypeRel.id, agency.id, agency.postcode, - consultantId + consultantId, + agency.topicIds ) .catch((response) => response.json()) .then((response) => { @@ -288,15 +293,31 @@ export const Login = () => { [locale] ); + const topicsAreRequired = useMemo( + () => + tenantData?.settings?.topicsInRegistrationEnabled && + tenantData?.settings?.featureTopicsEnabled, + [ + tenantData?.settings?.topicsInRegistrationEnabled, + tenantData?.settings?.featureTopicsEnabled + ] + ); + useEffect(() => { if ( possibleAgencies.length === 1 && - possibleConsultingTypes.length === 1 + possibleConsultingTypes.length === 1 && + (!topicsAreRequired || possibleTopicIds.length === 1) ) { setAgency(possibleAgencies[0]); setValidity(VALIDITY_VALID); } - }, [possibleAgencies, possibleConsultingTypes]); + }, [ + possibleAgencies, + possibleConsultingTypes, + possibleTopicIds.length, + topicsAreRequired + ]); useEffect(() => { deleteCookieByName('tenantId'); @@ -334,22 +355,28 @@ export const Login = () => { if ( possibleAgencies.length === 1 && - possibleConsultingTypes.length === 1 + possibleConsultingTypes.length === 1 && + (!topicsAreRequired || possibleTopicIds.length === 1) ) { - handleRegistration(possibleAgencies[0]); + handleRegistration({ + ...possibleAgencies[0], + topicIds: possibleTopicIds + }); } else { setRegisterOverlayActive(true); } }), [ + reloadUserData, locale, initLocale, consultant, possibleAgencies, possibleConsultingTypes.length, - reloadUserData, - handleRegistration, - gcid + topicsAreRequired, + possibleTopicIds, + gcid, + handleRegistration ] ); diff --git a/src/components/mainTopicSelection/MainTopicSelection.tsx b/src/components/mainTopicSelection/MainTopicSelection.tsx index a66c112af..771e19ef0 100644 --- a/src/components/mainTopicSelection/MainTopicSelection.tsx +++ b/src/components/mainTopicSelection/MainTopicSelection.tsx @@ -1,4 +1,4 @@ -import React, { useCallback } from 'react'; +import React, { useCallback, useContext, useMemo } from 'react'; import { useEffect, useState } from 'react'; import './MainTopicSelection.styles'; import { apiGetTopicsData } from '../../api/apiGetTopicsData'; @@ -10,6 +10,7 @@ import { } from '../registration/registrationHelpers'; import { useTranslation } from 'react-i18next'; import { TopicsDataInterface } from '../../globalState/interfaces/TopicsDataInterface'; +import { UrlParamsContext } from '../../globalState/provider/UrlParamsProvider'; export interface MainTopicSelectionProps { name: string; @@ -26,13 +27,34 @@ export const MainTopicSelection = ({ }: MainTopicSelectionProps) => { const { t: translate } = useTranslation(); - const [topics, setTopics] = useState([]); + const { agency, consultant, topic } = useContext(UrlParamsContext); + + const [loadedTopics, setLoadedTopics] = useState([]); const [isTouched, setIsTouched] = useState(false); useEffect(() => { - apiGetTopicsData().then((data) => setTopics(data)); + apiGetTopicsData().then(setLoadedTopics); }, []); + /* Handle url parameter preselection logic */ + const topics = useMemo( + () => + loadedTopics + // Filter topic by preselected topic + .filter((t) => !topic || t.id === topic?.id) + // Filter topics by consultant topics + .filter( + (t) => + !consultant || + consultant.agencies.some((a) => + a.topicIds?.includes(t.id) + ) + ) + // Filter topics by preselected agency + .filter((t) => !agency || agency.topicIds?.includes(t.id)), + [loadedTopics, topic, consultant, agency] + ); + useEffect(() => { if (!isTouched) return; @@ -47,6 +69,15 @@ export const MainTopicSelection = ({ [onChange] ); + useEffect(() => { + if ( + topics.length === 1 && + (!value || !topics.some((t) => t.id === value.id)) + ) { + handleChange(topics[0]); + } + }, [topics, handleChange, value]); + // If options change, check for still valid preselected topic useEffect(() => { if (!value || topics.some((t) => t.id === value.id)) { diff --git a/src/components/registration/Registration.tsx b/src/components/registration/Registration.tsx index 35bf44644..c6ecc0ae5 100644 --- a/src/components/registration/Registration.tsx +++ b/src/components/registration/Registration.tsx @@ -13,16 +13,9 @@ import useIsFirstVisit from '../../utils/useIsFirstVisit'; import { useTranslation } from 'react-i18next'; import { GlobalComponentContext } from '../../globalState/provider/GlobalComponentContext'; import { UrlParamsContext } from '../../globalState/provider/UrlParamsProvider'; +import { useAppConfig } from '../../hooks/useAppConfig'; -interface RegistrationProps { - handleUnmatchConsultingType: Function; - handleUnmatchConsultant: Function; -} - -export const Registration = ({ - handleUnmatchConsultingType, - handleUnmatchConsultant -}: RegistrationProps) => { +export const Registration = () => { const { t: translate } = useTranslation([ 'common', 'consultingTypes', @@ -34,6 +27,7 @@ export const Registration = ({ const agencyId = getUrlParameter('aid'); const consultantId = getUrlParameter('cid'); const postcodeParameter = getUrlParameter('postcode'); + const settings = useAppConfig(); const { setInformal } = useContext(InformalContext); const { Stage } = useContext(GlobalComponentContext); @@ -46,8 +40,9 @@ export const Registration = ({ .map(([key, value]) => `${key}=${value}`) .join('&'); - const [showWelcomeScreen, setShowWelcomeScreen] = - useState(!postcodeParameter); + const [showWelcomeScreen, setShowWelcomeScreen] = useState( + postcodeParameter === null + ); const [isReady, setIsReady] = useState(false); @@ -56,7 +51,7 @@ export const Registration = ({ window.scrollTo({ top: 0 }); }; - const { agency, consultingType, consultant, loaded } = + const { agency, consultingType, consultant, topic, loaded } = useContext(UrlParamsContext); useEffect(() => { @@ -64,22 +59,16 @@ export const Registration = ({ return; } - if (!consultingType && !agency && !consultant) { + if (!consultingType && !agency && !consultant && !topic) { console.error( - 'No `consultingType`, `consultant` or `agency` found in URL.' + 'No `consultingType`, `consultant`, `agency` or `topic` found in URL.' ); + window.location.href = settings.urls.toRegistration; return; } try { - if (consultantId) { - if (!consultant) { - handleUnmatchConsultant(); - throw new Error( - `Unknown consultant with id ${consultantId}` - ); - } - + if (consultant) { // If all consultant agencies are informal then use informal const isInformal = consultant.agencies.every( (agency) => !agency.consultingTypeRel.languageFormal @@ -102,18 +91,6 @@ export const Registration = ({ )}`; } } else { - if (!consultingType) { - handleUnmatchConsultingType(); - throw new Error( - agency - ? `Unknown consulting type with agency ${translate( - [`agency.${agency.id}.name`, agency.name], - { ns: 'agencies' } - )}` - : `Unknown consulting type with slug ${consultingTypeSlug}` - ); - } - if ( consultingType.urls?.requiredAidMissingRedirectUrl && !agency @@ -146,12 +123,11 @@ export const Registration = ({ agency, consultant, loaded, - consultantId, - handleUnmatchConsultant, - handleUnmatchConsultingType, consultingTypeSlug, translate, - setInformal + setInformal, + settings.urls.toRegistration, + topic ]); const isFirstVisit = useIsFirstVisit(); diff --git a/src/components/registration/RegistrationForm.tsx b/src/components/registration/RegistrationForm.tsx index 7c5afa28b..52b541c2e 100644 --- a/src/components/registration/RegistrationForm.tsx +++ b/src/components/registration/RegistrationForm.tsx @@ -13,6 +13,7 @@ import { TenantContext, useLocaleData } from '../../globalState'; +import { TopicsDataInterface } from '../../globalState/interfaces/TopicsDataInterface'; import { FormAccordion } from '../formAccordion/FormAccordion'; import { ReactComponent as WelcomeIcon } from '../../resources/img/illustrations/welcome.svg'; import './registrationForm.styles'; @@ -27,7 +28,6 @@ import { getTenantSettings } from '../../utils/tenantSettingsHelper'; import { budibaseLogout } from '../budibase/budibaseLogout'; import { getUrlParameter } from '../../utils/getUrlParameter'; import { UrlParamsContext } from '../../globalState/provider/UrlParamsProvider'; -import { TopicsDataInterface } from '../../globalState/interfaces/TopicsDataInterface'; import { ConsultingTypeRegistrationDefaults } from '../../containers/registration/components/ProposedAgencies/ProposedAgencies'; import { apiPostError, ERROR_LEVEL_ERROR } from '../../api/apiPostError'; @@ -49,7 +49,7 @@ export const RegistrationForm = () => { const { locale } = useLocaleData(); const settings = useAppConfig(); const postcode = getUrlParameter('postcode'); - const { agency, consultingType, consultant, topic } = + const { agency, consultingType, consultant, topic, slugFallback } = useContext(UrlParamsContext); const [formAccordionData, setFormAccordionData] = @@ -58,13 +58,18 @@ export const RegistrationForm = () => { agency: agency || null, consultingType: consultingType || null, mainTopic: topic || null, - postcode: postcode || null + postcode: postcode }; const { autoSelectPostcode } = consultingType?.registration || ConsultingTypeRegistrationDefaults; - if (consultingType && agency && !postcode && autoSelectPostcode) { + if ( + consultingType && + agency && + postcode === null && + autoSelectPostcode + ) { initData.postcode = agency.postcode; } @@ -118,6 +123,10 @@ export const RegistrationForm = () => { setIsUsernameAlreadyInUse(false); setIsSubmitButtonDisabled(true); + const { autoSelectPostcode } = + formAccordionData.consultingType?.registration || + ConsultingTypeRegistrationDefaults; + const registrationData = { username: formAccordionData.username, password: encodeURIComponent(formAccordionData.password), @@ -129,7 +138,14 @@ export const RegistrationForm = () => { preferredLanguage: locale, ...(formAccordionData.state && { state: formAccordionData.state }), ...(formAccordionData.age && { age: formAccordionData.age }), - ...(consultant && { consultantId: consultant.consultantId }) + ...(consultant && { consultantId: consultant.consultantId }), + ...(slugFallback && { + consultingType: + formAccordionData.agency.consultingTypeRel?.id?.toString(), + postcode: autoSelectPostcode + ? formAccordionData.agency.postcode + : formAccordionData.postcode + }) }; const missingFields = [ diff --git a/src/components/serviceExplanation/ServiceExplanation.tsx b/src/components/serviceExplanation/ServiceExplanation.tsx index b968bea91..f04e983f5 100644 --- a/src/components/serviceExplanation/ServiceExplanation.tsx +++ b/src/components/serviceExplanation/ServiceExplanation.tsx @@ -44,7 +44,8 @@ export const ServiceExplanation = ({ title: translate( [ `consultingType.${consultingTypeId}.welcomeScreen.anonymous.title`, - welcomeScreenConfig?.anonymous.title ?? + `consultingType.fallback.welcomeScreen.anonymous.title`, + welcomeScreenConfig?.anonymous.title || 'registration.welcomeScreen.info4.title' ], { ns: ['consultingTypes', 'common'] } @@ -52,7 +53,8 @@ export const ServiceExplanation = ({ text: translate( [ `consultingType.${consultingTypeId}.welcomeScreen.anonymous.text`, - welcomeScreenConfig?.anonymous.text ?? + `consultingType.fallback.welcomeScreen.anonymous.text`, + welcomeScreenConfig?.anonymous.text || 'registration.welcomeScreen.info4.text' ], { ns: ['consultingTypes', 'common'] } diff --git a/src/components/waitingRoom/WaitingRoomLoader.tsx b/src/components/waitingRoom/WaitingRoomLoader.tsx index 4ba3a61ab..280d00312 100644 --- a/src/components/waitingRoom/WaitingRoomLoader.tsx +++ b/src/components/waitingRoom/WaitingRoomLoader.tsx @@ -1,18 +1,19 @@ import * as React from 'react'; -import { useEffect, useState } from 'react'; -import { useParams } from 'react-router-dom'; +import { useCallback, useEffect, useState } from 'react'; +import { useHistory, useParams } from 'react-router-dom'; import { apiGetConsultingType } from '../../api'; import { WaitingRoom } from '../waitingRoom/WaitingRoom'; +import { useAppConfig } from '../../hooks/useAppConfig'; export interface WaitingRoomLoaderProps { - handleUnmatch: () => void; onAnonymousRegistration: Function; } export const WaitingRoomLoader = ({ - handleUnmatch, onAnonymousRegistration }: WaitingRoomLoaderProps) => { + const history = useHistory(); + const settings = useAppConfig(); const [isAnonymousConversationAllowed, setIsAnonymousConversationAllowed] = useState(); const { consultingTypeSlug } = useParams<{ @@ -20,16 +21,20 @@ export const WaitingRoomLoader = ({ }>(); const [consultingTypeId, setConsultingTypeId] = useState(); + const handleUnmatched = useCallback(() => { + history.push(settings.urls.toLogin); + }, [history, settings.urls.toLogin]); + useEffect(() => { apiGetConsultingType({ consultingTypeSlug }).then((result) => { if (result?.isAnonymousConversationAllowed) { setConsultingTypeId(result.id); setIsAnonymousConversationAllowed(true); } else { - handleUnmatch(); + handleUnmatched(); } }); - }, [consultingTypeSlug, handleUnmatch]); + }, [consultingTypeSlug, handleUnmatched]); if (isAnonymousConversationAllowed) { return ( diff --git a/src/containers/registration/components/ProposedAgencies/ProposedAgencies.tsx b/src/containers/registration/components/ProposedAgencies/ProposedAgencies.tsx index 1e3863354..4d798849b 100644 --- a/src/containers/registration/components/ProposedAgencies/ProposedAgencies.tsx +++ b/src/containers/registration/components/ProposedAgencies/ProposedAgencies.tsx @@ -45,7 +45,8 @@ export const ProposedAgencies = ({ }: ProposedAgenciesProps) => { const { t } = useTranslation(); - const { agency: preSelectedAgency } = useContext(UrlParamsContext); + const { agency: preSelectedAgency, slugFallback } = + useContext(UrlParamsContext); const [isTouched, setIsTouched] = useState(false); @@ -79,19 +80,21 @@ export const ProposedAgencies = ({ const handleAgencyChange = useCallback( (agency: AgencyDataInterface, isTouched = true) => { handleChange( - { - agency, - consultingType: consultingTypes.find( - (ct) => ct.id === agency?.consultingType - ), - ...(autoSelectPostcode - ? { postcode: agency?.postcode } - : {}) - }, + slugFallback + ? { + agency + } + : { + agency, + consultingType: agency?.consultingTypeRel, + ...(autoSelectPostcode + ? { postcode: agency?.postcode } + : {}) + }, isTouched ); }, - [autoSelectPostcode, consultingTypes, handleChange] + [autoSelectPostcode, handleChange, slugFallback] ); // If options change, check for still valid preselected agency @@ -119,14 +122,13 @@ export const ProposedAgencies = ({ agencies, autoSelectAgency, formAccordionData.agency, - onChange, - handleAgencyChange, - preSelectedAgency + handleAgencyChange ]); // If options change, check for still valid consulting type or select first one useEffect(() => { if ( + slugFallback || (formAccordionData.consultingType && consultingTypes.some( (ct) => ct.id === formAccordionData.consultingType.id @@ -137,7 +139,12 @@ export const ProposedAgencies = ({ } return onChange({ consultingType: consultingTypes?.[0] || null }); - }, [consultingTypes, formAccordionData.consultingType, onChange]); + }, [ + consultingTypes, + formAccordionData.consultingType, + onChange, + slugFallback + ]); // Validate form if there are no changeable fields or changeable fields and they are touched useEffect(() => { diff --git a/src/containers/registration/hooks/useAgenciesForRegistration.ts b/src/containers/registration/hooks/useAgenciesForRegistration.ts index 322ef7e9b..89fd182db 100644 --- a/src/containers/registration/hooks/useAgenciesForRegistration.ts +++ b/src/containers/registration/hooks/useAgenciesForRegistration.ts @@ -2,15 +2,15 @@ import unionBy from 'lodash/unionBy'; import { useContext, useEffect, useMemo, useState } from 'react'; import { apiAgencySelection } from '../../../api'; import { DEFAULT_POSTCODE } from '../../../components/registration/prefillPostcode'; +import { TopicsDataInterface } from '../../../globalState/interfaces/TopicsDataInterface'; import { AgencyDataInterface, ConsultingTypeInterface, useTenant } from '../../../globalState'; -import { useConsultantAgenciesAndConsultingTypes } from './useConsultantAgenciesAndConsultingTypes'; +import { useConsultantRegistrationData } from './useConsultantRegistrationData'; import { ConsultingTypeRegistrationDefaults } from '../components/ProposedAgencies/ProposedAgencies'; import { UrlParamsContext } from '../../../globalState/provider/UrlParamsProvider'; -import { TopicsDataInterface } from '../../../globalState/interfaces/TopicsDataInterface'; interface AgenciesForRegistrationArgs { consultingType: ConsultingTypeInterface; @@ -28,30 +28,42 @@ export const useAgenciesForRegistration = ({ } => { const tenantData = useTenant(); + const { + consultant, + agency: preselectedAgency, + consultingType: preselectedConsultingType, + slugFallback + } = useContext(UrlParamsContext); + const { agencies: consultantAgencies, consultingTypes: consultantConsultingTypes - } = useConsultantAgenciesAndConsultingTypes(); + } = useConsultantRegistrationData(); const [isLoading, setIsLoading] = useState(true); const [agencies, setAgencies] = useState([]); - const { - consultant, - agency, - consultingType: preselectedConsultingType - } = useContext(UrlParamsContext); const { autoSelectPostcode, autoSelectAgency } = consultingType?.registration || ConsultingTypeRegistrationDefaults; + const topicsEnabledAndUnSelected = useMemo( + () => + tenantData?.settings?.featureTopicsEnabled && + tenantData?.settings?.topicsInRegistrationEnabled && + topic?.id === undefined, + [tenantData?.settings, topic?.id] + ); + const allAgencies = useMemo(() => { - // As long as no consulting type is selected we can't show any agencies - if (!consultingType) { + // As long as no consulting type or topic is selected we can't show any agencies + if (!consultingType || topicsEnabledAndUnSelected) { return []; } let uniqueAgencies = unionBy( - [agency, ...agencies, ...consultantAgencies].filter(Boolean), + [preselectedAgency, ...agencies, ...consultantAgencies].filter( + Boolean + ), 'id' ); @@ -61,22 +73,31 @@ export const useAgenciesForRegistration = ({ (agency) => !agency.external ); } - if (consultingType) { - uniqueAgencies = uniqueAgencies.filter( - (agency) => agency.consultingType === consultingType.id + + uniqueAgencies = uniqueAgencies + // Filter by preselected agency + + // Filter by consultingType + .filter( + (agency) => + slugFallback || + !consultingType || + agency.consultingType === consultingType.id ); - } + if (autoSelectAgency && uniqueAgencies.length > 0) { uniqueAgencies = [uniqueAgencies[0]]; } return uniqueAgencies; }, [ - agency, + preselectedAgency, + topicsEnabledAndUnSelected, agencies, consultantAgencies, consultingType, autoSelectPostcode, - autoSelectAgency + autoSelectAgency, + slugFallback ]); const allConsultingTypes = useMemo( @@ -95,13 +116,7 @@ export const useAgenciesForRegistration = ({ useEffect(() => { const abortController = new AbortController(); // if we already have information from consulting types we can ignore the request - if ( - consultant || - agency || - (tenantData?.settings?.featureTopicsEnabled && - tenantData?.settings?.topicsInRegistrationEnabled && - topic?.id === undefined) - ) { + if (consultant || preselectedAgency || topicsEnabledAndUnSelected) { setIsLoading(false); return; } @@ -111,7 +126,8 @@ export const useAgenciesForRegistration = ({ { postcode: autoSelectPostcode ? DEFAULT_POSTCODE : postcode, consultingType: consultingType?.id, - topicId: topic?.id + topicId: topic?.id, + fetchConsultingTypeDetails: true }, abortController.signal ) @@ -129,13 +145,13 @@ export const useAgenciesForRegistration = ({ abortController?.abort(); }; }, [ - agency, + preselectedAgency, autoSelectPostcode, consultant, consultingType?.id, topic?.id, postcode, - tenantData?.settings + topicsEnabledAndUnSelected ]); return { diff --git a/src/containers/registration/hooks/useConsultantAgenciesAndConsultingTypes.ts b/src/containers/registration/hooks/useConsultantAgenciesAndConsultingTypes.ts deleted file mode 100644 index 0cb4c7053..000000000 --- a/src/containers/registration/hooks/useConsultantAgenciesAndConsultingTypes.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { useState, useEffect, useContext } from 'react'; -import unionBy from 'lodash/unionBy'; - -import { - ConsultingTypeInterface, - AgencyDataInterface -} from '../../../globalState'; -import { useAppConfig } from '../../../hooks/useAppConfig'; -import { UrlParamsContext } from '../../../globalState/provider/UrlParamsProvider'; - -export const useConsultantAgenciesAndConsultingTypes = () => { - const settings = useAppConfig(); - const { consultingType, consultant, agency } = useContext(UrlParamsContext); - - const [consultingTypes, setConsultingTypes] = useState< - ConsultingTypeInterface[] - >([]); - - const [agencies, setAgencies] = useState([]); - - useEffect(() => { - if (!consultant) { - return; - } - - // When we've the multi tenancy with single domain we can simply ignore the - // consulting types because we'll get agencies across tenants - // ToDo: This logic breaks consultant direct links with multiple consulting types - if ( - settings.multitenancyWithSingleDomainEnabled && - consultant?.agencies?.length > 0 - ) { - setAgencies(consultant?.agencies); - setConsultingTypes([consultingType]); - return; - } - - const consultingTypes = - // Remove consultingType duplicates - unionBy( - consultant.agencies.map( - ({ consultingTypeRel }) => consultingTypeRel - ), - 'id' - ) - // If consultingType was preselected by url slug - .filter((c) => !consultingType || c.id === consultingType.id); - - if (agency) { - const consultingTypeIds = consultingTypes.map((c) => c.id); - const preselectedAgency = consultant.agencies.find( - (a) => - a.id === agency.id && - consultingTypeIds.includes(a.consultingType) - ); - if (preselectedAgency) { - setAgencies([preselectedAgency]); - setConsultingTypes([preselectedAgency.consultingTypeRel]); - return; - } - } - - const possibleAgencies = consultant.agencies - // If a consultingType is selected filter the agencies - .filter((agency) => - consultingTypes.find((ct) => ct.id === agency.consultingType) - ); - - setAgencies(possibleAgencies); - setConsultingTypes(consultingTypes); - }, [ - consultant, - consultingType, - agency, - settings.multitenancyWithSingleDomainEnabled - ]); - - return { agencies, consultingTypes }; -}; diff --git a/src/containers/registration/hooks/useConsultantRegistrationData.ts b/src/containers/registration/hooks/useConsultantRegistrationData.ts new file mode 100644 index 000000000..a80a856d2 --- /dev/null +++ b/src/containers/registration/hooks/useConsultantRegistrationData.ts @@ -0,0 +1,118 @@ +import { useState, useEffect, useContext, useMemo } from 'react'; +import unionBy from 'lodash/unionBy'; + +import { + ConsultingTypeInterface, + AgencyDataInterface +} from '../../../globalState'; +import { useAppConfig } from '../../../hooks/useAppConfig'; +import { UrlParamsContext } from '../../../globalState/provider/UrlParamsProvider'; + +export const useConsultantRegistrationData = () => { + const settings = useAppConfig(); + const { + consultingType: preselectedConsultingType, + consultant, + agency: preselectedAgency, + topic: preselectedTopic, + slugFallback + } = useContext(UrlParamsContext); + + const [consultingTypes, setConsultingTypes] = useState< + ConsultingTypeInterface[] + >([]); + const [agencies, setAgencies] = useState([]); + + const topicIds = useMemo( + () => [ + ...new Set( + agencies + .reduce( + (topicIds, agency) => + topicIds.concat(agency?.topicIds || []), + [] + ) + // Filter topic by preselected topic + .filter( + (tid) => + !preselectedTopic || tid === preselectedTopic?.id + ) + // Filter topics by consultant topics + .filter( + (tid) => + !consultant || + consultant.agencies.some((a) => + a.topicIds?.includes(tid) + ) + ) + // Filter topics by preselected agency + .filter( + (tid) => + !preselectedAgency || + preselectedAgency.topicIds?.includes(tid) + ) + ) + ], + [agencies, consultant, preselectedAgency, preselectedTopic] + ); + + useEffect(() => { + if (!consultant) { + return; + } + + const consultingTypes = + // Remove consultingType duplicates + unionBy( + consultant.agencies.map( + ({ consultingTypeRel }) => consultingTypeRel + ), + 'id' + ) + // Filter consultingTypes by preselected consultingType + .filter( + (c) => + !preselectedConsultingType || + (slugFallback + ? c.slug === slugFallback + : c.id === preselectedConsultingType.id) + ); + if (preselectedAgency) { + setAgencies([preselectedAgency]); + setConsultingTypes([preselectedAgency.consultingTypeRel]); + return; + } + + const consultingTypeIds = consultingTypes.map((c) => c.id); + const possibleAgencies = consultant.agencies + // If a consultingType or topic is selected filter the agencies + .filter((agency) => + consultingTypeIds.includes(agency.consultingType) + ) + // Filter agencies by preselected topic + .filter( + (a) => + !preselectedTopic || + a.topicIds?.includes(preselectedTopic?.id) + ) + // Filter agencies by preselected agency + .filter((a) => !preselectedAgency || preselectedAgency.id === a.id); + setAgencies(possibleAgencies); + setConsultingTypes( + slugFallback + ? [preselectedConsultingType || consultingTypes.pop()].filter( + Boolean + ) + : consultingTypes + ); + }, [ + consultant, + preselectedConsultingType, + preselectedAgency, + preselectedTopic, + settings.multitenancyWithSingleDomainEnabled, + slugFallback + ]); + + return { agencies, consultingTypes, topicIds }; +}; diff --git a/src/globalState/interfaces/AppConfig/AppConfigInterface.ts b/src/globalState/interfaces/AppConfig/AppConfigInterface.ts index 880bcac39..c62399257 100644 --- a/src/globalState/interfaces/AppConfig/AppConfigInterface.ts +++ b/src/globalState/interfaces/AppConfig/AppConfigInterface.ts @@ -31,11 +31,7 @@ export interface AppConfigInterface extends AppSettingsInterface { }; groupChat?: GroupChatConfig; registration?: { - directlink?: { - fallbackLoader?: { - enabled?: boolean; - }; - }; + useConsultingTypeSlug?: boolean; }; } diff --git a/src/globalState/interfaces/UserDataInterface.ts b/src/globalState/interfaces/UserDataInterface.ts index 1bd2d0112..944d03496 100644 --- a/src/globalState/interfaces/UserDataInterface.ts +++ b/src/globalState/interfaces/UserDataInterface.ts @@ -35,9 +35,7 @@ export interface UserDataInterface { export interface ConsultantDataInterface extends Omit { consultantId: string; - agencies: (AgencyDataInterface & { - consultingTypeRel?: ConsultingTypeInterface; - })[]; + agencies: AgencyDataInterface[]; } export interface AgencyDataInterface { @@ -53,6 +51,8 @@ export interface AgencyDataInterface { external?: boolean; tenantId?: number; agencySpecificPrivacy?: string; + consultingTypeRel?: ConsultingTypeInterface; + topicIds?: number[]; } export interface ConsultingTypeDataInterface { diff --git a/src/globalState/provider/AgencySpecificProvider.tsx b/src/globalState/provider/AgencySpecificProvider.tsx index a5aba8b3d..9e2715e7a 100644 --- a/src/globalState/provider/AgencySpecificProvider.tsx +++ b/src/globalState/provider/AgencySpecificProvider.tsx @@ -8,7 +8,7 @@ import { useEffect } from 'react'; import { UserDataContext } from '../context/UserDataContext'; -import { AgencyDataInterface } from '../interfaces/UserDataInterface'; +import { AgencyDataInterface } from '..'; import useUrlParamsLoader from '../../utils/useUrlParamsLoader'; export const AgencySpecificContext = createContext<{ diff --git a/src/globalState/provider/UrlParamsProvider.tsx b/src/globalState/provider/UrlParamsProvider.tsx index faa7cd84d..8810b370b 100644 --- a/src/globalState/provider/UrlParamsProvider.tsx +++ b/src/globalState/provider/UrlParamsProvider.tsx @@ -1,11 +1,17 @@ -import React, { createContext, FC } from 'react'; +import React, { + createContext, + PropsWithChildren, + useCallback, + useMemo +} from 'react'; import { AgencyDataInterface, ConsultantDataInterface, ConsultingTypeInterface } from '..'; -import useUrlParamsLoader from '../../utils/useUrlParamsLoader'; import { TopicsDataInterface } from '../interfaces/TopicsDataInterface'; +import useUrlParamsLoader from '../../utils/useUrlParamsLoader'; +import { useAppConfig } from '../../hooks/useAppConfig'; export const UrlParamsContext = createContext<{ agency: AgencyDataInterface | null; @@ -13,22 +19,39 @@ export const UrlParamsContext = createContext<{ consultant: ConsultantDataInterface | null; topic: TopicsDataInterface | null; loaded: boolean; + slugFallback: string; }>({ agency: null, consultingType: null, consultant: null, topic: null, - loaded: false + loaded: false, + slugFallback: undefined }); -export const UrlParamsProvider: FC = ({ children }) => { - const { agency, consultingType, consultant, topic, loaded } = - useUrlParamsLoader(); +export const UrlParamsProvider = ({ children }: PropsWithChildren<{}>) => { + const settings = useAppConfig(); + const handleBadRequest = useCallback( + () => (document.location.href = settings.urls.toRegistration), + [settings.urls.toRegistration] + ); + const { agency, consultingType, consultant, topic, loaded, slugFallback } = + useUrlParamsLoader(handleBadRequest); + + const context = useMemo( + () => ({ + agency, + consultingType, + consultant, + topic, + loaded, + slugFallback + }), + [agency, consultingType, consultant, topic, loaded, slugFallback] + ); return ( - + {children} ); diff --git a/src/i18n.ts b/src/i18n.ts index 37c35b5e4..b9fc10fdb 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -209,6 +209,10 @@ export const init = async ( config ?? {} ), () => { + if ((window as any).Cypress) { + (window as any).i18n = i18n; + } + if ( (localStorage.getItem( STORAGE_KEY_ENABLE_TRANSLATION_CHECK diff --git a/src/utils/getUrlParameter.ts b/src/utils/getUrlParameter.ts index 20f29be6f..4f9ab233b 100644 --- a/src/utils/getUrlParameter.ts +++ b/src/utils/getUrlParameter.ts @@ -1,9 +1,10 @@ -export const getUrlParameter = (name: string) => { +export const getUrlParameter = ( + name: string, + fallback: string = null +): string => { name = name.replace(/[[]/, '\\[').replace(/[\]]/, '\\]'); - let regex = new RegExp('[\\?&]' + name + '=([^&#]*)', 'i'); - // eslint-disable-next-line no-restricted-globals - let results = regex.exec(location.search); - return results === null - ? '' - : decodeURIComponent(results[1].replace(/\+/g, ' ')); + const url = new URL(window.location.href); + return url.searchParams.has(name) + ? decodeURIComponent(url.searchParams.get(name).replace(/\+/g, ' ')) + : fallback; }; diff --git a/src/utils/loadConsultingTypeForAgency.ts b/src/utils/loadConsultingTypeForAgency.ts new file mode 100644 index 000000000..817561640 --- /dev/null +++ b/src/utils/loadConsultingTypeForAgency.ts @@ -0,0 +1,11 @@ +import { apiGetConsultingType } from '../api'; +import { AgencyDataInterface } from '../globalState'; + +export const loadConsultingTypeForAgency = async ( + agency: AgencyDataInterface +): Promise => ({ + ...agency, + consultingTypeRel: await apiGetConsultingType({ + consultingTypeId: agency?.consultingType + }) +}); diff --git a/src/utils/useTenantTheming.ts b/src/utils/useTenantTheming.ts index 5c7b6e7e1..47729937f 100644 --- a/src/utils/useTenantTheming.ts +++ b/src/utils/useTenantTheming.ts @@ -1,4 +1,4 @@ -import { useCallback, useContext, useEffect, useState } from 'react'; +import { useCallback, useContext, useEffect, useMemo, useState } from 'react'; import { apiGetTenantTheming } from '../api/apiGetTenantTheming'; import { TenantContext, useLocaleData } from '../globalState'; import { TenantDataInterface } from '../globalState/interfaces/TenantDataInterface'; @@ -227,9 +227,14 @@ const useTenantTheming = () => { settings.useTenantService ); + const cypressTenantEnabled = useMemo( + () => (window as any).Cypress?.env('TENANT_ENABLED'), + [] + ); + const onTenantServiceResponse = useCallback( (tenant: TenantDataInterface) => { - if (!subdomain) { + if (!subdomain && cypressTenantEnabled !== '1') { tenantContext?.setTenant({ settings } as any); } else { // ToDo: See VIC-428 + VIC-427 @@ -247,7 +252,7 @@ const useTenantTheming = () => { } return; }, - [settings, subdomain, tenantContext] + [settings, subdomain, tenantContext, cypressTenantEnabled] ); useEffect(() => { diff --git a/src/utils/useUrlParamsLoader.tsx b/src/utils/useUrlParamsLoader.tsx index 1cb38401f..1ce0a4552 100644 --- a/src/utils/useUrlParamsLoader.tsx +++ b/src/utils/useUrlParamsLoader.tsx @@ -1,22 +1,22 @@ -import { useState, useEffect, useContext } from 'react'; +import { useState, useEffect, useContext, useCallback } from 'react'; import { useParams } from 'react-router-dom'; import { getUrlParameter } from './getUrlParameter'; +import { TopicsDataInterface } from '../globalState/interfaces/TopicsDataInterface'; import { AgencyDataInterface, ConsultantDataInterface, - ConsultingTypeInterface + ConsultingTypeInterface, + LocaleContext } from '../globalState'; -import { LocaleContext } from '../globalState/context/LocaleContext'; import { apiGetAgencyById, apiGetConsultingType } from '../api'; import { apiGetConsultant } from '../api/apiGetConsultant'; import { isNumber } from './isNumber'; -import { TopicsDataInterface } from '../globalState/interfaces/TopicsDataInterface'; import { apiGetTopicById } from '../api/apiGetTopicId'; import { useAppConfig } from '../hooks/useAppConfig'; import { isString } from 'lodash'; import { apiGetTopicsData } from '../api/apiGetTopicsData'; -export default function useUrlParamsLoader() { +export default function useUrlParamsLoader(handleBadRequest?: () => void) { const { setLocale } = useContext(LocaleContext); const { consultingTypeSlug } = useParams<{ consultingTypeSlug: string; @@ -34,15 +34,121 @@ export default function useUrlParamsLoader() { useState(null); const [loaded, setLoaded] = useState(false); const [topic, setTopic] = useState(null); + const [slugFallback, setSlugFallback] = useState(); + + const loadTopic = useCallback( + async (agency) => { + let topic = null; + if (isNumber(topicIdOrName)) { + topic = await apiGetTopicById(topicIdOrName).catch(() => null); + } else if (isString(topicIdOrName)) { + topic = await apiGetTopicsData() + .then( + (allTopics) => + allTopics.find( + (topic) => + topic.name?.toLowerCase() === + decodeURIComponent( + topicIdOrName.toLowerCase() + ) + ) || null + ) + .catch(() => null); + } + + if (!topic || !agency) { + return [agency, topic]; + } + + // If agency is preselected but did not fit the topic preselection set it to null + if (!agency.topicIds.includes(topic.id)) { + return [null, topic]; + } + + return [agency, topic]; + }, + [topicIdOrName] + ); + + const handleConsultant = useCallback( + async (agency, consultingType, topic) => { + const consultant = await apiGetConsultant(consultantId, true).catch( + () => null + ); + + if (!consultant) { + return [agency, consultingType, topic, null]; + } + + // If the agency does not match the consultant's agency, set the agency to null + if ( + agency && + !consultant.agencies.some((a) => a.id === agency?.id) + ) { + agency = null; + } + + // If the topic does not match the consultant's agency topics, set the topic to null + if ( + topic && + !consultant.agencies.some((a) => a.topicIds.includes(topic?.id)) + ) { + topic = null; + } + + // If the consultant agency consulting types does not match the consulting type, we'll set the consulting type to null + // If the agency is invalid and set to null already the consulting type was loaded by the agency. If the consultant + // has switched to another agency with the same consulting type this will not be catched by this conditions + // and the consulting type will be kept and only agencies from the consultant with the same consulting type will be shown + // but this should be fine. + + // Fallback logic for special client because slug is not unique. So try reversed logic + if ( + settings?.registration?.useConsultingTypeSlug && + consultingType + ) { + setSlugFallback(consultingType.slug); + const slugAgencies = consultant.agencies.filter( + (a) => a.consultingTypeRel.slug === consultingType.slug + ); + if (slugAgencies.length > 0) { + consultingType = slugAgencies[0].consultingTypeRel; + } + } else if ( + settings?.registration?.useConsultingTypeSlug && + !consultingType + ) { + consultingType = consultant.agencies?.[0]?.consultingTypeRel; + setSlugFallback(consultingType?.slug); + } else if ( + // If the consultingType does not match the consultant's consultingTypes, set the consultingType to null + !consultant.agencies.some( + (a) => + !consultingType || + a.consultingType === consultingType?.id + ) + ) { + consultingType = null; + } + + return [agency, consultingType, topic, consultant]; + }, + [consultantId, settings?.registration?.useConsultingTypeSlug] + ); useEffect(() => { (async () => { try { - let agency, - consultingType = null; - - if (isNumber(agencyId)) { - agency = await apiGetAgencyById(agencyId).catch(() => null); + let agency: AgencyDataInterface = null, + consultingType: ConsultingTypeInterface = null, + consultant: ConsultantDataInterface = null, + topic: TopicsDataInterface = null; + + if (agencyId !== null && isNumber(agencyId)) { + agency = await apiGetAgencyById( + parseInt(agencyId), + true + ).catch(() => null); } if (consultingTypeSlug || agency) { @@ -50,100 +156,49 @@ export default function useUrlParamsLoader() { consultingTypeSlug, consultingTypeId: agency?.consultingType }); + + // Fallback logic for special client because slug is not unique. So try reversed logic + if ( + settings?.registration?.useConsultingTypeSlug && + consultingType + ) { + setSlugFallback(consultingType.slug); + } else if ( + agency?.consultingType !== consultingType?.id || + (agency?.external && + !consultingType?.registration?.autoSelectPostcode) + ) { + agency = null; + } } - if (consultantId) { - const consultant = await apiGetConsultant( - consultantId, - true, - 'basic' - ).catch(() => { - // consultant not found -> go to registration - document.location.href = settings.urls.toRegistration; - }); + if (topicIdOrName !== null) { + [agency, topic] = await loadTopic(agency); + } - if (consultant) { - setConsultant(consultant); - - // If the agency does not match the consultant's agency, we'll set the agency to null - if ( - !consultant.agencies.some( - (a) => a.id === agency?.id - ) - ) { - agency = null; - } - - // If the consultant agency consulting types does not match the consulting type, we'll set the consulting type to null - // If the agency is invalid and set to null already the consulting type was loaded by the agency. If the consultant - // has switched to another agency with the same consulting type this will not be catched by this conditions - // and the consulting type will be kept and only agencies from the consultant with the same consulting type will be shown - // but this should be fine. - if ( - !consultant.agencies.some( - (a) => - !consultingType || - a.consultingType === consultingType?.id - ) - ) { - consultingType = null; - - // Fallback logic for special client because slug is not unique. So try reversed logicc - if ( - settings?.registration?.directlink - ?.fallbackLoader?.enabled && - consultingTypeSlug - ) { - const loadConsultingType = async (id) => { - const ct = await apiGetConsultingType({ - consultingTypeId: id - }); - return ct.slug === consultingTypeSlug - ? ct - : null; - }; - - for (const { - consultingType: ctId - } of consultant.agencies) { - const res = await loadConsultingType(ctId); - if (res) { - consultingType = res; - break; - } - } - } - } - } + if (consultantId !== null) { + [agency, consultingType, topic, consultant] = + await handleConsultant(agency, consultingType, topic); } - // When we've the multi tenancy with single domain enabled we'll always have multiple consulting types + const isConsultantOk = consultantId === null || !!consultant; + const isConsultingTypeOk = + !consultingTypeSlug || !!consultingType; + const isAgencyOk = agencyId === null || !!agency; + const isTopicOk = topicIdOrName === null || !!topic; if ( - !settings.multitenancyWithSingleDomainEnabled && - agency?.consultingType !== consultingType?.id + !isConsultantOk && + !isConsultingTypeOk && + !isAgencyOk && + !isTopicOk && + handleBadRequest ) { - agency = null; - } - - if (isNumber(topicIdOrName) && topicIdOrName !== '') { - await apiGetTopicById(topicIdOrName) - .then(setTopic) - .catch(() => null); - } else if (isString(topicIdOrName) && topicIdOrName !== '') { - await apiGetTopicsData() - .then((allTopics) => { - const topic = allTopics.find( - (topic) => - topic.name?.toLowerCase() === - decodeURIComponent( - topicIdOrName.toLowerCase() - ) - ); - setTopic(topic); - }) - .catch(() => null); + handleBadRequest(); + return; } + setTopic(topic); + setConsultant(consultant); setConsultingType(consultingType); setAgency(agency); setLoaded(true); @@ -158,14 +213,17 @@ export default function useUrlParamsLoader() { topicIdOrName, settings.multitenancyWithSingleDomainEnabled, settings.urls.toRegistration, - settings?.registration?.directlink?.fallbackLoader?.enabled + settings?.registration?.useConsultingTypeSlug, + handleConsultant, + loadTopic, + handleBadRequest ]); useEffect(() => { - if (language) { + if (language !== null) { setLocale(language); } }, [language, setLocale]); - return { agency, consultant, consultingType, loaded, topic }; + return { agency, consultant, consultingType, loaded, topic, slugFallback }; } From e66a9482572328ac9977620e2be7662b397f10e7 Mon Sep 17 00:00:00 2001 From: Marc Itzenthaler Date: Wed, 28 Feb 2024 02:29:24 +0100 Subject: [PATCH 2/8] fix: agency list update registration --- .../ConsultingTypeAgencySelection.tsx | 47 ++++++++++++------- .../formAccordion/FormAccordion.tsx | 2 +- src/components/login/Login.tsx | 2 +- .../hooks/useAgenciesForRegistration.ts | 5 +- .../hooks/useConsultantRegistrationData.ts | 19 +++++++- src/resources/i18n/de/common.json | 7 +++ src/resources/i18n/de@informal/common.json | 4 ++ src/resources/i18n/en/common.json | 5 ++ 8 files changed, 69 insertions(+), 22 deletions(-) diff --git a/src/components/consultingTypeSelection/ConsultingTypeAgencySelection.tsx b/src/components/consultingTypeSelection/ConsultingTypeAgencySelection.tsx index 14b451b57..0f4baa3e9 100644 --- a/src/components/consultingTypeSelection/ConsultingTypeAgencySelection.tsx +++ b/src/components/consultingTypeSelection/ConsultingTypeAgencySelection.tsx @@ -66,7 +66,13 @@ export const ConsultingTypeAgencySelection = ({ agencies: possibleAgencies, consultingTypes: possibleConsultingTypes, topicIds: possibleTopicIds - } = useConsultantRegistrationData(); + } = useConsultantRegistrationData({ + consultingTypeId: + selectedConsultingTypeOption?.value && + parseInt(selectedConsultingTypeOption.value), + topicId: + selectedTopicOption?.value && parseInt(selectedTopicOption.value) + }); useEffect(() => { apiGetTopicsData() @@ -185,7 +191,11 @@ export const ConsultingTypeAgencySelection = ({ defaultValue: selectedTopicOption }; - if (possibleAgencies.length <= 1 && possibleConsultingTypes.length <= 1) { + if ( + possibleAgencies.length <= 1 && + possibleConsultingTypes.length <= 1 && + possibleTopicIds.length <= 1 + ) { return null; } @@ -218,23 +228,24 @@ export const ConsultingTypeAgencySelection = ({
)} - {selectedConsultingTypeOption && agencyOptions.length > 1 && ( -
- {consultingTypeOptions.length <= 1 && ( - 1 && ( +
+ {consultingTypeOptions.length <= 1 && ( + + )} + - )} - -
- )} +
+ )} ); }; diff --git a/src/components/formAccordion/FormAccordion.tsx b/src/components/formAccordion/FormAccordion.tsx index 0ab3c1b51..1d6ddf05f 100644 --- a/src/components/formAccordion/FormAccordion.tsx +++ b/src/components/formAccordion/FormAccordion.tsx @@ -71,7 +71,7 @@ export const FormAccordion = ({ const { setSpecificAgency, specificAgency } = useContext( AgencySpecificContext ); - const { consultingTypes } = useConsultantRegistrationData(); + const { consultingTypes } = useConsultantRegistrationData({}); const [activeItem, setActiveItem] = useState(1); diff --git a/src/components/login/Login.tsx b/src/components/login/Login.tsx index 2f439a12d..c17a1e215 100644 --- a/src/components/login/Login.tsx +++ b/src/components/login/Login.tsx @@ -196,7 +196,7 @@ export const Login = () => { agencies: possibleAgencies, consultingTypes: possibleConsultingTypes, topicIds: possibleTopicIds - } = useConsultantRegistrationData(); + } = useConsultantRegistrationData({}); const registerOverlay = useMemo( (): OverlayItem => ({ diff --git a/src/containers/registration/hooks/useAgenciesForRegistration.ts b/src/containers/registration/hooks/useAgenciesForRegistration.ts index 89fd182db..98452ffc3 100644 --- a/src/containers/registration/hooks/useAgenciesForRegistration.ts +++ b/src/containers/registration/hooks/useAgenciesForRegistration.ts @@ -38,7 +38,10 @@ export const useAgenciesForRegistration = ({ const { agencies: consultantAgencies, consultingTypes: consultantConsultingTypes - } = useConsultantRegistrationData(); + } = useConsultantRegistrationData({ + topicId: topic?.id, + consultingTypeId: consultingType?.id + }); const [isLoading, setIsLoading] = useState(true); const [agencies, setAgencies] = useState([]); diff --git a/src/containers/registration/hooks/useConsultantRegistrationData.ts b/src/containers/registration/hooks/useConsultantRegistrationData.ts index a80a856d2..fc84afb7a 100644 --- a/src/containers/registration/hooks/useConsultantRegistrationData.ts +++ b/src/containers/registration/hooks/useConsultantRegistrationData.ts @@ -8,7 +8,15 @@ import { import { useAppConfig } from '../../../hooks/useAppConfig'; import { UrlParamsContext } from '../../../globalState/provider/UrlParamsProvider'; -export const useConsultantRegistrationData = () => { +interface ConsultantRegistrationDataArgs { + consultingTypeId?: number; + topicId?: number; +} + +export const useConsultantRegistrationData = ({ + consultingTypeId, + topicId +}: ConsultantRegistrationDataArgs) => { const settings = useAppConfig(); const { consultingType: preselectedConsultingType, @@ -89,12 +97,19 @@ export const useConsultantRegistrationData = () => { .filter((agency) => consultingTypeIds.includes(agency.consultingType) ) + // Filter agencies by selected topic + .filter( + (a) => + !consultingTypeId || a.consultingType === consultingTypeId + ) // Filter agencies by preselected topic .filter( (a) => !preselectedTopic || a.topicIds?.includes(preselectedTopic?.id) ) + // Filter agencies by selected topic + .filter((a) => !topicId || a.topicIds?.includes(topicId)) // Filter agencies by preselected agency .filter((a) => !preselectedAgency || preselectedAgency.id === a.id); setAgencies(possibleAgencies); @@ -106,6 +121,8 @@ export const useConsultantRegistrationData = () => { : consultingTypes ); }, [ + topicId, + consultingTypeId, consultant, preselectedConsultingType, preselectedAgency, diff --git a/src/resources/i18n/de/common.json b/src/resources/i18n/de/common.json index 2de3c829f..ae0cfdb25 100644 --- a/src/resources/i18n/de/common.json +++ b/src/resources/i18n/de/common.json @@ -1824,6 +1824,13 @@ "label": "Themenfeld" } }, + "topic": { + "headline": "Bitte wählen Sie ein Themenfeld", + "infoText": "Ihr_e Berater_in ist in mehreren Themenfeldern tätig. Bitte wählen Sie Ihr gewünschtes Themenfeld.", + "select": { + "label": "Themenfeld" + } + }, "agency": { "headline": "Bitte wählen Sie eine Beratungsstelle", "infoText": "Ihr_e Berater_in ist in mehreren Beratungsstellen tätig. Bitte wählen Sie Ihre gewünschte Beratungsstelle." diff --git a/src/resources/i18n/de@informal/common.json b/src/resources/i18n/de@informal/common.json index 76615c5cf..6600fb890 100644 --- a/src/resources/i18n/de@informal/common.json +++ b/src/resources/i18n/de@informal/common.json @@ -637,6 +637,10 @@ "headline": "Bitte wähle ein Themenfeld", "infoText": "Dein_e Berater_in ist in mehreren Themenfeldern tätig. Bitte wähle Dein gewünschtes Themenfeld." }, + "topic": { + "headline": "Bitte wähle ein Themenfeld", + "infoText": "Dein_e Berater_in ist in mehreren Themenfeldern tätig. Bitte wähle Dein gewünschtes Themenfeld." + }, "agency": { "headline": "Bitte wähle eine Beratungsstelle", "infoText": "Dein_e Berater_in ist in mehreren Beratungsstellen tätig. Bitte wähle Deine gewünschte Beratungsstelle." diff --git a/src/resources/i18n/en/common.json b/src/resources/i18n/en/common.json index f305c136b..513028154 100644 --- a/src/resources/i18n/en/common.json +++ b/src/resources/i18n/en/common.json @@ -1818,6 +1818,11 @@ "infoText": "Your consultant is active in several subject areas. Please select your desired subject area.", "select.label": "Topic" }, + "topic": { + "headline": "Please select a topic", + "infoText": "Your consultant is active in several subject areas. Please select your desired subject area.", + "select.label": "Topic" + }, "agency": { "headline": "Please select a counseling center", "infoText": "Your consultant is active in several counseling centers. Please select your desired counseling center." From 61605197bb889cae8064d25f37c1281618522e56 Mon Sep 17 00:00:00 2001 From: Marc Itzenthaler Date: Wed, 28 Feb 2024 03:10:27 +0100 Subject: [PATCH 3/8] fix: agency list update registration --- cypress/e2e/login.cy.ts | 2 +- cypress/e2e/registration/topic.cy.ts | 18 ++++++------------ .../hooks/useConsultantRegistrationData.ts | 4 +++- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/cypress/e2e/login.cy.ts b/cypress/e2e/login.cy.ts index e96c8a5a1..be54d30d4 100644 --- a/cypress/e2e/login.cy.ts +++ b/cypress/e2e/login.cy.ts @@ -30,7 +30,7 @@ describe('Login', () => { cy.contains('Datenschutzerklärung'); }); - it.only('displays the login for resorts', () => { + it('displays the login for resorts', () => { cy.visit('/suchtberatung'); cy.contains('Login'); }); diff --git a/cypress/e2e/registration/topic.cy.ts b/cypress/e2e/registration/topic.cy.ts index 2f79f17c4..955d21b70 100644 --- a/cypress/e2e/registration/topic.cy.ts +++ b/cypress/e2e/registration/topic.cy.ts @@ -871,23 +871,20 @@ describe('Registration', () => { cy.get('.agencySelection__proposedAgency').should( 'have.length', - 5 + 2 ); cy.get( '.agencySelection__proposedAgency .radioButton__input#agency-11' - ).should('exist'); + ).should('not.exist'); cy.get( '.agencySelection__proposedAgency .radioButton__input#agency-13' - ).should('exist'); + ).should('not.exist'); cy.get( '.agencySelection__proposedAgency .radioButton__input#agency-21' ).should('exist'); cy.get( '.agencySelection__proposedAgency .radioButton__input#agency-22' ).should('exist'); - cy.get( - '.agencySelection__proposedAgency .radioButton__input#agency-23' - ).should('exist'); }); }); describe('With valid cid parameters', () => { @@ -1080,23 +1077,20 @@ describe('Registration', () => { cy.get('.agencySelection__proposedAgency').should( 'have.length', - 5 + 2 ); cy.get( '.agencySelection__proposedAgency .radioButton__input#agency-11' - ).should('exist'); + ).should('not.exist'); cy.get( '.agencySelection__proposedAgency .radioButton__input#agency-13' - ).should('exist'); + ).should('not.exist'); cy.get( '.agencySelection__proposedAgency .radioButton__input#agency-21' ).should('exist'); cy.get( '.agencySelection__proposedAgency .radioButton__input#agency-22' ).should('exist'); - cy.get( - '.agencySelection__proposedAgency .radioButton__input#agency-23' - ).should('exist'); }); }); }); diff --git a/src/containers/registration/hooks/useConsultantRegistrationData.ts b/src/containers/registration/hooks/useConsultantRegistrationData.ts index fc84afb7a..db695602e 100644 --- a/src/containers/registration/hooks/useConsultantRegistrationData.ts +++ b/src/containers/registration/hooks/useConsultantRegistrationData.ts @@ -100,7 +100,9 @@ export const useConsultantRegistrationData = ({ // Filter agencies by selected topic .filter( (a) => - !consultingTypeId || a.consultingType === consultingTypeId + slugFallback || + !consultingTypeId || + a.consultingType === consultingTypeId ) // Filter agencies by preselected topic .filter( From 6b7bd78b2370b76469a932336741baf78be79361 Mon Sep 17 00:00:00 2001 From: Marc Itzenthaler Date: Wed, 28 Feb 2024 16:10:53 +0100 Subject: [PATCH 4/8] fix: default postcode optional, request reduction --- src/api/apiAgencySelection.ts | 86 +++++++++++-------- src/api/apiGetAgencyId.ts | 9 +- src/api/apiGetConsultant.ts | 32 ++++--- .../agencySelection/AgencySelection.tsx | 2 - .../hooks/useAgenciesForRegistration.ts | 13 +-- src/utils/loadConsultingTypeForAgency.ts | 11 --- 6 files changed, 85 insertions(+), 68 deletions(-) delete mode 100644 src/utils/loadConsultingTypeForAgency.ts diff --git a/src/api/apiAgencySelection.ts b/src/api/apiAgencySelection.ts index 21284ee86..f195cc467 100644 --- a/src/api/apiAgencySelection.ts +++ b/src/api/apiAgencySelection.ts @@ -1,15 +1,14 @@ import { endpoints } from '../resources/scripts/endpoints'; import { fetchData, FETCH_METHODS, FETCH_ERRORS } from './fetchData'; -import { VALID_POSTCODE_LENGTH } from '../components/agencySelection/agencySelectionHelpers'; import { AgencyDataInterface } from '../globalState'; -import { loadConsultingTypeForAgency } from '../utils/loadConsultingTypeForAgency'; +import { apiGetConsultingType } from './apiGetConsultingType'; export const apiAgencySelection = async ( { fetchConsultingTypeDetails, ...params }: { - postcode: string; + postcode?: string; consultingType: number | undefined; topicId?: number; age?: number; @@ -18,50 +17,61 @@ export const apiAgencySelection = async ( fetchConsultingTypeDetails?: boolean; }, signal?: AbortSignal -): Promise | null> => { +): Promise => { let queryStr = Object.keys(params) .filter((key) => params[key] !== undefined) .map((key) => key + '=' + params[key]) .join('&'); const url = endpoints.agencyServiceBase + '?' + queryStr; - if (params.postcode.length === VALID_POSTCODE_LENGTH) { - return fetchData({ - url: url, - method: FETCH_METHODS.GET, - skipAuth: true, - responseHandling: [FETCH_ERRORS.EMPTY], - ...(signal && { signal: signal }) - }) - .then((result) => { - if (result) { - // External agencies should only be returned - // if there are no internal ones. - const internalAgencies = result.filter( - (agency) => !agency.external - ); - if (internalAgencies.length > 0) { - return internalAgencies; - } else { - return result; - } + return fetchData({ + url: url, + method: FETCH_METHODS.GET, + skipAuth: true, + responseHandling: [FETCH_ERRORS.EMPTY], + ...(signal && { signal: signal }) + }) + .then((result) => { + if (result) { + // External agencies should only be returned + // if there are no internal ones. + const internalAgencies = result.filter( + (agency) => !agency.external + ); + if (internalAgencies.length > 0) { + return internalAgencies; } else { return result; } - }) - .then((agencies) => { - if (!fetchConsultingTypeDetails) { - return agencies; - } + } else { + return result; + } + }) + .then((agencies: AgencyDataInterface[]) => { + if (!fetchConsultingTypeDetails) { + return agencies; + } + + // Get unique consultingTypes to prevent multiple requests to api + const uniqueConsultingTypeIds = [ + ...new Set( + agencies.map((a) => a?.consultingType).filter(Boolean) + ) + ]; - return Promise.all( - agencies.map( - async (agency) => - await loadConsultingTypeForAgency(agency) + return Promise.all( + uniqueConsultingTypeIds.map((consultingTypeId) => + apiGetConsultingType({ + consultingTypeId + }) + ) + ).then((consultingTypes) => + agencies.map((a) => ({ + ...a, + consultingTypeRel: consultingTypes.find( + (c) => c.id === a.consultingType ) - ); - }); - } else { - return null; - } + })) + ); + }); }; diff --git a/src/api/apiGetAgencyId.ts b/src/api/apiGetAgencyId.ts index b36f96b64..fa27837bd 100644 --- a/src/api/apiGetAgencyId.ts +++ b/src/api/apiGetAgencyId.ts @@ -1,7 +1,7 @@ import { endpoints } from '../resources/scripts/endpoints'; import { fetchData, FETCH_METHODS, FETCH_ERRORS } from './fetchData'; import { AgencyDataInterface } from '../globalState'; -import { loadConsultingTypeForAgency } from '../utils/loadConsultingTypeForAgency'; +import { apiGetConsultingType } from './apiGetConsultingType'; export const apiGetAgencyById = async ( agencyId: number, @@ -21,6 +21,11 @@ export const apiGetAgencyById = async ( return agency; } - return await loadConsultingTypeForAgency(agency); + return { + ...agency, + consultingTypeRel: await apiGetConsultingType({ + consultingTypeId: agency?.consultingType + }) + }; }); }; diff --git a/src/api/apiGetConsultant.ts b/src/api/apiGetConsultant.ts index 263df069c..bf2b68bf7 100644 --- a/src/api/apiGetConsultant.ts +++ b/src/api/apiGetConsultant.ts @@ -1,7 +1,7 @@ import { endpoints } from '../resources/scripts/endpoints'; import { fetchData, FETCH_METHODS, FETCH_ERRORS } from './fetchData'; import { ConsultantDataInterface } from '../globalState'; -import { loadConsultingTypeForAgency } from '../utils/loadConsultingTypeForAgency'; +import { apiGetConsultingType } from './apiGetConsultingType'; export const apiGetConsultant = async ( consultantId: string, @@ -14,20 +14,32 @@ export const apiGetConsultant = async ( method: FETCH_METHODS.GET, skipAuth: true, responseHandling: [FETCH_ERRORS.CATCH_ALL] - }).then((user) => { + }).then((user: ConsultantDataInterface) => { if (!fetchConsultingTypeDetails) { return user; } + // Get unique consultingTypes to prevent multiple requests to api + const uniqueConsultingTypeIds = [ + ...new Set( + user.agencies.map((a) => a?.consultingType).filter(Boolean) + ) + ]; + return Promise.all( - user.agencies.map( - async (agency) => await loadConsultingTypeForAgency(agency) + uniqueConsultingTypeIds.map((consultingTypeId) => + apiGetConsultingType({ + consultingTypeId + }) ) - ).then( - (agencies): ConsultantDataInterface => ({ - ...user, - agencies - }) - ); + ).then((consultingTypes) => ({ + ...user, + agencies: user.agencies.map((a) => ({ + ...a, + consultingTypeRel: consultingTypes.find( + (c) => c.id === a.consultingType + ) + })) + })); }); }; diff --git a/src/components/agencySelection/AgencySelection.tsx b/src/components/agencySelection/AgencySelection.tsx index 60f85e09c..634f7980d 100644 --- a/src/components/agencySelection/AgencySelection.tsx +++ b/src/components/agencySelection/AgencySelection.tsx @@ -11,7 +11,6 @@ import { InputField, InputFieldItem } from '../inputField/InputField'; import { VALID_POSTCODE_LENGTH } from './agencySelectionHelpers'; import './agencySelection.styles'; import '../profile/profile.styles'; -import { DEFAULT_POSTCODE } from '../registration/prefillPostcode'; import { RadioButton } from '../radioButton/RadioButton'; import { Loading } from '../app/Loading'; import { Text, LABEL_TYPES } from '../text/Text'; @@ -84,7 +83,6 @@ export const AgencySelection = (props: AgencySelectionProps) => { try { if (autoSelectAgency) { const response = await apiAgencySelection({ - postcode: DEFAULT_POSTCODE, consultingType: props.consultingType.id, topicId: props?.mainTopicId }); diff --git a/src/containers/registration/hooks/useAgenciesForRegistration.ts b/src/containers/registration/hooks/useAgenciesForRegistration.ts index 98452ffc3..dcdc73d02 100644 --- a/src/containers/registration/hooks/useAgenciesForRegistration.ts +++ b/src/containers/registration/hooks/useAgenciesForRegistration.ts @@ -1,7 +1,6 @@ import unionBy from 'lodash/unionBy'; import { useContext, useEffect, useMemo, useState } from 'react'; import { apiAgencySelection } from '../../../api'; -import { DEFAULT_POSTCODE } from '../../../components/registration/prefillPostcode'; import { TopicsDataInterface } from '../../../globalState/interfaces/TopicsDataInterface'; import { AgencyDataInterface, @@ -11,6 +10,7 @@ import { import { useConsultantRegistrationData } from './useConsultantRegistrationData'; import { ConsultingTypeRegistrationDefaults } from '../components/ProposedAgencies/ProposedAgencies'; import { UrlParamsContext } from '../../../globalState/provider/UrlParamsProvider'; +import { VALID_POSTCODE_LENGTH } from '../../../components/agencySelection/agencySelectionHelpers'; interface AgenciesForRegistrationArgs { consultingType: ConsultingTypeInterface; @@ -78,8 +78,6 @@ export const useAgenciesForRegistration = ({ } uniqueAgencies = uniqueAgencies - // Filter by preselected agency - // Filter by consultingType .filter( (agency) => @@ -119,7 +117,12 @@ export const useAgenciesForRegistration = ({ useEffect(() => { const abortController = new AbortController(); // if we already have information from consulting types we can ignore the request - if (consultant || preselectedAgency || topicsEnabledAndUnSelected) { + if ( + consultant || + preselectedAgency || + topicsEnabledAndUnSelected || + (!autoSelectPostcode && postcode?.length !== VALID_POSTCODE_LENGTH) + ) { setIsLoading(false); return; } @@ -127,7 +130,7 @@ export const useAgenciesForRegistration = ({ setIsLoading(true); apiAgencySelection( { - postcode: autoSelectPostcode ? DEFAULT_POSTCODE : postcode, + ...(autoSelectPostcode ? {} : { postcode }), consultingType: consultingType?.id, topicId: topic?.id, fetchConsultingTypeDetails: true diff --git a/src/utils/loadConsultingTypeForAgency.ts b/src/utils/loadConsultingTypeForAgency.ts deleted file mode 100644 index 817561640..000000000 --- a/src/utils/loadConsultingTypeForAgency.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { apiGetConsultingType } from '../api'; -import { AgencyDataInterface } from '../globalState'; - -export const loadConsultingTypeForAgency = async ( - agency: AgencyDataInterface -): Promise => ({ - ...agency, - consultingTypeRel: await apiGetConsultingType({ - consultingTypeId: agency?.consultingType - }) -}); From 781643f0df89e028420170ca62cc6640eaba58ad Mon Sep 17 00:00:00 2001 From: Marc Itzenthaler Date: Wed, 28 Feb 2024 16:27:52 +0100 Subject: [PATCH 5/8] feat: unique duplicate logic --- src/api/apiAgencySelection.ts | 24 ++---------------- src/api/apiGetConsultant.ts | 28 ++++----------------- src/utils/loadConsultingTypesForAgencies.ts | 26 +++++++++++++++++++ 3 files changed, 33 insertions(+), 45 deletions(-) create mode 100644 src/utils/loadConsultingTypesForAgencies.ts diff --git a/src/api/apiAgencySelection.ts b/src/api/apiAgencySelection.ts index f195cc467..0e7392d1a 100644 --- a/src/api/apiAgencySelection.ts +++ b/src/api/apiAgencySelection.ts @@ -1,7 +1,7 @@ import { endpoints } from '../resources/scripts/endpoints'; import { fetchData, FETCH_METHODS, FETCH_ERRORS } from './fetchData'; import { AgencyDataInterface } from '../globalState'; -import { apiGetConsultingType } from './apiGetConsultingType'; +import { loadConsultingTypesForAgencies } from '../utils/loadConsultingTypesForAgencies'; export const apiAgencySelection = async ( { @@ -52,26 +52,6 @@ export const apiAgencySelection = async ( return agencies; } - // Get unique consultingTypes to prevent multiple requests to api - const uniqueConsultingTypeIds = [ - ...new Set( - agencies.map((a) => a?.consultingType).filter(Boolean) - ) - ]; - - return Promise.all( - uniqueConsultingTypeIds.map((consultingTypeId) => - apiGetConsultingType({ - consultingTypeId - }) - ) - ).then((consultingTypes) => - agencies.map((a) => ({ - ...a, - consultingTypeRel: consultingTypes.find( - (c) => c.id === a.consultingType - ) - })) - ); + return loadConsultingTypesForAgencies(agencies); }); }; diff --git a/src/api/apiGetConsultant.ts b/src/api/apiGetConsultant.ts index bf2b68bf7..d53b238d3 100644 --- a/src/api/apiGetConsultant.ts +++ b/src/api/apiGetConsultant.ts @@ -1,7 +1,7 @@ import { endpoints } from '../resources/scripts/endpoints'; import { fetchData, FETCH_METHODS, FETCH_ERRORS } from './fetchData'; import { ConsultantDataInterface } from '../globalState'; -import { apiGetConsultingType } from './apiGetConsultingType'; +import { loadConsultingTypesForAgencies } from '../utils/loadConsultingTypesForAgencies'; export const apiGetConsultant = async ( consultantId: string, @@ -14,32 +14,14 @@ export const apiGetConsultant = async ( method: FETCH_METHODS.GET, skipAuth: true, responseHandling: [FETCH_ERRORS.CATCH_ALL] - }).then((user: ConsultantDataInterface) => { + }).then(async (user: ConsultantDataInterface) => { if (!fetchConsultingTypeDetails) { return user; } - // Get unique consultingTypes to prevent multiple requests to api - const uniqueConsultingTypeIds = [ - ...new Set( - user.agencies.map((a) => a?.consultingType).filter(Boolean) - ) - ]; - - return Promise.all( - uniqueConsultingTypeIds.map((consultingTypeId) => - apiGetConsultingType({ - consultingTypeId - }) - ) - ).then((consultingTypes) => ({ + return { ...user, - agencies: user.agencies.map((a) => ({ - ...a, - consultingTypeRel: consultingTypes.find( - (c) => c.id === a.consultingType - ) - })) - })); + agencies: await loadConsultingTypesForAgencies(user.agencies) + }; }); }; diff --git a/src/utils/loadConsultingTypesForAgencies.ts b/src/utils/loadConsultingTypesForAgencies.ts new file mode 100644 index 000000000..09a183fea --- /dev/null +++ b/src/utils/loadConsultingTypesForAgencies.ts @@ -0,0 +1,26 @@ +import { apiGetConsultingType } from '../api'; +import { AgencyDataInterface } from '../globalState/interfaces'; + +export const loadConsultingTypesForAgencies = async ( + agencies: AgencyDataInterface[] +): Promise => { + // Get unique consultingTypes to prevent multiple requests to api + const uniqueConsultingTypeIds = [ + ...new Set(agencies.map((a) => a?.consultingType).filter(Boolean)) + ]; + + return Promise.all( + uniqueConsultingTypeIds.map((consultingTypeId) => + apiGetConsultingType({ + consultingTypeId + }) + ) + ).then((consultingTypes) => + agencies.map((a) => ({ + ...a, + consultingTypeRel: consultingTypes.find( + (c) => c.id === a.consultingType + ) + })) + ); +}; From b18eb3ccf25f327beba9a8311f03b23f2b316de9 Mon Sep 17 00:00:00 2001 From: Marc Itzenthaler Date: Wed, 28 Feb 2024 16:34:59 +0100 Subject: [PATCH 6/8] fix: import --- src/utils/loadConsultingTypesForAgencies.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/loadConsultingTypesForAgencies.ts b/src/utils/loadConsultingTypesForAgencies.ts index 09a183fea..dfa9d3e0d 100644 --- a/src/utils/loadConsultingTypesForAgencies.ts +++ b/src/utils/loadConsultingTypesForAgencies.ts @@ -1,5 +1,5 @@ import { apiGetConsultingType } from '../api'; -import { AgencyDataInterface } from '../globalState/interfaces'; +import { AgencyDataInterface } from '../globalState'; export const loadConsultingTypesForAgencies = async ( agencies: AgencyDataInterface[] From d96ef45503de20bebfb6883e90b3f00476c5b659 Mon Sep 17 00:00:00 2001 From: Marc Itzenthaler Date: Thu, 29 Feb 2024 16:17:41 +0100 Subject: [PATCH 7/8] fix: enable consulting type slug registration by default --- proxy/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxy/config.js b/proxy/config.js index 9b5d9e9b2..df181c87e 100644 --- a/proxy/config.js +++ b/proxy/config.js @@ -15,7 +15,7 @@ module.exports = { }, registration: { useConsultingTypeSlug: !!parseInt( - process.env.FRONTEND_REGISTRATION_USE_CONSULTINGTYPE_SLUG || '0' + process.env.FRONTEND_REGISTRATION_USE_CONSULTINGTYPE_SLUG || '1' ) } }; From 519558140e3118eccec67421bf942934cb71fb06 Mon Sep 17 00:00:00 2001 From: Marc Itzenthaler Date: Wed, 13 Mar 2024 13:55:25 +0100 Subject: [PATCH 8/8] fix: removed default consultingType overrides --- src/resources/i18n/de/consultingTypes.json | 420 +----------------- src/resources/i18n/en/consultingTypes.json | 486 +-------------------- 2 files changed, 2 insertions(+), 904 deletions(-) diff --git a/src/resources/i18n/de/consultingTypes.json b/src/resources/i18n/de/consultingTypes.json index 239d9760d..bb8144ee4 100644 --- a/src/resources/i18n/de/consultingTypes.json +++ b/src/resources/i18n/de/consultingTypes.json @@ -1,421 +1,3 @@ { - "consultingType": { - "0": { - "titles": { - "default": "Suchtberatung", - "short": "Sucht", - "long": "Suchtberatung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Suchtberatung" - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - } - }, - "1": { - "titles": { - "default": "[U25]", - "short": "[U25]", - "long": "Beratung für suizidgefährdete junge Menschen [U25]", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Beratung für suizidgefährdete junge Menschen [U25]" - }, - "anonymous": { - "text": "Du bleibst anonym und erhältst kostenfreie Beratung und Hilfe", - "title": "Anonym und kostenfrei" - }, - "requiredComponents": { - "age": { - "0": "unter 12", - "1": "12", - "2": "13", - "3": "14", - "4": "15", - "5": "16", - "6": "17", - "7": "18", - "8": "19", - "9": "20", - "10": "21", - "11": "22", - "12": "23", - "13": "24", - "14": "25", - "15": "über 25" - } - } - }, - "2": { - "titles": { - "default": "Schwangerschaftsberatung", - "short": "Schwangerschaft", - "long": "Schwangerschaftsberatung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Schwangerschaftsberatung" - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Du bleibst anonym und erhältst kostenfreie Beratung und Hilfe" - } - } - }, - "3": { - "titles": { - "default": "Eltern und Familien", - "short": "Eltern Familie", - "long": "Beratung für Eltern und Familien", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Eltern und Familien" - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - } - }, - "4": { - "titles": { - "default": "Kurberatung", - "short": "Kurberatung", - "long": "Kurberatung für Mütter und Väter", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Kurberatung" - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - } - }, - "5": { - "titles": { - "default": "Schuldnerberatung", - "short": "Schulden", - "long": "Beratung zum Thema Schulden", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Schuldnerberatung" - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - } - }, - "6": { - "titles": { - "default": "Sozialberatung", - "short": "ASB", - "long": "Allgemeine Sozialberatung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Sozialberatung" - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - } - }, - "7": { - "titles": { - "default": "Leben im Alter", - "short": "Alter", - "long": "Leben im Alter", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Leben im Alter" - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - } - }, - "8": { - "titles": { - "default": "Beeinträchtigung", - "short": "Beeinträchtigung", - "long": "Leben mit Behinderung und psychischer Erkrankung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Beeinträchtigung" - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - } - }, - "9": { - "titles": { - "default": "Go on – Start up!", - "short": "Go on – Start up!", - "long": "Go on – Start up!", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Go on – Start up!" - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - } - }, - "10": { - "titles": { - "default": "Rechtliche Betreuung und Vorsorge", - "short": "(rechtl.) Betreuung", - "long": "Rechtliche Betreuung und Vorsorge", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Rechtliche Betreuung und Vorsorge" - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - } - }, - "11": { - "titles": { - "default": "Straffälligenhilfe", - "short": "Straffälligenhilfe", - "long": "Beratung für Angehörige von Straffälligen", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Straffälligenhilfe" - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - } - }, - "12": { - "titles": { - "default": "HIV / AIDS", - "short": "HIV", - "long": "HIV/AIDS-Beratung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "HIV / AIDS" - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - } - }, - "13": { - "titles": { - "default": "Kinder-Reha", - "short": "Kinder-Reha", - "long": "Kinder- und Jugend-Rehabilitation", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Kinder-Reha" - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - } - }, - "14": { - "titles": { - "default": "Kinder Jugendliche", - "short": "Kinder Jugendliche", - "long": "Beratung für Kinder und Jugendliche", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Kinder Jugendliche" - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - } - }, - "15": { - "titles": { - "default": "Sucht", - "short": "Sucht", - "long": "Sucht-Selbsthilfe – Kreuzbund-Chat", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Sucht-Selbsthilfe - Kreuzbund" - }, - "groupChatRules": { - "0": "In der Sucht-Selbsthilfe duzen wir uns, sowohl in den Gruppen vor Ort als auch hier im Chat. Wer damit Probleme hat, teile das im Chat mit – wir stellen uns gerne darauf ein!", - "1": "Menschen sind verschieden, ihre Meinungen sind es auch. Aufeinander zu achten sowie wertschätzende Chat-Beiträge gewährleisten ein helfendes Miteinander.", - "2": "Moderator_innen haben die Aufgabe, dafür zu sorgen, dass sich die Chat-Teilnehmenden austauschen können. Sie bieten gegebenenfalls auch Sucht-Themen zur Diskussion an. Ihren Aufforderungen ist zu folgen, beispielsweise dann, wenn Chat-Regeln nicht eingehalten werden." - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - } - }, - "16": { - "titles": { - "default": "Migrationsberatung", - "short": "Migrationsberatung", - "long": "Migrationsberatung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Migrationsberatung" - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - } - }, - "17": { - "titles": { - "default": "Auswanderung", - "short": "Auswanderung", - "long": "Aus-/Rück- & Weiterwanderung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Auswanderung" - }, - "anonymous": { - "title": "Anonym" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten Beratung und Hilfe" - } - } - }, - "18": { - "titles": { - "default": "Hospiz-Palliativ-Trauer", - "short": "Hospiz-Palliativ", - "long": "Hospiz-, Palliativ- und Trauerberatung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Hospiz-Palliativ-Trauer" - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - } - }, - "19": { - "titles": { - "default": "Regionale Angebote", - "short": "Regionale Angebote", - "long": "Regionale Angebote", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Regionale Angebote" - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - } - }, - "20": { - "titles": { - "default": "Jungen und Männer", - "short": "Jungen und Männer", - "long": "Jungen- und Männerberatung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Jungen und Männer" - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - } - }, - "21": { - "titles": { - "default": "Selbsthilfe Vechta", - "short": "Selbsthilfe", - "long": "Kontakt- und Beratungsstelle Selbsthilfe", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Selbsthilfe Vechta" - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "groupChatRules": { - "0": "In der Selbsthilfe duzen wir uns, sowohl in den Gruppen vor Ort als auch hier im Chat. Wer damit Probleme hat, teile das im Chat mit – wir stellen uns gerne darauf ein!", - "1": "Menschen sind verschieden, ihre Meinungen sind es auch. Aufeinander zu achten sowie wertschätzende Chat-Beiträge gewährleisten ein helfendes Miteinander.", - "2": "Moderator_innen haben die Aufgabe, dafür zu sorgen, dass sich die Chat-User_innen austauschen können. Ihren Aufforderungen ist zu folgen, beispielsweise dann, wenn Chat-Regeln nicht eingehalten werden." - } - }, - "22": { - "titles": { - "default": "#gemeinsamstatteinsam", - "short": "#gse", - "long": "#gemeinsamstatteinsam – Onlineberatung für junge Menschen in besonderen Zeiten", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "#gemeinsamstatteinsam" - }, - "anonymous": { - "title": "Anonym und kostenfrei" - }, - "welcomeScreen": { - "anonymous": { - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - } - } - } + "consultingType": {} } diff --git a/src/resources/i18n/en/consultingTypes.json b/src/resources/i18n/en/consultingTypes.json index 3f1a454f0..bb8144ee4 100644 --- a/src/resources/i18n/en/consultingTypes.json +++ b/src/resources/i18n/en/consultingTypes.json @@ -1,487 +1,3 @@ { - "consultingType": { - "0": { - "titles": { - "default": "Addiction consulting", - "short": "Addiction", - "long": "Addiction consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Addiction consulting" - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - }, - "voluntaryComponents": { - "relation": { - "headline": "Background", - "affected": "Affected", - "relative": "Affiliated", - "otherType": "Other" - }, - "addictiveDrugs": { - "headline": "Narcotics", - "alcohol": "Alcohol", - "drugs": "Drugs", - "legalHighs": "Legal Highs", - "tabacco": "Tobacco", - "medication": "Medication", - "gambling": "Gambling", - "internetUse": "Internet/Computer", - "eatingDisorder": "Eating disorders", - "otherDrug": "Other" - }, - "age": { - "headline": "Age", - "selectInputLabel": "Select age", - "0": "0-17", - "1": "18-20", - "2": "21-30", - "3": "31-40", - "4": "41-59", - "5": "60+" - }, - "gender": { - "headline": "Gender", - "female": "Female", - "male": "Male", - "diverseGender": "Divers" - } - } - }, - "1": { - "titles": { - "default": "[U25]", - "short": "[U25]", - "long": "Counseling for suicidal young people [U25].", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Counseling for suicidal young people [U25]." - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - }, - "voluntaryComponents": { - "gender": { - "headline": "Gender", - "female": "Female", - "male": "Male", - "diverseGender": "Divers" - } - }, - "requiredComponents": { - "age": { - "0": "under 12", - "1": "12", - "2": "13", - "3": "14", - "4": "15", - "5": "16", - "6": "17", - "7": "18", - "8": "19", - "9": "20", - "10": "21", - "11": "22", - "12": "23", - "13": "24", - "14": "25", - "15": "over 25" - } - } - }, - "2": { - "titles": { - "default": "Pregnancy counseling", - "short": "Pregnancy", - "long": "Pregnancy counseling", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Pregnancy counseling" - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - } - }, - "3": { - "titles": { - "default": "Parents and families", - "short": "Parents Family", - "long": "Consulting for parents and families", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Parents and families" - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - } - }, - "4": { - "titles": { - "default": "Cure Consultation", - "short": "Cure Consultation", - "long": "Cure counseling for mothers and fathers", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Cure Consultation" - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - } - }, - "5": { - "titles": { - "default": "Debt consulting", - "short": "Debt", - "long": "Debt consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Debt consulting" - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - } - }, - "6": { - "titles": { - "default": "Social consulting", - "short": "ASB", - "long": "General social consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Social Counseling" - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - } - }, - "7": { - "titles": { - "default": "Life in old age", - "short": "old age", - "long": "Life in old age", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Life in old age" - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - } - }, - "8": { - "titles": { - "default": "impairment", - "short": "impairment", - "long": "Living with disability and mental illness", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Impairment" - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - } - }, - "9": { - "titles": { - "default": "Let's go - get started", - "short": "Let's go - Get started!", - "long": "Let's go - Get started!", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Let's go - Get started!" - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - } - }, - "10": { - "titles": { - "default": "Legal care and precaution", - "short": "(legal) care", - "long": "Legal care and precaution", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Legal support and precaution" - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - } - }, - "11": { - "titles": { - "default": "Offender assistance", - "short": "Offender assistance", - "long": "consulting for relatives of offenders", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Offender assistance" - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - } - }, - "12": { - "titles": { - "default": "HIV / AIDS", - "short": "HIV", - "long": "HIV/AIDS consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "HIV / AIDS" - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - } - }, - "13": { - "titles": { - "default": "Children's rehab", - "short": "Children's rehab", - "long": "Child and adolescent rehab", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Children's rehab" - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - } - }, - "14": { - "titles": { - "default": "Children Adolescents", - "short": "Children Adolescents", - "long": "Consulting for children and adolescents", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Children Adolescents" - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - } - }, - "15": { - "titles": { - "default": "Addiction", - "short": "Addiction", - "long": "Addiction self-help - Kreuzbund chat", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Sucht-Selbsthilfe - Kreuzbund" - }, - "groupChatRules": { - "0": "In addiction self-help we are on first name terms, both in the groups on site and here in the chat. Anyone who has problems with this, let us know in the chat - we'll be happy to adjust!", - "1": "People are different, so are their opinions. Paying attention to each other as well as appreciative chat contributions guarantee a helping togetherness.", - "2": "Moderators have the task of ensuring that chat participants can exchange ideas. If necessary, they also offer addiction topics for discussion. Their requests are to be followed, for example if chat rules are not followed." - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - } - }, - "16": { - "titles": { - "default": "Migration consulting", - "short": "Migration consulting", - "long": "migration consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Migration consulting" - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - } - }, - "17": { - "titles": { - "default": "Emigration", - "short": "Emigration", - "long": "Emigration/Return & Onward Migration", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Emigration" - }, - "anonymous": { - "title": "Anonymous" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive advice and help" - } - } - }, - "18": { - "titles": { - "default": "Hospice-Palliative-Mourning", - "short": "Hospice-Palliative", - "long": "Hospice, palliative and bereavement consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Hospice palliative grief" - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - } - }, - "19": { - "titles": { - "default": "Regional offers", - "short": "Regional offerings", - "long": "Regional offerings", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Regional Offers" - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - } - }, - "20": { - "titles": { - "default": "Boys and men", - "short": "Boys and men", - "long": "Boys and men consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Boys and men" - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - } - }, - "21": { - "titles": { - "default": "Self-help Vechta", - "short": "Self-help", - "long": "Contact and advice center self-help", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Selbsthilfe Vechta" - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - }, - "groupChatRules": { - "0": "In self-help we are on a first name basis, both in the groups on site and here in the chat. Anyone who has problems with this, let us know in the chat - we'll be happy to adjust!", - "1": "People are different, so are their opinions. Paying attention to each other as well as appreciative chat contributions guarantee a helping togetherness.", - "2": "Moderators have the task of ensuring that chat users can exchange ideas. Their requests have to be followed, for example if chat rules are not followed." - } - }, - "22": { - "titles": { - "default": "#togethertogether", - "short": "#gse", - "long": "#togetherasone - online consulting for young people in special times", - "welcome": "Welcome to online consulting", - "registrationDropdown": "#gemeinsamstatteinsam" - }, - "anonymous": { - "title": "Anonymous and free of charge" - }, - "welcomeScreen": { - "anonymous": { - "text": "You remain anonymous and receive free advice and help" - } - }, - "voluntaryComponents": { - "gender": { - "female": "Female", - "male": "Male", - "diverseGender": "Divers" - } - }, - "requiredComponents": { - "age": { - "50": "20", - "51": "21", - "52": "22", - "53": "23", - "54": "24", - "55": "25", - "56": "26" - } - } - } - } + "consultingType": {} }