Target [Illuminate\Contracts\Routing\ResponseFactory] is not instantiable - lumen

I am trying to return a response like this:
return response()->json(['name' => 'Abigail', 'state' => 'CA']);
however, I got error:
Target [Illuminate\Contracts\Routing\ResponseFactory] is not instantiable.
Any idea?
Here is my composer.json:
{
"name": "laravel/lumen",
"description": "The Laravel Lumen Framework.",
"keywords": [
"framework",
"laravel",
"lumen"
],
"license": "MIT",
"type": "project",
"require": {
"php": ">=5.5.9",
"laravel/lumen-framework": "5.2.*",
"vlucas/phpdotenv": "~2.2",
"generationtux/jwt-artisan": "^0.1.7",
"barryvdh/laravel-cors": "^0.8.0",
"neomerx/cors-illuminate": "^1.1",
"fenos/notifynder": "3.1.*",
"franzose/closure-table": "^4.1",
"mlntn/lumen-artisan-serve": "~1",
"guzzlehttp/guzzle": "~6.0",
"league/flysystem": " ~1.0",
"bugsnag/bugsnag-laravel": "^2.0"
},
"require-dev": {
"fzaninotto/faker": "~1.4",
"phpunit/phpunit": "~4.0"
},
"autoload": {
"psr-4": {
"App\\": "app/",
"GuzzleHttp\\": "/vendor/guzzlehttp/"
},
"classmap": [
"database/"
]
},
"autoload-dev": {
"classmap": [
"tests/",
"database/"
]
},
"config": {
"preferred-install": "dist"
}
}

I still get the error in 2020. Here's an updated version of the solution by #sunben:
In bootstrap/app.php, uncomment the following line
$app->register(App\Providers\AppServiceProvider::class);
Then in app\Providers\AppServiceProvider.php, update register method to add:
$this->app->singleton(\Illuminate\Contracts\Routing\ResponseFactory::class, function() {
return new \Laravel\Lumen\Http\ResponseFactory();
});

Might be late but found the solution.
In bootstrap/app.php, uncomment the following line
$app->register(App\Providers\AppServiceProvider::class);
Then in app\Providers\AppServiceProvider.php, update register method to add:
public function register()
{
$this->app->singleton('Illuminate\Contracts\Routing\ResponseFactory', function ($app) {
return new \Illuminate\Routing\ResponseFactory(
$app['Illuminate\Contracts\View\Factory'],
$app['Illuminate\Routing\Redirector']
);
});
}

The response helper may be used to conveniently generate other types of response instances. When the response helper is called without arguments, an implementation of the Laravel\Lumen\Http\ResponseFactory class is returned.
use Laravel\Lumen\Http\ResponseFactory;

Try like this
public function register() { $this->app->singleton(\Illuminate\Contracts\Routing\ResponseFactory::class, function() { return new \Laravel\Lumen\Http\ResponseFactory(); }); $this->app->bind(\Illuminate\Contracts\Routing\UrlGenerator::class, function ($app) { return new \Laravel\Lumen\Routing\UrlGenerator($app); }); }

call
use Tests\TestCase;
instead of
use PHPUnit\Framework\TestCase;
your function depends on another function, So you should extend like feature test and not unit tests.

Those who are still getting routing related error, just put the following line in your composer.json file and run the command composer update
"illuminate/routing": "^5.6"
composer update
and boom here we go, wish all things are working great now

https://stackoverflow.com/a/48678862/9751944
#sunben's answer worked for me but I added the following inside the register method
$this->app->bind(\Illuminate\Routing\RouteCollectionInterface::class, function ($app) { return new \Illuminate\Routing\RouteCollection; });

Related

How to add a plugin in Aurelia

