Proxyquire + sinon -> stubbing Docker namespace - docker

I can't figure out why this doesn't work.
my module under test is this dockerService:
const Docker = require('dockerode');
const docker = new Docker();
[...]
async function appDockerStart(idOrName) {
// container ID or name
const containers = await dockerListContainers(true);
const myContainer = containers.find([...] using containers);
const dockerContainer = docker.getContainer(myContainer.Id);
await dockerContainer.start(); <=== this is what I'm trying to stub
return `started.`;
}
my test
describe('tests', () => {
const appName = 'website';
let containerStub;
beforeEach(() => {
containerStub = {
start: sinon.stub().returns('started'),
};
const dockerodeStub = {
Container: containerStub,
};
dockerService = proxyquire('../../dockerService',
{
dockerode: dockerodeStub,
});
});
afterEach(() => {
sinon.restore();
});
it('should return a valid stats object', async () => {
const res = await dockerService.appDockerStart(appName);
});
});
but I'm getting an error - TypeError: Docker is not a constructor
it seems like the first file is failing on const docker = new Docker();
the dockerode itself a namespace which has a class Container etc etc.
How do I go about it without modifying the first file?

Related

How to respond with a stream in a Sveltekit server load function

Below I try to respond with a stream when I receive ticker updates.
+page.server.js:
import YahooFinanceTicker from "yahoo-finance-ticker";
const ticker = new YahooFinanceTicker();
const tickerListener = await ticker.subscribe(["BTC-USD"])
const stream = new ReadableStream({
start(controller) {
tickerListener.on("ticker", (ticker) => {
console.log(ticker.price);
controller.enqueue(ticker.price);
});
}
});
export async function load() {
return response????
};
Note: The YahooFinanceTicker can't run in the browser.
How to handle / set the response in the Sveltekit load function.
To my knowledge, the load functions cannot be used for this as their responses are JS/JSON serialized. You can use an endpoint in +server to return a Response object which can be constructed from a ReadableStream.
Solution: H.B. comment showed me the right direction to push unsollicited price ticker updates the client.
api route: yahoo-finance-ticker +server.js
import YahooFinanceTicker from "yahoo-finance-ticker";
const ticker = new YahooFinanceTicker();
const tickerListener = await ticker.subscribe(["BTC-USD"])
/** #type {import('./$types').RequestHandler} */
export function GET({ request }) {
const ac = new AbortController();
console.log("GET api: yahoo-finance-ticker")
const stream = new ReadableStream({
start(controller) {
tickerListener.on("ticker", (ticker) => {
console.log(ticker.price);
controller.enqueue(String(ticker.price));
}, { signal: ac.signal });
},
cancel() {
console.log("cancel and abort");
ac.abort();
},
})
return new Response(stream, {
headers: {
'content-type': 'text/event-stream',
}
});
}
page route: +page.svelte
<script>
let result = "";
async function getStream() {
const response = await fetch("/api/yahoo-finance-ticker");
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
while (true) {
const { value, done } = await reader.read();
console.log("resp", done, value);
if (done) break;
result += `${value}<br>`;
}
}
getStream();
</script>
<section>
<p>{#html result}</p>
</section>

Exporting a Test To Another File?

I have a file structure that looks like this
Folder Structure
I have a file called "login.js" that will contain a function that logs into the page. Currently it looks like this
// login.js
const { chromium } = require('playwright');
async function Login() {
const browser = await chromium.launch({
headless: false,
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('http://test.local/');
return true;
}
/*
This is just a example of logging in and not complet
*/
I want to export it so all my other tests can continue AFTER this one function logs in. Once it successfully logs in, tests such as 'example.spec.js' can get all the cookies/headers from the login script and continue
How can I do that?
You should be doing this.
// login.js
const { chromium } = require('playwright');
module.exports = async function login() {
const browser = await chromium.launch({
headless: false,
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('http://test.local/');
return true;
}
Then you can access it in another file like this.
const login = require('./test.js'); // path has to be altered based on your folder structure
login();

Use formData to upload two filetypes in an iOS app?

I would like my uploadFormPage() function to be able to take jpegs and pdf's. Is it possible for me to have 2 file types for the same FormData() const?`
export function uploadFormPage(documentId, formId, file, callback) {
return async dispatch => {
try {
const formData = new FormData();
formData.append('page', {
name: `document-${documentId}-${formId}-${Date.now()}.jpg`,
type: 'image/jpeg',
uri: file,
});
const result = await Api.uploadFiles(formData);
const entity = {
id: formId,
resourceKey: result.page,
};
const rsp = await Api.uploadFormPage(documentId, entity);
dispatch({type: LOAD_DOCUMENTS, data: rsp});
callback(null, rsp);
} catch (e) {
callback(e, null);
}
};
}

Transfer img from redux store in react-konva

User selects image from his pc. Then app reads file with FileReader as DataUrl and then the result is dispatched in store. And now I need to make an image for display from that DataUrl. I think it should be somehow transferred and parsed in react-konva.
inputImageChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.currentTarget.files[0];
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = evt =>
this.props.dispatch(
surfaceGridModalActions.inputSurfaceGridImage(evt.target.result)
);
};
You just need to use that data url as image source:
class UserImage extends React.Component {
state = {
image: new window.Image()
};
componentDidMount() {
this.state.image.src = this.props.dataURL;
this.state.image.onload = () => {
// so we need to update layer manually
this.imageNode.getLayer().batchDraw();
};
}
render() {
return (
<Image
image={this.state.image}
y={250}
ref={node => {
this.imageNode = node;
}}
/>
);
}
}

feathersjs sequelize call stored procedure by hook doesn't resolve

I have a problem creating a hook calling a stored procedure.
My custom service hooks (customservice.hooks.js) are :
const callstored = require('../../hooks/callstored')
module.exports = {
before: {
all: [],
find: [callstored()],
get: [],
create: [],
update: [],
patch: [],
remove: []
},
...
My service class (customservice.class.js):
const mysql = require('mysql')
class Service {
constructor (options) {
this.options = options || {};
}
find (params) {
return Promise.resolve( [] );
}
get (id, params) {
return Promise.resolve({
id, text: `A new message with ID: ${id}!`
});
}
create (data, params) {
if (Array.isArray(data)) {
return Promise.all(data.map(current => this.create(current)));
}
return Promise.resolve(data);
}
update (id, data, params) {
return Promise.resolve(data);
}
patch (id, data, params) {
return Promise.resolve(data);
}
remove (id, params) {
return Promise.resolve({ id });
}
}
module.exports = function (options) {
return new Service(options);
};
module.exports.Service = Service;
And my service (customservice.service.js) :
const createService = require('./rankingvotes.class.js');
const hooks = require('./rankingvotes.hooks');
module.exports = function (app) {
const paginate = app.get('paginate');
const options = {
name: 'rankingvotes',
paginate
};
// Initialize our service with any options it requires
app.use('/rankingvotes', createService(options));
// Get our initialized service so that we can register hooks and filters
const service = app.service('rankingvotes');
service.hooks(hooks);
app.publish(() => {
});
};
And finally my hook is (callstored.js)
const Sequelize = require('sequelize');
module.exports = function () {
return function (hook) {
sequelize = hook.app.get('sequelizeClient');
let result=[];
return sequelize.query('CALL RANKING();',{
nest: true,
raw: true }).then(function(response){
console.log(response[0]) //data are correct
hook.data=response[0];
return hook;
}).error(function(err){
console.log(err);
return hook;
});
}
}
If I check the console I got data correctly, but nothing calling from a REST client like Postman.
Any idea? Thank you.
If you want to change the response you have to set hook.result.
const Sequelize = require('sequelize');
module.exports = function () {
return async hook => {
try {
const sequelize = hook.app.get('sequelizeClient');
const response = await sequelize.query('CALL RANKING();',{
nest: true,
raw: true
});
console.log(response[0]) //data are correct
context.result = response[0];
} catch(error) {
console.error(error);
}
return hook;
}
}
hook.data is the request data and is only available for create, update and patch.
Keep in mind that setting hook.result will skip your custom service find if it is set in a before hook.

Resources