techdocs-node: inline aws-s3 mock
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { EventEmitter } from 'events';
|
||||
import { ReadStream } from 'fs';
|
||||
import { IStorageFilesMock } from '../src/testUtils/types';
|
||||
|
||||
export { Credentials } from 'aws-sdk';
|
||||
|
||||
const storage = global.storageFilesMock as IStorageFilesMock;
|
||||
|
||||
export class S3 {
|
||||
constructor() {
|
||||
storage.emptyFiles();
|
||||
}
|
||||
|
||||
headObject({ Key }: { Key: string }) {
|
||||
return {
|
||||
promise: async () => {
|
||||
if (!storage.fileExists(Key)) {
|
||||
throw new Error('File does not exist');
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
getObject({ Key }: { Key: string }) {
|
||||
return {
|
||||
promise: async () => storage.fileExists(Key),
|
||||
createReadStream: () => {
|
||||
const emitter = new EventEmitter();
|
||||
process.nextTick(() => {
|
||||
if (storage.fileExists(Key)) {
|
||||
emitter.emit('data', Buffer.from(storage.readFile(Key)));
|
||||
emitter.emit('end');
|
||||
} else {
|
||||
emitter.emit('error', new Error(`The file ${Key} does not exist!`));
|
||||
}
|
||||
});
|
||||
return emitter;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
headBucket({ Bucket }) {
|
||||
return {
|
||||
promise: async () => {
|
||||
if (Bucket === 'errorBucket') {
|
||||
throw new Error('Bucket does not exist');
|
||||
}
|
||||
return {};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
upload({ Key, Body }: { Key: string; Body: ReadStream }) {
|
||||
return {
|
||||
promise: () =>
|
||||
new Promise(async resolve => {
|
||||
const chunks = [];
|
||||
Body.on('data', chunk => {
|
||||
chunks.push(chunk);
|
||||
});
|
||||
Body.once('end', () => {
|
||||
storage.writeFile(Key, Buffer.concat(chunks));
|
||||
resolve(null);
|
||||
});
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
listObjectsV2({ Bucket }) {
|
||||
return {
|
||||
promise: () => {
|
||||
if (
|
||||
Bucket === 'delete_stale_files_success' ||
|
||||
Bucket === 'delete_stale_files_error'
|
||||
) {
|
||||
return Promise.resolve({
|
||||
Contents: [{ Key: 'stale_file.png' }],
|
||||
});
|
||||
}
|
||||
return Promise.resolve({});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
deleteObject({ Bucket }) {
|
||||
return {
|
||||
promise: () => {
|
||||
if (Bucket === 'delete_stale_files_error') {
|
||||
throw new Error('Message');
|
||||
}
|
||||
return Promise.resolve();
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
S3,
|
||||
};
|
||||
@@ -21,12 +21,112 @@ import express from 'express';
|
||||
import request from 'supertest';
|
||||
import mockFs from 'mock-fs';
|
||||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import fs, { ReadStream } from 'fs-extra';
|
||||
import { EventEmitter } from 'events';
|
||||
import { AwsS3Publish } from './awsS3';
|
||||
import { storageRootDir } from '../../testUtils/StorageFilesMock';
|
||||
|
||||
// NOTE: /plugins/techdocs-node/__mocks__ is being used to mock aws-sdk client library
|
||||
jest.mock('aws-sdk', () => {
|
||||
const { StorageFilesMock } = require('../../testUtils/StorageFilesMock');
|
||||
const storage = new StorageFilesMock();
|
||||
|
||||
const rootDir = (global as any).rootDir; // Set by setupTests.ts
|
||||
return {
|
||||
__esModule: true,
|
||||
Credentials: jest.requireActual('aws-sdk').Credentials,
|
||||
default: {
|
||||
S3: class {
|
||||
constructor() {
|
||||
storage.emptyFiles();
|
||||
}
|
||||
|
||||
headObject({ Key }: { Key: string }) {
|
||||
return {
|
||||
promise: async () => {
|
||||
if (!storage.fileExists(Key)) {
|
||||
throw new Error('File does not exist');
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
getObject({ Key }: { Key: string }) {
|
||||
return {
|
||||
promise: async () => storage.fileExists(Key),
|
||||
createReadStream: () => {
|
||||
const emitter = new EventEmitter();
|
||||
process.nextTick(() => {
|
||||
if (storage.fileExists(Key)) {
|
||||
emitter.emit('data', Buffer.from(storage.readFile(Key)));
|
||||
emitter.emit('end');
|
||||
} else {
|
||||
emitter.emit(
|
||||
'error',
|
||||
new Error(`The file ${Key} does not exist!`),
|
||||
);
|
||||
}
|
||||
});
|
||||
return emitter;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
headBucket({ Bucket }: { Bucket: string }) {
|
||||
return {
|
||||
promise: async () => {
|
||||
if (Bucket === 'errorBucket') {
|
||||
throw new Error('Bucket does not exist');
|
||||
}
|
||||
return {};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
upload({ Key, Body }: { Key: string; Body: ReadStream }) {
|
||||
return {
|
||||
promise: () =>
|
||||
new Promise(async resolve => {
|
||||
const chunks = new Array<Buffer>();
|
||||
Body.on('data', chunk => {
|
||||
chunks.push(chunk as Buffer);
|
||||
});
|
||||
Body.once('end', () => {
|
||||
storage.writeFile(Key, Buffer.concat(chunks));
|
||||
resolve(null);
|
||||
});
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
listObjectsV2({ Bucket }: { Bucket: string }) {
|
||||
return {
|
||||
promise: () => {
|
||||
if (
|
||||
Bucket === 'delete_stale_files_success' ||
|
||||
Bucket === 'delete_stale_files_error'
|
||||
) {
|
||||
return Promise.resolve({
|
||||
Contents: [{ Key: 'stale_file.png' }],
|
||||
});
|
||||
}
|
||||
return Promise.resolve({});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
deleteObject({ Bucket }: { Bucket: string }) {
|
||||
return {
|
||||
promise: () => {
|
||||
if (Bucket === 'delete_stale_files_error') {
|
||||
throw new Error('Message');
|
||||
}
|
||||
return Promise.resolve();
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const getEntityRootDir = (entity: Entity) => {
|
||||
const {
|
||||
@@ -34,7 +134,7 @@ const getEntityRootDir = (entity: Entity) => {
|
||||
metadata: { namespace, name },
|
||||
} = entity;
|
||||
|
||||
return path.join(rootDir, namespace || DEFAULT_NAMESPACE, kind, name);
|
||||
return path.join(storageRootDir, namespace || DEFAULT_NAMESPACE, kind, name);
|
||||
};
|
||||
|
||||
const logger = getVoidLogger();
|
||||
@@ -213,7 +313,7 @@ describe('AwsS3Publish', () => {
|
||||
|
||||
it('should fail to publish a directory', async () => {
|
||||
const wrongPathToGeneratedDirectory = path.join(
|
||||
rootDir,
|
||||
storageRootDir,
|
||||
'wrong',
|
||||
'path',
|
||||
'to',
|
||||
|
||||
@@ -19,12 +19,13 @@ import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import { IStorageFilesMock } from './types';
|
||||
|
||||
const rootDir: string = os.platform() === 'win32' ? 'C:\\rootDir' : '/rootDir';
|
||||
export const storageRootDir: string =
|
||||
os.platform() === 'win32' ? 'C:\\rootDir' : '/rootDir';
|
||||
|
||||
const encoding = 'utf8';
|
||||
|
||||
export class StorageFilesMock implements IStorageFilesMock {
|
||||
static rootDir = rootDir;
|
||||
static rootDir = storageRootDir;
|
||||
|
||||
private files: Record<string, string>;
|
||||
|
||||
@@ -37,20 +38,20 @@ export class StorageFilesMock implements IStorageFilesMock {
|
||||
}
|
||||
|
||||
public fileExists(targetPath: string): boolean {
|
||||
const filePath = path.join(rootDir, targetPath);
|
||||
const filePath = path.join(storageRootDir, targetPath);
|
||||
const posixPath = filePath.split(path.posix.sep).join(path.sep);
|
||||
return this.files[posixPath] !== undefined;
|
||||
}
|
||||
|
||||
public readFile(targetPath: string): Buffer {
|
||||
const filePath = path.join(rootDir, targetPath);
|
||||
const filePath = path.join(storageRootDir, targetPath);
|
||||
return Buffer.from(this.files[filePath] ?? '', encoding);
|
||||
}
|
||||
|
||||
public writeFile(targetPath: string, sourcePath: string): void;
|
||||
public writeFile(targetPath: string, sourceBuffer: Buffer): void;
|
||||
public writeFile(targetPath: string, source: string | Buffer): void {
|
||||
const filePath = path.join(rootDir, targetPath);
|
||||
const filePath = path.join(storageRootDir, targetPath);
|
||||
if (typeof source === 'string') {
|
||||
this.files[filePath] = fs.readFileSync(source).toString(encoding);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user