• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

atlp-rwanda / champs-ec-fe / 13ba735d-90f9-49d3-9acb-f5a6c957f324

18 Jun 2024 10:20PM UTC coverage: 58.852% (-28.3%) from 87.175%
13ba735d-90f9-49d3-9acb-f5a6c957f324

Pull #13

circleci

k3lly003
Merge pull request #26 from atlp-rwanda/ft-disable-users-#187300202

Ft disable users #187300202
Pull Request #13: feat(ProductView): ProductView (all/one) according to there user's role #187300196

70 of 95 branches covered (73.68%)

Branch coverage included in aggregate %.

84 of 626 new or added lines in 24 files covered. (13.42%)

219 existing lines in 7 files now uncovered.

1366 of 2345 relevant lines covered (58.25%)

2.27 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

52.14
/src/redux/slices/productSlice.ts
1
import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit';
1✔
2
import axios from 'axios';
1✔
3

1✔
4
interface IProduct {
1✔
5
  id: string;
1✔
6
  productName: string;
1✔
7
  productCategory: string;
1✔
8
  productPrice: number;
1✔
9
  discount: number;
1✔
10
  currency: string;
1✔
11
  expireDate: string;
1✔
12
  stockLevel: number;
1✔
13
  description: string;
1✔
14
  loading: false;
1✔
15
  productPictures: File[];
1✔
16
}
1✔
17

1✔
18
interface ICategory {
1✔
19
  id: string;
1✔
20
  categoryName: string;
1✔
21
}
1✔
22

1✔
23
interface ICreateProductInput {
1✔
24
  productName: string;
1✔
25
  productCategory: string;
1✔
26
  productPrice: number;
1✔
27
  discount: number;
1✔
28
  currency: string;
1✔
29
  expireDate: string;
1✔
30
  stockLevel: number;
1✔
31
  description: string;
1✔
32
  productPictures: File[];
1✔
33
}
1✔
34

1✔
35
const URL = process.env.NEXT_PUBLIC_URL;
1✔
36

1✔
37
export const fetchCategories = createAsyncThunk(
1✔
38
  'products/fetchCategories',
1✔
39
  async (_, { rejectWithValue }) => {
1✔
UNCOV
40
    try {
×
UNCOV
41
      const response = await axios.get(`${URL}/categories`, {
×
UNCOV
42
        headers: {
×
UNCOV
43
          Authorization: `Bearer ${localStorage.getItem('token')}`,
×
UNCOV
44
        },
×
UNCOV
45
      });
×
46
      return response.data.categories;
×
UNCOV
47
    } catch (error: any) {
×
UNCOV
48
      if (error.response && error.response.data.error) {
×
49
        return rejectWithValue(error.response.data);
×
50
      } else {
×
51
        return rejectWithValue(error.message);
×
52
      }
×
UNCOV
53
    }
×
UNCOV
54
  }
×
55
);
1✔
56

1✔
57
export const createProduct = createAsyncThunk(
1✔
58
  'products/createProduct',
1✔
59
  async (data: ICreateProductInput, { rejectWithValue }) => {
1✔
60
    try {
×
61
      const token = localStorage.getItem('token');
×
62
      if (!token) {
×
63
        throw new Error('No token found');
×
64
      }
×
65

×
66
      const formData = new FormData();
×
67
      formData.append('productName', data.productName);
×
68
      formData.append('productCategory', data.productCategory);
×
69
      formData.append('productPrice', data.productPrice.toString());
×
70
      // formData.append('discount', data.discount.toString());
×
71
      formData.append('productCurrency', data.currency.trim());
×
72
      formData.append('expireDate', data.expireDate);
×
73
      formData.append('stockLevel', data.stockLevel.toString());
×
74
      formData.append('productDescription', data.description);
×
75
      for (const picture of data.productPictures) {
×
76
        formData.append('productImage', picture);
×
77
      }
×
78

×
79
      const response = await axios.post(`${URL}/products`, formData, {
×
80
        headers: {
×
81
          Authorization: `Bearer ${token}`,
×
82
          'Content-Type': 'multipart/form-data',
×
83
        },
×
84
      });
×
85
      return response.data;
×
86
    } catch (error: any) {
×
87
      if (error.response && error.response.data) {
×
88
        return rejectWithValue(error.response.data);
×
89
      } else {
×
90
        return rejectWithValue(error.message);
×
91
      }
×
92
    }
×
93
  }
×
94
);
1✔
95

1✔
96
const productsSlice = createSlice({
1✔
97
  name: 'products',
1✔
98
  initialState: {
1✔
99
    products: [] as IProduct[],
1✔
100
    categories: [] as ICategory[],
1✔
101
    status: 'idle' as string,
1✔
102
    error: null as string | null,
1✔
103
  },
1✔
104
  reducers: {
1✔
105
    addProduct: (state, action: PayloadAction<IProduct>) => {
1✔
106
      state.products.push(action.payload);
×
107
    },
×
108
  },
1✔
109
  extraReducers: (builder) => {
1✔
110
    builder
4✔
111
      .addCase(fetchCategories.pending, (state) => {
4✔
UNCOV
112
        state.status = 'loading';
×
UNCOV
113
      })
×
114
      .addCase(fetchCategories.fulfilled, (state, action) => {
4✔
115
        state.status = 'succeeded';
×
116
        state.categories = action.payload;
×
117
      })
×
118
      .addCase(fetchCategories.rejected, (state, action) => {
4✔
UNCOV
119
        state.status = 'failed';
×
UNCOV
120
        state.error = action.payload as string;
×
UNCOV
121
      })
×
122
      .addCase(createProduct.pending, (state) => {
4✔
123
        state.status = 'loading';
×
124
      })
×
125
      .addCase(createProduct.fulfilled, (state, action) => {
4✔
126
        state.status = 'succeeded';
×
127
        state.products.push(action.payload);
×
128
      })
×
129
      .addCase(createProduct.rejected, (state, action) => {
4✔
130
        state.status = 'failed';
×
131
        state.error = action.payload as string;
×
132
      });
×
133
  },
4✔
134
});
1✔
135

1✔
136
export const { addProduct } = productsSlice.actions;
1✔
137
const productsAddReducers = productsSlice.reducer;
1✔
138

1✔
139
export default productsAddReducers;
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc