diff --git a/src/components/RealTimeInterface/SessionStarted.vue b/src/components/RealTimeInterface/SessionStarted.vue index a2cd13f..a66bfd8 100644 --- a/src/components/RealTimeInterface/SessionStarted.vue +++ b/src/components/RealTimeInterface/SessionStarted.vue @@ -8,12 +8,11 @@ import { calcAltAz } from '../../utils/visibility.js' import { useRealTimeSessionsStore } from '../../stores/realTimeSessions' import sites from '../../utils/sites.JSON' import { fetchApiCall } from '../../utils/api' +import { getFilterList } from '../../utils/populateInstrumentsUtils' import { useConfigurationStore } from '../../stores/configuration' -import { useUserDataStore } from '../../stores/userData' const realTimeSessionsStore = useRealTimeSessionsStore() const configurationStore = useConfigurationStore() -const userDataStore = useUserDataStore() const isCapturingImages = computed(() => { if (configurationStore.demo == true) { @@ -144,21 +143,6 @@ const sendGoCommand = async () => { }) } -// This should change from configdbUrl/opticalelementgroups/128/ to -// https://observe.lco.global/api/instruments and map the instruments based on what telescope is being used -const getFilterList = async () => { - await fetchApiCall({ - url: configurationStore.configdbUrl + 'opticalelementgroups/128/', - method: 'GET', - successCallback: (data) => { - filterList.value = data.optical_elements - .filter(filter => filter.schedulable) - .map(filter => ({ name: filter.name, code: filter.code })) - }, - failCallback: (error) => { console.error('API failed with error', error) } - }) -} - function updateRenderGallery (value) { if (!value) { realTimeSessionsStore.updateImageCaptureState(false) @@ -174,9 +158,9 @@ watch(exposureTime, (newTime) => { exposureError.value = '' }) -onMounted(() => { +onMounted(async () => { loading.value = false - getFilterList() + filterList.value = await getFilterList() }) diff --git a/src/components/Scheduling/SchedulingSettings.vue b/src/components/Scheduling/SchedulingSettings.vue index 723645b..5e08d1a 100644 --- a/src/components/Scheduling/SchedulingSettings.vue +++ b/src/components/Scheduling/SchedulingSettings.vue @@ -1,7 +1,7 @@ diff --git a/src/tests/integration/components/schedulingSettings.test.js b/src/tests/integration/components/schedulingSettings.test.js index 4f7f835..f613c91 100644 --- a/src/tests/integration/components/schedulingSettings.test.js +++ b/src/tests/integration/components/schedulingSettings.test.js @@ -16,31 +16,6 @@ describe('SchedulingSettings.vue', () => { fetchApiCall.mockClear() const { pinia } = createTestStores() - fetchApiCall.mockImplementationOnce(({ successCallback }) => { - if (successCallback) { - successCallback({ - '0M4-SCICAM-QHY600': { - 'class': '0m4', - 'optical_elements': { - 'filters': [ - { name: 'Filter A', code: 'FA', schedulable: true }, - { name: 'Filter B', code: 'FB', schedulable: false } - ] - } - }, - '0M4-SCICAM-FLI': { - 'class': '0m4', - 'optical_elements': { - 'filters': [ - { name: 'Filter D', code: 'FD', schedulable: true }, - { name: 'Filter E', code: 'FE', schedulable: true } - ] - } - } - }) - } - }) - wrapper = mount(SchedulingSettings, { global: { plugins: [pinia], @@ -53,28 +28,6 @@ describe('SchedulingSettings.vue', () => { }) }) - it('calls fetchApiCall to get filter list on mount', async () => { - expect(fetchApiCall).toHaveBeenCalledWith( - expect.objectContaining({ - url: 'http://mock-api.com/instruments', - method: 'GET', - successCallback: expect.any(Function), - failCallback: expect.any(Function) - }) - ) - - await flushPromises() - - // filters through the non-schedulable filters - expect(wrapper.vm.filterList).toEqual([ - { name: 'Filter A', code: 'FA' }, - { name: 'Filter D', code: 'FD' }, - { name: 'Filter E', code: 'FE' } - ]) - - expect(fetchApiCall).toHaveBeenCalledTimes(1) - }) - it('fetches RA and Dec based on the target name and updates state correctly', async () => { const mockRaDecResponse = { 'dec': '+41 16 07.50', @@ -116,32 +69,4 @@ describe('SchedulingSettings.vue', () => { expect(wrapper.vm.targetError).toBe('Target not found, try another target.') }) - - it('emits exposuresUpdated when exposures are added', async () => { - // Checks that filterList has been populated correctly - expect(wrapper.vm.filterList).toEqual([ - { name: 'Filter A', code: 'FA' }, - { name: 'Filter D', code: 'FD' }, - { name: 'Filter E', code: 'FE' } - ]) - - // Simulates selecting a filter from the dropdown - wrapper.vm.settings.filter = 'FA' - wrapper.vm.settings.filterName = 'Filter A' - wrapper.vm.settings.exposureTime = '30' - wrapper.vm.settings.count = '15' - - await wrapper.vm.addExposure() - - // Check that the event is emitted with the expected payload - expect(wrapper.emitted().exposuresUpdated).toBeTruthy() - expect(wrapper.emitted().exposuresUpdated[0][0]).toEqual([ - { - filter: 'FA', - filterName: 'Filter A', - exposureTime: '30', - count: '15' - } - ]) - }) }) diff --git a/src/tests/unit/utils/populateInstrumentsUtils.test.js b/src/tests/unit/utils/populateInstrumentsUtils.test.js new file mode 100644 index 0000000..52971e1 --- /dev/null +++ b/src/tests/unit/utils/populateInstrumentsUtils.test.js @@ -0,0 +1,89 @@ +import { vi, describe, it, expect, beforeEach } from 'vitest' +import { getFilterList } from '../../../utils/populateInstrumentsUtils.js' +import { fetchApiCall } from '../../../utils/api.js' +import { createTestStores } from '../../../utils/testUtils' + +vi.mock('@/utils/api.js', () => ({ + fetchApiCall: vi.fn() +})) + +describe('thumbnailsUtils.js', () => { + let configurationStore + + beforeEach(() => { + const { configurationStore: store } = createTestStores() + configurationStore = store + fetchApiCall.mockClear() + }) + + describe('getFilterList', () => { + beforeEach(() => { + fetchApiCall.mockClear() + }) + + it('fetches instruments and returns schedulable filters', async () => { + // Mock API response + fetchApiCall.mockResolvedValueOnce({ + '0M4-SCICAM-QHY600': { + class: '0m4', + optical_elements: { + filters: [ + { name: 'Filter A', code: 'FA', schedulable: true }, + { name: 'Filter B', code: 'FB', schedulable: false } + ] + } + }, + '0M4-SCICAM-FLI': { + class: '0m4', + optical_elements: { + filters: [ + { name: 'Filter D', code: 'FD', schedulable: true }, + { name: 'Filter E', code: 'FE', schedulable: true } + ] + } + }, + // This instrument should be ignored + '1M0-SCICAM': { + class: '1m0', + optical_elements: { + filters: [ + { name: 'Filter X', code: 'FX', schedulable: true } + ] + } + } + }) + + const result = await getFilterList() + + expect(result).toEqual([ + { name: 'Filter A', code: 'FA' }, + { name: 'Filter D', code: 'FD' }, + { name: 'Filter E', code: 'FE' } + ]) + + expect(fetchApiCall).toHaveBeenCalledWith( + expect.objectContaining({ + url: expect.stringContaining('instruments'), + method: 'GET' + }) + ) + }) + + it('returns an empty array if no schedulable filters are found', async () => { + fetchApiCall.mockResolvedValueOnce({ + '0M4-SCICAM-QHY600': { + class: '0m4', + optical_elements: { + filters: [ + { name: 'Filter A', code: 'FA', schedulable: false } + ] + } + } + }) + + const result = await getFilterList() + + expect(result).toEqual([]) + }) + }) +}) diff --git a/src/utils/populateInstrumentsUtils.js b/src/utils/populateInstrumentsUtils.js new file mode 100644 index 0000000..7d28829 --- /dev/null +++ b/src/utils/populateInstrumentsUtils.js @@ -0,0 +1,24 @@ +import { fetchApiCall } from './api.js' +import { useConfigurationStore } from '../stores/configuration.js' + +export const getFilterList = async () => { + const configurationStore = useConfigurationStore() + const response = await fetchApiCall({ + url: `${configurationStore.observationPortalUrl}instruments`, + method: 'GET' + }) + const filterList = [] + if (!response) { + return filterList + } + const instrumentClass = '0m4' + Object.values(response).forEach((instrument) => { + if (instrument.class === instrumentClass && instrument.optical_elements.filters) { + const schedulableFilters = instrument.optical_elements.filters + .filter(filter => filter.schedulable) + .map(filter => ({ name: filter.name, code: filter.code })) + filterList.push(...schedulableFilters) + } + }) + return filterList +}