How can I access Dart functions/variables from the Dartium DevTool Console? - dart

In JavaScript you can access global variables and functions from the DevTool console (e.g. to call a function manually).
I tried to do this in Dartium, but I always get a reference error.
I tried following variations:
testFunc () {
return "test";
}
var testFunc2 = () {
return "test";
}
void main() {
var testFunc3 () {
return "test";
}
}
but none can be called via DevTool console of Dartium.

You need to select a Dart context.
When you open devtools > Console tab there is <top frame> selected by default.
You need to switch to a Dart context like dart:core.
As far as I remember it doesn't matter which Dart context is selected, just one of the Dart contexts.

Related

How to use Dart's analysis server method search.findTopLevelDeclarations?

I'm trying to get list of top level class declarations with Dart's analysis server. So, I'm sending search.findTopLevelDeclarations request, but search results are always empty.
It seems to me that analysis server don't know where to search. I've tried to set my project's root as execution context (execution.createContext) root and/or analysis root (analysis.setAnalysisRoots), but search results are still empty.
What should I do to make server understand where to search declarations?
Never played with this before so I got into quite a journey...
I don't know how you are interacting with the analysis server but I have made a working example using the analysis_server_client package. One problem doing that is that the version on pub.dev is quite old so I ended up fetching the version from the stable branch of Dart SDK:
https://github.com/dart-lang/sdk/tree/stable/pkg/analysis_server_client
You can then import the package in your pubspec.yaml by doing:
dependencies:
analysis_server_client:
path: /path/to/analysis_server_client
I then made a simplified version of the example code from:
https://github.com/dart-lang/sdk/blob/stable/pkg/analysis_server_client/example/example.dart
import 'dart:io' show exit;
import 'package:analysis_server_client/handler/connection_handler.dart';
import 'package:analysis_server_client/handler/notification_handler.dart';
import 'package:analysis_server_client/protocol.dart';
import 'package:analysis_server_client/server.dart';
final server = Server();
Future<void> main(List<String> args) async {
const targetDirPath = r'C:\tmp\simple_project';
const searchPattern = 'main';
// Launch the server
await server.start();
// Connect to the server
final handler = _Handler(server);
server.listenToOutput(notificationProcessor: handler.handleEvent);
if (!await handler.serverConnected(timeLimit: const Duration(seconds: 15))) {
exit(1);
}
await server.send(ANALYSIS_REQUEST_SET_ANALYSIS_ROOTS,
AnalysisSetAnalysisRootsParams([targetDirPath], const []).toJson());
await server.send(SEARCH_REQUEST_FIND_TOP_LEVEL_DECLARATIONS,
SearchFindTopLevelDeclarationsParams(searchPattern).toJson());
}
class _Handler with NotificationHandler, ConnectionHandler {
#override
final Server server;
_Handler(this.server);
#override
void onSearchResults(SearchResultsParams params) {
print('-- Start of result --');
params.results.forEach(print);
print('-- End of result --');
server.stop();
}
}
The project at C:\tmp\simple_project is a simple project created with the following which means it just contains a single main method:
dart create -t console-simple simple_project
When I run my analyzer program I get the following output:
-- Start of result --
{"location":{"file":"C:\\tmp\\simple_project\\bin\\simple_project.dart","offset":5,"length":4,"startLine":1,"startColumn":6,"endLine":1,"endColumn":10},"kind":"DECLARATION","isPotential":false,"path":[{"kind":"FUNCTION","name":"main","location":{"file":"C:\\tmp\\simple_project\\bin\\simple_project.dart","offset":5,"length":4,"startLine":1,"startColumn":6,"endLine":1,"endColumn":10},"flags":8,"parameters":"(List<String> arguments)","returnType":"void"},{"kind":"COMPILATION_UNIT","name":"simple_project.dart","location":{"file":"C:\\tmp\\simple_project\\bin\\simple_project.dart","offset":0,"length":0,"startLine":1,"startColumn":1,"endLine":1,"endColumn":1},"flags":16},{"kind":"LIBRARY","name":"","location":{"file":"C:\\tmp\\simple_project\\bin\\simple_project.dart","offset":0,"length":0,"startLine":1,"startColumn":1,"endLine":1,"endColumn":1},"flags":0}]}
-- End of result --
If I change searchPattern to an empty String, I gets a long list of top level declarations around the default included Dart SDK libraries. I am sure there are a way to exclude those.
But as far as I can see, the searchPattern is a regular expression tested against the name of each top level declaration and includes the declaration if its name contain any part of the regular expression.
I found the code responsible for the search here:
#override
Future<List<SearchMatch>> searchTopLevelDeclarations(String pattern) async {
var allElements = <Element>{};
var regExp = RegExp(pattern);
var drivers = _drivers.toList();
for (var driver in drivers) {
var elements = await driver.search.topLevelElements(regExp);
allElements.addAll(elements);
}
return allElements.map(SearchMatchImpl.forElement).toList();
}
https://github.com/dart-lang/sdk/blob/1278bd5adb6a857580f137e47bc521976222f7b9/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart#L113-L123
Which calls into:
/// Returns top-level elements with names matching the given [regExp].
Future<List<Element>> topLevelElements(RegExp regExp) async {
List<Element> elements = <Element>[];
void addElement(Element element) {
if (!element.isSynthetic && regExp.hasMatch(element.displayName)) {
elements.add(element);
}
}
List<FileState> knownFiles = _driver.fsState.knownFiles.toList();
for (FileState file in knownFiles) {
var unitResult = await _driver.getUnitElement(file.path);
if (unitResult is UnitElementResult) {
CompilationUnitElement unitElement = unitResult.element;
unitElement.accessors.forEach(addElement);
unitElement.classes.forEach(addElement);
unitElement.enums.forEach(addElement);
unitElement.extensions.forEach(addElement);
unitElement.functions.forEach(addElement);
unitElement.mixins.forEach(addElement);
unitElement.topLevelVariables.forEach(addElement);
unitElement.typeAliases.forEach(addElement);
}
}
return elements;
}
https://github.com/dart-lang/sdk/blob/1278bd5adb6a857580f137e47bc521976222f7b9/pkg/analyzer/lib/src/dart/analysis/search.dart#L166-L192

