Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions commands/fetch-assets.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,13 @@ const run = async (argv) => {
ui.log.info('Done');
}
} catch (error) {
ui.log.error('Done with errors', context.errors);
// `context.errors` is often empty here, so fall back to the thrown error
// to avoid reporting a failure with no detail at all
ui.log.error('Done with errors', context.errors.length ? context.errors : error);
return;
}

if (argv.zip) {
if (argv.zip && context.outputFile) {
ui.log.ok(`Zip file (${(context.outputFile.size / (1000 * 1000)).toFixed(2)}MB) saved at: ${context.outputFile.path}`);
}

Expand Down
4 changes: 3 additions & 1 deletion tasks/fetch-assets.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {join} from 'node:path';
import MgAssetScraperDb from '@tryghost/mg-assetscraper-db';
import fsUtils from '@tryghost/mg-fs-utils';
import {makeTaskRunner} from '@tryghost/listr-smart-renderer';
Expand Down Expand Up @@ -36,7 +37,8 @@ const getTaskRunner = (options, logger) => {
{
title: 'Create JSON file',
task: async (ctx) => {
await ctx.assetScraper.writeUpdatedJson(ctx.fileCache.jsonDir);
// `jsonDir` is a directory, so the scraper needs a file path within it to write to
await ctx.assetScraper.writeUpdatedJson(join(ctx.fileCache.jsonDir, 'ghost-import.json'));
}
},
{
Expand Down
82 changes: 82 additions & 0 deletions test/fetch-assets.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import {describe, test, mock, beforeEach} from 'node:test';
import assert from 'node:assert/strict';
import {join} from 'node:path';
import errors from '@tryghost/errors';

const jsonDir = '/tmp/mg/abc123/zip';

const mockWriteUpdatedJson = mock.fn(() => Promise.resolve());
const mockInit = mock.fn(() => Promise.resolve());
const mockGetTasks = mock.fn(() => []);

mock.module('@tryghost/mg-assetscraper-db', {
defaultExport: function MgAssetScraperDb() {
return {
init: mockInit,
getTasks: mockGetTasks,
writeUpdatedJson: mockWriteUpdatedJson
};
}
});

const mockZipWrite = mock.fn(() => Promise.resolve({path: '/tmp/out.zip', size: 1024}));

mock.module('@tryghost/mg-fs-utils', {
defaultExport: {
FileCache: function FileCache() {
return {
jsonDir: jsonDir,
zipDir: jsonDir,
defaultZipFileName: 'gh-example-123.zip'
};
},
zip: {
write: mockZipWrite
}
}
});

describe('Fetch assets', function () {
beforeEach(() => {
mockWriteUpdatedJson.mock.resetCalls();
mockZipWrite.mock.resetCalls();
});

test('writes the updated JSON to a file path, not to the JSON directory', async function () {
const fetchAssets = await import('../tasks/fetch-assets.js');
const runner = fetchAssets.default.getTaskRunner({
jsonFile: '/tmp/example.ghost.json',
zip: false,
verbose: false
});

await runner.run({errors: []});

assert.strictEqual(mockWriteUpdatedJson.mock.callCount(), 1);

const [outputPath] = mockWriteUpdatedJson.mock.calls[0].arguments;
assert.notStrictEqual(outputPath, jsonDir, 'must not pass the directory itself — writeFile would throw EISDIR');
assert.strictEqual(outputPath, join(jsonDir, 'ghost-import.json'));
});
});

describe('Fetch assets command', function () {
beforeEach(() => {
mockWriteUpdatedJson.mock.resetCalls();
mockZipWrite.mock.resetCalls();
});

test('does not throw when an earlier task failed and no zip was produced', async function () {
mockWriteUpdatedJson.mock.mockImplementationOnce(() => {
return Promise.reject(new errors.InternalServerError({message: 'EISDIR: illegal operation on a directory'}));
});

const command = await import('../commands/fetch-assets.js');

await assert.doesNotReject(async () => {
await command.default.run({jsonFile: '/tmp/example.ghost.json', zip: true, verbose: false});
});

assert.strictEqual(mockZipWrite.mock.callCount(), 0, 'zip must not be reported when it never ran');
});
});