@apollo-annotation/cli 0.3.1 → 0.3.3
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/README.md +73 -39
- package/dist/commands/assembly/add-from-fasta.js +23 -8
- package/dist/commands/export/gff3.d.ts +15 -0
- package/dist/commands/export/gff3.js +74 -0
- package/dist/test/test.d.ts +11 -0
- package/dist/test/test.js +978 -0
- package/dist/test/test_docker.d.ts +1 -0
- package/dist/test/test_docker.js +51 -0
- package/dist/test/utils.d.ts +9 -0
- package/dist/test/utils.js +28 -0
- package/oclif.manifest.json +272 -214
- package/package.json +9 -3
|
@@ -0,0 +1,978 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
5
|
+
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
6
|
+
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
7
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
8
|
+
/**
|
|
9
|
+
* USAGE
|
|
10
|
+
* From package root directory (`packages/apollo-cli`). Run all tests:
|
|
11
|
+
*
|
|
12
|
+
* yarn test:cli
|
|
13
|
+
*
|
|
14
|
+
* Run only matching pattern:
|
|
15
|
+
*
|
|
16
|
+
* yarn test:cli --test-name-pattern='Print help|Feature get'
|
|
17
|
+
*/
|
|
18
|
+
import assert from 'node:assert';
|
|
19
|
+
import { before, beforeEach, afterEach, describe } from 'node:test';
|
|
20
|
+
import { Shell } from './utils.js';
|
|
21
|
+
import fs from 'node:fs';
|
|
22
|
+
import * as crypto from 'node:crypto';
|
|
23
|
+
import path from 'node:path';
|
|
24
|
+
const apollo = 'yarn dev';
|
|
25
|
+
const P = '--profile testAdmin';
|
|
26
|
+
let configFile = '';
|
|
27
|
+
let configFileBak = '';
|
|
28
|
+
void describe('Test CLI', () => {
|
|
29
|
+
before(() => {
|
|
30
|
+
configFile = new Shell(`${apollo} config --get-config-file`).stdout.trim();
|
|
31
|
+
configFileBak = `${path.basename(configFile)}.bak`;
|
|
32
|
+
if (fs.existsSync(configFileBak)) {
|
|
33
|
+
throw new Error(`Backup config file ${configFileBak} already exists. If safe to do so, delete it before testing`);
|
|
34
|
+
}
|
|
35
|
+
new Shell(`${apollo} config ${P} address http://localhost:3999`);
|
|
36
|
+
new Shell(`${apollo} config ${P} accessType root`);
|
|
37
|
+
new Shell(`${apollo} config ${P} rootPassword pass`);
|
|
38
|
+
new Shell(`${apollo} login ${P} -f`);
|
|
39
|
+
});
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
// Backup starting config file
|
|
42
|
+
fs.copyFileSync(configFile, configFileBak);
|
|
43
|
+
});
|
|
44
|
+
afterEach(() => {
|
|
45
|
+
// Put back starting config file
|
|
46
|
+
fs.renameSync(configFileBak, configFile);
|
|
47
|
+
});
|
|
48
|
+
void globalThis.itName('Print help', () => {
|
|
49
|
+
const p = new Shell(`${apollo} --help`);
|
|
50
|
+
assert.ok(p.stdout.includes('COMMANDS'));
|
|
51
|
+
});
|
|
52
|
+
void globalThis.itName('Get config file', () => {
|
|
53
|
+
const p = new Shell(`${apollo} config --get-config-file`);
|
|
54
|
+
assert.ok(p.stdout.startsWith('/'));
|
|
55
|
+
});
|
|
56
|
+
void globalThis.itName('Config invalid keys', () => {
|
|
57
|
+
let p = new Shell(`${apollo} config ${P} address spam`, false);
|
|
58
|
+
assert.strictEqual(1, p.returncode);
|
|
59
|
+
assert.ok(p.stderr.includes('Invalid setting:'));
|
|
60
|
+
p = new Shell(`${apollo} config ${P} ADDRESS http://localhost:3999`, false);
|
|
61
|
+
assert.strictEqual(1, p.returncode);
|
|
62
|
+
assert.ok(p.stderr.includes('Invalid setting:'));
|
|
63
|
+
p = new Shell(`${apollo} config ${P} accessType spam`, false);
|
|
64
|
+
assert.strictEqual(1, p.returncode);
|
|
65
|
+
assert.ok(p.stderr.includes('Invalid setting:'));
|
|
66
|
+
});
|
|
67
|
+
void globalThis.itName('Can change access type', () => {
|
|
68
|
+
const p = new Shell(`${apollo} config ${P} accessType google`);
|
|
69
|
+
assert.strictEqual('', p.stdout.trim());
|
|
70
|
+
});
|
|
71
|
+
void globalThis.itName('Apollo status', () => {
|
|
72
|
+
let p = new Shell(`${apollo} status ${P}`);
|
|
73
|
+
assert.strictEqual(p.stdout.trim(), 'testAdmin: Logged in');
|
|
74
|
+
new Shell(`${apollo} logout ${P}`);
|
|
75
|
+
p = new Shell(`${apollo} status ${P}`);
|
|
76
|
+
assert.strictEqual(p.stdout.trim(), 'testAdmin: Logged out');
|
|
77
|
+
new Shell(`${apollo} login ${P} -f`);
|
|
78
|
+
});
|
|
79
|
+
void globalThis.itName('Feature get', () => {
|
|
80
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a vv1 -f`);
|
|
81
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a vv2 -f`);
|
|
82
|
+
let p = new Shell(`${apollo} feature get ${P} -a vv1`);
|
|
83
|
+
assert.ok(p.stdout.includes('ctgA'));
|
|
84
|
+
assert.ok(p.stdout.includes('SomeContig'));
|
|
85
|
+
p = new Shell(`${apollo} feature get ${P} -r ctgA`, false);
|
|
86
|
+
assert.ok(p.returncode != 0);
|
|
87
|
+
assert.ok(p.stderr.includes('found in more than one assembly'));
|
|
88
|
+
p = new Shell(`${apollo} feature get ${P} -a vv1 -r ctgA`);
|
|
89
|
+
let out = JSON.parse(p.stdout);
|
|
90
|
+
assert.ok(Object.keys(out.at(0)).length > 2);
|
|
91
|
+
p = new Shell(`${apollo} feature get ${P} -a vv1 -r ctgA -s 40 -e 41`);
|
|
92
|
+
out = JSON.parse(p.stdout);
|
|
93
|
+
assert.strictEqual(out.length, 1);
|
|
94
|
+
p = new Shell(`${apollo} feature get ${P} -a vv1 -r ctgA -s 1000 -e 1000`);
|
|
95
|
+
out = JSON.parse(p.stdout);
|
|
96
|
+
assert.deepStrictEqual(out, []);
|
|
97
|
+
p = new Shell(`${apollo} feature get ${P} -r FOOBAR`);
|
|
98
|
+
out = JSON.parse(p.stdout);
|
|
99
|
+
assert.deepStrictEqual(out, []);
|
|
100
|
+
p = new Shell(`${apollo} feature get ${P} -a FOOBAR -r ctgA`, false);
|
|
101
|
+
assert.ok(p.returncode != 0);
|
|
102
|
+
assert.ok(p.stderr.includes('returned 0 assemblies'));
|
|
103
|
+
});
|
|
104
|
+
void globalThis.itName('Assembly get', () => {
|
|
105
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tiny.fasta -a vv1 -e -f`);
|
|
106
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tiny.fasta -a vv2 -e -f`);
|
|
107
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tiny.fasta -a vv3 -e -f`);
|
|
108
|
+
let p = new Shell(`${apollo} assembly get ${P}`);
|
|
109
|
+
assert.ok(p.stdout.includes('vv1'));
|
|
110
|
+
assert.ok(p.stdout.includes('vv2'));
|
|
111
|
+
assert.ok(p.stdout.includes('vv3'));
|
|
112
|
+
p = new Shell(`${apollo} assembly get ${P} -a vv1 vv2`);
|
|
113
|
+
assert.ok(p.stdout.includes('vv1'));
|
|
114
|
+
assert.ok(p.stdout.includes('vv2'));
|
|
115
|
+
assert.ok(p.stdout.includes('vv3') == false);
|
|
116
|
+
const out = JSON.parse(p.stdout);
|
|
117
|
+
const aid = out.filter((x) => x.name === 'vv1').at(0)._id;
|
|
118
|
+
p = new Shell(`${apollo} assembly get ${P} -a ${aid} vv2`);
|
|
119
|
+
assert.ok(p.stdout.includes('vv1'));
|
|
120
|
+
assert.ok(p.stdout.includes('vv2'));
|
|
121
|
+
assert.ok(p.stdout.includes('vv3') == false);
|
|
122
|
+
});
|
|
123
|
+
void globalThis.itName('Delete assembly', () => {
|
|
124
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a volvox1 -f`);
|
|
125
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a volvox2 -f`);
|
|
126
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a volvox3 -f`);
|
|
127
|
+
let p = new Shell(`${apollo} assembly get ${P} | jq '.[] | select(.name == "volvox1") | ._id'`);
|
|
128
|
+
const aid = p.stdout.trim();
|
|
129
|
+
p = new Shell(`${apollo} assembly delete ${P} -v -a ${aid} volvox2 volvox2`);
|
|
130
|
+
const out = JSON.parse(p.stdout);
|
|
131
|
+
assert.strictEqual(out.length, 2);
|
|
132
|
+
assert.ok(p.stderr.includes('2 '));
|
|
133
|
+
new Shell(`${apollo} assembly delete ${P} -a ${aid} volvox2`);
|
|
134
|
+
p = new Shell(`${apollo} assembly get ${P}`);
|
|
135
|
+
assert.ok(p.stdout.includes(aid) == false);
|
|
136
|
+
assert.ok(p.stdout.includes('volvox1') == false);
|
|
137
|
+
assert.ok(p.stdout.includes('volvox2') == false);
|
|
138
|
+
assert.ok(p.stdout.includes('volvox3'));
|
|
139
|
+
});
|
|
140
|
+
void globalThis.itName('Id reader', () => {
|
|
141
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a v1 -f`);
|
|
142
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a v2 -f`);
|
|
143
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a v3 -f`);
|
|
144
|
+
let p = new Shell(`${apollo} assembly get ${P}`);
|
|
145
|
+
const xall = JSON.parse(p.stdout);
|
|
146
|
+
p = new Shell(`${apollo} assembly get ${P} -a v1 v2`);
|
|
147
|
+
let out = JSON.parse(p.stdout);
|
|
148
|
+
assert.strictEqual(out.length, 2);
|
|
149
|
+
// This is interpreted as an assembly named 'v1 v2'
|
|
150
|
+
p = new Shell(`echo v1 v2 | ${apollo} assembly get ${P} -a -`);
|
|
151
|
+
out = JSON.parse(p.stdout);
|
|
152
|
+
assert.strictEqual(out.length, 0);
|
|
153
|
+
// These are two assemblies
|
|
154
|
+
p = new Shell(`echo -e 'v1 \n v2' | ${apollo} assembly get ${P} -a -`);
|
|
155
|
+
out = JSON.parse(p.stdout);
|
|
156
|
+
assert.strictEqual(out.length, 2);
|
|
157
|
+
p = new Shell(`${apollo} assembly get ${P} | ${apollo} assembly get ${P} -a -`);
|
|
158
|
+
out = JSON.parse(p.stdout);
|
|
159
|
+
assert.ok(out.length >= 3);
|
|
160
|
+
// From json file
|
|
161
|
+
new Shell(`${apollo} assembly get ${P} > test_data/tmp.json`);
|
|
162
|
+
p = new Shell(`${apollo} assembly get ${P} -a test_data/tmp.json`);
|
|
163
|
+
out = JSON.parse(p.stdout);
|
|
164
|
+
assert.ok(out.length >= 3);
|
|
165
|
+
fs.unlinkSync('test_data/tmp.json');
|
|
166
|
+
// From text file, one name or id per line
|
|
167
|
+
fs.writeFileSync('test_data/tmp.txt', 'v1 \n v2 \r\n v3 \n');
|
|
168
|
+
p = new Shell(`${apollo} assembly get ${P} -a test_data/tmp.txt`);
|
|
169
|
+
out = JSON.parse(p.stdout);
|
|
170
|
+
assert.strictEqual(out.length, 3);
|
|
171
|
+
fs.unlinkSync('test_data/tmp.txt');
|
|
172
|
+
// From json string
|
|
173
|
+
const aid = xall.at(0)._id;
|
|
174
|
+
let j = `{"_id": "${aid}"}`;
|
|
175
|
+
p = new Shell(`${apollo} assembly get ${P} -a '${j}'`);
|
|
176
|
+
out = JSON.parse(p.stdout);
|
|
177
|
+
assert.strictEqual(out.length, 1);
|
|
178
|
+
assert.strictEqual(out.at(0)._id, aid);
|
|
179
|
+
const id1 = xall.at(0)._id;
|
|
180
|
+
const id2 = xall.at(1)._id;
|
|
181
|
+
j = `[{"_id": "${id1}"}, {"_id": "${id2}"}]`;
|
|
182
|
+
p = new Shell(`${apollo} assembly get ${P} -a '${j}'`);
|
|
183
|
+
out = JSON.parse(p.stdout);
|
|
184
|
+
assert.strictEqual(out.length, 2);
|
|
185
|
+
j = `{"XYZ": "${aid}"}`;
|
|
186
|
+
p = new Shell(`${apollo} assembly get ${P} -a '${j}'`);
|
|
187
|
+
out = JSON.parse(p.stdout);
|
|
188
|
+
assert.strictEqual(out.length, 0);
|
|
189
|
+
p = new Shell(`${apollo} assembly get ${P} -a '[...'`);
|
|
190
|
+
out = JSON.parse(p.stdout);
|
|
191
|
+
assert.strictEqual(out.length, 0);
|
|
192
|
+
});
|
|
193
|
+
void globalThis.itName('Add assembly from gff', () => {
|
|
194
|
+
let p = new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a vv1 --omit-features -f`);
|
|
195
|
+
const out = JSON.parse(p.stdout);
|
|
196
|
+
assert.ok(Object.keys(out.fileIds).includes('fa'));
|
|
197
|
+
// Get id of assembly named vv1 and check there are no features
|
|
198
|
+
p = new Shell(`${apollo} assembly get ${P} -a vv1`);
|
|
199
|
+
assert.ok(p.stdout.includes('vv1'));
|
|
200
|
+
assert.ok(p.stdout.includes('vv2') == false);
|
|
201
|
+
const asm_id = JSON.parse(p.stdout).at(0)._id;
|
|
202
|
+
p = new Shell(`${apollo} refseq get ${P}`);
|
|
203
|
+
const refseq = JSON.parse(p.stdout.trim());
|
|
204
|
+
const vv1ref = refseq.filter((x) => x.assembly === asm_id);
|
|
205
|
+
const refseq_id = vv1ref.filter((x) => x.name === 'ctgA').at(0)._id;
|
|
206
|
+
p = new Shell(`${apollo} feature get ${P} -r ${refseq_id}`);
|
|
207
|
+
const ff = JSON.parse(p.stdout);
|
|
208
|
+
assert.deepStrictEqual(ff, []);
|
|
209
|
+
p = new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a vv1`, false);
|
|
210
|
+
assert.ok(p.returncode != 0);
|
|
211
|
+
assert.ok(p.stderr.includes('Error: Assembly "vv1" already exists'));
|
|
212
|
+
// Default assembly name
|
|
213
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -f`);
|
|
214
|
+
p = new Shell(`${apollo} assembly get ${P} -a tiny.fasta.gff3`);
|
|
215
|
+
assert.ok(p.stdout.includes('tiny.fasta.gff3'));
|
|
216
|
+
});
|
|
217
|
+
void globalThis.itName('Add assembly large input', () => {
|
|
218
|
+
fs.writeFileSync('test_data/tmp.fa', '>chr1\n');
|
|
219
|
+
const stream = fs.createWriteStream('test_data/tmp.fa', { flags: 'a' });
|
|
220
|
+
for (let i = 0; i < 10_000; i++) {
|
|
221
|
+
stream.write('CATTGTTGCGGAGTTGAACAACGGCATTAGGAACACTTCCGTCTC\n');
|
|
222
|
+
}
|
|
223
|
+
stream.close();
|
|
224
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tmp.fa -a test -e -f`, true, 60_000);
|
|
225
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tmp.fa -a test -f`, false, 60_000);
|
|
226
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tmp.fa -a test -e -f`, true, 60_000);
|
|
227
|
+
fs.unlinkSync('test_data/tmp.fa');
|
|
228
|
+
});
|
|
229
|
+
void globalThis.itName('FIXME Checks are triggered and resolved', () => {
|
|
230
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/checks.gff -f`);
|
|
231
|
+
let p = new Shell(`${apollo} feature get ${P} -a checks.gff`);
|
|
232
|
+
const out = JSON.parse(p.stdout);
|
|
233
|
+
p = new Shell(`${apollo} feature check ${P} -a checks.gff`);
|
|
234
|
+
assert.deepStrictEqual(p.stdout.trim(), '[]'); // No failing check
|
|
235
|
+
// Get the ID of the CDS. We need need it to modify the CDS coordinates
|
|
236
|
+
const gene = out.filter((x) => JSON.stringify(x.attributes.gff_id) === JSON.stringify(['gene01']));
|
|
237
|
+
const mrna = Object.values(gene.at(0).children).at(0);
|
|
238
|
+
const cds = Object.values(mrna.children).find((x) => x.attributes.gff_id.at(0) === 'cds01');
|
|
239
|
+
const cds_id = cds._id;
|
|
240
|
+
// Introduce problems
|
|
241
|
+
new Shell(`${apollo} feature edit-coords ${P} -i ${cds_id} --start 4 --end 24`);
|
|
242
|
+
p = new Shell(`${apollo} feature check ${P} -a checks.gff`);
|
|
243
|
+
const checks = JSON.parse(p.stdout);
|
|
244
|
+
// FIXME: There should be 2 failing checks, not 3
|
|
245
|
+
assert.strictEqual(checks.length, 3);
|
|
246
|
+
assert.ok(p.stdout.includes('InternalStopCodonCheck'));
|
|
247
|
+
assert.ok(p.stdout.includes('MissingStopCodonCheck'));
|
|
248
|
+
// Problems fixed
|
|
249
|
+
new Shell(`${apollo} feature edit-coords ${P} -i ${cds_id} --start 16 --end 27`);
|
|
250
|
+
p = new Shell(`${apollo} feature check ${P} -a checks.gff`);
|
|
251
|
+
// FIXME: After fixing, how many warnings do we expect?
|
|
252
|
+
assert.deepStrictEqual(JSON.parse(p.stdout).length, 4);
|
|
253
|
+
});
|
|
254
|
+
void globalThis.itName('Add assembly from local fasta', () => {
|
|
255
|
+
let p = new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tiny.fasta -a vv1 -e -f`);
|
|
256
|
+
const out = JSON.parse(p.stdout);
|
|
257
|
+
assert.ok(Object.keys(out.fileIds).includes('fa'));
|
|
258
|
+
p = new Shell(`${apollo} assembly get ${P} -a vv1`);
|
|
259
|
+
assert.ok(p.stdout.includes('vv1'));
|
|
260
|
+
p = new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tiny.fasta -a vv1 -e`, false);
|
|
261
|
+
assert.ok(p.returncode != 0);
|
|
262
|
+
assert.ok(p.stderr.includes('Error: Assembly "vv1" already exists'));
|
|
263
|
+
p = new Shell(`${apollo} assembly add-from-fasta ${P} na.fa -a vv1 -e -f`, false);
|
|
264
|
+
assert.ok(p.returncode != 0);
|
|
265
|
+
assert.ok(p.stderr.includes('Input'));
|
|
266
|
+
// Test default name
|
|
267
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tiny.fasta -e -f`);
|
|
268
|
+
p = new Shell(`${apollo} assembly get ${P} -a tiny.fasta`);
|
|
269
|
+
assert.ok(p.stdout.includes('tiny.fasta'));
|
|
270
|
+
});
|
|
271
|
+
void globalThis.itName('Add assembly from external fasta', () => {
|
|
272
|
+
let p = new Shell(`${apollo} assembly add-from-fasta ${P} -a vv1 -f http://localhost:3131/volvox.fa.gz`);
|
|
273
|
+
const out = JSON.parse(p.stdout);
|
|
274
|
+
assert.ok(Object.keys(out.externalLocation).includes('fa'));
|
|
275
|
+
p = new Shell(`${apollo} assembly get ${P} -a vv1`);
|
|
276
|
+
assert.ok(p.stdout.includes('vv1'));
|
|
277
|
+
p = new Shell(`${apollo} assembly sequence ${P} -a vv1 -r ctgA -s 1 -e 10`);
|
|
278
|
+
const seq = p.stdout.trim().split('\n');
|
|
279
|
+
assert.strictEqual(seq[1], 'cattgttgcg');
|
|
280
|
+
p = new Shell(`${apollo} assembly add-from-fasta ${P} -a vv1 -f https://x.fa.gz --fai https://x.fa.gz.fai --gzi https://x.fa.gz.gzi`, false);
|
|
281
|
+
assert.ok(p.returncode != 0);
|
|
282
|
+
});
|
|
283
|
+
void globalThis.itName('Detect missing external index', () => {
|
|
284
|
+
const p = new Shell(`${apollo} assembly add-from-fasta ${P} -a vv1 -f https://raw.githubusercontent.com/GMOD/Apollo3/refs/heads/main/packages/apollo-cli/test_data/tiny.fasta`, false);
|
|
285
|
+
assert.ok(p.returncode != 0);
|
|
286
|
+
assert.ok(p.stderr.includes('Index file') && p.stderr.includes('does not exist'));
|
|
287
|
+
});
|
|
288
|
+
void globalThis.itName('Editable sequence not allowed with external source', () => {
|
|
289
|
+
const cmd = `${apollo} assembly add-from-fasta ${P} -a vv1 -f https://raw.githubusercontent.com/GMOD/Apollo3/refs/heads/main/packages/apollo-cli/test_data/tiny.fasta.gz`;
|
|
290
|
+
new Shell(cmd);
|
|
291
|
+
const p = new Shell(`${cmd} -e`, false);
|
|
292
|
+
assert.ok(p.returncode != 0);
|
|
293
|
+
assert.ok(p.stderr.includes('External fasta files are not editable'));
|
|
294
|
+
});
|
|
295
|
+
void globalThis.itName('Edit feature from json', () => {
|
|
296
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a vv1 -f`);
|
|
297
|
+
let p = new Shell(`${apollo} feature search ${P} -a vv1 -t BAC`);
|
|
298
|
+
let out = JSON.parse(p.stdout).at(0);
|
|
299
|
+
assert.strictEqual(out.type, 'BAC');
|
|
300
|
+
p = new Shell(`${apollo} assembly get ${P} -a vv1`);
|
|
301
|
+
const asm_id = JSON.parse(p.stdout).at(0)._id;
|
|
302
|
+
const req = [
|
|
303
|
+
{
|
|
304
|
+
typeName: 'TypeChange',
|
|
305
|
+
changedIds: [out._id],
|
|
306
|
+
assembly: asm_id,
|
|
307
|
+
featureId: out._id,
|
|
308
|
+
oldType: 'BAC',
|
|
309
|
+
newType: 'G_quartet',
|
|
310
|
+
},
|
|
311
|
+
];
|
|
312
|
+
const j = JSON.stringify(req);
|
|
313
|
+
new Shell(`echo '${j}' | ${apollo} feature edit ${P} -j -`);
|
|
314
|
+
p = new Shell(`${apollo} feature search ${P} -a vv1 -t G_quartet`);
|
|
315
|
+
out = JSON.parse(p.stdout).at(0);
|
|
316
|
+
assert.strictEqual(out.type, 'G_quartet');
|
|
317
|
+
});
|
|
318
|
+
void globalThis.itName('Edit feature type', () => {
|
|
319
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a vv1 -f`);
|
|
320
|
+
// Get id of assembly named vv1
|
|
321
|
+
let p = new Shell(`${apollo} assembly get ${P} -a vv1`);
|
|
322
|
+
const asm_id = JSON.parse(p.stdout).at(0)._id;
|
|
323
|
+
// Get refseqs in assembly vv1
|
|
324
|
+
p = new Shell(`${apollo} refseq get ${P} | jq '.[] | select(.assembly == "${asm_id}" and .name == "ctgA") | ._id'`);
|
|
325
|
+
const refseq = p.stdout.trim();
|
|
326
|
+
// Get feature in vv1
|
|
327
|
+
p = new Shell(`${apollo} feature get ${P} -r ${refseq}`);
|
|
328
|
+
const features = JSON.parse(p.stdout);
|
|
329
|
+
assert.ok(features.length > 2);
|
|
330
|
+
// Get id of feature of type contig
|
|
331
|
+
let contig = features.filter((x) => x.type === 'contig');
|
|
332
|
+
assert.strictEqual(contig.length, 1);
|
|
333
|
+
const contig_id = contig.at(0)._id;
|
|
334
|
+
// Edit type of "contig" feature
|
|
335
|
+
p = new Shell(`${apollo} feature edit-type ${P} -i ${contig_id} -t region`);
|
|
336
|
+
p = new Shell(`${apollo} feature get ${P} -r ${refseq} | jq '.[] | select(._id == "${contig_id}")'`);
|
|
337
|
+
contig = JSON.parse(p.stdout);
|
|
338
|
+
assert.deepStrictEqual(contig.type, 'region');
|
|
339
|
+
// Return current type
|
|
340
|
+
p = new Shell(`${apollo} feature edit-type ${P} -i ${contig_id}`);
|
|
341
|
+
assert.deepStrictEqual(p.stdout.trim(), 'region');
|
|
342
|
+
});
|
|
343
|
+
void globalThis.itName('Edit feature coords', () => {
|
|
344
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a vv1 -f`);
|
|
345
|
+
// Get id of assembly named vv1
|
|
346
|
+
let p = new Shell(`${apollo} assembly get ${P} -a vv1`);
|
|
347
|
+
const asm_id = JSON.parse(p.stdout).at(0)._id;
|
|
348
|
+
// Get refseqs in assembly vv1
|
|
349
|
+
p = new Shell(`${apollo} refseq get ${P} | jq '.[] | select(.assembly == "${asm_id}" and .name == "ctgA") | ._id'`);
|
|
350
|
+
const refseq = p.stdout.trim();
|
|
351
|
+
// Get feature in vv1
|
|
352
|
+
p = new Shell(`${apollo} feature get ${P} -r ${refseq}`);
|
|
353
|
+
const features = JSON.parse(p.stdout);
|
|
354
|
+
assert.ok(features.length > 2);
|
|
355
|
+
// Get id of feature of type contig
|
|
356
|
+
let contig = features.filter((x) => x.type === 'contig');
|
|
357
|
+
assert.strictEqual(contig.length, 1);
|
|
358
|
+
const contig_id = contig.at(0)._id;
|
|
359
|
+
// Edit start and end coordinates
|
|
360
|
+
new Shell(`${apollo} feature edit-coords ${P} -i ${contig_id} -s 80 -e 160`);
|
|
361
|
+
new Shell(`${apollo} feature edit-coords ${P} -i ${contig_id} -s 20 -e 100`);
|
|
362
|
+
p = new Shell(`${apollo} feature get ${P} -r ${refseq} | jq '.[] | select(._id == "${contig_id}")'`);
|
|
363
|
+
contig = JSON.parse(p.stdout);
|
|
364
|
+
assert.strictEqual(contig.min, 20 - 1);
|
|
365
|
+
assert.strictEqual(contig.max, 100);
|
|
366
|
+
p = new Shell(`${apollo} feature edit-coords ${P} -i ${contig_id} -s 1 -e 1`);
|
|
367
|
+
p = new Shell(`${apollo} feature get ${P} -r ${refseq} | jq '.[] | select(._id == "${contig_id}")'`);
|
|
368
|
+
contig = JSON.parse(p.stdout);
|
|
369
|
+
assert.strictEqual(contig.min, 0);
|
|
370
|
+
assert.strictEqual(contig.max, 1);
|
|
371
|
+
p = new Shell(`${apollo} feature edit-coords ${P} -i ${contig_id} -s 0`, false);
|
|
372
|
+
assert.strictEqual(p.returncode, 2);
|
|
373
|
+
assert.ok(p.stderr.includes('Coordinates must be greater than 0'));
|
|
374
|
+
p = new Shell(`${apollo} feature edit-coords ${P} -i ${contig_id} -s 10 -e 9`, false);
|
|
375
|
+
assert.strictEqual(p.returncode, 2);
|
|
376
|
+
assert.ok(p.stderr.includes('Error: The new end coordinate is lower than the new start coordinate'));
|
|
377
|
+
// Edit a feature by extending beyond the boundary of its parent and
|
|
378
|
+
// check it throws a meaningful error message
|
|
379
|
+
// let eden_gene = undefined
|
|
380
|
+
const eden_gene = features
|
|
381
|
+
.filter((x) => x.type === 'gene' && x.attributes.gff_name.at(0) === 'EDEN')
|
|
382
|
+
.at(0);
|
|
383
|
+
assert.ok(eden_gene);
|
|
384
|
+
const mrna_id = Object.keys(eden_gene.children).at(0);
|
|
385
|
+
p = new Shell(`${apollo} feature edit-coords ${P} -i ${mrna_id} -s 1`, false);
|
|
386
|
+
assert.ok(p.returncode != 0);
|
|
387
|
+
assert.ok(p.stderr.includes('exceeds the bounds of its parent'));
|
|
388
|
+
});
|
|
389
|
+
void globalThis.itName('Edit attributes', () => {
|
|
390
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a vv1 -f`);
|
|
391
|
+
// Get id of assembly named vv1
|
|
392
|
+
let p = new Shell(`${apollo} assembly get ${P} -a vv1`);
|
|
393
|
+
const asm_id = JSON.parse(p.stdout).at(0)._id;
|
|
394
|
+
p = new Shell(`${apollo} refseq get ${P} | jq '.[] | select(.assembly == "${asm_id}" and .name == "ctgA") | ._id'`);
|
|
395
|
+
const refseq = p.stdout.trim();
|
|
396
|
+
// Get feature in vv1
|
|
397
|
+
p = new Shell(`${apollo} feature get ${P} -r ${refseq} | jq '.[] | select(.type == "contig") | ._id'`);
|
|
398
|
+
const fid = p.stdout.trim();
|
|
399
|
+
// Edit existing attribute value
|
|
400
|
+
p = new Shell(`${apollo} feature edit-attribute ${P} -i $${fid} -a source -v 'Eggs & Stuff'`);
|
|
401
|
+
p = new Shell(`${apollo} feature edit-attribute ${P} -i ${fid} -a source`);
|
|
402
|
+
let out = JSON.parse(p.stdout);
|
|
403
|
+
assert.deepStrictEqual(out.at(0), `Eggs & Stuff`);
|
|
404
|
+
// Add attribute
|
|
405
|
+
new Shell(`${apollo} feature edit-attribute ${P} -i ${fid} -a newAttr -v stuff`);
|
|
406
|
+
p = new Shell(`${apollo} feature edit-attribute ${P} -i ${fid} -a newAttr`);
|
|
407
|
+
assert.ok(p.stdout.includes('stuf'));
|
|
408
|
+
// Non existing attr
|
|
409
|
+
p = new Shell(`${apollo} feature edit-attribute ${P} -i ${fid} -a NonExist`);
|
|
410
|
+
assert.deepStrictEqual(p.stdout.trim(), '');
|
|
411
|
+
// List of values
|
|
412
|
+
p = new Shell(`${apollo} feature edit-attribute ${P} -i ${fid} -a newAttr -v A B C`);
|
|
413
|
+
p = new Shell(`${apollo} feature edit-attribute ${P} -i ${fid} -a newAttr`);
|
|
414
|
+
out = JSON.parse(p.stdout);
|
|
415
|
+
assert.deepStrictEqual(out, ['A', 'B', 'C']);
|
|
416
|
+
// Delete attribute
|
|
417
|
+
new Shell(`${apollo} feature edit-attribute ${P} -i ${fid} -a newAttr -d`);
|
|
418
|
+
p = new Shell(`${apollo} feature edit-attribute ${P} -i ${fid} -a newAttr`);
|
|
419
|
+
assert.deepStrictEqual(p.stdout.trim(), '');
|
|
420
|
+
// Delete again is ok
|
|
421
|
+
new Shell(`${apollo} feature edit-attribute ${P} -i ${fid} -a newAttr -d`);
|
|
422
|
+
// Special fields
|
|
423
|
+
p = new Shell(`${apollo} feature edit-attribute ${P} -i ${fid} -a 'Gene Ontology' -v GO:0051728 GO:0019090`);
|
|
424
|
+
p = new Shell(`${apollo} feature edit-attribute ${P} -i ${fid} -a 'Gene Ontology'`);
|
|
425
|
+
out = JSON.parse(p.stdout);
|
|
426
|
+
assert.deepStrictEqual(out, ['GO:0051728', 'GO:0019090']);
|
|
427
|
+
// This should fail
|
|
428
|
+
p = new Shell(`${apollo} feature edit-attribute ${P} -i ${fid} -a 'Gene Ontology' -v FOOBAR`);
|
|
429
|
+
});
|
|
430
|
+
void globalThis.itName('Search features', () => {
|
|
431
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a vv1 -f`);
|
|
432
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a vv2 -f`);
|
|
433
|
+
let p = new Shell(`${apollo} feature search ${P} -a vv1 vv2 -t EDEN`);
|
|
434
|
+
let out = JSON.parse(p.stdout);
|
|
435
|
+
assert.strictEqual(out.length, 2);
|
|
436
|
+
assert.ok(p.stdout.includes('EDEN'));
|
|
437
|
+
p = new Shell(`${apollo} feature search ${P} -t EDEN`);
|
|
438
|
+
out = JSON.parse(p.stdout);
|
|
439
|
+
assert.ok(out.length >= 2);
|
|
440
|
+
p = new Shell(`${apollo} feature search ${P} -a vv1 -t EDEN`);
|
|
441
|
+
out = JSON.parse(p.stdout);
|
|
442
|
+
assert.strictEqual(out.length, 1);
|
|
443
|
+
assert.ok(p.stdout.includes('EDEN'));
|
|
444
|
+
p = new Shell(`${apollo} feature search ${P} -a foobar -t EDEN`);
|
|
445
|
+
assert.strictEqual('[]', p.stdout.trim());
|
|
446
|
+
assert.ok(p.stderr.includes('Warning'));
|
|
447
|
+
p = new Shell(`${apollo} feature search ${P} -a vv1 -t foobarspam`);
|
|
448
|
+
assert.deepStrictEqual(p.stdout.trim(), '[]');
|
|
449
|
+
// It searches attributes values, not attribute names
|
|
450
|
+
p = new Shell(`${apollo} feature search ${P} -a vv1 -t multivalue`);
|
|
451
|
+
assert.deepStrictEqual(p.stdout.trim(), '[]');
|
|
452
|
+
// Search feature type
|
|
453
|
+
p = new Shell(`${apollo} feature search ${P} -a vv1 -t contig`);
|
|
454
|
+
assert.ok(p.stdout.includes('"type": "contig"'));
|
|
455
|
+
// Search source (which in fact is an attribute)
|
|
456
|
+
p = new Shell(`${apollo} feature search ${P} -a vv1 -t someExample`);
|
|
457
|
+
assert.ok(p.stdout.includes('SomeContig'));
|
|
458
|
+
// Case insensitive
|
|
459
|
+
p = new Shell(`${apollo} feature search ${P} -a vv1 -t SOMEexample`);
|
|
460
|
+
assert.ok(p.stdout.includes('SomeContig'));
|
|
461
|
+
// No partial word match
|
|
462
|
+
p = new Shell(`${apollo} feature search ${P} -a vv1 -t Fingerpri`);
|
|
463
|
+
assert.deepStrictEqual(p.stdout.trim(), '[]');
|
|
464
|
+
// Match full word not necessarily full value
|
|
465
|
+
p = new Shell(`${apollo} feature search ${P} -a vv1 -t Fingerprinted`);
|
|
466
|
+
assert.ok(p.stdout.includes('Fingerprinted'));
|
|
467
|
+
// Does not search contig names (reference sequence name)
|
|
468
|
+
p = new Shell(`${apollo} feature search ${P} -a vv1 -t ctgB`);
|
|
469
|
+
assert.deepStrictEqual(p.stdout.trim(), '[]');
|
|
470
|
+
// Does not match common words (?) ...
|
|
471
|
+
p = new Shell(`${apollo} feature search ${P} -a vv1 -t with`);
|
|
472
|
+
assert.deepStrictEqual(p.stdout.trim(), '[]');
|
|
473
|
+
// ...But "fake" is ok
|
|
474
|
+
p = new Shell(`${apollo} feature search ${P} -a vv1 -t fake`);
|
|
475
|
+
assert.ok(p.stdout.includes('FakeSNP1'));
|
|
476
|
+
// ...or a single unusual letter
|
|
477
|
+
p = new Shell(`${apollo} feature search ${P} -a vv1 -t Q`);
|
|
478
|
+
assert.ok(p.stdout.includes('"Q"'));
|
|
479
|
+
});
|
|
480
|
+
void globalThis.itName('Delete features', () => {
|
|
481
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a vv1 -f`);
|
|
482
|
+
let p = new Shell(`${apollo} feature search ${P} -a vv1 -t EDEN`);
|
|
483
|
+
const fid = JSON.parse(p.stdout).at(0)._id;
|
|
484
|
+
p = new Shell(`${apollo} feature delete ${P} -i ${fid} --dry-run`);
|
|
485
|
+
assert.ok(p.stdout.includes(fid));
|
|
486
|
+
new Shell(`${apollo} feature delete ${P} -i ${fid}`);
|
|
487
|
+
p = new Shell(`${apollo} feature search ${P} -a vv1 -t EDEN`);
|
|
488
|
+
assert.deepStrictEqual(p.stdout.trim(), '[]');
|
|
489
|
+
p = new Shell(`${apollo} feature delete ${P} -i ${fid}`, false);
|
|
490
|
+
assert.strictEqual(p.returncode, 1);
|
|
491
|
+
assert.ok(p.stderr.includes('The following featureId was not found in database'));
|
|
492
|
+
p = new Shell(`${apollo} feature delete ${P} --force -i ${fid}`);
|
|
493
|
+
assert.strictEqual(p.returncode, 0);
|
|
494
|
+
});
|
|
495
|
+
void globalThis.itName('Add child features', () => {
|
|
496
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a vv1 -f`);
|
|
497
|
+
let p = new Shell(`${apollo} feature search ${P} -a vv1 -t contig`);
|
|
498
|
+
const fid = JSON.parse(p.stdout).at(0)._id;
|
|
499
|
+
new Shell(`${apollo} feature add-child ${P} -i ${fid} -s 10 -e 20 -t contig_read`);
|
|
500
|
+
p = new Shell(`${apollo} feature search ${P} -a vv1 -t contig_read`);
|
|
501
|
+
assert.ok(p.stdout.includes('contig_read'));
|
|
502
|
+
assert.ok(p.stdout.includes('"min": 9'));
|
|
503
|
+
assert.ok(p.stdout.includes('"max": 20'));
|
|
504
|
+
p = new Shell(`${apollo} feature add-child ${P} -i ${fid} -s 10 -e 2000 -t contig_read`, false);
|
|
505
|
+
assert.ok(p.returncode != 0);
|
|
506
|
+
assert.ok(p.stderr.includes('Child feature coordinates'));
|
|
507
|
+
// Should this fail?
|
|
508
|
+
p = new Shell(`${apollo} feature add-child ${P} -i ${fid} -s 10 -e 20 -t FOOBAR`, false);
|
|
509
|
+
assert.strictEqual(p.returncode, 0);
|
|
510
|
+
});
|
|
511
|
+
void globalThis.itName('Import features', () => {
|
|
512
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tiny.fasta -a vv1 -e -f`);
|
|
513
|
+
new Shell(`${apollo} feature import ${P} test_data/tiny.fasta.gff3 -a vv1`);
|
|
514
|
+
let p = new Shell(`${apollo} feature search ${P} -a vv1 -t contig`);
|
|
515
|
+
let out = JSON.parse(p.stdout);
|
|
516
|
+
assert.strictEqual(out.length, 2);
|
|
517
|
+
// Import again: Add to existing feature
|
|
518
|
+
p = new Shell(`${apollo} feature import ${P} test_data/tiny.fasta.gff3 -a vv1`);
|
|
519
|
+
p = new Shell(`${apollo} feature search ${P} -a vv1 -t contig`);
|
|
520
|
+
out = JSON.parse(p.stdout);
|
|
521
|
+
assert.strictEqual(out.length, 4);
|
|
522
|
+
// Import again: delete ${P} existing
|
|
523
|
+
p = new Shell(`${apollo} feature import ${P} -d test_data/tiny.fasta.gff3 -a vv1`);
|
|
524
|
+
p = new Shell(`${apollo} feature search ${P} -a vv1 -t contig`);
|
|
525
|
+
out = JSON.parse(p.stdout);
|
|
526
|
+
assert.strictEqual(out.length, 2);
|
|
527
|
+
p = new Shell(`${apollo} assembly delete ${P} -a vv2`);
|
|
528
|
+
p = new Shell(`${apollo} feature import ${P} test_data/tiny.fasta.gff3 -a vv2`, false);
|
|
529
|
+
assert.ok(p.returncode != 0);
|
|
530
|
+
assert.ok(p.stderr.includes('Assembly "vv2" does not exist'));
|
|
531
|
+
p = new Shell(`${apollo} feature import ${P} foo.gff3 -a vv1`, false);
|
|
532
|
+
assert.ok(p.returncode != 0);
|
|
533
|
+
assert.ok(p.stderr.includes('File "foo.gff3" does not exist'));
|
|
534
|
+
});
|
|
535
|
+
void globalThis.itName('Copy feature', () => {
|
|
536
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a source -f`);
|
|
537
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tiny.fasta -a dest -e -f`);
|
|
538
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tiny.fasta -a dest2 -e -f`);
|
|
539
|
+
let p = new Shell(`${apollo} feature search ${P} -a source -t contig`);
|
|
540
|
+
const fid = JSON.parse(p.stdout).at(0)._id;
|
|
541
|
+
new Shell(`${apollo} feature copy ${P} -i ${fid} -r ctgA -a dest -s 1`);
|
|
542
|
+
p = new Shell(`${apollo} feature search ${P} -a dest -t contig`);
|
|
543
|
+
let out = JSON.parse(p.stdout).at(0);
|
|
544
|
+
assert.strictEqual(out.min, 0);
|
|
545
|
+
assert.strictEqual(out.max, 50);
|
|
546
|
+
// RefSeq id does not need assembly
|
|
547
|
+
p = new Shell(`${apollo} refseq get ${P} -a dest2`);
|
|
548
|
+
const destRefSeq = JSON.parse(p.stdout)
|
|
549
|
+
.filter((x) => x.name === 'ctgA')
|
|
550
|
+
.at(0)._id;
|
|
551
|
+
p = new Shell(`${apollo} feature copy ${P} -i ${fid} -r ${destRefSeq} -s 2`);
|
|
552
|
+
p = new Shell(`${apollo} feature search ${P} -a dest2 -t contig`);
|
|
553
|
+
out = JSON.parse(p.stdout).at(0);
|
|
554
|
+
assert.strictEqual(out.min, 1);
|
|
555
|
+
assert.strictEqual(out.max, 51);
|
|
556
|
+
// Copy to same assembly
|
|
557
|
+
new Shell(`${apollo} feature copy ${P} -i ${fid} -r ctgA -a source -s 10`);
|
|
558
|
+
p = new Shell(`${apollo} feature search ${P} -a source -t contig`);
|
|
559
|
+
out = JSON.parse(p.stdout);
|
|
560
|
+
// Copy non-existant feature or refseq
|
|
561
|
+
p = new Shell(`${apollo} feature copy ${P} -i FOOBAR -r ctgA -a dest -s 1`, false);
|
|
562
|
+
assert.ok(p.returncode != 0);
|
|
563
|
+
assert.ok(p.stderr.includes('ERROR'));
|
|
564
|
+
p = new Shell(`${apollo} feature copy ${P} -i ${fid} -r FOOBAR -a dest -s 1`, false);
|
|
565
|
+
assert.ok(p.returncode != 0);
|
|
566
|
+
assert.ok(p.stderr.includes('No reference'));
|
|
567
|
+
// Ambiguous refseq
|
|
568
|
+
p = new Shell(`${apollo} feature copy ${P} -i ${fid} -r ctgA -s 1`, false);
|
|
569
|
+
assert.ok(p.returncode != 0);
|
|
570
|
+
assert.ok(p.stderr.includes('more than one'));
|
|
571
|
+
});
|
|
572
|
+
void globalThis.itName('Get changes', () => {
|
|
573
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tiny.fasta -a myAssembly -e -f`);
|
|
574
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tiny.fasta -a yourAssembly -e -f`);
|
|
575
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tiny.fasta -a ourAssembly -e -f`);
|
|
576
|
+
let p = new Shell(`${apollo} change get ${P}`);
|
|
577
|
+
JSON.parse(p.stdout);
|
|
578
|
+
assert.ok(p.stdout.includes('myAssembly'));
|
|
579
|
+
assert.ok(p.stdout.includes('yourAssembly'));
|
|
580
|
+
p = new Shell(`${apollo} change get ${P} -a myAssembly ourAssembly`);
|
|
581
|
+
assert.ok(p.stdout.includes('myAssembly'));
|
|
582
|
+
assert.ok(p.stdout.includes('ourAssembly'));
|
|
583
|
+
assert.ok(p.stdout.includes('yourAssembly') == false);
|
|
584
|
+
// Delete assemblies and get changes by assembly name: Nothing is
|
|
585
|
+
// returned because the assemblies collection doesn't contain that name
|
|
586
|
+
// anymore. Ideally you should still be able to get changes by name?
|
|
587
|
+
new Shell(`${apollo} assembly delete ${P} -a myAssembly yourAssembly ourAssembly`);
|
|
588
|
+
p = new Shell(`${apollo} change get ${P} -a myAssembly`);
|
|
589
|
+
const out = JSON.parse(p.stdout);
|
|
590
|
+
assert.strictEqual(out.length, 0);
|
|
591
|
+
});
|
|
592
|
+
void globalThis.itName('Get sequence', () => {
|
|
593
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tiny.fasta -a v1 -e -f`);
|
|
594
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tiny.fasta -a v2 -e -f`);
|
|
595
|
+
let p = new Shell(`${apollo} assembly sequence ${P} -a nonExistant`, false);
|
|
596
|
+
assert.ok(p.returncode != 0);
|
|
597
|
+
assert.ok(p.stderr.includes('returned 0 assemblies'));
|
|
598
|
+
p = new Shell(`${apollo} assembly sequence ${P} -a v1 -s 0`, false);
|
|
599
|
+
assert.ok(p.returncode != 0);
|
|
600
|
+
assert.ok(p.stderr.includes('must be greater than 0'));
|
|
601
|
+
p = new Shell(`${apollo} assembly sequence ${P} -a v1`);
|
|
602
|
+
let seq = p.stdout.trim().split('\n');
|
|
603
|
+
assert.strictEqual(seq.length, 25);
|
|
604
|
+
assert.deepStrictEqual(seq.at(0), '>ctgA:1..420');
|
|
605
|
+
assert.deepStrictEqual(seq.at(1), 'cattgttgcggagttgaacaACGGCATTAGGAACACTTCCGTCTCtcacttttatacgattatgattggttctttagcct');
|
|
606
|
+
assert.deepStrictEqual(seq.at(6), 'ttggtcgctccgttgtaccc');
|
|
607
|
+
assert.deepStrictEqual(seq.at(7), '>ctgB:1..800');
|
|
608
|
+
assert.deepStrictEqual(seq.at(-1), 'ttggtcgctccgttgtaccc');
|
|
609
|
+
p = new Shell(`${apollo} assembly sequence ${P} -a v1 -r ctgB -s 1 -e 1`);
|
|
610
|
+
seq = p.stdout.split('\n');
|
|
611
|
+
assert.deepStrictEqual(seq.at(0), '>ctgB:1..1');
|
|
612
|
+
assert.deepStrictEqual(seq.at(1), 'A');
|
|
613
|
+
p = new Shell(`${apollo} assembly sequence ${P} -a v1 -r ctgB -s 2 -e 4`);
|
|
614
|
+
seq = p.stdout.split('\n');
|
|
615
|
+
assert.deepStrictEqual(seq.at(0), '>ctgB:2..4');
|
|
616
|
+
assert.deepStrictEqual(seq.at(1), 'CAT');
|
|
617
|
+
p = new Shell(`${apollo} assembly sequence ${P} -r ctgB`, false);
|
|
618
|
+
assert.ok(p.returncode != 0);
|
|
619
|
+
assert.ok(p.stderr.includes('found in more than one'));
|
|
620
|
+
});
|
|
621
|
+
void globalThis.itName('Get feature by id', () => {
|
|
622
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a v1 -f`);
|
|
623
|
+
let p = new Shell(`${apollo} feature get ${P} -a v1`);
|
|
624
|
+
const ff = JSON.parse(p.stdout);
|
|
625
|
+
const x1 = ff.at(0)._id;
|
|
626
|
+
const x2 = ff.at(1)._id;
|
|
627
|
+
p = new Shell(`${apollo} feature get-id ${P} -i ${x1} ${x1} ${x2}`);
|
|
628
|
+
let out = JSON.parse(p.stdout);
|
|
629
|
+
assert.strictEqual(out.length, 2);
|
|
630
|
+
assert.deepStrictEqual(out.at(0)._id, x1);
|
|
631
|
+
assert.deepStrictEqual(out.at(1)._id, x2);
|
|
632
|
+
p = new Shell(`${apollo} feature get-id ${P} -i FOOBAR`);
|
|
633
|
+
assert.deepStrictEqual(p.stdout.trim(), '[]');
|
|
634
|
+
p = new Shell(`echo -e '${x1} \n ${x2}' | ${apollo} feature get-id ${P}`);
|
|
635
|
+
out = JSON.parse(p.stdout);
|
|
636
|
+
assert.strictEqual(out.length, 2);
|
|
637
|
+
});
|
|
638
|
+
void globalThis.itName('Assembly checks', () => {
|
|
639
|
+
// TODO: Improve tests once more checks exist (currently there is only
|
|
640
|
+
// CDSCheck)
|
|
641
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a v1 -f`);
|
|
642
|
+
// Test view available check type
|
|
643
|
+
let p = new Shell(`${apollo} assembly check ${P}`);
|
|
644
|
+
let out = JSON.parse(p.stdout);
|
|
645
|
+
assert.ok(p.stdout.includes('CDSCheck'));
|
|
646
|
+
const cdsCheckId = out.filter((x) => x.name === 'CDSCheck').at(0)._id;
|
|
647
|
+
// Test view checks set for assembly
|
|
648
|
+
p = new Shell(`${apollo} assembly check ${P} -a v1`);
|
|
649
|
+
out = JSON.parse(p.stdout);
|
|
650
|
+
assert.strictEqual(out.length, 1);
|
|
651
|
+
// Test non-existant assembly
|
|
652
|
+
p = new Shell(`${apollo} assembly check ${P} -a non-existant`, false);
|
|
653
|
+
assert.strictEqual(p.returncode, 1);
|
|
654
|
+
assert.ok(p.stderr.includes('non-existant'));
|
|
655
|
+
// Test non-existant check
|
|
656
|
+
p = new Shell(`${apollo} assembly check ${P} -a v1 -c not-a-check`, false);
|
|
657
|
+
assert.strictEqual(p.returncode, 1);
|
|
658
|
+
assert.ok(p.stderr.includes('not-a-check'));
|
|
659
|
+
// Test add checks. Test check is added as opposed to replacing current
|
|
660
|
+
// checks with input list
|
|
661
|
+
new Shell(`${apollo} assembly check ${P} -a v1 -c CDSCheck CDSCheck`);
|
|
662
|
+
p = new Shell(`${apollo} assembly check ${P} -a v1`);
|
|
663
|
+
out = JSON.parse(p.stdout);
|
|
664
|
+
assert.strictEqual(out.length, 1);
|
|
665
|
+
assert.deepStrictEqual(out.at(0).name, 'CDSCheck');
|
|
666
|
+
// Works also with check id
|
|
667
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a v2 -f`);
|
|
668
|
+
new Shell(`${apollo} assembly check ${P} -a v2 -c ${cdsCheckId}`);
|
|
669
|
+
p = new Shell(`${apollo} assembly check ${P} -a v2`);
|
|
670
|
+
out = JSON.parse(p.stdout);
|
|
671
|
+
assert.strictEqual(out.length, 1);
|
|
672
|
+
assert.deepStrictEqual(out.at(0).name, 'CDSCheck');
|
|
673
|
+
// Delete check
|
|
674
|
+
new Shell(`${apollo} assembly check ${P} -a v1 -d -c CDSCheck`);
|
|
675
|
+
p = new Shell(`${apollo} assembly check ${P} -a v1`);
|
|
676
|
+
out = JSON.parse(p.stdout);
|
|
677
|
+
assert.deepStrictEqual(p.stdout.trim(), '[]');
|
|
678
|
+
});
|
|
679
|
+
void globalThis.itName('Feature checks', () => {
|
|
680
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a v1 -f`);
|
|
681
|
+
new Shell(`${apollo} assembly check ${P} -a v1 -c CDSCheck`);
|
|
682
|
+
let p = new Shell(`${apollo} feature check ${P} -a v1`);
|
|
683
|
+
const out = JSON.parse(p.stdout);
|
|
684
|
+
assert.ok(out.length > 1);
|
|
685
|
+
assert.ok(p.stdout.includes('InternalStopCodonCheck'));
|
|
686
|
+
// Ids with checks
|
|
687
|
+
const ids = out.map((x) => x.ids);
|
|
688
|
+
assert.ok(new Set(ids).size > 1);
|
|
689
|
+
// Retrieve by feature id
|
|
690
|
+
const xid = [...ids].join(' ');
|
|
691
|
+
p = new Shell(`${apollo} feature check ${P} -i ${xid}`);
|
|
692
|
+
assert.ok(p.stdout.includes('InternalStopCodonCheck'));
|
|
693
|
+
});
|
|
694
|
+
void globalThis.itName('Feature checks indexed', () => {
|
|
695
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} -a v1 test_data/tiny.fasta.gz -f`);
|
|
696
|
+
new Shell(`${apollo} assembly check ${P} -a v1 -c CDSCheck`);
|
|
697
|
+
new Shell(`${apollo} feature import ${P} -a v1 test_data/tiny.fasta.gff3 -d`);
|
|
698
|
+
let p = new Shell(`${apollo} feature check ${P} -a v1`);
|
|
699
|
+
const out = JSON.parse(p.stdout);
|
|
700
|
+
assert.ok(out.length > 1);
|
|
701
|
+
assert.ok(p.stdout.includes('InternalStopCodonCheck'));
|
|
702
|
+
// Ids with checks
|
|
703
|
+
const ids = out.map((x) => x.ids);
|
|
704
|
+
assert.ok(new Set(ids).size > 1);
|
|
705
|
+
// Retrieve by feature id
|
|
706
|
+
const xid = [...ids].join(' ');
|
|
707
|
+
p = new Shell(`${apollo} feature check ${P} -i ${xid}`);
|
|
708
|
+
assert.ok(p.stdout.includes('InternalStopCodonCheck'));
|
|
709
|
+
});
|
|
710
|
+
void globalThis.itName('User', () => {
|
|
711
|
+
let p = new Shell(`${apollo} user get ${P}`);
|
|
712
|
+
let out = JSON.parse(p.stdout);
|
|
713
|
+
assert.ok(out.length > 0);
|
|
714
|
+
p = new Shell(`${apollo} user get ${P} -r admin`);
|
|
715
|
+
const out2 = JSON.parse(p.stdout);
|
|
716
|
+
assert.ok(out.length > 0);
|
|
717
|
+
assert.ok(out.length > out2.length);
|
|
718
|
+
p = new Shell(`${apollo} user get ${P} -r admin -u root`);
|
|
719
|
+
out = JSON.parse(p.stdout);
|
|
720
|
+
assert.strictEqual(out.length, 1);
|
|
721
|
+
p = new Shell(`${apollo} user get ${P} -r readOnly -u root`);
|
|
722
|
+
out = JSON.parse(p.stdout);
|
|
723
|
+
assert.strictEqual(out.length, 0);
|
|
724
|
+
});
|
|
725
|
+
void globalThis.itName('Apollo profile env', () => {
|
|
726
|
+
const p = new Shell(`export APOLLO_PROFILE=testAdmin2
|
|
727
|
+
${apollo} config address http://localhost:3999
|
|
728
|
+
${apollo} config accessType root
|
|
729
|
+
${apollo} config rootPassword pass
|
|
730
|
+
${apollo} login -f
|
|
731
|
+
${apollo} status
|
|
732
|
+
${apollo} user get`);
|
|
733
|
+
assert.ok(p.stdout.includes('testAdmin2: Logged in'));
|
|
734
|
+
assert.ok(p.stdout.includes('createdAt'));
|
|
735
|
+
});
|
|
736
|
+
void globalThis.itName('Apollo config create env', () => {
|
|
737
|
+
let p = new Shell(`\
|
|
738
|
+
export APOLLO_DISABLE_CONFIG_CREATE=1
|
|
739
|
+
rm -f tmp.yml
|
|
740
|
+
${apollo} config --config-file tmp.yml address http://localhost:3999`, false);
|
|
741
|
+
assert.ok(p.returncode != 0);
|
|
742
|
+
assert.ok(p.stderr.includes('does not exist yet'));
|
|
743
|
+
assert.ok(!fs.existsSync('tmp.yml'));
|
|
744
|
+
p = new Shell(`\
|
|
745
|
+
export APOLLO_DISABLE_CONFIG_CREATE=0
|
|
746
|
+
rm -f tmp.yml
|
|
747
|
+
${apollo} config --config-file tmp.yml address http://localhost:3999`);
|
|
748
|
+
assert.strictEqual(0, p.returncode);
|
|
749
|
+
assert.ok(fs.existsSync('tmp.yml'));
|
|
750
|
+
p = new Shell(`\
|
|
751
|
+
unset APOLLO_DISABLE_CONFIG_CREATE
|
|
752
|
+
rm -f tmp.yml
|
|
753
|
+
${apollo} config --config-file tmp.yml address http://localhost:3999`);
|
|
754
|
+
assert.strictEqual(0, p.returncode);
|
|
755
|
+
assert.ok(fs.existsSync('tmp.yml'));
|
|
756
|
+
fs.unlinkSync('tmp.yml');
|
|
757
|
+
});
|
|
758
|
+
void globalThis.itName('Invalid access', () => {
|
|
759
|
+
const p = new Shell(`${apollo} user get --profile foo`, false);
|
|
760
|
+
assert.strictEqual(1, p.returncode);
|
|
761
|
+
assert.ok(p.stderr.includes('Profile "foo" does not exist'));
|
|
762
|
+
});
|
|
763
|
+
void globalThis.itName('Refname alias configuration', () => {
|
|
764
|
+
new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a asm1 -f`);
|
|
765
|
+
let p = new Shell(`${apollo} assembly get ${P} -a asm1`);
|
|
766
|
+
assert.ok(p.stdout.includes('asm1'));
|
|
767
|
+
assert.ok(p.stdout.includes('asm2') == false);
|
|
768
|
+
const asm_id = JSON.parse(p.stdout)[0]._id;
|
|
769
|
+
p = new Shell(`${apollo} refseq add-alias ${P} test_data/alias.txt -a asm2`, false);
|
|
770
|
+
assert.ok(p.stderr.includes('Assembly asm2 not found'));
|
|
771
|
+
p = new Shell(`${apollo} refseq add-alias ${P} test_data/alias.txt -a asm1`, false);
|
|
772
|
+
assert.ok(p.stdout.includes('Reference name aliases added successfully to assembly asm1'));
|
|
773
|
+
p = new Shell(`${apollo} refseq get ${P}`);
|
|
774
|
+
const refseq = JSON.parse(p.stdout.trim());
|
|
775
|
+
const vv1ref = refseq.filter((x) => x.assembly === asm_id);
|
|
776
|
+
const refname_aliases = {};
|
|
777
|
+
for (const x of vv1ref) {
|
|
778
|
+
refname_aliases[x.name] = x.aliases;
|
|
779
|
+
}
|
|
780
|
+
assert.deepStrictEqual(JSON.stringify(refname_aliases.ctgA.sort()), JSON.stringify(['ctga', 'CTGA'].sort()));
|
|
781
|
+
assert.deepStrictEqual(JSON.stringify(refname_aliases.ctgB.sort()), JSON.stringify(['ctgb', 'CTGB'].sort()));
|
|
782
|
+
assert.deepStrictEqual(JSON.stringify(refname_aliases.ctgC.sort()), JSON.stringify(['ctgc', 'CTGC'].sort()));
|
|
783
|
+
});
|
|
784
|
+
// Works locally but fails on github
|
|
785
|
+
void globalThis.itName('Login', () => {
|
|
786
|
+
// This should wait for user's input
|
|
787
|
+
const p = new Shell(`${apollo} login ${P}`, false, 5000);
|
|
788
|
+
assert.ok(p.returncode != 0);
|
|
789
|
+
// This should be ok
|
|
790
|
+
new Shell(`${apollo} login ${P} --force`, true, 5000);
|
|
791
|
+
});
|
|
792
|
+
void globalThis.itName('File upload', () => {
|
|
793
|
+
let p = new Shell(`${apollo} file upload ${P} test_data/tiny.fasta`);
|
|
794
|
+
let out = JSON.parse(p.stdout);
|
|
795
|
+
assert.deepStrictEqual(out.type, 'text/x-fasta');
|
|
796
|
+
assert.ok(out._id);
|
|
797
|
+
p = new Shell(`${apollo} file upload ${P} test_data/tiny.fasta`);
|
|
798
|
+
out = JSON.parse(p.stdout);
|
|
799
|
+
assert.deepStrictEqual(out.type, 'text/x-fasta');
|
|
800
|
+
p = new Shell(`${apollo} file upload ${P} test_data/tiny.fasta.gff3`);
|
|
801
|
+
out = JSON.parse(p.stdout);
|
|
802
|
+
assert.deepStrictEqual(out.type, 'text/x-gff3');
|
|
803
|
+
p = new Shell(`${apollo} file upload ${P} test_data/guest.yaml`, false);
|
|
804
|
+
assert.ok(p.returncode != 0);
|
|
805
|
+
p = new Shell(`${apollo} file upload ${P} test_data/tiny.fasta.gz`, false);
|
|
806
|
+
assert.ok(p.stderr.includes('it may be gzip or bgzip compressed'));
|
|
807
|
+
assert.ok(p.returncode != 0);
|
|
808
|
+
});
|
|
809
|
+
void globalThis.itName('File upload gzip', () => {
|
|
810
|
+
// Uploading a gzip file must skip compression and just copy the file
|
|
811
|
+
const gz = fs.readFileSync('test_data/tiny.fasta.gz');
|
|
812
|
+
const md5 = crypto.createHash('md5').update(gz).digest('hex');
|
|
813
|
+
const p = new Shell(`${apollo} file upload ${P} test_data/tiny.fasta.gz -t text/x-fasta`);
|
|
814
|
+
const out = JSON.parse(p.stdout);
|
|
815
|
+
assert.strictEqual(out.checksum, md5);
|
|
816
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} -e -f ${out._id}`);
|
|
817
|
+
});
|
|
818
|
+
void globalThis.itName('Add assembly gzip', () => {
|
|
819
|
+
// Autodetect format
|
|
820
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tiny.fasta.gz -e -f -a vv1`);
|
|
821
|
+
let p = new Shell(`${apollo} assembly sequence ${P} -a vv1`);
|
|
822
|
+
assert.ok(p.stdout.startsWith('>'));
|
|
823
|
+
assert.ok(p.stdout.includes('cattgttgcggagttgaaca'));
|
|
824
|
+
// Skip autodetect
|
|
825
|
+
fs.copyFileSync('test_data/tiny.fasta', 'test_data/tmp.gz');
|
|
826
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tmp.gz -e -f -a vv1 --decompressed`);
|
|
827
|
+
p = new Shell(`${apollo} assembly sequence ${P} -a vv1`);
|
|
828
|
+
assert.ok(p.stdout.startsWith('>'));
|
|
829
|
+
assert.ok(p.stdout.includes('cattgttgcggagttgaaca'));
|
|
830
|
+
fs.unlinkSync('test_data/tmp.gz');
|
|
831
|
+
fs.copyFileSync('test_data/tiny.fasta.gz', 'test_data/fasta.tmp');
|
|
832
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} test_data/fasta.tmp -e -f -a vv1 --gzip`);
|
|
833
|
+
p = new Shell(`${apollo} assembly sequence ${P} -a vv1`);
|
|
834
|
+
assert.ok(p.stdout.startsWith('>'));
|
|
835
|
+
assert.ok(p.stdout.includes('cattgttgcggagttgaaca'));
|
|
836
|
+
// Autodetect false positive
|
|
837
|
+
p = new Shell(`${apollo} assembly add-from-fasta ${P} test_data/fasta.tmp -e -f -a vv1`, false);
|
|
838
|
+
assert.ok(p.returncode != 0);
|
|
839
|
+
fs.unlinkSync('test_data/fasta.tmp');
|
|
840
|
+
});
|
|
841
|
+
void globalThis.itName('Add editable assembly', () => {
|
|
842
|
+
// It would be good to check that really there was no sequence loading
|
|
843
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} -f test_data/tiny.fasta.gz`);
|
|
844
|
+
let p = new Shell(`${apollo} assembly sequence ${P} -a tiny.fasta.gz`);
|
|
845
|
+
assert.ok(p.stdout.startsWith('>'));
|
|
846
|
+
assert.ok(p.stdout.includes('cattgttgcggagttgaaca'));
|
|
847
|
+
p = new Shell(`${apollo} assembly add-from-fasta ${P} -f test_data/tiny.fasta`, false);
|
|
848
|
+
assert.ok(p.returncode != 0);
|
|
849
|
+
assert.ok(p.stderr.includes('unless option -e/--editable is set'));
|
|
850
|
+
// Setting --gzi & --fai
|
|
851
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} -f test_data/tiny2.fasta.gz --gzi test_data/tiny.fasta.gz.gzi --fai test_data/tiny.fasta.gz.fai`);
|
|
852
|
+
p = new Shell(`${apollo} assembly sequence ${P} -a tiny2.fasta.gz`);
|
|
853
|
+
assert.ok(p.stdout.startsWith('>'));
|
|
854
|
+
assert.ok(p.stdout.includes('cattgttgcggagttgaaca'));
|
|
855
|
+
});
|
|
856
|
+
void globalThis.itName('Add assembly from file ids not editable', () => {
|
|
857
|
+
// Upload and get Ids for: bgzip fasta, fai and gzi
|
|
858
|
+
let p = new Shell(`${apollo} file upload ${P} test_data/tiny.fasta.gz -t application/x-bgzip-fasta`);
|
|
859
|
+
const fastaId = JSON.parse(p.stdout)._id;
|
|
860
|
+
p = new Shell(`${apollo} file upload ${P} test_data/tiny.fasta.gz.fai`);
|
|
861
|
+
const faiId = JSON.parse(p.stdout)._id;
|
|
862
|
+
p = new Shell(`${apollo} file upload ${P} test_data/tiny.fasta.gz.gzi`);
|
|
863
|
+
const gziId = JSON.parse(p.stdout)._id;
|
|
864
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} -f ${fastaId} --fai test_data/tiny.fasta.gz.fai --gzi test_data/tiny.fasta.gz.gzi`);
|
|
865
|
+
p = new Shell(`${apollo} assembly sequence ${P} -a ${fastaId}`);
|
|
866
|
+
assert.ok(p.stdout.startsWith('>'));
|
|
867
|
+
assert.ok(p.stdout.includes('cattgttgcggagttgaaca'));
|
|
868
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} -f ${fastaId} --fai ${faiId} --gzi ${gziId}`);
|
|
869
|
+
p = new Shell(`${apollo} assembly sequence ${P} -a ${fastaId}`);
|
|
870
|
+
assert.ok(p.stdout.startsWith('>'));
|
|
871
|
+
});
|
|
872
|
+
void globalThis.itName('Add assembly from file id', () => {
|
|
873
|
+
let p = new Shell(`${apollo} file upload ${P} test_data/tiny.fasta`);
|
|
874
|
+
const fid = JSON.parse(p.stdout)._id;
|
|
875
|
+
p = new Shell(`${apollo} assembly add-from-fasta ${P} ${fid} -a up -e -f`);
|
|
876
|
+
const out = JSON.parse(p.stdout);
|
|
877
|
+
assert.deepStrictEqual(out.name, 'up');
|
|
878
|
+
assert.deepStrictEqual(out.fileIds.fa, fid);
|
|
879
|
+
});
|
|
880
|
+
void globalThis.itName('Get files', () => {
|
|
881
|
+
new Shell(`${apollo} file upload ${P} test_data/tiny.fasta`);
|
|
882
|
+
let p = new Shell(`${apollo} file upload ${P} test_data/tiny.fasta`);
|
|
883
|
+
const fid = JSON.parse(p.stdout)._id;
|
|
884
|
+
p = new Shell(`${apollo} file get ${P}`);
|
|
885
|
+
let out = JSON.parse(p.stdout);
|
|
886
|
+
assert.ok(out.length >= 2);
|
|
887
|
+
assert.ok(out.filter((x) => x._id === fid));
|
|
888
|
+
p = new Shell(`${apollo} file get ${P} -i ${fid} ${fid}`);
|
|
889
|
+
out = JSON.parse(p.stdout);
|
|
890
|
+
assert.strictEqual(out.length, 1);
|
|
891
|
+
p = new Shell(`${apollo} file get ${P} -i nonexists`);
|
|
892
|
+
out = JSON.parse(p.stdout);
|
|
893
|
+
assert.strictEqual(out.length, 0);
|
|
894
|
+
});
|
|
895
|
+
void globalThis.itName('Download file', () => {
|
|
896
|
+
let p = new Shell(`${apollo} file upload ${P} test_data/tiny.fasta`);
|
|
897
|
+
const up = JSON.parse(p.stdout);
|
|
898
|
+
if (fs.existsSync(up.basename)) {
|
|
899
|
+
throw new Error(`File ${up.basename} exists - if safe to do so, delete it before running this test`);
|
|
900
|
+
}
|
|
901
|
+
new Shell(`${apollo} file download ${P} -i ${up._id}`);
|
|
902
|
+
let down = fs.readFileSync(up.basename).toString();
|
|
903
|
+
assert.ok(down.startsWith('>'));
|
|
904
|
+
assert.ok(down.trim().endsWith('accc'));
|
|
905
|
+
fs.unlinkSync(up.basename);
|
|
906
|
+
new Shell(`${apollo} file download ${P} -i ${up._id} -o tmp.fa`);
|
|
907
|
+
down = fs.readFileSync('tmp.fa').toString();
|
|
908
|
+
assert.ok(down.startsWith('>'));
|
|
909
|
+
assert.ok(down.trim().endsWith('accc'));
|
|
910
|
+
fs.unlinkSync('tmp.fa');
|
|
911
|
+
p = new Shell(`${apollo} file download ${P} -i ${up._id} -o -`);
|
|
912
|
+
assert.ok(p.stdout.startsWith('>'));
|
|
913
|
+
assert.ok(p.stdout.trim().endsWith('accc'));
|
|
914
|
+
});
|
|
915
|
+
void globalThis.itName('Delete file', () => {
|
|
916
|
+
let p = new Shell(`${apollo} file upload ${P} test_data/tiny.fasta`);
|
|
917
|
+
const up1 = JSON.parse(p.stdout);
|
|
918
|
+
p = new Shell(`${apollo} file upload ${P} test_data/tiny.fasta`);
|
|
919
|
+
const up2 = JSON.parse(p.stdout);
|
|
920
|
+
p = new Shell(`${apollo} file delete ${P} -i ${up1._id} ${up2._id}`);
|
|
921
|
+
let out = JSON.parse(p.stdout);
|
|
922
|
+
assert.strictEqual(out.length, 2);
|
|
923
|
+
p = new Shell(`${apollo} file get ${P} -i ${up1._id} ${up2._id}`);
|
|
924
|
+
out = JSON.parse(p.stdout);
|
|
925
|
+
assert.strictEqual(out.length, 0);
|
|
926
|
+
});
|
|
927
|
+
void globalThis.itName('Export gff3 from editable assembly', () => {
|
|
928
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tiny.fasta.gz -a vv1 -f --editable`);
|
|
929
|
+
new Shell(`${apollo} feature import ${P} test_data/tiny.fasta.gff3 -a vv1`);
|
|
930
|
+
let p = new Shell(`${apollo} export gff3 ${P} vv1 --include-fasta`);
|
|
931
|
+
let gff = p.stdout;
|
|
932
|
+
assert.ok(gff.startsWith('##gff-version 3'));
|
|
933
|
+
assert.ok(gff.includes('multivalue=val1,val2,val3'));
|
|
934
|
+
assert.ok(gff.includes('##FASTA\n'));
|
|
935
|
+
assert.deepStrictEqual(gff.slice(-6, gff.length), 'taccc\n');
|
|
936
|
+
p = new Shell(`${apollo} export gff3 ${P} vv1`);
|
|
937
|
+
gff = p.stdout;
|
|
938
|
+
assert.ok(gff.startsWith('##gff-version 3'));
|
|
939
|
+
assert.ok(gff.includes('multivalue=val1,val2,val3'));
|
|
940
|
+
assert.ok(!gff.includes('##FASTA\n'));
|
|
941
|
+
// Invalid assembly
|
|
942
|
+
p = new Shell(`${apollo} export gff3 ${P} foobar`, false);
|
|
943
|
+
assert.ok(p.returncode != 0);
|
|
944
|
+
assert.ok(p.stderr.includes('foobar'));
|
|
945
|
+
});
|
|
946
|
+
void globalThis.itName('Export gff3 from non-editable assembly', () => {
|
|
947
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tiny.fasta.gz -a vv1 -f`);
|
|
948
|
+
new Shell(`${apollo} feature import ${P} test_data/tiny.fasta.gff3 -a vv1`);
|
|
949
|
+
let p = new Shell(`${apollo} export gff3 ${P} vv1 --include-fasta`);
|
|
950
|
+
let gff = p.stdout;
|
|
951
|
+
assert.ok(gff.startsWith('##gff-version 3'));
|
|
952
|
+
assert.ok(gff.includes('multivalue=val1,val2,val3'));
|
|
953
|
+
assert.ok(gff.includes('##FASTA\n'));
|
|
954
|
+
// We end with two newlines because the test data does have an extra newline at the end.
|
|
955
|
+
assert.deepStrictEqual(gff.slice(-7, gff.length), 'taccc\n\n');
|
|
956
|
+
p = new Shell(`${apollo} export gff3 ${P} vv1`);
|
|
957
|
+
gff = p.stdout;
|
|
958
|
+
assert.ok(gff.startsWith('##gff-version 3'));
|
|
959
|
+
assert.ok(gff.includes('multivalue=val1,val2,val3'));
|
|
960
|
+
assert.ok(!gff.includes('##FASTA\n'));
|
|
961
|
+
});
|
|
962
|
+
void globalThis.itName('Export gff3 from external assembly', () => {
|
|
963
|
+
new Shell(`${apollo} assembly add-from-fasta ${P} https://raw.githubusercontent.com/GMOD/Apollo3/refs/heads/main/packages/apollo-cli/test_data/tiny.fasta.gz -a vv1 -f`);
|
|
964
|
+
new Shell(`${apollo} feature import ${P} test_data/tiny.fasta.gff3 -a vv1`);
|
|
965
|
+
let p = new Shell(`${apollo} export gff3 ${P} vv1 --include-fasta`);
|
|
966
|
+
let gff = p.stdout;
|
|
967
|
+
assert.ok(gff.startsWith('##gff-version 3'));
|
|
968
|
+
assert.ok(gff.includes('multivalue=val1,val2,val3'));
|
|
969
|
+
assert.ok(gff.includes('##FASTA\n'));
|
|
970
|
+
// We end with two newlines because the test data does have an extra newline at the end.
|
|
971
|
+
assert.deepStrictEqual(gff.slice(-7, gff.length), 'taccc\n\n');
|
|
972
|
+
p = new Shell(`${apollo} export gff3 ${P} vv1`);
|
|
973
|
+
gff = p.stdout;
|
|
974
|
+
assert.ok(gff.startsWith('##gff-version 3'));
|
|
975
|
+
assert.ok(gff.includes('multivalue=val1,val2,val3'));
|
|
976
|
+
assert.ok(!gff.includes('##FASTA\n'));
|
|
977
|
+
});
|
|
978
|
+
});
|