I am trying to use wavesurfer.js in an Aurelia project. I am not able to use the wavesurfer.js. After building it says Container Element not found.
my app.js looks like this
import * as wavesurfer from '../node_modules/wavesurfer/dist/wavesurfer.js';
export class App {
wavesurferObj = WaveSurfer.create({
container: '#waveform',
waveColor: 'violet',
progressColor: 'purple',
scrollParent: true,
});
constructor() {
wavesurferObj.load('http://ia902606.us.archive.org/35/items/shortpoetry_047_librivox/song_cjrg_teasdale_64kb.mp3');
wavesurferObj.on(ready, function () {
wavesurferObj.play();
});
}
}
and my main.js looks like this
// regenerator-runtime is to support async/await syntax in ESNext.
// If you target latest browsers (have native support), or don't use async/await, you can remove regenerator-runtime.
import * as wavesurfer from '../node_modules/wavesurfer/dist/wavesurfer.js';
// import * as timeline from '../node_modules/wavesurfer/plugin/wavesurfer.timeline.js';
// import * as regions from '../node_modules/wavesurfer/plugin/wavesurfer.regions.js';
import 'regenerator-runtime/runtime';
import * as environment from '../config/environment.json';
import {
PLATFORM
} from 'aurelia-pal';
export function configure(aurelia) {
aurelia.use
.standardConfiguration()
.feature(PLATFORM.moduleName('resources/index'));
aurelia.use.plugin(PLATFORM.moduleName('wavesurfer'));
// aurelia.use.plugin(PLATFORM.moduleName('timeline'));
// aurelia.use.plugin(PLATFORM.moduleName('regions'));
aurelia.use.developmentLogging(environment.debug ? 'debug' : 'warn');
if (environment.testing) {
aurelia.use.plugin(PLATFORM.moduleName('aurelia-testing'));
}
aurelia.start().then(() => aurelia.setRoot(PLATFORM.moduleName('app')));
}
and just the build section in Aurelia.json looks like this
"build": {
"options": {
"server": "dev",
"extractCss": "prod",
"coverage": false
},
"bundles": [{
"name": "vendor-bundle.js",
"dependencies": [{
"name": "wavesurfer",
"path": "../node_modules/wavesurfer/dist",
"main": "wavesurfer"
},
{
"name": "wavesurfer.timeline",
"path": "../node_modules/wavesurfer/plugin",
"main": "wavesurfer.timeline",
"deps": [
"wavesurfer"
]
},
{
"name": "wavesurfer.regions",
"path": "../node_modules/wavesurfer/plugin",
"main": "wavesurfer.regions",
"deps": [
"wavesurfer"
]
}
]
}]
},
Here is the error:
WaveSurfer is not defined.
Can someone indicate what is the right way to add this plugin please.
Thanks a lot in advance.
Without having a look at all of your actual code, i'm guessing you have at least 3 errors:
First one is using different variable names: wave surfer is imported as wavesurfer, but the way it's used is WaveSurfer, notice the case.
Using direct path to the dist file in a node_modules package:
import * as wavesurfer from '../node_modules/wavesurfer/dist/wavesurfer.js';
It should be:
import * as wavesurfer from 'wavesurfer';
3rd one is targeting an element via a CSS selector string #waveform. If this is not ready by the time you create an instance of class App, it will not work properly. Where is #waveform? from the document? from app.html? If it's from the document, it's ok, but if it's from app.html, you will need to change that code to something like this
<template>
....
<div ref="waveformElement"></div>
</template>
And in your app code:
import * as WaveSurfer from 'wavesurfer';
export class App {
bind() {
this.wavesurferObj = WaveSurfer.create({
container: this.waveformElement,
waveColor: 'violet',
progressColor: 'purple',
scrollParent: true,
});
this.wavesurferObj.load( 'http://ia902606.us.archive.org/35/items/shortpoetry_047_librivox/song_cjrg_teasdale_64kb.mp3');
this.wavesurferObj.on(ready, () => {
this.wavesurferObj.play();
});
}
}

Mocking a class in typescript with jest

