mirror of
https://github.com/directus/directus.git
synced 2026-02-16 15:05:13 -05:00
Add projects-store with tests
This commit is contained in:
158
src/stores/projects.test.ts
Normal file
158
src/stores/projects.test.ts
Normal file
@@ -0,0 +1,158 @@
|
||||
import Vue from 'vue';
|
||||
import VueCompositionAPI from '@vue/composition-api';
|
||||
import api from '@/api';
|
||||
import { useProjectsStore } from './projects';
|
||||
import { setActiveReq } from 'pinia';
|
||||
|
||||
describe('Stores / Projects', () => {
|
||||
beforeAll(() => {
|
||||
Vue.use(VueCompositionAPI);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
setActiveReq({});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('getProjects', () => {
|
||||
it('Fetches the project info for each individual project', async () => {
|
||||
const spy = jest.spyOn(api, 'get');
|
||||
|
||||
spy.mockImplementation((path: string) => {
|
||||
switch (path) {
|
||||
case '/server/projects':
|
||||
return Promise.resolve({
|
||||
data: { data: ['my-project', 'another-project'] }
|
||||
});
|
||||
case '/my-project/':
|
||||
case '/another-project/':
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
data: {}
|
||||
}
|
||||
});
|
||||
}
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
const projectsStore = useProjectsStore();
|
||||
await projectsStore.getProjects();
|
||||
|
||||
expect(spy).toHaveBeenCalledWith('/server/projects');
|
||||
expect(spy).toHaveBeenCalledWith('/my-project/');
|
||||
expect(spy).toHaveBeenCalledWith('/another-project/');
|
||||
|
||||
expect(projectsStore.state.error).toBe(null);
|
||||
expect(projectsStore.state.projects).toEqual([
|
||||
{ key: 'my-project' },
|
||||
{ key: 'another-project' }
|
||||
]);
|
||||
});
|
||||
|
||||
it('Sets the error state if the API errors out while fetching project keys', async () => {
|
||||
const spy = jest.spyOn(api, 'get');
|
||||
|
||||
spy.mockImplementation((path: string) => {
|
||||
switch (path) {
|
||||
case '/server/projects':
|
||||
return Promise.reject({ response: { status: 500 }, message: 'Error' });
|
||||
}
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
const projectsStore = useProjectsStore();
|
||||
await projectsStore.getProjects();
|
||||
|
||||
expect(projectsStore.state.error).toEqual({ status: 500, error: 'Error' });
|
||||
});
|
||||
|
||||
it('Sets the needsInstall boolean to true if the API returns a 503 error on projects retrieving', async () => {
|
||||
const spy = jest.spyOn(api, 'get');
|
||||
|
||||
spy.mockImplementation((path: string) => {
|
||||
switch (path) {
|
||||
case '/server/projects':
|
||||
return Promise.reject({ response: { status: 503 } });
|
||||
}
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
const projectsStore = useProjectsStore();
|
||||
await projectsStore.getProjects();
|
||||
|
||||
expect(projectsStore.state.error).toBe(null);
|
||||
expect(projectsStore.state.needsInstall).toBe(true);
|
||||
});
|
||||
|
||||
it('Adds an error key to the individual project if one of them fails', async () => {
|
||||
const spy = jest.spyOn(api, 'get');
|
||||
|
||||
spy.mockImplementation((path: string) => {
|
||||
switch (path) {
|
||||
case '/server/projects':
|
||||
return Promise.resolve({
|
||||
data: { data: ['my-project', 'another-project'] }
|
||||
});
|
||||
case '/my-project/':
|
||||
return Promise.resolve({ data: {} });
|
||||
case '/another-project/':
|
||||
return Promise.reject({
|
||||
response: {
|
||||
status: 500,
|
||||
data: {
|
||||
error: {
|
||||
code: 10,
|
||||
message: 'error message'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
const projectsStore = useProjectsStore();
|
||||
await projectsStore.getProjects();
|
||||
|
||||
expect(projectsStore.state.projects).toEqual([
|
||||
{ key: 'my-project' },
|
||||
{ key: 'another-project', error: 'error message', status: 500 }
|
||||
]);
|
||||
});
|
||||
|
||||
it('Uses the error message of the request if API did not return any data', async () => {
|
||||
const spy = jest.spyOn(api, 'get');
|
||||
|
||||
spy.mockImplementation((path: string) => {
|
||||
switch (path) {
|
||||
case '/server/projects':
|
||||
return Promise.resolve({
|
||||
data: { data: ['my-project', 'another-project'] }
|
||||
});
|
||||
case '/my-project/':
|
||||
return Promise.resolve({ data: {} });
|
||||
case '/another-project/':
|
||||
return Promise.reject({
|
||||
message: 'Error fallback',
|
||||
response: {
|
||||
status: 500,
|
||||
data: {}
|
||||
}
|
||||
});
|
||||
}
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
const projectsStore = useProjectsStore();
|
||||
await projectsStore.getProjects();
|
||||
|
||||
expect(projectsStore.state.projects).toEqual([
|
||||
{ key: 'my-project' },
|
||||
{ key: 'another-project', error: 'Error fallback', status: 500 }
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
63
src/stores/projects.ts
Normal file
63
src/stores/projects.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { createStore } from 'pinia';
|
||||
import { Project } from '@/types/project';
|
||||
import api from '@/api';
|
||||
|
||||
interface ProjectWithKey extends Project {
|
||||
key: string;
|
||||
}
|
||||
|
||||
interface ProjectError {
|
||||
key: string;
|
||||
status: number;
|
||||
error: {
|
||||
code: number;
|
||||
message: string;
|
||||
} | null;
|
||||
}
|
||||
|
||||
type Projects = (ProjectWithKey | ProjectError)[];
|
||||
|
||||
export const useProjectsStore = createStore({
|
||||
id: 'projects',
|
||||
state: () => ({
|
||||
needsInstall: false,
|
||||
error: null as any,
|
||||
projects: [] as Projects
|
||||
}),
|
||||
actions: {
|
||||
async getProjects() {
|
||||
try {
|
||||
const projectsResponse = await api.get('/server/projects');
|
||||
const projectKeys: string[] = projectsResponse.data.data;
|
||||
let projects: Projects = [];
|
||||
|
||||
for (let index = 0; index < projectKeys.length; index++) {
|
||||
try {
|
||||
const projectInfoResponse = await api.get(`/${projectKeys[index]}/`);
|
||||
projects.push({
|
||||
key: projectKeys[index],
|
||||
...projectInfoResponse.data.data
|
||||
});
|
||||
} catch (error) {
|
||||
projects.push({
|
||||
key: projectKeys[index],
|
||||
status: error.response.status,
|
||||
error: error.response.data?.error?.message || error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.state.projects = projects;
|
||||
} catch (error) {
|
||||
if (error.response.status === 503) {
|
||||
this.state.needsInstall = true;
|
||||
} else {
|
||||
this.state.error = {
|
||||
status: error.response.status,
|
||||
error: error.message
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user