@opencloning/ui 1.5.6 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/package.json +10 -3
- package/src/components/dummy/index.js +1 -0
- package/src/hooks/useDatabase.js +2 -17
- package/src/providers/DatabaseContext.jsx +15 -0
- package/src/version.js +1 -1
- package/src/components/eLabFTW/ELabFTWCategorySelect.cy.jsx +0 -86
- package/src/components/eLabFTW/ELabFTWCategorySelect.jsx +0 -43
- package/src/components/eLabFTW/ELabFTWFileSelect.cy.jsx +0 -43
- package/src/components/eLabFTW/ELabFTWFileSelect.jsx +0 -29
- package/src/components/eLabFTW/ELabFTWResourceSelect.cy.jsx +0 -107
- package/src/components/eLabFTW/ELabFTWResourceSelect.jsx +0 -23
- package/src/components/eLabFTW/GetPrimerComponent.cy.jsx +0 -261
- package/src/components/eLabFTW/GetPrimerComponent.jsx +0 -55
- package/src/components/eLabFTW/GetSequenceFileAndDatabaseIdComponent.cy.jsx +0 -184
- package/src/components/eLabFTW/GetSequenceFileAndDatabaseIdComponent.jsx +0 -62
- package/src/components/eLabFTW/LoadHistoryComponent.cy.jsx +0 -235
- package/src/components/eLabFTW/LoadHistoryComponent.jsx +0 -51
- package/src/components/eLabFTW/PrimersNotInDatabaseComponent.cy.jsx +0 -159
- package/src/components/eLabFTW/PrimersNotInDatabaseComponent.jsx +0 -54
- package/src/components/eLabFTW/SubmitToDatabaseComponent.cy.jsx +0 -185
- package/src/components/eLabFTW/SubmitToDatabaseComponent.jsx +0 -51
- package/src/components/eLabFTW/common.js +0 -26
- package/src/components/eLabFTW/eLabFTWInterface.js +0 -293
- package/src/components/eLabFTW/eLabFTWInterface.test.js +0 -839
- package/src/components/eLabFTW/envValues.js +0 -7
- package/src/components/eLabFTW/utils.js +0 -30
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import GetPrimerComponent from './GetPrimerComponent';
|
|
3
|
-
import { eLabFTWHttpClient } from './common';
|
|
4
|
-
|
|
5
|
-
const PRIMER_CATEGORY_ID = 3;
|
|
6
|
-
|
|
7
|
-
describe('<GetPrimerComponent />', () => {
|
|
8
|
-
it('shows category select and then resource select after category is chosen', () => {
|
|
9
|
-
const setPrimerSpy = cy.spy().as('setPrimerSpy');
|
|
10
|
-
const setErrorSpy = cy.spy().as('setErrorSpy');
|
|
11
|
-
|
|
12
|
-
// Stub both endpoints in a single stub
|
|
13
|
-
cy.stub(eLabFTWHttpClient, 'get').callsFake((url) => {
|
|
14
|
-
if (url === '/api/v2/items_types') {
|
|
15
|
-
return Promise.resolve({
|
|
16
|
-
data: [
|
|
17
|
-
{ id: PRIMER_CATEGORY_ID, title: 'Primers' },
|
|
18
|
-
{ id: 2, title: 'Other Category' },
|
|
19
|
-
],
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
return Promise.resolve({ data: [] });
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
cy.mount(<GetPrimerComponent setPrimer={setPrimerSpy} setError={setErrorSpy} />);
|
|
26
|
-
|
|
27
|
-
// Initially, only category select should be visible
|
|
28
|
-
cy.get('.MuiAutocomplete-root').should('have.length', 1);
|
|
29
|
-
|
|
30
|
-
// Select a category
|
|
31
|
-
cy.get('.MuiAutocomplete-input').first().click();
|
|
32
|
-
cy.get('.MuiAutocomplete-input').first().type('Primers');
|
|
33
|
-
cy.get('li').contains('Primers').click();
|
|
34
|
-
|
|
35
|
-
// Now resource select should appear
|
|
36
|
-
cy.get('.MuiAutocomplete-root').should('have.length', 2);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('successfully selects a primer with valid metadata', () => {
|
|
40
|
-
const setPrimerSpy = cy.spy().as('setPrimerSpy');
|
|
41
|
-
const setErrorSpy = cy.spy().as('setErrorSpy');
|
|
42
|
-
|
|
43
|
-
// Stub both endpoints in a single stub
|
|
44
|
-
cy.stub(eLabFTWHttpClient, 'get').callsFake((url, config) => {
|
|
45
|
-
if (url === '/api/v2/items_types') {
|
|
46
|
-
return Promise.resolve({
|
|
47
|
-
data: [{ id: PRIMER_CATEGORY_ID, title: 'Primers' }],
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
if (url === '/api/v2/items' && config?.params?.cat === PRIMER_CATEGORY_ID) {
|
|
51
|
-
return Promise.resolve({
|
|
52
|
-
data: [{
|
|
53
|
-
id: 1,
|
|
54
|
-
title: 'Test Primer',
|
|
55
|
-
metadata: JSON.stringify({
|
|
56
|
-
extra_fields: {
|
|
57
|
-
sequence: { value: 'ATCG' },
|
|
58
|
-
},
|
|
59
|
-
}),
|
|
60
|
-
}],
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
return Promise.resolve({ data: [] });
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
cy.mount(<GetPrimerComponent setPrimer={setPrimerSpy} setError={setErrorSpy} />);
|
|
67
|
-
|
|
68
|
-
// Select category
|
|
69
|
-
cy.get('.MuiAutocomplete-input').first().click();
|
|
70
|
-
cy.get('.MuiAutocomplete-input').first().type('Primers');
|
|
71
|
-
cy.get('li').contains('Primers').click();
|
|
72
|
-
|
|
73
|
-
// Select primer
|
|
74
|
-
cy.get('.MuiAutocomplete-input').last().type('test');
|
|
75
|
-
cy.get('li').contains('Test Primer').click();
|
|
76
|
-
|
|
77
|
-
// Check if setPrimer was called with correct data
|
|
78
|
-
cy.get('@setPrimerSpy').should('have.been.calledWith', {
|
|
79
|
-
name: 'Test Primer',
|
|
80
|
-
sequence: 'ATCG',
|
|
81
|
-
database_id: 1,
|
|
82
|
-
});
|
|
83
|
-
cy.get('@setErrorSpy').should('not.have.been.called');
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('handles primer with invalid metadata', () => {
|
|
87
|
-
const setPrimerSpy = cy.spy().as('setPrimerSpy');
|
|
88
|
-
const setErrorSpy = cy.spy().as('setErrorSpy');
|
|
89
|
-
|
|
90
|
-
// Stub both endpoints in a single stub
|
|
91
|
-
cy.stub(eLabFTWHttpClient, 'get').callsFake((url, config) => {
|
|
92
|
-
if (url === '/api/v2/items_types') {
|
|
93
|
-
return Promise.resolve({
|
|
94
|
-
data: [{ id: PRIMER_CATEGORY_ID, title: 'Primers' }],
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
if (url === '/api/v2/items' && config?.params?.cat === PRIMER_CATEGORY_ID) {
|
|
98
|
-
return Promise.resolve({
|
|
99
|
-
data: [{
|
|
100
|
-
id: 1,
|
|
101
|
-
title: 'Invalid Primer',
|
|
102
|
-
metadata: JSON.stringify({
|
|
103
|
-
extra_fields: {
|
|
104
|
-
// Missing sequence field
|
|
105
|
-
},
|
|
106
|
-
}),
|
|
107
|
-
}],
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
if (url === '/api/v2/info') {
|
|
111
|
-
return Promise.resolve({
|
|
112
|
-
data: {
|
|
113
|
-
elabftw_version_int: 50200,
|
|
114
|
-
},
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
cy.mount(<GetPrimerComponent setPrimer={setPrimerSpy} setError={setErrorSpy} />);
|
|
120
|
-
|
|
121
|
-
// Select category
|
|
122
|
-
cy.get('.MuiAutocomplete-input').first().click();
|
|
123
|
-
cy.get('.MuiAutocomplete-input').first().type('Primers');
|
|
124
|
-
cy.get('li').contains('Primers').click();
|
|
125
|
-
|
|
126
|
-
// Select primer
|
|
127
|
-
cy.get('.MuiAutocomplete-input').last().type('test');
|
|
128
|
-
cy.get('li').contains('Invalid Primer').click();
|
|
129
|
-
|
|
130
|
-
// Check if error was set and primer was cleared
|
|
131
|
-
cy.get('@setErrorSpy').should('have.been.calledWith', 'No sequence found in metadata');
|
|
132
|
-
cy.get('@setPrimerSpy').should('have.been.calledWith', null);
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it('clears primer when category is cleared', () => {
|
|
136
|
-
const setPrimerSpy = cy.spy().as('setPrimerSpy');
|
|
137
|
-
const setErrorSpy = cy.spy().as('setErrorSpy');
|
|
138
|
-
|
|
139
|
-
cy.stub(eLabFTWHttpClient, 'get').callsFake((url) => {
|
|
140
|
-
if (url === '/api/v2/items_types') {
|
|
141
|
-
return Promise.resolve({
|
|
142
|
-
data: [{ id: PRIMER_CATEGORY_ID, title: 'Primers' }],
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
if (url === '/api/v2/info') {
|
|
146
|
-
return Promise.resolve({
|
|
147
|
-
data: {
|
|
148
|
-
elabftw_version_int: 50200,
|
|
149
|
-
},
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
cy.mount(<GetPrimerComponent setPrimer={setPrimerSpy} setError={setErrorSpy} />);
|
|
155
|
-
|
|
156
|
-
// Select category
|
|
157
|
-
cy.get('.MuiAutocomplete-input').first().click();
|
|
158
|
-
cy.get('.MuiAutocomplete-input').first().type('Primers');
|
|
159
|
-
cy.get('li').contains('Primers').click();
|
|
160
|
-
|
|
161
|
-
// Clear category
|
|
162
|
-
cy.get('.MuiAutocomplete-clearIndicator').first().click();
|
|
163
|
-
|
|
164
|
-
// Check if primer was cleared
|
|
165
|
-
cy.get('@setPrimerSpy').should('have.been.calledWith', null);
|
|
166
|
-
cy.get('.MuiAutocomplete-root').should('have.length', 1);
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
it('clears error when resource is cleared', () => {
|
|
170
|
-
const setPrimerSpy = cy.spy().as('setPrimerSpy');
|
|
171
|
-
const setErrorSpy = cy.spy().as('setErrorSpy');
|
|
172
|
-
|
|
173
|
-
// Stub both endpoints in a single stub
|
|
174
|
-
cy.stub(eLabFTWHttpClient, 'get').callsFake((url, config) => {
|
|
175
|
-
if (url === '/api/v2/items_types') {
|
|
176
|
-
return Promise.resolve({
|
|
177
|
-
data: [{ id: PRIMER_CATEGORY_ID, title: 'Primers' }],
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
if (url === '/api/v2/items' && config?.params?.cat === PRIMER_CATEGORY_ID) {
|
|
181
|
-
return Promise.resolve({
|
|
182
|
-
data: [{
|
|
183
|
-
id: 1,
|
|
184
|
-
title: 'Invalid Primer',
|
|
185
|
-
metadata: '{invalid json}',
|
|
186
|
-
}],
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
if (url === '/api/v2/info') {
|
|
190
|
-
return Promise.resolve({
|
|
191
|
-
data: {
|
|
192
|
-
elabftw_version_int: 50200,
|
|
193
|
-
},
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
cy.mount(<GetPrimerComponent setPrimer={setPrimerSpy} setError={setErrorSpy} />);
|
|
199
|
-
|
|
200
|
-
// Select category
|
|
201
|
-
cy.get('.MuiAutocomplete-input').first().click();
|
|
202
|
-
cy.get('.MuiAutocomplete-input').first().type('Primers');
|
|
203
|
-
cy.get('li').contains('Primers').click();
|
|
204
|
-
|
|
205
|
-
// Select and then clear resource
|
|
206
|
-
cy.get('.MuiAutocomplete-input').last().type('test');
|
|
207
|
-
cy.get('li').contains('Invalid Primer').click();
|
|
208
|
-
cy.get('.MuiAutocomplete-clearIndicator').last().click();
|
|
209
|
-
|
|
210
|
-
// Check if error was cleared
|
|
211
|
-
cy.get('@setErrorSpy').should('have.been.calledWith', '');
|
|
212
|
-
cy.get('@setPrimerSpy').should('have.been.calledWith', null);
|
|
213
|
-
});
|
|
214
|
-
it('handles network errors', () => {
|
|
215
|
-
const setPrimerSpy = cy.spy().as('setPrimerSpy');
|
|
216
|
-
const setErrorSpy = cy.spy().as('setErrorSpy');
|
|
217
|
-
|
|
218
|
-
let firstCallCategory = true;
|
|
219
|
-
let firstCallPrimer = true;
|
|
220
|
-
cy.stub(eLabFTWHttpClient, 'get').callsFake((url, config) => {
|
|
221
|
-
if (url === '/api/v2/items_types') {
|
|
222
|
-
if (firstCallCategory) {
|
|
223
|
-
firstCallCategory = false;
|
|
224
|
-
return Promise.reject(new Error('Network error'));
|
|
225
|
-
}
|
|
226
|
-
return Promise.resolve({
|
|
227
|
-
data: [{ id: PRIMER_CATEGORY_ID, title: 'Primers' }],
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
if (url === '/api/v2/items' && config?.params?.cat === PRIMER_CATEGORY_ID) {
|
|
231
|
-
if (firstCallPrimer) {
|
|
232
|
-
firstCallPrimer = false;
|
|
233
|
-
return Promise.reject(new Error('Network error'));
|
|
234
|
-
}
|
|
235
|
-
return Promise.resolve({
|
|
236
|
-
data: [{ id: 1, title: 'Test Primer' }],
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
if (url === '/api/v2/info') {
|
|
240
|
-
return Promise.resolve({
|
|
241
|
-
data: {
|
|
242
|
-
elabftw_version_int: 50200,
|
|
243
|
-
},
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
cy.mount(<GetPrimerComponent setPrimer={setPrimerSpy} setError={setErrorSpy} />);
|
|
249
|
-
|
|
250
|
-
cy.get('.MuiAlert-message').should('contain', 'Could not retrieve categories');
|
|
251
|
-
cy.get('button').contains('Retry').click();
|
|
252
|
-
cy.get('.MuiAutocomplete-input').first().click();
|
|
253
|
-
cy.get('.MuiAutocomplete-input').first().type('Primers');
|
|
254
|
-
cy.get('li').contains('Primers').click();
|
|
255
|
-
cy.get('.MuiAutocomplete-input').last().type('test');
|
|
256
|
-
cy.get('.MuiAlert-message').should('contain', 'Could not retrieve');
|
|
257
|
-
cy.get('button').contains('Retry').click();
|
|
258
|
-
cy.get('.MuiAutocomplete-root').eq(1).click();
|
|
259
|
-
cy.get('li').contains('Test Primer').click();
|
|
260
|
-
});
|
|
261
|
-
});
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import React, { useCallback } from 'react';
|
|
2
|
-
import ELabFTWCategorySelect from './ELabFTWCategorySelect';
|
|
3
|
-
import ELabFTWResourceSelect from './ELabFTWResourceSelect';
|
|
4
|
-
|
|
5
|
-
function GetPrimerComponent({ primer, setPrimer, setError }) {
|
|
6
|
-
const [category, setCategory] = React.useState(null);
|
|
7
|
-
|
|
8
|
-
React.useEffect(() => {
|
|
9
|
-
if (category === null) {
|
|
10
|
-
setPrimer(null);
|
|
11
|
-
}
|
|
12
|
-
}, [category]);
|
|
13
|
-
|
|
14
|
-
const handleResourceSelect = useCallback(async (resource) => {
|
|
15
|
-
if (resource === null) {
|
|
16
|
-
setPrimer(null);
|
|
17
|
-
setError('');
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
let sequence;
|
|
21
|
-
try {
|
|
22
|
-
sequence = JSON.parse(resource.metadata).extra_fields?.sequence?.value;
|
|
23
|
-
if (!sequence) {
|
|
24
|
-
setError('No sequence found in metadata');
|
|
25
|
-
setPrimer(null);
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
} catch (e) {
|
|
29
|
-
setError('No sequence found in metadata');
|
|
30
|
-
setPrimer(null);
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
setPrimer({ name: resource.title, sequence, database_id: resource.id });
|
|
35
|
-
}, [setPrimer, setError]);
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<>
|
|
39
|
-
<ELabFTWCategorySelect
|
|
40
|
-
setCategory={setCategory}
|
|
41
|
-
fullWidth
|
|
42
|
-
/>
|
|
43
|
-
|
|
44
|
-
{category && (
|
|
45
|
-
<ELabFTWResourceSelect
|
|
46
|
-
setResource={handleResourceSelect}
|
|
47
|
-
categoryId={category.id}
|
|
48
|
-
fullWidth
|
|
49
|
-
/>
|
|
50
|
-
)}
|
|
51
|
-
</>
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export default GetPrimerComponent;
|
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import GetSequenceFileAndDatabaseIdComponent from './GetSequenceFileAndDatabaseIdComponent';
|
|
3
|
-
import { eLabFTWHttpClient } from './common';
|
|
4
|
-
import { clearAutocompleteValue, clickMultiSelectOption, setAutocompleteValue } from '../../../../../cypress/e2e/common_functions';
|
|
5
|
-
|
|
6
|
-
let uniqueId = 1;
|
|
7
|
-
const newUniqueId = () => uniqueId++;
|
|
8
|
-
const SEQUENCE_CATEGORY_ID = newUniqueId();
|
|
9
|
-
const OTHER_CATEGORY_ID = newUniqueId();
|
|
10
|
-
const SEQUENCE_RESOURCE_ID = newUniqueId();
|
|
11
|
-
const OTHER_RESOURCE_ID = newUniqueId();
|
|
12
|
-
const SEQUENCE_FILE_ID = newUniqueId();
|
|
13
|
-
const OTHER_FILE_ID = newUniqueId();
|
|
14
|
-
const TEST_FILE_CONTENT = 'test content';
|
|
15
|
-
|
|
16
|
-
const commonStubHandler = (url, config) => {
|
|
17
|
-
if (url === '/api/v2/items_types') {
|
|
18
|
-
return Promise.resolve({
|
|
19
|
-
data: [
|
|
20
|
-
{ id: SEQUENCE_CATEGORY_ID, title: 'Sequences' },
|
|
21
|
-
{ id: OTHER_CATEGORY_ID, title: 'Other Category' },
|
|
22
|
-
],
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
if (url === '/api/v2/items' && config?.params?.cat === 1) {
|
|
26
|
-
return Promise.resolve({
|
|
27
|
-
data: [{
|
|
28
|
-
id: SEQUENCE_RESOURCE_ID,
|
|
29
|
-
title: 'Test Sequence',
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
id: OTHER_RESOURCE_ID,
|
|
33
|
-
title: 'Other Resource',
|
|
34
|
-
},
|
|
35
|
-
],
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
if (url === `/api/v2/items/${SEQUENCE_RESOURCE_ID}`) {
|
|
39
|
-
return Promise.resolve({
|
|
40
|
-
data: {
|
|
41
|
-
uploads: [
|
|
42
|
-
{ id: SEQUENCE_FILE_ID, real_name: 'sequence.gb' },
|
|
43
|
-
{ id: OTHER_FILE_ID, real_name: 'other.txt' },
|
|
44
|
-
],
|
|
45
|
-
},
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
if (url === '/api/v2/info') {
|
|
49
|
-
return Promise.resolve({
|
|
50
|
-
data: {
|
|
51
|
-
elabftw_version_int: 50200,
|
|
52
|
-
},
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
return null;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
describe('<GetSequenceFileAndDatabaseIdComponent />', () => {
|
|
59
|
-
it('normal case', () => {
|
|
60
|
-
const setFileSpy = cy.spy().as('setFileSpy');
|
|
61
|
-
const setDatabaseIdSpy = cy.spy().as('setDatabaseIdSpy');
|
|
62
|
-
|
|
63
|
-
// Stub API calls
|
|
64
|
-
cy.stub(eLabFTWHttpClient, 'get').callsFake((url, config) => {
|
|
65
|
-
const commonResponse = commonStubHandler(url, config);
|
|
66
|
-
if (commonResponse !== null) {
|
|
67
|
-
return commonResponse;
|
|
68
|
-
}
|
|
69
|
-
if (url === `/api/v2/items/${SEQUENCE_RESOURCE_ID}/uploads/${SEQUENCE_FILE_ID}?format=binary`) {
|
|
70
|
-
return Promise.resolve({ data: new Blob([TEST_FILE_CONTENT], { type: 'application/octet-stream' }) });
|
|
71
|
-
}
|
|
72
|
-
return Promise.resolve({ data: [] });
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
cy.mount(<GetSequenceFileAndDatabaseIdComponent setFile={setFileSpy} setDatabaseId={setDatabaseIdSpy} />);
|
|
76
|
-
|
|
77
|
-
// Initially, only category select should be visible
|
|
78
|
-
cy.get('.MuiAutocomplete-root').should('have.length', 1);
|
|
79
|
-
|
|
80
|
-
// Select a category
|
|
81
|
-
cy.get('.MuiAutocomplete-input').first().click();
|
|
82
|
-
cy.get('.MuiAutocomplete-input').first().type('Sequences');
|
|
83
|
-
cy.get('li').contains('Sequences').click();
|
|
84
|
-
|
|
85
|
-
// Resource select should appear
|
|
86
|
-
cy.get('.MuiAutocomplete-root').should('have.length', 2);
|
|
87
|
-
|
|
88
|
-
// Select a resource
|
|
89
|
-
cy.get('.MuiAutocomplete-input').last().type('Test');
|
|
90
|
-
cy.get('li').contains('Test Sequence').click();
|
|
91
|
-
|
|
92
|
-
// File select should appear
|
|
93
|
-
clickMultiSelectOption('File with sequence', 'sequence.gb', 'div');
|
|
94
|
-
// We must compare like this, because using have.been.calledWith does not compare files
|
|
95
|
-
cy.get('@setFileSpy').should((spy) => {
|
|
96
|
-
const calledFile = spy.lastCall.args[0]; // Get the first argument of the first call
|
|
97
|
-
expect(calledFile).to.be.instanceOf(File);
|
|
98
|
-
expect(calledFile.name).to.equal('sequence.gb');
|
|
99
|
-
// Read the file content and compare
|
|
100
|
-
const reader = new FileReader();
|
|
101
|
-
reader.onload = (e) => {
|
|
102
|
-
const actualContent = e.target.result;
|
|
103
|
-
expect(actualContent).to.equal(TEST_FILE_CONTENT);
|
|
104
|
-
};
|
|
105
|
-
reader.readAsText(calledFile);
|
|
106
|
-
});
|
|
107
|
-
cy.get('@setDatabaseIdSpy').should('have.been.calledWith', SEQUENCE_RESOURCE_ID);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it('handles error when getting file', () => {
|
|
111
|
-
const setFileSpy = cy.spy().as('setFileSpy');
|
|
112
|
-
const setDatabaseIdSpy = cy.spy().as('setDatabaseIdSpy');
|
|
113
|
-
|
|
114
|
-
let firstCall = true;
|
|
115
|
-
cy.stub(eLabFTWHttpClient, 'get').callsFake((url, config) => {
|
|
116
|
-
const commonResponse = commonStubHandler(url, config);
|
|
117
|
-
if (commonResponse !== null) {
|
|
118
|
-
return commonResponse;
|
|
119
|
-
}
|
|
120
|
-
if (url === `/api/v2/items/${SEQUENCE_RESOURCE_ID}/uploads/${SEQUENCE_FILE_ID}?format=binary`) {
|
|
121
|
-
if (firstCall) {
|
|
122
|
-
firstCall = false;
|
|
123
|
-
return Promise.reject(new Error('File not found'));
|
|
124
|
-
}
|
|
125
|
-
return Promise.resolve({ data: new Blob([TEST_FILE_CONTENT], { type: 'application/octet-stream' }) });
|
|
126
|
-
}
|
|
127
|
-
return Promise.resolve({ data: [] });
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
cy.mount(<GetSequenceFileAndDatabaseIdComponent setFile={setFileSpy} setDatabaseId={setDatabaseIdSpy} />);
|
|
131
|
-
|
|
132
|
-
// Select a category
|
|
133
|
-
clickMultiSelectOption('Resource category', 'Sequences', 'div');
|
|
134
|
-
setAutocompleteValue('Resource', 'Test Sequence', '.elabftw-resource-select');
|
|
135
|
-
clickMultiSelectOption('File with sequence', 'sequence.gb', 'div');
|
|
136
|
-
cy.get('.MuiAlert-message').should('contain', 'Error loading file');
|
|
137
|
-
cy.get('button').contains('Retry').click();
|
|
138
|
-
cy.get('.MuiAlert-message').should('not.exist');
|
|
139
|
-
cy.get('@setFileSpy').should((spy) => {
|
|
140
|
-
const calledFile = spy.lastCall.args[0]; // Get the first argument of the first call
|
|
141
|
-
expect(calledFile).to.be.instanceOf(File);
|
|
142
|
-
expect(calledFile.name).to.equal('sequence.gb');
|
|
143
|
-
// Read the file content and compare
|
|
144
|
-
const reader = new FileReader();
|
|
145
|
-
reader.onload = (e) => {
|
|
146
|
-
const actualContent = e.target.result;
|
|
147
|
-
expect(actualContent).to.equal(TEST_FILE_CONTENT);
|
|
148
|
-
};
|
|
149
|
-
reader.readAsText(calledFile);
|
|
150
|
-
});
|
|
151
|
-
cy.get('@setDatabaseIdSpy').should('have.been.calledWith', SEQUENCE_RESOURCE_ID);
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
it('unsets subsequent fields when an upper one changes', () => {
|
|
155
|
-
cy.stub(eLabFTWHttpClient, 'get').callsFake(commonStubHandler);
|
|
156
|
-
cy.mount(<GetSequenceFileAndDatabaseIdComponent setFile={cy.spy()} setDatabaseId={cy.spy()} />);
|
|
157
|
-
clickMultiSelectOption('Resource category', 'Sequences', 'div');
|
|
158
|
-
setAutocompleteValue('Resource', 'Test Sequence', '.elabftw-resource-select');
|
|
159
|
-
clickMultiSelectOption('File with sequence', 'sequence.gb', 'div');
|
|
160
|
-
|
|
161
|
-
// Unset category should clear the rest
|
|
162
|
-
clearAutocompleteValue('Resource category', 'div.elabftw-category-select');
|
|
163
|
-
cy.get('.elabftw-resource-select').should('not.exist');
|
|
164
|
-
cy.get('.elabftw-file-select').should('not.exist');
|
|
165
|
-
cy.get('.elabftw-category-select').click();
|
|
166
|
-
|
|
167
|
-
clickMultiSelectOption('Resource category', 'Sequences', 'div');
|
|
168
|
-
|
|
169
|
-
// Resource value should be unset
|
|
170
|
-
cy.get('.elabftw-resource-select input').should('have.value', '');
|
|
171
|
-
setAutocompleteValue('Resource', 'Test Sequence', '.elabftw-resource-select');
|
|
172
|
-
|
|
173
|
-
// File value should be unset
|
|
174
|
-
cy.get('.elabftw-file-select input').should('have.value', '');
|
|
175
|
-
clickMultiSelectOption('File with sequence', 'sequence.gb', 'div');
|
|
176
|
-
|
|
177
|
-
// Unset resource should clear file
|
|
178
|
-
clearAutocompleteValue('Resource', '.elabftw-resource-select');
|
|
179
|
-
cy.get('.elabftw-file-select').should('not.exist');
|
|
180
|
-
cy.get('.elabftw-resource-select').click();
|
|
181
|
-
setAutocompleteValue('Resource', 'Test Sequence', '.elabftw-resource-select');
|
|
182
|
-
cy.get('.elabftw-file-select input').should('have.value', '');
|
|
183
|
-
});
|
|
184
|
-
});
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import ELabFTWCategorySelect from './ELabFTWCategorySelect';
|
|
3
|
-
import ELabFTWResourceSelect from './ELabFTWResourceSelect';
|
|
4
|
-
import ELabFTWFileSelect from './ELabFTWFileSelect';
|
|
5
|
-
import { getFileFromELabFTW } from './utils';
|
|
6
|
-
import RetryAlert from '../form/RetryAlert';
|
|
7
|
-
|
|
8
|
-
function GetSequenceFileAndDatabaseIdComponent({ setFile, setDatabaseId }) {
|
|
9
|
-
const [category, setCategory] = React.useState(null);
|
|
10
|
-
const [resource, setResource] = React.useState(null);
|
|
11
|
-
const [fileInfo, setFileInfo] = React.useState(null);
|
|
12
|
-
const [fileLoadError, setFileLoadError] = React.useState('');
|
|
13
|
-
const [retry, setRetry] = React.useState(0);
|
|
14
|
-
|
|
15
|
-
// Reset if category changes
|
|
16
|
-
React.useEffect(() => {
|
|
17
|
-
setResource(null);
|
|
18
|
-
setFileInfo(null);
|
|
19
|
-
setFile(null);
|
|
20
|
-
setDatabaseId(null);
|
|
21
|
-
}, [category]);
|
|
22
|
-
|
|
23
|
-
// Reset if resource changes
|
|
24
|
-
React.useEffect(() => {
|
|
25
|
-
setFileInfo(null);
|
|
26
|
-
setFile(null);
|
|
27
|
-
setDatabaseId(null);
|
|
28
|
-
}, [resource]);
|
|
29
|
-
|
|
30
|
-
React.useEffect(() => {
|
|
31
|
-
setFile(null);
|
|
32
|
-
setDatabaseId(null);
|
|
33
|
-
}, [fileInfo]);
|
|
34
|
-
|
|
35
|
-
React.useEffect(() => {
|
|
36
|
-
const loadFile = async () => {
|
|
37
|
-
if (!resource || !fileInfo) return;
|
|
38
|
-
try {
|
|
39
|
-
const file = await getFileFromELabFTW(resource.id, fileInfo);
|
|
40
|
-
setFile(file);
|
|
41
|
-
setDatabaseId(resource.id);
|
|
42
|
-
setFileLoadError('');
|
|
43
|
-
} catch (error) {
|
|
44
|
-
setFileLoadError('Error loading file');
|
|
45
|
-
console.error('Error loading file', error);
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
loadFile();
|
|
50
|
-
}, [resource, fileInfo, retry]);
|
|
51
|
-
|
|
52
|
-
return (
|
|
53
|
-
<>
|
|
54
|
-
<ELabFTWCategorySelect fullWidth setCategory={setCategory} className="elabftw-category-select" />
|
|
55
|
-
{category && <ELabFTWResourceSelect fullWidth setResource={setResource} categoryId={category.id} className="elabftw-resource-select" />}
|
|
56
|
-
{resource && <ELabFTWFileSelect fullWidth setFileInfo={setFileInfo} itemId={resource.id} className="elabftw-file-select" />}
|
|
57
|
-
{fileLoadError && <RetryAlert severity="error" onRetry={() => setRetry((prev) => prev + 1)}>{fileLoadError}</RetryAlert>}
|
|
58
|
-
</>
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export default GetSequenceFileAndDatabaseIdComponent;
|