I am trying to unit test (with Jest) my handler module that makes use of a summary class.
My original summary class looks like:
import DynamoDBClient from './ddbClient/DynamoDBClient'
import { DynamoDB } from 'aws-sdk'
import { iSummaryReader, iObsSummariesAttributes } from './Summary.d'
import { JSONAPIResource } from '../JSONAPIResponse'
export default class Summary {
reader: iSummaryReader
constructor(reader: iSummaryReader) {
this.reader = reader
}
getSummary = async (keyName: string, keyValue: string): Promise<JSONAPIResource<iObsSummariesAttributes>> => {
return new Promise<JSONAPIResource<iObsSummariesAttributes>>((resolve, reject) => {
const gettingItem = this.reader.getItem(keyName, keyValue)
console.log(gettingItem)
gettingItem.then((resp) => {
resolve(resp)
}).catch((err: Error) => {
reject(err.message)
})
})
}
}
In my handler module I import with import Summary from './lib/Summary'
(Note: same line is used in handler.test.ts
Inside the handler function
try {
const dynamodbObj: iSummaryReader = new DynamoDBClient(documentClient, someTable)
const summary = new Summary(dynamodbObj)
const data: JSONAPIResource<iObsSummariesAttributes> = await summary.getSummary('id', someID)
}
My results depend on my approach if try an automatic mock
jest.mock('./lib/Summary', () =>
{
return {
getSummary: jest.fn()
}
})
I get the error
TypeError: Summary_1.default is not a constructor
If I create a manual mock under lib/__mocks__/Summary.ts with jest.mock('./lib/Summary') it does work until I get the point
expect(Summary).toHaveBeenCalledTimes(1)
Where it complains about me not being able to do this on summary. I also am unable to access my method to test that they are being called this way.
Note: My hanlder is for a lambda function so I am unable to inject the class that way where I have successfully tested that I can mock an injected class.
EDIT
The tsconfig.json is:
{
"compilerOptions": {
"rootDir": "./src",
"outDir": "./build",
"declaration": false,
"target": "es2015",
"moduleResolution": "node",
"module": "commonjs",
"noImplicitReturns": true,
"noImplicitThis": true,
"strictNullChecks": true,
"alwaysStrict": true,
"lib": [
"dom",
"es2015.promise",
"es2017.object",
"es2016"
],
},
"include": [
"src/**/*.ts"
],
}
I do not know why this was failing, but I the following steps seem to work to fix it.
Change the class export from default
From
`export default class Summary {`
to
`class summary`
+ export = summary at the end
Use import = require to import it.
import Summary = require('./lib/Summary')
Those two changes allowed it to find the jest.mock.

Only 2 intents work 'MAIN' and 'TEXT'

I'm trying building my first app with actions-on-google / google-assistant-sdk, I wanted to start using 3 intents, the MAIN, respond to input TEXT, and HELP that the user can call anytime:
The action.json is:
{
"actions": [
{
"description": "Default Welcome Intent",
"name": "MAIN",
"fulfillment": {
"conversationName": "conversation_1"
},
"intent": {
"name": "actions.intent.MAIN"
}
},
{
"description": "Help Intent",
"name": "Help",
"fulfillment": {
"conversationName": "conversation_1"
},
"intent": {
"name": "app.StandardIntents.HELP",
"trigger": {
"queryPatterns": [
"Help",
"HELP",
"help"
]
}
}
}
],
"conversations": {
"conversation_1": {
"name": "conversation_1",
"url": "https://us-central1-sillytest-16570.cloudfunctions.net/sayNumber",
"fulfillmentApiVersion": 2
}
}
}
The index.js:
'use strict';
process.env.DEBUG = 'actions-on-google:*';
const ActionsSdkApp = require('actions-on-google').ActionsSdkApp;
const functions = require('firebase-functions');
const NO_INPUTS = [
'I didn\'t hear that.',
'If you\'re still there, say that again.',
'We can stop here. See you soon.'
];
exports.sayNumber = functions.https.onRequest((request, response) => {
const app = new ActionsSdkApp({request, response});
function mainIntent (app) {
console.log('mainIntent');
let inputPrompt = app.buildInputPrompt(true, '<speak>Hi! <break time="1"/> ' +
'I can read out an ordinal like ' +
'<say-as interpret-as="ordinal">123</say-as>. Say a number.</speak>', NO_INPUTS);
app.ask(inputPrompt);
}
function rawInput (app) {
console.log('rawInput');
if (app.getRawInput() === 'bye') {
app.tell('Goodbye!');
} else {
let inputPrompt = app.buildInputPrompt(true, '<speak>You said, <say-as interpret-as="ordinal">' +
app.getRawInput() + '</say-as></speak>', NO_INPUTS);
app.ask(inputPrompt);
}
}
function helpHandler (app) {
console.log('rawInput');
app.ask('<speak>What kind of help do you need?</speak>');
}
let actionMap = new Map();
actionMap.set(app.StandardIntents.MAIN, mainIntent);
actionMap.set(app.StandardIntents.TEXT, rawInput);
actionMap.set(app.StandardIntents.HELP, helpHandler);
app.handleRequest(actionMap);
});
I pushed the firebase as:
firebase deploy --only functions
And pushed the Google Actions as:
gactions update --action_package action.json --project <YOUR_PROJECT_ID>
While testing the assistant here, it started in a good way, and repeat the number that I enter, wait for another number, and so on, but when I enter help it is terminated and not responding!
UPDATE
I tried the below, but did not work:
actionMap.set("app.StandardIntents.HELP", helpHandler);
I should expect the app to "What kind of help do you need?" when I enter/say "Help", but what happened is just re-writing it, same way it do with any other number.
Non-built-in Intents are only supported for the first message in a conversation. After that, while you can use them for speech biasing, you will only get a built-in one such as the TEXT Intent.
Your actionMap is looking for app.StandardIntents.HELP but it doesn't exist. You can view all of the standard intents in the GitHub repo.
app.StandardIntents.MAIN returns another string which corresponds to "'actions.intent.MAIN'". It does not read your action.json and generate new intents. Thus, app.StandardIntents.HELP actually returns undefined and is never called.
Your map should use a string for your help intent since it is not available as a constant in the app object.
actionMap.set("app.StandardIntents.HELP", helpHandler);
This should resolve your issue. Let me know if it does not.

How to ask permission in Actions on Google without the SDK?

I would like to know the name of the user, however I cannot use the nodejs sdk since I use another language.
How can I ask for permission?
I would prefer a way with the normal json responses.
I hacked this minimal script to get the JSON reponse which the nodejs sdk would return:
gaction.js:
const DialogflowApp = require('actions-on-google').DialogflowApp;
const app = new DialogflowApp({
request: {
body: {
result: {
action: 'Test',
contexts: []
}
},
get: (h) => h
},
response: {
append: (h, v) => console.log(`${h}: ${v}`),
status: (code) => {
return {send: (resp) => console.log(JSON.stringify(resp, null, 2))}
}
}
});
function testCode(app) {
app.askForPermission('To locate you', app.SupportedPermissions.DEVICE_PRECISE_LOCATION);
}
app.handleRequest(new Map().set('Test', testCode));
I'm still no node.js expert so this might be not an optimal solution. When you have installed node and run the command npm install actions-on-google, this will install the necessary dependencies.
When done you just need to run node gaction which will create this output:
Google-Assistant-API-Version: Google-Assistant-API-Version
Content-Type: application/json
{
"speech": "PLACEHOLDER_FOR_PERMISSION",
"contextOut": [
{
"name": "_actions_on_google_",
"lifespan": 100,
"parameters": {}
}
],
"data": {
"google": {
"expect_user_response": true,
"no_input_prompts": [],
"is_ssml": false,
"system_intent": {
"intent": "assistant.intent.action.PERMISSION",
"spec": {
"permission_value_spec": {
"opt_context": "To locate you",
"permissions": [
"DEVICE_PRECISE_LOCATION"
]
}
}
}
}
}
}
If you send now the JSON above you will be asked from Google Home. Have fun!
The request/response JSON formats for the API.AI webhooks with Actions is documented at https://developers.google.com/actions/apiai/webhook
As you've discovered, the data.google.permissions_request attribute contains two fields regarding the request:
opt_context contains a string which is read to give some context about why you're asking for the information.
permissions is an array of strings specifying what information you're requesting. The strings can have the values
NAME
DEVICE_COARSE_LOCATION
DEVICE_PRECISE_LOCATION
If you are using Java or Kotlin there is an Unofficial SDK. It matches the official SDK api nearly exactly.
https://github.com/TicketmasterMobileStudio/actions-on-google-kotlin

unit testing for chrome api using jasmine

How can I test chrome.runtime.getManifest() using jasmine? Below is what i tried:
var manifestData = {"name": "Pearson App Chromebook Edition", "version": "0.0.1", "manifest_version": 2};
beforeEach(function() {
module(function ($provide) {
$provide.value('chrome.runtime', {
getManifest: function () {
return manifestData;
}
});
});
});
I am getting 'TypeError: chrome.runtime.getManifest is not a function' error.
Thanks in advance.
The thing that worked for me was:
chrome = {
runtime: {
getManifest: function(){}
}
};
spyOn(chrome.runtime, 'getManifest').and.returnValue(manifestData);
where manifestData is the mock of manifest.json