diff --git a/frontend/src/components/SkeletonBlock.vue b/frontend/src/components/SkeletonBlock.vue
deleted file mode 100644
index 89ab8d7c04..0000000000
--- a/frontend/src/components/SkeletonBlock.vue
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
diff --git a/frontend/src/composables/useActiveApplication.ts b/frontend/src/composables/useActiveApplication.ts
new file mode 100644
index 0000000000..1f7cad7209
--- /dev/null
+++ b/frontend/src/composables/useActiveApplication.ts
@@ -0,0 +1,27 @@
+import { useRouter } from 'vue-router'
+
+import { useDataFarmApplicationsStore } from '@/stores/data-farm-applications'
+import type { ApplicationSummary } from '@/types'
+
+export function useActiveApplication () {
+ const router = useRouter()
+ const applicationsStore = useDataFarmApplicationsStore()
+
+ async function loadActiveApplication (id: string): Promise {
+ if (!id) return null
+ try {
+ return await applicationsStore.loadActiveApplication(id)
+ } catch {
+ const current = router.currentRoute.value
+ router.push({
+ name: 'page-not-found',
+ params: { pathMatch: current.path.substring(1).split('/') },
+ query: current.query,
+ hash: current.hash
+ })
+ return null
+ }
+ }
+
+ return { loadActiveApplication }
+}
diff --git a/frontend/src/layouts/Page.vue b/frontend/src/layouts/Page.vue
index 6c9b758218..4baa4c85f0 100644
--- a/frontend/src/layouts/Page.vue
+++ b/frontend/src/layouts/Page.vue
@@ -1,11 +1,18 @@
-
-
-
-
+
+
+
+
+
+
+
-
-
diff --git a/frontend/src/pages/team/Applications/index.vue b/frontend/src/pages/team/Applications/index.vue
index 12e0cdcc09..e7c758b19a 100644
--- a/frontend/src/pages/team/Applications/index.vue
+++ b/frontend/src/pages/team/Applications/index.vue
@@ -33,9 +33,7 @@
-
-
-
+
({
route: null,
- application: null,
instance: null,
device: null
}),
getters: {
+ application () {
+ return useDataFarmApplicationsStore().activeApplication
+ },
team () {
return useDataFarmTeamsStore().activeTeam
},
@@ -97,7 +100,7 @@ export const useContextStore = defineStore('context', {
teamSlug: this.team?.slug || null,
instanceId: state.instance ? state.instance.id : null,
deviceId: state.device ? state.device.id : null,
- applicationId: state.application ? state.application.id : null,
+ applicationId: this.application ? this.application.id : null,
deviceOwnerType: state.device?.ownerType ?? null,
isTrialAccount: this.isTrialAccount,
pageName: state.route.name,
@@ -135,15 +138,7 @@ export const useContextStore = defineStore('context', {
this.setApplication(device?.application ?? null)
},
setApplication (application) {
- if (application) {
- this.application = {
- id: application.id,
- name: application.name,
- description: application.description,
- }
- } else {
- this.application = null
- }
+ useDataFarmApplicationsStore().setActiveApplication(application)
},
clearInstance () { this.setInstance(null) },
setTeam (team) {
diff --git a/frontend/src/stores/data-farm-applications.ts b/frontend/src/stores/data-farm-applications.ts
index 3afc4ac662..1cc290fe73 100644
--- a/frontend/src/stores/data-farm-applications.ts
+++ b/frontend/src/stores/data-farm-applications.ts
@@ -1,20 +1,25 @@
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
-import applicationApi from '../api/application.js'
-import teamApi from '../api/team.js'
-
+import applicationApi from '@/api/application.js'
+import teamApi from '@/api/team.js'
+import { useContextStore } from '@/stores/context.js'
import type { ApplicationSummary } from '@/types'
export const useDataFarmApplicationsStore = defineStore('data-farm-applications', () => {
const applicationsById = ref>({})
const teamApplicationIds = ref([])
- const loadedTeamId = ref(null)
- const isLoadingTeamApplications = ref(false)
+ const activeApplicationId = ref(null)
+ const applicationsListHydrated = ref(false)
+ const applicationHydrated = ref(false)
const teamApplications = computed(() => teamApplicationIds.value
.map(id => applicationsById.value[id]))
+ const activeApplication = computed(() => (activeApplicationId.value
+ ? applicationsById.value[activeApplicationId.value] ?? null
+ : null))
+
function upsertApplication (application: ApplicationSummary): void {
if (!application?.id) return
const existing = applicationsById.value[application.id]
@@ -29,30 +34,26 @@ export const useDataFarmApplicationsStore = defineStore('data-farm-applications'
teamApplicationIds.value = teamApplicationIds.value.filter(applicationId => applicationId !== id)
}
- async function ensureTeamApplicationsLoaded (teamId: string, { force = false } = {}): Promise {
+ async function ensureTeamApplicationsLoaded ({ force = false } = {}): Promise {
+ const teamId = useContextStore().team?.id
if (!teamId) return
- if (!force && loadedTeamId.value === teamId) return
-
- isLoadingTeamApplications.value = true
- try {
- const response = await teamApi.getTeamApplications(teamId, {
- includeApplicationSummary: true,
- includeInstances: false,
- includeApplicationDevices: false
- })
- const applications: ApplicationSummary[] = response.applications ?? []
- const byId: Record = {}
- const ids: string[] = []
- applications.forEach(application => {
- byId[application.id] = application
- ids.push(application.id)
- })
- applicationsById.value = byId
- teamApplicationIds.value = ids
- loadedTeamId.value = teamId
- } finally {
- isLoadingTeamApplications.value = false
- }
+ if (!force && applicationsListHydrated.value) return
+
+ const response = await teamApi.getTeamApplications(teamId, {
+ includeApplicationSummary: true,
+ includeInstances: false,
+ includeApplicationDevices: false
+ })
+ const applications: ApplicationSummary[] = response.applications ?? []
+ const byId: Record = {}
+ const ids: string[] = []
+ applications.forEach(application => {
+ byId[application.id] = application
+ ids.push(application.id)
+ })
+ applicationsById.value = byId
+ teamApplicationIds.value = ids
+ applicationsListHydrated.value = true
}
async function createApplication (payload: { name?: string, description?: string, teamId: string }): Promise {
@@ -72,6 +73,30 @@ export const useDataFarmApplicationsStore = defineStore('data-farm-applications'
removeApplication(id)
}
+ function setActiveApplication (application: ApplicationSummary | null): void {
+ if (!application?.id) {
+ activeApplicationId.value = null
+ applicationHydrated.value = false
+ return
+ }
+ const existing = applicationsById.value[application.id]
+ applicationsById.value[application.id] = { ...existing, ...application }
+ activeApplicationId.value = application.id
+ }
+
+ async function loadActiveApplication (id: string): Promise {
+ if (!id) return null
+ applicationHydrated.value = false
+ const application = await applicationApi.getApplication(id)
+ setActiveApplication(application)
+ applicationHydrated.value = true
+ return application
+ }
+
+ function clearActiveApplication (): void {
+ setActiveApplication(null)
+ }
+
function applyRealtimeEvent (event: { id?: string, action?: string, data?: ApplicationSummary }): void {
if (!event?.id || !event.action) return
if (event.action === 'deleted') {
@@ -84,22 +109,28 @@ export const useDataFarmApplicationsStore = defineStore('data-farm-applications'
function reset (): void {
applicationsById.value = {}
teamApplicationIds.value = []
- loadedTeamId.value = null
- isLoadingTeamApplications.value = false
+ activeApplicationId.value = null
+ applicationsListHydrated.value = false
+ applicationHydrated.value = false
}
return {
applicationsById,
teamApplicationIds,
- loadedTeamId,
- isLoadingTeamApplications,
+ activeApplicationId,
+ applicationsListHydrated,
+ applicationHydrated,
teamApplications,
+ activeApplication,
upsertApplication,
removeApplication,
ensureTeamApplicationsLoaded,
createApplication,
updateApplication,
deleteApplication,
+ setActiveApplication,
+ loadActiveApplication,
+ clearActiveApplication,
applyRealtimeEvent,
reset
}
diff --git a/frontend/src/stores/ux-loading.js b/frontend/src/stores/ux-loading.js
index b7f00bc44a..dbd1978360 100644
--- a/frontend/src/stores/ux-loading.js
+++ b/frontend/src/stores/ux-loading.js
@@ -3,7 +3,9 @@ import { defineStore } from 'pinia'
export const useUxLoadingStore = defineStore('ux-loading', {
state: () => ({
appLoader: true,
- offline: null
+ offline: null,
+ pageLoader: false,
+ pageLoaderMessage: null
}),
actions: {
setAppLoader (value) {
@@ -14,6 +16,10 @@ export const useUxLoadingStore = defineStore('ux-loading', {
},
setOffline (value) {
this.offline = value
+ },
+ setPageLoader (value, message = null) {
+ this.pageLoader = value
+ this.pageLoaderMessage = value ? message : null
}
}
})
diff --git a/test/unit/frontend/composables/useActiveApplication.spec.js b/test/unit/frontend/composables/useActiveApplication.spec.js
new file mode 100644
index 0000000000..29218ebbc0
--- /dev/null
+++ b/test/unit/frontend/composables/useActiveApplication.spec.js
@@ -0,0 +1,66 @@
+import { createPinia, setActivePinia } from 'pinia'
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
+
+import { useActiveApplication } from '../../../../frontend/src/composables/useActiveApplication.ts'
+import { useDataFarmApplicationsStore } from '../../../../frontend/src/stores/data-farm-applications.ts'
+
+const routerMock = vi.hoisted(() => ({
+ push: vi.fn(),
+ currentRoute: { value: { path: '/team/t1/applications/a1', query: { q: '1' }, hash: '#h' } }
+}))
+
+vi.mock('vue-router', async (importOriginal) => ({
+ ...await importOriginal(),
+ useRouter: () => routerMock
+}))
+
+describe('useActiveApplication', () => {
+ beforeEach(() => {
+ setActivePinia(createPinia())
+ routerMock.push.mockClear()
+ })
+
+ afterEach(() => {
+ vi.restoreAllMocks()
+ })
+
+ it('returns null and does not touch the store or router when no id is given', async () => {
+ const store = useDataFarmApplicationsStore()
+ const spy = vi.spyOn(store, 'loadActiveApplication')
+ const { loadActiveApplication } = useActiveApplication()
+
+ const result = await loadActiveApplication('')
+
+ expect(result).toBe(null)
+ expect(spy).not.toHaveBeenCalled()
+ expect(routerMock.push).not.toHaveBeenCalled()
+ })
+
+ it('delegates to the store and returns the application', async () => {
+ const store = useDataFarmApplicationsStore()
+ vi.spyOn(store, 'loadActiveApplication').mockResolvedValue({ id: 'a1', name: 'Detail' })
+ const { loadActiveApplication } = useActiveApplication()
+
+ const result = await loadActiveApplication('a1')
+
+ expect(store.loadActiveApplication).toHaveBeenCalledWith('a1')
+ expect(result).toEqual({ id: 'a1', name: 'Detail' })
+ expect(routerMock.push).not.toHaveBeenCalled()
+ })
+
+ it('redirects to page-not-found and returns null when the fetch fails', async () => {
+ const store = useDataFarmApplicationsStore()
+ vi.spyOn(store, 'loadActiveApplication').mockRejectedValue(new Error('boom'))
+ const { loadActiveApplication } = useActiveApplication()
+
+ const result = await loadActiveApplication('a1')
+
+ expect(result).toBe(null)
+ expect(routerMock.push).toHaveBeenCalledWith({
+ name: 'page-not-found',
+ params: { pathMatch: ['team', 't1', 'applications', 'a1'] },
+ query: { q: '1' },
+ hash: '#h'
+ })
+ })
+})
diff --git a/test/unit/frontend/stores/data-farm-applications.spec.js b/test/unit/frontend/stores/data-farm-applications.spec.js
index 8d144926e2..fa7606dcfb 100644
--- a/test/unit/frontend/stores/data-farm-applications.spec.js
+++ b/test/unit/frontend/stores/data-farm-applications.spec.js
@@ -4,10 +4,12 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import applicationApi from '@/api/application.js'
import teamApi from '@/api/team.js'
import { useDataFarmApplicationsStore } from '@/stores/data-farm-applications'
+import { useDataFarmTeamsStore } from '@/stores/data-farm-teams'
describe('data-farm-applications store', () => {
beforeEach(() => {
setActivePinia(createPinia())
+ useDataFarmTeamsStore().setActiveTeam({ id: 'team-1' })
})
afterEach(() => {
@@ -18,9 +20,9 @@ describe('data-farm-applications store', () => {
const store = useDataFarmApplicationsStore()
expect(store.applicationsById).toEqual({})
expect(store.teamApplicationIds).toEqual([])
- expect(store.loadedTeamId).toBe(null)
- expect(store.isLoadingTeamApplications).toBe(false)
expect(store.teamApplications).toEqual([])
+ expect(store.applicationsListHydrated).toBe(false)
+ expect(store.applicationHydrated).toBe(false)
})
describe('ensureTeamApplicationsLoaded', () => {
@@ -30,21 +32,20 @@ describe('data-farm-applications store', () => {
})
const store = useDataFarmApplicationsStore()
- await store.ensureTeamApplicationsLoaded('team-1')
+ await store.ensureTeamApplicationsLoaded()
expect(spy).toHaveBeenCalledWith('team-1', expect.objectContaining({ includeApplicationSummary: true }))
- expect(store.loadedTeamId).toBe('team-1')
expect(store.teamApplicationIds).toEqual(['a1', 'a2'])
expect(store.teamApplications.map(a => a.name)).toEqual(['One', 'Two'])
- expect(store.isLoadingTeamApplications).toBe(false)
+ expect(store.applicationsListHydrated).toBe(true)
})
it('does not refetch when the team is already loaded', async () => {
const spy = vi.spyOn(teamApi, 'getTeamApplications').mockResolvedValue({ applications: [{ id: 'a1' }] })
const store = useDataFarmApplicationsStore()
- await store.ensureTeamApplicationsLoaded('team-1')
- await store.ensureTeamApplicationsLoaded('team-1')
+ await store.ensureTeamApplicationsLoaded()
+ await store.ensureTeamApplicationsLoaded()
expect(spy).toHaveBeenCalledTimes(1)
})
@@ -53,31 +54,53 @@ describe('data-farm-applications store', () => {
const spy = vi.spyOn(teamApi, 'getTeamApplications').mockResolvedValue({ applications: [{ id: 'a1' }] })
const store = useDataFarmApplicationsStore()
- await store.ensureTeamApplicationsLoaded('team-1')
- await store.ensureTeamApplicationsLoaded('team-1', { force: true })
+ await store.ensureTeamApplicationsLoaded()
+ await store.ensureTeamApplicationsLoaded({ force: true })
expect(spy).toHaveBeenCalledTimes(2)
})
- it('refetches and replaces the list when the team changes', async () => {
+ it('replaces the list after reset when the team changes', async () => {
vi.spyOn(teamApi, 'getTeamApplications')
.mockResolvedValueOnce({ applications: [{ id: 'a1' }] })
.mockResolvedValueOnce({ applications: [{ id: 'b1' }] })
const store = useDataFarmApplicationsStore()
- await store.ensureTeamApplicationsLoaded('team-1')
- await store.ensureTeamApplicationsLoaded('team-2')
+ await store.ensureTeamApplicationsLoaded()
+ store.reset()
+ useDataFarmTeamsStore().setActiveTeam({ id: 'team-2' })
+ await store.ensureTeamApplicationsLoaded()
- expect(store.loadedTeamId).toBe('team-2')
expect(store.teamApplicationIds).toEqual(['b1'])
})
- it('clears the loading flag even when the fetch rejects', async () => {
+ it('does not mark the list hydrated when the fetch rejects', async () => {
vi.spyOn(teamApi, 'getTeamApplications').mockRejectedValue(new Error('boom'))
const store = useDataFarmApplicationsStore()
- await expect(store.ensureTeamApplicationsLoaded('team-1')).rejects.toThrow('boom')
- expect(store.isLoadingTeamApplications).toBe(false)
+ await expect(store.ensureTeamApplicationsLoaded()).rejects.toThrow('boom')
+ expect(store.applicationsListHydrated).toBe(false)
+ })
+
+ it('reads the current team from the context store', async () => {
+ const spy = vi.spyOn(teamApi, 'getTeamApplications').mockResolvedValue({ applications: [] })
+ useDataFarmTeamsStore().setActiveTeam({ id: 'team-9' })
+ const store = useDataFarmApplicationsStore()
+
+ await store.ensureTeamApplicationsLoaded()
+
+ expect(spy).toHaveBeenCalledWith('team-9', expect.any(Object))
+ })
+
+ it('does nothing when no team is set in context', async () => {
+ const spy = vi.spyOn(teamApi, 'getTeamApplications').mockResolvedValue({ applications: [] })
+ useDataFarmTeamsStore().setActiveTeam(null)
+ const store = useDataFarmApplicationsStore()
+
+ await store.ensureTeamApplicationsLoaded()
+
+ expect(spy).not.toHaveBeenCalled()
+ expect(store.applicationsListHydrated).toBe(false)
})
})
@@ -86,7 +109,7 @@ describe('data-farm-applications store', () => {
vi.spyOn(teamApi, 'getTeamApplications').mockResolvedValue({ applications: [{ id: 'a1', name: 'One' }] })
vi.spyOn(applicationApi, 'createApplication').mockResolvedValue({ id: 'a2', name: 'New' })
const store = useDataFarmApplicationsStore()
- await store.ensureTeamApplicationsLoaded('team-1')
+ await store.ensureTeamApplicationsLoaded()
const created = await store.createApplication({ name: 'New', teamId: 'team-1' })
@@ -104,7 +127,7 @@ describe('data-farm-applications store', () => {
})
vi.spyOn(applicationApi, 'updateApplication').mockResolvedValue({ id: 'a1', name: 'Renamed', description: 'd' })
const store = useDataFarmApplicationsStore()
- await store.ensureTeamApplicationsLoaded('team-1')
+ await store.ensureTeamApplicationsLoaded()
await store.updateApplication('a1', { name: 'Renamed', description: 'd' })
@@ -121,7 +144,7 @@ describe('data-farm-applications store', () => {
})
vi.spyOn(applicationApi, 'deleteApplication').mockResolvedValue(undefined)
const store = useDataFarmApplicationsStore()
- await store.ensureTeamApplicationsLoaded('team-1')
+ await store.ensureTeamApplicationsLoaded()
await store.deleteApplication('a1', 'team-1')
@@ -151,7 +174,7 @@ describe('data-farm-applications store', () => {
it('upserts on a created event (cross-session add)', async () => {
vi.spyOn(teamApi, 'getTeamApplications').mockResolvedValue({ applications: [{ id: 'a1', name: 'One' }] })
const store = useDataFarmApplicationsStore()
- await store.ensureTeamApplicationsLoaded('team-1')
+ await store.ensureTeamApplicationsLoaded()
store.applyRealtimeEvent({ id: 'a2', action: 'created', data: { id: 'a2', name: 'Two' } })
@@ -164,7 +187,7 @@ describe('data-farm-applications store', () => {
applications: [{ id: 'a1', name: 'Old', instanceCount: 3 }]
})
const store = useDataFarmApplicationsStore()
- await store.ensureTeamApplicationsLoaded('team-1')
+ await store.ensureTeamApplicationsLoaded()
store.applyRealtimeEvent({ id: 'a1', action: 'updated', data: { id: 'a1', name: 'Renamed' } })
@@ -174,7 +197,7 @@ describe('data-farm-applications store', () => {
it('removes on a deleted event (cross-session remove)', async () => {
vi.spyOn(teamApi, 'getTeamApplications').mockResolvedValue({ applications: [{ id: 'a1' }, { id: 'a2' }] })
const store = useDataFarmApplicationsStore()
- await store.ensureTeamApplicationsLoaded('team-1')
+ await store.ensureTeamApplicationsLoaded()
store.applyRealtimeEvent({ id: 'a1', action: 'deleted' })
@@ -196,18 +219,93 @@ describe('data-farm-applications store', () => {
})
})
+ describe('loadActiveApplication', () => {
+ it('fetches the application, sets it active, and returns it', async () => {
+ vi.spyOn(applicationApi, 'getApplication').mockResolvedValue({ id: 'a1', name: 'Detail' })
+ const store = useDataFarmApplicationsStore()
+
+ const application = await store.loadActiveApplication('a1')
+
+ expect(applicationApi.getApplication).toHaveBeenCalledWith('a1')
+ expect(application).toEqual({ id: 'a1', name: 'Detail' })
+ expect(store.activeApplication).toEqual({ id: 'a1', name: 'Detail' })
+ expect(store.applicationHydrated).toBe(true)
+ // the active app is cached but not a member of the team list
+ expect(store.teamApplicationIds).toEqual([])
+ })
+
+ it('does not mark the application hydrated when the fetch rejects', async () => {
+ vi.spyOn(applicationApi, 'getApplication').mockRejectedValue(new Error('boom'))
+ const store = useDataFarmApplicationsStore()
+
+ await expect(store.loadActiveApplication('a1')).rejects.toThrow('boom')
+ expect(store.applicationHydrated).toBe(false)
+ })
+ })
+
+ describe('setActiveApplication / activeApplication', () => {
+ it('returns null when no active application is set', () => {
+ const store = useDataFarmApplicationsStore()
+ expect(store.activeApplication).toBe(null)
+ })
+
+ it('sets the active application and caches it WITHOUT adding it to the team list', () => {
+ const store = useDataFarmApplicationsStore()
+
+ store.setActiveApplication({ id: 'a1', name: 'Detail' })
+
+ expect(store.activeApplication).toEqual({ id: 'a1', name: 'Detail' })
+ // the active app is not a list member — viewing it must not pollute teamApplications
+ expect(store.teamApplicationIds).toEqual([])
+ expect(store.teamApplications).toEqual([])
+ })
+
+ it('merges into an existing list entry without duplicating its id', async () => {
+ vi.spyOn(teamApi, 'getTeamApplications').mockResolvedValue({
+ applications: [{ id: 'a1', name: 'One', instanceCount: 2 }]
+ })
+ const store = useDataFarmApplicationsStore()
+ await store.ensureTeamApplicationsLoaded()
+
+ store.setActiveApplication({ id: 'a1', name: 'One', description: 'd' })
+
+ expect(store.activeApplication).toEqual({ id: 'a1', name: 'One', description: 'd', instanceCount: 2 })
+ expect(store.teamApplicationIds).toEqual(['a1'])
+ })
+
+ it('clears the active application and its hydration flag on null', () => {
+ const store = useDataFarmApplicationsStore()
+ store.setActiveApplication({ id: 'a1', name: 'Detail' })
+ store.applicationHydrated = true
+ store.setActiveApplication(null)
+ expect(store.activeApplication).toBe(null)
+ expect(store.applicationHydrated).toBe(false)
+ })
+
+ it('clearActiveApplication resets the active application and its hydration flag', () => {
+ const store = useDataFarmApplicationsStore()
+ store.setActiveApplication({ id: 'a1', name: 'Detail' })
+ store.applicationHydrated = true
+ store.clearActiveApplication()
+ expect(store.activeApplication).toBe(null)
+ expect(store.applicationHydrated).toBe(false)
+ })
+ })
+
describe('reset', () => {
it('resets all state (team-switch / logout teardown)', async () => {
vi.spyOn(teamApi, 'getTeamApplications').mockResolvedValue({ applications: [{ id: 'a1' }] })
const store = useDataFarmApplicationsStore()
- await store.ensureTeamApplicationsLoaded('team-1')
+ await store.ensureTeamApplicationsLoaded()
+ store.setActiveApplication({ id: 'a1' })
store.reset()
expect(store.applicationsById).toEqual({})
expect(store.teamApplicationIds).toEqual([])
- expect(store.loadedTeamId).toBe(null)
- expect(store.isLoadingTeamApplications).toBe(false)
+ expect(store.activeApplication).toBe(null)
+ expect(store.applicationsListHydrated).toBe(false)
+ expect(store.applicationHydrated).toBe(false)
})
})
})
diff --git a/test/unit/frontend/stores/ux-loading.spec.js b/test/unit/frontend/stores/ux-loading.spec.js
index d890c988bd..4caa3aef3b 100644
--- a/test/unit/frontend/stores/ux-loading.spec.js
+++ b/test/unit/frontend/stores/ux-loading.spec.js
@@ -42,14 +42,48 @@ describe('ux-loading store', () => {
})
})
+ describe('page loader', () => {
+ it('starts inactive with no message', () => {
+ const store = useUxLoadingStore()
+ expect(store.pageLoader).toBe(false)
+ expect(store.pageLoaderMessage).toBeNull()
+ })
+
+ it('setPageLoader with true stores the loader and message', () => {
+ const store = useUxLoadingStore()
+ store.setPageLoader(true, 'Loading Applications...')
+ expect(store.pageLoader).toBe(true)
+ expect(store.pageLoaderMessage).toBe('Loading Applications...')
+ })
+
+ it('setPageLoader with false clears the loader and message', () => {
+ const store = useUxLoadingStore()
+ store.setPageLoader(true, 'Loading Applications...')
+ store.setPageLoader(false)
+ expect(store.pageLoader).toBe(false)
+ expect(store.pageLoaderMessage).toBeNull()
+ })
+
+ it('setPageLoader with true and no message clears a previously-set message', () => {
+ const store = useUxLoadingStore()
+ store.setPageLoader(true, 'Loading Applications...')
+ store.setPageLoader(true)
+ expect(store.pageLoader).toBe(true)
+ expect(store.pageLoaderMessage).toBeNull()
+ })
+ })
+
describe('$reset', () => {
it('restores default state', () => {
const store = useUxLoadingStore()
store.appLoader = false
store.offline = true
+ store.setPageLoader(true, 'Loading Applications...')
store.$reset()
expect(store.appLoader).toBe(true)
expect(store.offline).toBeNull()
+ expect(store.pageLoader).toBe(false)
+ expect(store.pageLoaderMessage).toBeNull()
})
})
})