Mysterious anonymous function in Dart

I know the usage of anonymous function with () {} but what () {}() mean?
I'm using it in a Text widget like this:
new Text(
() {
return "hello";
}(),
),
It works pretty well but why do I need to add () after the anonymous function?
Without the second set of parentheses, you're just declaring an anonymous function, nothing else. So without that second set, you would be passing a function reference to the Text widget.
Now when you add the second set of parentheses you're actually calling the function that you defined.
If you look at it another way it might make it more clear. If you give that anonymous function a name you'll get the same result.
Function test = () {
return "hello";
};
print(test());
is equivalent to
print(() {
return "hello";
}());

How to add something like isClickable() in my appium native app tests

How to add something like isClickable() in my appium native app tests. I have written my tests, however they are very flaky and fail sometimes because it cannot find the element. I am thinking about making custom click and set value functions with the implicit wait times.
I thought about using isClickable() but the appium documentation says - Please note that isClickable works only in web and webviews, it doesn't work in mobile app native context.
Is there any other alternative i can use? can i use smartwait? if yes how can i implement that
Here is how i am defining home.screen.js
import AppScreen from './app.screen';
const SELECTORS = {
HOME_SCREEN: '~homeBarButton',
PRODUCTSEARCH_SCREEN: '~productSearchBarButton',
CUSTOMERSEARCH_SCREEN: '~customersBarButton',
STOREHUB_SCREEN: '~storeHubBarButton',
SETTING_ICON: '~SettingsIcon',
LOGOUT_BUTTON: '~settingsMainLogoutButton'
};
class HomeScreen extends AppScreen {
constructor () {
super(SELECTORS.HOME_SCREEN);
}
get homescreenButton () {
return $(SELECTORS.HOME_SCREEN);
}
get productsearchField () {
return $(SELECTORS.PRODUCTSEARCH_SCREEN);
}
get customersearchButon () {
return $(SELECTORS.CUSTOMERSEARCH_SCREEN);
}
get storehubButon () {
return $(SELECTORS.STOREHUB_SCREEN);
}
get settingIcon () {
return $(SELECTORS.SETTING_ICON);
}
get logoutButton () {
return $(SELECTORS.LOGOUT_BUTTON);
}
}
export default new HomeScreen();
And i am writing my test like this test.js:
import HomeScreen from '../screenobjects/home.screen';
import FormScreen from '../screenobjects/forms.screen';
import CommonPage from '../pageobjects/common.page';
describe('Sending item successfullt,', () => {
beforeEach(() => {
CommonPage.login()
});
afterEach(() => {
CommonPage.logout()
});
it('should be able to send the item to the mirror', () => {
driver.pause(3000)
HomeScreen.productsearchField.click();
driver.pause(3000)
HomeScreen.customersearchButon.click();
});
});
As you can see above, I have to add driver.pause otherwise my tests would fail because of button not clickable or typeable.
My suggestion is that you can get your elements attribute clickable and if its true keep doing your things
public boolean isClickable(String element) {
return androidDriver.findElementByAccessibilityId(element).getAttribute("clickable").equals("true");
}
You can use any method to find your element.
Best approach is to stop using implicit waits and do an explicit wait before each driver UI interaction.
You should do some reading on waitUntil / WebDriverWait (not sure if you have that in node.js implementation).
Then create functions for interacting with all types of elements in your app that perform an explicit wait before execution.
Pseudo code:
get clickButton (Selector element) {
waitUntil(clickable(element),...);
return $(driver.click(element));
}
Write generic methods for all type of elements in your app (button, textfield, dropdown...) and remove implicit waits from driver. You will see a big difference in your test stability.

