How can I convert this part of my test to React Testing Library so that I'm not using shallow anymore?
const renderComponent = (jsx) => {
const component = shallow(jsx);
const title = component.find('.tile-bottom__title');
const content = component.find('.tile-bottom__text');
return {
component,
title,
content,
};
};
Since for react-testing-library, you can read the DOM nodes from screen, you can update the function to
const renderComponent = (jsx) => {
const { container, getByTestId } = render(jsx);
const title = getByTestId('tile-bottom__title'); // not class but testId
const content = getByTestId('tile-bottom__text'); // // not class but testId
return {
// component, // not needed to return component as you can use `screen` for further assertions
title,
content,
};
};
Related
I've been using Google Cloud Video Intelligence for text detection. Now, I want to use it for speech transcription so I added SPEECH_TRANSCRIPTION feature to TEXT_DETECTION but the response only contains result for one feature, the last one.
const gcsUri = 'gs://path-to-the-video-on-gcs'
const request = {
inputUri: gcsUri,
features: ['TEXT_DETECTION', 'SPEECH_TRANSCRIPTION'],
};
// Detects text in a video
const [operation] = await video.annotateVideo(request);
const [operationResult] = await operation.promise();
const annotationResult = operationResult.annotationResults[0]
const textAnnotations = annotationResult.textAnnotations
const speechTranscriptions = annotationResult.speechTranscriptions
console.log(textAnnotations) // --> []
console.log(speechTranscriptions) // --> [{...}]
Is this a case where annotation is performed on only one feature at a time?
Annotation will be performed for both features. Below is an example code.
const videoIntelligence = require('#google-cloud/video-intelligence');
const client = new videoIntelligence.VideoIntelligenceServiceClient();
const gcsUri = 'gs://cloud-samples-data/video/JaneGoodall.mp4';
async function analyzeVideoTranscript() {
const videoContext = {
speechTranscriptionConfig: {
languageCode: 'en-US',
enableAutomaticPunctuation: true,
},
};
const request = {
inputUri: gcsUri,
features: ['TEXT_DETECTION','SPEECH_TRANSCRIPTION'],
videoContext: videoContext,
};
const [operation] = await client.annotateVideo(request);
const results = await operation.promise();
console.log('Waiting for operation to complete...');
// Gets annotations for video
console.log('Result------------------->');
console.log(results[0].annotationResults);
var i=1;
results[0].annotationResults.forEach(annotationResult=> {
console.log("annotation result no: "+i+" =======================>")
console.log(annotationResult.speechTranscriptions);
console.log(annotationResult.textAnnotations);
i++;
});
}
analyzeVideoTranscript();
N.B: What I have found is that annotationResult may not return the result in the same order of the declared features . You may want to change the code accordingly as per your need.
I'm currenty trying to write unit tests for my Nestjs Backend. Therefore i use the integrated Jest Framework. Now i have problems with mocking static exports without a certain class.
This is the function i want to test:
export const createGetLatestAssetsMetadataQuery = ({
assetsCatalogueVersion,
sorting,
}: AFilter): RequestParams.Search<any> => {
const match = createCatalogueVersionMatchFactory(VERSION_TIME_STAMP_FIELD)(
assetsCatalogueVersion
);
...
return ...
This is the function which is called to set the match constant. This method is inside an Util-File but doesn't belong to an Class.
export const createCatalogueVersionMatchFactory = (basePath: string) => (
filter?: string
): { [key: string]: { query: any } } => {
const result: { [key: string]: any } = {};
if (filter) {
const date = parseISO(normalizeDTStringTZ(filter));
result[basePath] = { query: date };
}
return result;
};
The Goal is to mock the Return Value of this function.
For functions inside a service i can use
jest.spyOn(service, "functionname").mockResolvedValue(returnValue);
How can i do it for static functions without a service
I have a file a function fetchPosts() which is in charge of getting new Posts from a server and store them in a local sqlite database.
As recommended on the sqflite doc, I store a single ref to my database.
Here is the content of my database.dart file:
import 'dart:async';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
class DBProvider {
DBProvider._();
static final DBProvider db = DBProvider._();
static Database _database;
static Future<Database> get database async {
if (_database != null) return _database;
// if _database is null, we instantiate it
_database = await _initDB();
return _database;
}
static Future<Database> _initDB() async {
final dbPath = await getDatabasesPath();
String path = join(dbPath, 'demo.db');
return await openDatabase(path, version: 1, onCreate: _onCreate);
}
static Future<String> insert(String table, Map<String, dynamic> values) async { /* insert the record*/ }
// Other functions like update, delete etc.
}
Then I use it as such in my fetchPosts.dart file
import 'dart:convert';
import 'package:http/http.dart' as http;
import '../services/database.dart';
const url = 'https://myapp.herokuapp.com';
Future<void> fetchPosts() {
final client = http.Client();
return fetchPostsUsingClient(client);
}
Future<void> fetchPostsUsingClient(http.Client client) async {
final res = await client.get(url);
final posts await Post.fromJson(json.decode(response.body));
for (var i = 0; i < posts.length; i++) {
await DBProvider.insert('posts', posts[i]);
}
}
In my test, how can I verify that DBProvider.insert() has been called?
fetchPosts_test.dart
import 'package:test/test.dart';
import 'package:http/http.dart' as http;
import 'package:mockito/mockito.dart';
import 'package:../services/fetchPosts.dart';
// Create a MockClient using the Mock class provided by the Mockito package.
// Create new instances of this class in each test.
class MockClient extends Mock implements http.Client {}
void main() {
group('fetchPosts', () {
test('update local db', () async {
final client = MockClient();
// Use Mockito to return a successful response when it calls the provided http.Client.
when(client.get()).thenAnswer((_) async => http.Response('{"title": "Test"}', 200));
await fetchPostsWithClient(client);
verify(/* DBProvider.insert has been called ?*/);
});
});
}
The question was some while ago, but here is another solution. You can refactor calls to that static function to be called from a class "wrapper" method. This is a pattern I often use to mock requests to third party services.
Let me give you an example. To make it simple lets say Engine has 3 static methods that need to be mocked: brake() and accelerate() and speed().
class Car {
int currentSpeed;
void accelerateTo(int speed) {
while(currentSpeed > speed) {
Engine.brake();
currentSpeed = Engine.speed();
}
while(currentSpeed < speed) {
Engine.accelerate();
currentSpeed = Engine.speed();
}
}
}
Now you want to mock all calls to the engine, to do so we could refactor the code to:
class Car {
int currentSpeed;
void accelerateTo(int speed) {
while(currentSpeed > speed) {
brake();
currentSpeed = speed();
}
while(currentSpeed < speed) {
accelerate();
currentSpeed = speed();
}
}
/// wrapper to mock Engine calls during test
void brake() {
Engine.brake();
}
/// wrapper to mock Engine calls during test
int speed() {
Engine.speed();
}
/// wrapper to mock Engine calls during test
void accelerate() {
Engine.accelerate();
}
}
In the integration test you can now mock the 3 methods that interact with the static methods directly but you can now test your main method. While you could here also refactor the Engine class itself, often that class would be within a third party service.
This example is not based on the Volkswagen scandal ;).
Eventually, I had to rewrite my database.dart to make it testable / mockable.
Here's the new file:
import 'dart:async';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
class DBProvider {
static final DBProvider _singleton = DBProvider._internal();
factory DBProvider() {
return _singleton;
}
DBProvider._internal();
static Database _db;
static Future<Database> _getDatabase() async {
if (_db != null) return _db;
// if _database is null, we instantiate it
_db = await _initDB();
return _db;
}
static Future<Database> _initDB() async {
final dbPath = await getDatabasesPath();
String path = join(dbPath, 'demo.db');
return openDatabase(path, version: 1, onCreate: _onCreate);
}
Future<String> insert(String table, Map<String, dynamic> values) async {
final db = await _getDatabase();
return db.insert(table, values);
}
// ...
}
Now I can use the same trick as with the http.Client.
Thank you #RĂ©miRousselet
Let's say we want to test [TargetClass.someMethodCallOtherStaticMethod]
Class StaticMethodClass {
static int someStaticMethod() {};
}
Class TargetClass {
int someMethodCallOtherStaticMethod() {
return StaticMethodClass.someStaticMethod();
}
}
We should refactor [[TargetClass.someMethodCallOtherStaticMethod]] for testing,
like this:
Class TargetClass {
int someMethodCallOtherStaticMethod({#visibleForTesting dynamic staticMethodClassForTesting}) {
if (staticMethodClassForTesting != null) {
return staticMethodClassForTesting.someStaticMethod();
} else {
return StaticMethodClass.someStaticMethod();
}
}
}
Now you can write your test case like this:
// MockClass need to implement nothing, just extends Mock
MockClass extends Mock {}
test('someMethodCallOtherStaticMethod', () {
// We MUST define `mocked` as a dynamic type, so that no errors will be reported during compilation
dynamic mocked = MockClass();
TargetClass target = TargetClass();
when(mocked.someStaticMethod()).thenAnswer((realInvocation) => 42);
expect(target.someMethodCallOtherStaticMethod(staticMethodClassForTesting: mocked), 42);
})
I'm trying to make dose schedule app that when the user set the alarm the app shows a page to check if the user takes a medicine or not. and the user should choose snooze or done with swiping ("done" to the left, "snooze" to the right).
I want the app gets opened automatically from the background on time.
I've already tried "nativescript-local-notification", but this one, the user must press the notification to open or enter the app and read "nativescript background service" but it seems to be the same as I've tried.
Could you tell me the way or give me some example to do?
I've solved it by myself. I put the solution that might be helped someone like me.
First you have set an alarm.
alarm.helper.js
import * as AlarmReceiver from '#/services/AlarmReceiver' // Do not remove
export const setAlarm = data => {
const ad = utils.ad
const context = ad.getApplicationContext()
const alarmManager = application.android.context.getSystemService(android.content.Context.ALARM_SERVICE)
const intent = new android.content.Intent(context, io.nerdrun.AlarmReceiver.class)
const { id, time, title, name } = data
// set up alarm
intent.putExtra('id', id)
intent.putExtra('title', title)
intent.putExtra('name', name)
intent.putExtra('time', time.toString())
const pendingIntent = android.app.PendingIntent.getBroadcast(context, id, intent, android.app.PendingIntent.FLAG_UPDATE_CURRENT)
alarmManager.setExact(alarmManager.RTC_WAKEUP, time.getTime(), pendingIntent)
console.log('registered alarm')
}
Extends AlarmReceiver on Android.
AlarmReceiver.js
export const AlarmReceiver = android.content.BroadcastReceiver.extend('io.nerdrun.AlarmReceiver', {
init: function() {
console.log('init receiver')
},
onReceive: function(context, intent) {
console.log('You got the receiver man!!')
const activityIntent = new android.content.Intent(context, com.tns.NativeScriptActivity.class)
const id = intent.getExtras().getInt('id')
const title = intent.getExtras().getString('title')
const name = intent.getExtras().getString('name')
const time = intent.getExtras().getString('time')
activityIntent.putExtra('id', id)
activityIntent.putExtra('title', title)
activityIntent.putExtra('name', name)
activityIntent.putExtra('time', time)
activityIntent.setFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(activityIntent)
}
})
register receiver to your manifest.
AndroidManifest.xml
<receiver android:name="io.nerdrun.AlarmReceiver" />
Of course, you can extend Activity on android into your project, but I haven't implemented it.
After the receiver worked it would navigate to Main Activity, you might control whatever you want in app.js below:
app.js
application.on(application.resumeEvent, args => {
if(args.android) {
console.log('resume succeed!!!')
const android = args.android
const intent = android.getIntent()
const extras = intent.getExtras()
if(extras) {
const id = extras.getInt('id')
const title = extras.getString('title')
const name = extras.getString('name')
const time = extras.getString('time')
Vue.prototype.$store = store
Vue.prototype.$navigateTo(routes.home, { clearHistory: true, props: props })
}
}
}
})
I have a component whose job it is to add certain properties to its child:
const Parent = React.createClass({
doStuff() {
// ...
},
render() {
const child = React.cloneElement(this.props.children, {doStuff: this.doStuff});
return <div>{child}</div>;
}
});
With 0.13 I could test it like this:
const {renderIntoDocument, findRenderedDOMComponentWithClass} = TestUtils;
const parent = renderIntoDocument(<Parent><span className="test" /></Parent>);
const child = findRenderedDOMComponentWithClass(parent, "test");
expect(child.props.doStuff).to.equal(parent.doStuff);
What is the "0.14 way" of testing this?
PS. I test the behavior of Parent.doStuff elsewhere, but I also need to ensure that the given child gets a reference to this method.
PPS. I read How to check props of a DOM node in an unit test in React 0.14? but it does not apply to my problem because I'm not testing props that I could read with domNode.getAttribute().
Finally I got it. Here is what now works for me (Parent is the unit under test):
const TestChild = () => <div />;
const TestContainer = React.createClass({
getParent() {
return this.refs.parent;
},
getChild() {
return this.refs.testChild;
},
render() {
return <Parent ref="parent"><TestChild ref="testChild" /></Parent>;
}
});
const {renderIntoDocument, findRenderedDOMComponentWithClass} = TestUtils;
const testContainer = renderIntoDocument(<TestContainer />);
const parent = testContainer.getParent();
const child = testContainer.getChild();
expect(child.props.doStuff).to.equal(parent.doStuff);
TestChild has to be a custom component, otherwise this.refs.testChild only returns a DOM node instead of a component instance.