Is this loginRequired(f)() the way to handle login required functions in dart?

I am new to Dart programming. I am trying to figure out what is the proper way (what everyone will do) to handle/guard those functions which are login required. The following is my first trial:
$ vim login_sample.dart:
var isLoggedIn;
class LoginRequiredException implements Exception {
String cause;
LoginRequiredException(this.cause);
}
Function loginRequired(Function f) {
if (!isLoggedIn) {
throw new LoginRequiredException("Login is reuiqred.");
}
return f;
}
void secretPrint() {
print("This is a secret");
}
void main(List<String> args) {
if (args.length != 1) return null;
isLoggedIn = (args[0] == '1') ? true : false;
try {
loginRequired(secretPrint)();
} on LoginRequiredException {
print("Login is required!");
}
}
then, run it with $ dart login_sample.dart 1 and $ dart login_sample.dart 2.
I am wondering if this is the recommended way to guard login required functions or not.
Thank you very much for your help.
Edited:
My question is more about general programming skills in Dart than how to use a plugin. In python, I just need to add #login_required decorator in the front of the function to protect it. I am wondering if this decorator function way is recommended in dart or not.
PS: All firebase/google/twitter/facebook etc... are blocked in my country.
I like the functional approach. I'd only avoid using globals, you can wrap it in a Context so you can mock then for tests and use Futures as Monads: https://dartpad.dartlang.org/ac24a5659b893e8614f3c29a8006a6cc
Passing the function is not buying much value. In a typical larger Dart project using a framework there will be some way to guard at a higher level than a function - such as an entire page or component/widget.
If you do want to guard at a per-function level you first need to decide with it should be the function or the call site that decides what needs to be guarded. In your example it is the call site making the decision. After that decision you can implement a throwIfNotAuthenticated and add a call at either the definition or call site.
void throwIfNotAuthenticated() {
if (!userIsAuthenticated) {
throw new LoginRequiredException();
}
}
// Function decides authentication is required:
void secretPrint() {
throwIfNotAuthenticated();
print('This is a secret');
}
// Call site decides authentication is required:
void main() {
// do stuff...
throwIfNotAuthenticated();
anotherSecreteMethod();
}

how to unwrap underlying event object from event listener argument in dart

i have following dart code:
#override
void attached() {
document.onCopy.listen(_onCopyHandler);
}
void _onCopyHandler(Event event) {
// Here i'd like to access event.clipboardData but it
// does not work for Firefox using Dart code so i need to
// get access to underlying javascript event object
}
i've already tried following without any success on Firefox (for Chrome it worked):
var jsEvent = new JsObject.fromBrowserObject(event);
as soon as i'll have a reference to JsObject i know how to call the method, i just need to get an access to that reference.

Resources